1 /* XQF - Quake server browser and launcher
2 * Copyright (C) 1998-2000 Roman Pozlevich <roma@botik.ru>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
17 */
18
19 #include "gnuconfig.h"
20
21 #include <sys/types.h>
22 #include <stdio.h>
23 #include <stdlib.h> /* atoi */
24 #include <sys/socket.h> /* inet_ntoa */
25 #include <netinet/in.h> /* inet_ntoa */
26 #include <arpa/inet.h> /* inet_ntoa */
27 #include <time.h> /* time */
28 #include <string.h> /* strlen */
29 #include <ctype.h> /* isspace */
30 #include <getopt.h>
31
32 // select, fork, pipe...
33 #include <sys/time.h>
34 #include <sys/types.h>
35 #include <errno.h>
36 #include <unistd.h>
37 #include <signal.h> /* kill... */
38 #include <sys/wait.h>
39
40
41 #ifdef ENABLE_NLS
42 # include <locale.h>
43 #endif
44
45 #include <gtk/gtk.h>
46 #include <gdk/gdkkeysyms.h>
47 #include <gdk-pixbuf/gdk-pixbuf.h>
48 #include <gdk-pixbuf/gdk-pixbuf-loader.h>
49
50 #include "i18n.h"
51 #include "xqf.h"
52 #include "xqf-ui.h"
53 #include "game.h"
54 #include "stat.h"
55 #include "source.h"
56 #include "pref.h"
57 #include "filter.h"
58 #include "flt-player.h"
59 #include "skin.h"
60 #include "dialogs.h"
61 #include "utils.h"
62 #include "server.h"
63 #include "launch.h"
64 #include "host.h"
65 #include "xutils.h"
66 #include "srv-list.h"
67 #include "srv-info.h"
68 #include "srv-prop.h"
69 #include "rc.h"
70 #include "pixmaps.h"
71 #include "rcon.h"
72 #include "statistics.h"
73 #include "psearch.h"
74 #include "addserver.h"
75 #include "addmaster.h"
76 #include "sort.h"
77 #include "menus.h"
78 #include "config.h"
79 #include "debug.h"
80 #include "redial.h"
81 #include "splash.h"
82 #include "loadpixmap.h"
83 #include "trayicon.h"
84 #include "scripts.h"
85 #include "tga/memtopixmap.h"
86
87 #ifdef USE_GEOIP
88 #include "country-filter.h"
89 #endif
90
91 static const char gslisthome[] = "http://aluigi.altervista.org/papers.htm#gslist";
92
93 static const char required_qstat_version[]="2.10";
94
95 time_t xqf_start_time;
96
97 int dontlaunch = 0;
98
99 int event_type = 0;
100
101 char* xqf_PACKAGE_DATA_DIR = PACKAGE_DATA_DIR;
102 char* xqf_LOCALEDIR = LOCALEDIR;
103
104 char* qstat_configfile = NULL;
105
106 GtkWidget *main_window = NULL;
107 GtkWidget *source_ctree = NULL;
108 GtkCList *server_clist = NULL;
109 GtkCList *player_clist = NULL;
110 GtkCTree *srvinf_ctree = NULL;
111
112 GtkEditable *selection_manager = NULL;
113
114 GSList *cur_source = NULL; /* GSList <struct master *> */
115 GSList *cur_server_list = NULL; /* GSList <struct server *> */
116 GSList *cur_userver_list = NULL; /* GSList <struct userver *> */
117
118 struct server *cur_server = NULL;
119
120 struct stat_job *stat_process = NULL;
121
122 static GtkWidget *main_toolbar = NULL;
123 static GtkWidget *main_status_bar = NULL;
124 static GtkWidget *main_filter_status_bar = NULL;
125 static GtkWidget *main_progress_bar = NULL;
126
127 static char *progress_bar_str = NULL;
128
129 // static GtkWidget *server_filter_menu = NULL; /* baa */
130
131 static GtkWidget *server_menu = NULL;
132 static GtkWidget *source_menu = NULL;
133 static GtkWidget *player_menu = NULL;
134 static GtkWidget *server_info_menu = NULL;
135
136 static GtkWidget *connect_menu_item = NULL;
137 static GtkWidget *observe_menu_item = NULL;
138 static GtkWidget *record_menu_item = NULL;
139 static GtkWidget *favadd_menu_item = NULL;
140 static GtkWidget *add_menu_item = NULL;
141 static GtkWidget *delete_menu_item = NULL;
142 static GtkWidget *refresh_menu_item = NULL;
143 static GtkWidget *refrsel_menu_item = NULL;
144 static GtkWidget *resolve_menu_item = NULL;
145 static GtkWidget *properties_menu_item = NULL;
146 static GtkWidget *rcon_menu_item = NULL;
147 // static GtkWidget *cancel_redial_menu_item = NULL;
148
149 static GtkWidget *file_quit_menu_item = NULL;
150 static GtkWidget *file_statistics_menu_item = NULL;
151
152 static GtkWidget *edit_add_menu_item = NULL;
153 static GtkWidget *edit_favadd_menu_item = NULL;
154 static GtkWidget *edit_delete_menu_item = NULL;
155 static GtkWidget *edit_update_master_builtin_menu_item = NULL;
156 static GtkWidget *edit_update_master_gslist_menu_item = NULL;
157 static GtkWidget *edit_add_master_menu_item = NULL;
158 static GtkWidget *edit_edit_master_menu_item = NULL;
159 static GtkWidget *edit_delete_master_menu_item = NULL;
160 static GtkWidget *edit_clear_master_servers_menu_item = NULL;
161 static GtkWidget *edit_find_player_menu_item = NULL;
162 static GtkWidget *edit_find_again_menu_item = NULL;
163
164 // rmb popup
165 static GtkWidget *source_add_master_menu_item = NULL;
166 static GtkWidget *source_edit_master_menu_item = NULL;
167 static GtkWidget *source_delete_master_menu_item = NULL;
168 static GtkWidget *source_clear_master_servers_menu_item = NULL;
169
170 static GtkWidget *view_refresh_menu_item = NULL;
171 static GtkWidget *view_refrsel_menu_item = NULL;
172 static GtkWidget *view_update_menu_item = NULL;
173
174 GtkWidget *view_hostnames_menu_item = NULL;
175 GtkWidget *view_defport_menu_item = NULL;
176
177 static GtkWidget *server_connect_menu_item = NULL;
178 static GtkWidget *server_observe_menu_item = NULL;
179 static GtkWidget *server_record_menu_item = NULL;
180 static GtkWidget *server_favadd_menu_item = NULL;
181 static GtkWidget *server_delete_menu_item = NULL;
182 static GtkWidget *server_resolve_menu_item = NULL;
183 static GtkWidget *server_properties_menu_item = NULL;
184 static GtkWidget *server_rcon_menu_item = NULL;
185 // static GtkWidget *server_cancel_redial_menu_item = NULL;
186
187 static GtkWidget *server_serverfilter_menu_item = NULL;
188 static GArray* server_filter_menu_items;
189
190 static GtkWidget *player_filter_menu_item = NULL;
191
192 static GtkWidget *update_button = NULL;
193 static GtkWidget *refresh_button = NULL;
194 static GtkWidget *refrsel_button = NULL;
195 static GtkWidget *stop_button = NULL;
196
197 static GtkWidget *connect_button = NULL;
198 // static GtkWidget *observe_button = NULL;
199 // static GtkWidget *record_button = NULL;
200
201 static GtkWidget *filter_buttons[FILTERS_TOTAL] = {0};
202
203 /* filter widgtet for toolbar */
204 // static GtkWidget *filter_option_menu_toolbar;
205
206 static GtkWidget *player_skin_popup = NULL;
207 static GtkWidget *player_skin_popup_preview = NULL;
208 /*
209 static GtkWidget *server_filter_1_widget = NULL;
210 static GtkWidget *server_filter_2_widget = NULL;
211 static GtkWidget *server_filter_3_widget = NULL;
212 */
213
214 // XXX: GtkWidget *server_filter_widget[MAX_SERVER_FILTERS + 3];
215
216 static gboolean check_launch (struct condef* con);
217 static void refresh_selected_callback (GtkWidget *widget, gpointer data);
218 static void launch_close_handler_part2(struct condef *con);
219
220 static void copy_text_to_clipboard(const char* text);
221
222 /** build server filter menu for menubar */
223 static GtkWidget* create_filter_menu();
224 // static GtkWidget* create_filter_menu_toolbar();
225 // static GtkWidget* filter_menu = NULL; // need to store that for toggling the checkboxes
226 static GSList* filter_menu_radio_buttons = NULL; // for finding the widgets to activate
227
228 static int redialserver = 0;
229
sighandler_debug(int signum)230 static void sighandler_debug(int signum) {
231 if (signum == SIGUSR1) {
232 set_debug_level(get_debug_level()+1);
233 }
234 else if (signum == SIGUSR2) {
235 set_debug_level(get_debug_level()-1);
236 }
237
238 debug(0,"debug level now at %d", get_debug_level());
239 }
240
241 // returns 0 if equal, -1 if too old, 1 if have > expected
compare_qstat_version(const char * have,const char * expected)242 int compare_qstat_version (const char* have, const char* expected) {
243 int have_major, expected_major;
244 int have_minor, expected_minor;
245 char have_pl=0, expected_pl=0;
246 const char* have_pos1=NULL, *expected_pos1=NULL;
247 const char* have_pos2=NULL, *expected_pos2=NULL;
248 char* buf;
249
250 debug(3,"compare_qstat_version(%s,%s)",have,expected);
251
252 if (!strcmp(have,expected)) {
253 return 0;
254 }
255
256 have_pos1 = strchr(have,'.');
257 expected_pos1 = strchr(expected,'.');
258
259 if (!have_pos1 || !expected_pos1) {
260 return -1;
261 }
262
263 buf = g_strndup(have,have_pos1-have);
264 have_major = atoi(buf);
265 g_free(buf);
266 buf = g_strndup(expected,expected_pos1-expected);
267 expected_major = atoi(buf);
268 g_free(buf);
269
270 debug(3,"compare_qstat_version -- compare major %d %d",have_major,expected_major);
271 if (have_major < expected_major) {
272 return -1;
273 }
274 if (have_major > expected_major) {
275 return 1;
276 }
277
278 have_pos1++;
279 expected_pos1++;
280
281 for (have_pos2=have_pos1;
282 have_pos2 && *have_pos2 && isdigit(*have_pos2);
283 have_pos2++);
284 for (expected_pos2=expected_pos1;
285 expected_pos2 && *expected_pos2 && isdigit(*expected_pos2);
286 expected_pos2++);
287
288 buf = g_strndup(have_pos1,have_pos2-have_pos1);
289 have_minor = atoi(buf);
290 g_free(buf);
291 buf = g_strndup(expected_pos1,expected_pos2-expected_pos1);
292 expected_minor = atoi(buf);
293 g_free(buf);
294
295 debug(3,"compare_qstat_version -- compare minor %d %d",have_minor,expected_minor);
296 if (have_minor < expected_minor) {
297 return -1;
298 }
299 if (have_minor > expected_minor) {
300 return 1;
301 }
302
303 if (have_pos2 && *have_pos2) have_pl=*have_pos2;
304 if (expected_pos2 && *expected_pos2) expected_pl=*expected_pos2;
305
306 debug(3,"compare_qstat_version -- compare pl %c %c",have_pl,expected_pl);
307 if (!have_pl && expected_pl) {
308 return -1;
309 }
310 if (have_pl && expected_pl && have_pl < expected_pl) {
311 return -1;
312 }
313
314 return 1;
315 }
316
qstat_version_string(struct external_program_connection * conn)317 void qstat_version_string(struct external_program_connection* conn) {
318 static const char search_for[] = "qstat version";
319 const char *ptr, *version_end;
320 char* found_version = NULL;
321
322 if (!conn) {
323 return;
324 }
325
326 // we already found a valid version string
327 if (conn->result) {
328 return;
329 }
330 if (!conn->current_line) {
331 return;
332 }
333
334 if (!strncmp(conn->current_line,search_for,strlen(search_for))) {
335 ptr = conn->current_line + strlen(search_for);
336 // skip whitespace
337 for (;isspace(*ptr);++ptr);
338 if (!*ptr) {
339 conn->result = FALSE;
340 return;
341 }
342 // skip until end of version string
343 for (version_end=ptr;
344 version_end &&
345 *version_end != '\0' && !isspace(*version_end);
346 ++version_end);
347 found_version=g_strndup(ptr,version_end-ptr);
348 // debug(0,"found version <%s>",found_version);
349
350 if (compare_qstat_version(found_version,required_qstat_version)>=0) {
351 conn->result=TRUE;
352 }
353
354 g_free(found_version);
355 }
356 }
357
check_qstat_version()358 int check_qstat_version() {
359 char* cmd[] = {QSTAT_EXEC,NULL};
360
361 return external_program_foreach_line(cmd, qstat_version_string, NULL);
362 }
363
reset_main_status_bar()364 void reset_main_status_bar() {
365 // Reset bottom left status bar to show number of servers
366 print_status (main_status_bar,
367 ngettext(_("%d server"),_("%d servers"), server_clist->rows),
368 server_clist->rows);
369 }
370
set_widgets_sensitivity(void)371 void set_widgets_sensitivity (void) {
372 GList *selected = server_clist->selection;
373 int sens;
374 int i;
375 int source_is_favorites;
376 int masters_to_update;
377 int masters_to_delete;
378
379 /*
380 * Every button with callback that can modify its sensitivity
381 * should be explicitly put to GTK_STATE_NORMAL state before
382 * changing its insensitivity
383 */
384
385 source_is_favorites = (cur_source != NULL &&
386 cur_source->next == NULL &&
387 (struct master *) cur_source->data == favorites);
388
389 if (source_is_favorites) {
390 masters_to_update = masters_to_delete = FALSE;
391 }
392 else {
393 masters_to_update = source_has_masters_to_update (cur_source);
394 masters_to_delete = source_has_masters_to_delete (cur_source);
395 }
396
397 sens = (!stat_process && cur_server);
398
399 gtk_widget_set_sensitive (properties_menu_item, sens);
400 gtk_widget_set_sensitive (server_properties_menu_item, sens);
401
402 sens = (!stat_process && cur_server &&
403 (games[cur_server->type].flags & GAME_CONNECT) != 0);
404
405 gtk_widget_set_sensitive (connect_menu_item, sens);
406 gtk_widget_set_sensitive (server_connect_menu_item, sens);
407
408 gtk_widget_set_state (connect_button, GTK_STATE_NORMAL);
409 gtk_widget_set_sensitive (connect_button, sens);
410
411 sens = (!stat_process && cur_server &&
412 (games[cur_server->type].flags & GAME_SPECTATE) != 0 &&
413 (cur_server->flags & SERVER_SPECTATE) != 0);
414
415 gtk_widget_set_sensitive (observe_menu_item, sens);
416 gtk_widget_set_sensitive (server_observe_menu_item, sens);
417
418 // gtk_widget_set_state (observe_button, GTK_STATE_NORMAL);
419 // gtk_widget_set_sensitive (observe_button, sens);
420
421 sens = (!stat_process && cur_server &&
422 (games[cur_server->type].flags & GAME_RECORD) != 0);
423
424 gtk_widget_set_sensitive (record_menu_item, sens);
425 gtk_widget_set_sensitive (server_record_menu_item, sens);
426
427 // gtk_widget_set_state (record_button, GTK_STATE_NORMAL);
428 // gtk_widget_set_sensitive (record_button, sens);
429
430 sens = (!stat_process && cur_server &&
431 (games[cur_server->type].flags & GAME_RCON) != 0);
432
433 gtk_widget_set_sensitive (rcon_menu_item, sens);
434 gtk_widget_set_sensitive (server_rcon_menu_item, sens);
435
436 sens = (!stat_process && selected);
437
438 gtk_widget_set_sensitive (refrsel_menu_item, sens);
439 gtk_widget_set_sensitive (view_refrsel_menu_item, sens);
440
441 gtk_widget_set_state (refrsel_button, GTK_STATE_NORMAL);
442 gtk_widget_set_sensitive (refrsel_button, sens);
443
444 gtk_widget_set_sensitive (resolve_menu_item, sens);
445 gtk_widget_set_sensitive (server_resolve_menu_item, sens);
446
447 sens = (!stat_process);
448
449 gtk_widget_set_sensitive (file_statistics_menu_item, sens);
450 gtk_widget_set_sensitive (add_menu_item, sens);
451 gtk_widget_set_sensitive (edit_add_menu_item, sens);
452 gtk_widget_set_sensitive (edit_update_master_builtin_menu_item, sens);
453 gtk_widget_set_sensitive (edit_update_master_gslist_menu_item, sens);
454 gtk_widget_set_sensitive (edit_add_master_menu_item, sens);
455 gtk_widget_set_sensitive (edit_find_player_menu_item, sens);
456 gtk_widget_set_sensitive (edit_find_again_menu_item, sens);
457 gtk_widget_set_sensitive (player_filter_menu_item, sens);
458 gtk_widget_set_sensitive (source_ctree, sens);
459
460 sens = (!stat_process && selected && !source_is_favorites);
461
462 gtk_widget_set_sensitive (favadd_menu_item, sens);
463 gtk_widget_set_sensitive (edit_favadd_menu_item, sens);
464 gtk_widget_set_sensitive (server_favadd_menu_item, sens);
465
466 #if 0
467 sens = (!stat_process && selected && source_is_favorites);
468
469 gtk_widget_set_sensitive (delete_menu_item, sens);
470 gtk_widget_set_sensitive (edit_delete_menu_item, sens);
471 gtk_widget_set_sensitive (server_delete_menu_item, sens);
472 #endif
473
474 sens = (!stat_process && masters_to_delete);
475
476 gtk_widget_set_sensitive (edit_delete_master_menu_item, sens);
477 gtk_widget_set_sensitive (edit_clear_master_servers_menu_item, sens);
478 gtk_widget_set_sensitive (source_delete_master_menu_item, sens);
479 gtk_widget_set_sensitive (source_clear_master_servers_menu_item, sens);
480
481 // you can only edit one server a time, no groups and no favorites
482 sens = (cur_source && cur_source->next == NULL
483 && ! ((struct master *) cur_source->data)->isgroup
484 && ! source_is_favorites);
485
486 gtk_widget_set_sensitive (source_edit_master_menu_item, sens);
487 gtk_widget_set_sensitive (edit_edit_master_menu_item, sens);
488
489 sens = (!stat_process && (server_clist->rows > 0));
490
491 gtk_widget_set_sensitive (refresh_menu_item, sens);
492 gtk_widget_set_sensitive (view_refresh_menu_item, sens);
493
494 gtk_widget_set_state (refresh_button, GTK_STATE_NORMAL);
495 gtk_widget_set_sensitive (refresh_button, sens);
496
497 gtk_widget_set_sensitive (view_hostnames_menu_item, sens);
498 gtk_widget_set_sensitive (view_defport_menu_item, sens);
499
500 sens = (!stat_process && masters_to_update);
501
502 gtk_widget_set_sensitive (view_update_menu_item, sens);
503
504 gtk_widget_set_state (update_button, GTK_STATE_NORMAL);
505 gtk_widget_set_sensitive (update_button, sens);
506
507 sens = (stat_process != NULL);
508
509 gtk_widget_set_state (stop_button, GTK_STATE_NORMAL);
510 gtk_widget_set_sensitive (stop_button, sens);
511
512 sens = (stat_process == NULL);
513
514 for (i = 0; i < FILTERS_TOTAL; i++) {
515 if (!filter_buttons[i]) {
516 continue;
517 }
518 gtk_widget_set_state(filter_buttons[ i ],GTK_STATE_NORMAL);
519 gtk_widget_set_sensitive (filter_buttons[i], sens);
520 if (GTK_IS_TOGGLE_BUTTON(filter_buttons[i]) && GTK_TOGGLE_BUTTON(filter_buttons[i])->active) {
521 gtk_widget_set_state(filter_buttons[ i ],GTK_STATE_ACTIVE);
522 }
523 }
524 #if 0
525 // grey out button if not redialing
526 sens = (redialserver == 1);
527 gtk_widget_set_sensitive (cancel_redial_menu_item, sens);
528 gtk_widget_set_sensitive (server_cancel_redial_menu_item, sens);
529 #endif
530 }
531
532
533 static int forced_filters_flag = FALSE;
534
535
set_filters(unsigned char mask)536 static void set_filters (unsigned char mask) {
537 unsigned n;
538 int i;
539
540 forced_filters_flag = TRUE;
541
542 cur_filter = mask;
543
544 for (i = 0, n = 1; i < FILTERS_TOTAL; i++, n <<= 1) {
545 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (filter_buttons[i]),
546 ((cur_filter & n) != 0)? TRUE : FALSE);
547 }
548
549 forced_filters_flag = FALSE;
550 }
551
552
filter_toggle_callback(GtkWidget * widget,unsigned char mask)553 static void filter_toggle_callback (GtkWidget *widget, unsigned char mask) {
554
555
556 if (!forced_filters_flag) {
557 cur_filter ^= mask;
558 server_clist_build_filtered (cur_server_list, FALSE); /* in srv-list.c */
559 reset_main_status_bar();
560 }
561 }
562
563 // iterate through radio buttons and activate the one for the current server
564 // filter
filter_menu_activate_current()565 static void filter_menu_activate_current() {
566 unsigned int count = 0;
567 GSList* rbgroup = filter_menu_radio_buttons;
568 GtkWidget* widget = NULL;
569
570 while (rbgroup) {
571 if (GTK_IS_CHECK_MENU_ITEM(rbgroup->data)) {
572 if (count == current_server_filter) {
573 widget = GTK_WIDGET(rbgroup->data);
574 break;
575 }
576 count++;
577 }
578 rbgroup=rbgroup->next;
579 }
580
581 if (widget) {
582 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), TRUE);
583 }
584 }
585
586
587 /*refresh filtermenu on toolbar*/
588
set_filter_option_menu_toolbar(void)589 void set_filter_option_menu_toolbar (void) {
590
591 /*
592 gtk_option_menu_set_menu (GTK_OPTION_MENU (filter_option_menu_toolbar), create_filter_menu_toolbar());
593 gtk_option_menu_set_history(GTK_OPTION_MENU(filter_option_menu_toolbar), current_server_filter);
594 */
595 }
596
597
set_server_filter_menu_list_text(void)598 void set_server_filter_menu_list_text(void){
599
600 /* baa -- Set the names of the filters if they have been set in
601 the config file. The server_filters is defined in filter.h
602 */
603
604 char status_buf[64];
605 char* name;
606
607 #if 0
608 for (i = 0; i < MAX_SERVER_FILTERS; i++) {
609
610 if (i == 0){
611 if (current_server_filter == i) {
612 //server filter
613 snprintf(buf, 64, _("None <--"));
614 }
615 else {
616 snprintf(buf, 64, _("None"));
617 }
618 }
619 else {
620 if (server_filters[i].filter_name && strlen(server_filters[i].filter_name)){
621
622 if (current_server_filter == i) {
623 snprintf(buf, 64, "%s <--", server_filters[i].filter_name);
624 }
625 else {
626 snprintf(buf, 64, "%s", server_filters[i].filter_name);
627 }
628
629 }
630 else {
631
632 if (current_server_filter == i) {
633 snprintf(buf, 64, _("Filter %d <--"), i);
634 }
635 else {
636 snprintf(buf, 64, _("Filter %d"), i);
637 }
638
639 }
640 }
641
642 if (server_filter_widget[i + filter_start_index ] && GTK_BIN (server_filter_widget[i + filter_start_index])->child) {
643 GtkWidget *child = GTK_BIN (server_filter_widget[i + filter_start_index ])->child;
644 if (GTK_IS_LABEL (child)) {
645 gtk_label_set (GTK_LABEL (child), buf);
646 }
647 }
648 }
649
650 #endif
651
652
653 /* Show the active filter on the status bar
654 -- Add code to indicate if the filter button is checked.
655 */
656 if (current_server_filter == 0) {
657 snprintf(status_buf, 64, _("No Server Filter Active"));
658 }
659 else {
660 name = g_array_index (server_filters, struct server_filter_vars*, current_server_filter-1)->filter_name;
661 if (name) {
662 snprintf(status_buf, 64, _("Server Filter: %s"), name);
663 }
664 else {
665 snprintf(status_buf, 64, _("Server Filter: %d"), current_server_filter);
666 xqf_error("this is a bug");
667 }
668 }
669
670 print_status (main_filter_status_bar, status_buf);
671
672 reset_main_status_bar();
673
674 }
675
676
server_filter_select_callback(GtkWidget * widget,int number)677 static void server_filter_select_callback (GtkWidget *widget, int number) {
678
679 if (!GTK_IS_CHECK_MENU_ITEM(widget)) {
680 g_warning("no check menu item");
681 return;
682 }
683
684 if (GTK_CHECK_MENU_ITEM(widget)->active == 0) {
685 // signal was triggered for deactivation
686 return;
687 }
688
689 current_server_filter = number;
690
691 filters[FILTER_SERVER].changed = FILTER_CHANGED;
692 filters[FILTER_SERVER].last_changed = filter_time_inc();
693
694 server_clist_build_filtered (cur_server_list, FALSE); /* in srv-list.c */
695 set_server_filter_menu_list_text ();
696
697 /* refresh optionmenu on toolbar*/
698
699 set_filter_option_menu_toolbar();
700
701 config_push_prefix ("/" CONFIG_FILE "/Server Filter");
702 config_set_int ("current_server_filter", current_server_filter);
703 config_pop_prefix ();
704
705 return;
706 }
707
708 /* need new one to refresh filter radio buttons in menu */
709 #if 0
710 static void server_filter_select_callback_toolbar (GtkWidget *widget, int number) {
711
712 current_server_filter = number;
713
714 /*apply changes to radio buttons in menu*/
715
716 filter_menu_activate_current();
717
718 return;
719 }
720 #endif
721
722
start_preferences_dialog(GtkWidget * widget,int page_num)723 static void start_preferences_dialog (GtkWidget *widget, int page_num) {
724 preferences_dialog (page_num);
725 set_toolbar_appearance (GTK_TOOLBAR (main_toolbar), default_toolbar_style, default_toolbar_tips);
726 }
727
728
start_filters_cfg_dialog(GtkWidget * widget,int page_num)729 static void start_filters_cfg_dialog (GtkWidget *widget, int page_num) {
730 if (filters_cfg_dialog (page_num)) {
731 config_sync ();
732 rc_save ();
733 gtk_menu_item_set_submenu (GTK_MENU_ITEM (server_serverfilter_menu_item), create_filter_menu());
734 filter_menu_activate_current();
735
736 /* refresh optionmenu on toolbar*/
737 set_filter_option_menu_toolbar();
738
739 /* refresh filter status*/
740 set_server_filter_menu_list_text ();
741
742 //happes automagically server_clist_build_filtered (cur_server_list, TRUE);
743 player_clist_redraw ();
744 }
745 }
746
747
update_server_lists_from_selected_source(void)748 static void update_server_lists_from_selected_source (void) {
749 GSList *cur_masters = NULL;
750
751 debug (6, "update_server_lists_from_selected_source() --");
752 if (cur_server_list) {
753 debug (6, "update_server_lists_from_selected_source() -- Free cur_server_list %lx", cur_server_list);
754 server_list_free (cur_server_list);
755 cur_server_list = NULL;
756 }
757
758 if (cur_userver_list) {
759 userver_list_free (cur_userver_list);
760 cur_userver_list = NULL;
761 }
762
763 master_selection_to_lists (cur_source, &cur_masters, &cur_server_list, &cur_userver_list);
764 collate_server_lists (cur_masters, &cur_server_list, &cur_userver_list);
765 }
766
767 /**
768 update ui with aquired data during refresh and when refresh is done
769 */
stat_lists_refresh(struct stat_job * job)770 static int stat_lists_refresh (struct stat_job *job) {
771 int items;
772 int freeze;
773
774 items = g_slist_length (job->delayed.queued_servers) +
775 g_slist_length (job->delayed.queued_hosts);
776
777 debug (6, "stat_lists_refresh() -- Job %lx, items %d", job,items);
778
779 if (items>100) {
780 update_server_lists_from_selected_source ();
781 server_clist_build_filtered (cur_server_list, TRUE);
782 job->delayed.queued_servers = NULL;
783 job->delayed.queued_hosts = NULL;
784 }
785 else if (items) {
786 freeze = (items > 1) || default_refresh_sorts;
787
788 if (freeze) {
789 gtk_clist_freeze (server_clist);
790 }
791
792 g_slist_foreach (job->delayed.queued_servers, (GFunc) server_clist_refresh_server, NULL);
793 server_list_free (job->delayed.queued_servers);
794 job->delayed.queued_servers = NULL;
795
796 g_slist_foreach (job->delayed.queued_hosts, (GFunc) server_clist_show_hostname, NULL);
797 host_list_free (job->delayed.queued_hosts);
798 job->delayed.queued_hosts = NULL;
799
800 if (default_refresh_sorts) {
801 gtk_clist_sort (server_clist);
802 }
803
804 if (freeze) {
805 gtk_clist_thaw (server_clist);
806 }
807 }
808
809 // print_status (main_status_bar, (progress_bar_str)? progress_bar_str : "", job->progress.done, job->progress.tasks);
810 if (job->progress.tasks > 0) {
811 progress_bar_set_percentage (main_progress_bar, ((float)job->progress.done) / job->progress.tasks);
812 }
813
814 return TRUE;
815 }
816
817
stat_lists_state_handler(struct stat_job * job,enum stat_state state)818 static void stat_lists_state_handler (struct stat_job *job, enum stat_state state) {
819 if (!main_window) {
820 return;
821 }
822
823 switch (state) {
824
825 case STAT_UPDATE_SOURCE:
826 progress_bar_str = _("Updating lists...");
827 if (default_show_tray_icon) {
828 tray_icon_start_animation ();
829 }
830 break;
831
832 case STAT_RESOLVE_NAMES:
833 progress_bar_str = _("Resolving host names: %d/%d");
834 break;
835
836 case STAT_REFRESH_SERVERS:
837 progress_bar_str = _("Refreshing: %d/%d");
838 if (default_show_tray_icon) {
839 tray_icon_start_animation ();
840 }
841 break;
842
843 case STAT_RESOLVE_HOSTS:
844 progress_bar_str = _("Resolving host addresses: %d/%d");
845 break;
846
847 default:
848 progress_bar_str = NULL;
849 break;
850 }
851
852 progress_bar_start (main_progress_bar, state == STAT_UPDATE_SOURCE || job->progress.tasks <= 1);
853
854 stat_lists_refresh (job); /* flush */
855 }
856
857
stat_lists_close_handler(struct stat_job * job,int killed)858 static void stat_lists_close_handler (struct stat_job *job, int killed) {
859
860 if (!main_window) {
861 return;
862 }
863
864 if (job->need_redraw) {
865 update_server_lists_from_selected_source ();
866 server_clist_build_filtered (cur_server_list, TRUE);
867 }
868 /*
869 if (redialserver == 1) {
870 print_status (main_status_bar, _("Waiting to redial server(s)..."));
871 else {
872 }
873 */
874
875 tray_icon_stop_animation ();
876 reset_main_status_bar();
877
878 progress_bar_reset (main_progress_bar);
879
880 stat_process = NULL;
881 set_widgets_sensitivity ();
882 }
883
884
stat_lists_server_handler(struct stat_job * job,struct server * s)885 static void stat_lists_server_handler (struct stat_job *job, struct server *s) {
886 if (s == cur_server) {
887 if (job->delayed.refresh_handler) {
888 (*job->delayed.refresh_handler) (job);
889 }
890 player_clist_set_server (s);
891 srvinf_ctree_set_server (s);
892 }
893 }
894
895
stat_lists_master_handler(struct stat_job * job,struct master * m)896 static void stat_lists_master_handler (struct stat_job *job, struct master *m) {
897 source_ctree_show_node_status (source_ctree, m);
898 }
899
900
stat_lists(GSList * masters,GSList * names,GSList * servers,GSList * hosts)901 static void stat_lists (GSList *masters, GSList *names, GSList *servers, GSList *hosts) {
902
903 if (stat_process || (!masters && !names && !servers && !hosts)) {
904 return;
905 }
906 debug_increase_indent();
907 debug (7, "stat_lists() -- Server List %p", servers);
908
909 stat_process = stat_job_create (masters, names, servers, hosts);
910
911 stat_process->delayed.refresh_handler = (GtkFunction) stat_lists_refresh;
912
913 stat_process->state_handlers = g_slist_prepend (stat_process->state_handlers, stat_lists_state_handler);
914 stat_process->close_handlers = g_slist_prepend (stat_process->close_handlers, stat_lists_close_handler);
915
916 stat_process->server_handlers = g_slist_append (stat_process->server_handlers, stat_lists_server_handler);
917 stat_process->master_handlers = g_slist_append (stat_process->master_handlers, stat_lists_master_handler);
918
919 stat_start (stat_process);
920 set_widgets_sensitivity ();
921 debug_decrease_indent();
922 }
923
924
stat_one_server(struct server * server)925 static void stat_one_server (struct server *server) {
926 GSList *list;
927
928 debug (6, "Server %lx", server);
929 if (!stat_process && server) {
930 list = server_list_prepend (NULL, server);
931 stat_lists (NULL, NULL, list, NULL);
932 }
933 }
934
launch_close_handler(struct stat_job * job,int killed)935 static void launch_close_handler (struct stat_job *job, int killed) {
936 struct condef* con;
937
938 con = (struct condef *) job->data;
939 job->data = NULL;
940
941 if (killed) {
942 condef_free (con);
943 return;
944 }
945
946 gtk_timeout_add(0,(GtkFunction)check_launch, (gpointer)con);
947 }
948
949 /** called from inside timer, always return FALSE to stop it */
check_launch(struct condef * con)950 static gboolean check_launch (struct condef* con) {
951 struct server_props *props;
952 gboolean launch = FALSE;
953
954 struct server *s;
955
956 if (!con) {
957 return FALSE;
958 }
959
960 s = con->s;
961 props = properties (s);
962
963 if (props && props->sucks) {
964 char* comment = props->comment;
965 if (comment && strlen(comment)) {
966 comment = g_strdup_printf(_("\n\nThe server sucks for the following reason:\n%s"), props->comment);
967 }
968 else {
969 comment = NULL;
970 }
971 launch = dialog_yesno (NULL, 1, _("Yes"), _("No"),
972 /* translator: %s = optional reason why the server sucks */
973 _("You said this servers sucks.\nDo you want to risk a game this time?%s"), comment?comment:"");
974
975 g_free(comment);
976
977 if (!launch) {
978 condef_free (con);
979 return FALSE;
980 }
981 }
982
983 if (s->flags & SERVER_INCOMPATIBLE) {
984 launch = dialog_yesno (NULL, 1, _("Yes"), _("No"),
985 _("This server is not compatible with the version of %s you have"
986 " installed.\nLaunch client anyway?"), games[s->type].name);
987
988 if (!launch) {
989 condef_free (con);
990 return FALSE;
991 }
992 }
993
994 if (s->ping >= MAX_PING) {
995 launch = dialog_yesno (NULL, 1, _("Launch"), _("Cancel"),
996 _("Server %s:%d is %s.\n\nLaunch client anyway?"),
997 (s->host->name)? s->host->name : inet_ntoa (s->host->ip),
998 s->port,
999 (s->ping == MAX_PING)? "unreachable" : "down");
1000 if (!launch) {
1001 condef_free (con);
1002 return FALSE;
1003 }
1004 }
1005
1006 if (!launch && !con->spectate && server_need_redial(s, props)) {
1007 launch = dialog_yesnoredial (NULL, 1, _("Launch"), _("Cancel"), _("Redial"),
1008 _("Server %s:%d is full.\n\nLaunch client anyway?"),
1009 (s->host->name)? s->host->name : inet_ntoa (s->host->ip),
1010 s->port);
1011 if (!launch) {
1012 condef_free (con);
1013 return FALSE;
1014 }
1015 else if (launch==2)
1016 {
1017 redialserver = 1;
1018
1019 launch = redial_dialog(con->s, props);
1020
1021 if (launch == FALSE) {
1022 condef_free (con);
1023 return FALSE;
1024 }
1025 }
1026 else
1027 redialserver = 0;
1028 }
1029
1030 launch_close_handler_part2(con);
1031
1032 return FALSE;
1033 }
1034
1035 // stop XMMS if running
stopxmms()1036 static void stopxmms() {
1037 char* xmmssocket = NULL;
1038 pid_t pid;
1039
1040 if (!default_stopxmms) {
1041 return;
1042 }
1043
1044 xmmssocket = g_strdup_printf("/tmp/xmms_%s.0",g_get_user_name());
1045
1046 if (access(xmmssocket,R_OK)) {
1047 debug(3,"xmms not running");
1048 g_free(xmmssocket);
1049 return;
1050 }
1051
1052 pid = fork();
1053 if (pid == 0) {
1054 char *argv[3];
1055 argv[0] = "xmms";
1056 argv[1] = "-s";
1057 argv[2] = NULL;
1058 execvp(argv[0],argv);
1059 _exit(EXIT_FAILURE);
1060 }
1061 else if (pid > 0) {
1062 int status;
1063 waitpid(pid,&status,0);
1064
1065 if (WIFEXITED(status)) {
1066 debug(3,"xmms exited normally");
1067 }
1068 else {
1069 debug(3,"xmms exited with status %d",WEXITSTATUS(status));
1070 }
1071 if (WIFSIGNALED(status)) {
1072 debug(3,"xmms was killed by signal %d",WTERMSIG(status));
1073 }
1074 }
1075
1076 g_free(xmmssocket);
1077 }
1078
launch_close_handler_part2(struct condef * con)1079 static void launch_close_handler_part2(struct condef *con) {
1080 struct server_props *props;
1081 int launch = FALSE;
1082 int save = 0;
1083 FILE *f;
1084 char *fn;
1085 char *temp_name;
1086 char *temp_mod;
1087 char *temp_game;
1088
1089 struct server *s;
1090
1091 stopxmms();
1092
1093 if (redialserver == 1) // was called from a redial
1094 play_sound(sound_redial_success, 0);
1095 else
1096 play_sound(sound_server_connect, 0);
1097
1098 redialserver = 0; // Cancel any redialing
1099
1100 s = con->s;
1101 props = properties (s);
1102
1103 debug(3,"rest of launch_close_handler"); // alex
1104
1105 if (con->spectate) {
1106 if ((s->flags & SERVER_SP_PASSWORD) == 0) {
1107 // XXX: what's this good for? looks useless to me -- ln
1108 con->spectator_password = g_strdup ("1");
1109 }
1110 else {
1111 if (props && props->spectator_password) {
1112 con->spectator_password = g_strdup (props->spectator_password);
1113 }
1114 else {
1115 con->spectator_password = enter_string_with_option_dialog (FALSE,
1116 _("Save Password"), &save, _("Spectator Password:"));
1117 if (!con->spectator_password) {
1118 condef_free (con);
1119 return;
1120 }
1121 if (save) {
1122 if (!props) {
1123 props = properties_new (s->host, s->port);
1124 }
1125 props->spectator_password = g_strdup (con->spectator_password);
1126 props_save ();
1127 }
1128 }
1129 }
1130 }
1131 else {
1132 if (props && props->server_password) {
1133 con->password = g_strdup (props->server_password);
1134 }
1135 else if ((s->flags & SERVER_PASSWORD) != 0) {
1136 con->password = enter_string_with_option_dialog (FALSE,
1137 _("Save Password"), &save, _("Server Password:"));
1138 if (!con->password) {
1139 condef_free (con);
1140 return;
1141 }
1142 if (save) {
1143 if (!props) {
1144 props = properties_new (s->host, s->port);
1145 }
1146 props->server_password = g_strdup (con->password);
1147 props_save ();
1148 }
1149 }
1150 }
1151
1152 // con->server = g_strdup_printf ("%s:%5d", inet_ntoa (s->host->ip), s->port);
1153 con->server = g_strdup_printf ("%s:%d", inet_ntoa (s->host->ip), s->port);
1154 con->gamedir = g_strdup (s->game);
1155
1156 if (props && props->rcon_password) {
1157 con->rcon_password = g_strdup (props->rcon_password);
1158 }
1159
1160 if (props && props->custom_cfg) {
1161 con->custom_cfg = g_strdup (props->custom_cfg);
1162 }
1163
1164
1165 launch = client_launch (con, TRUE);
1166 condef_free (con);
1167
1168 if (!launch) {
1169 return;
1170 }
1171
1172 // Save address etc to LaunchInfo.txt
1173 if (default_launchinfo) {
1174 fn = file_in_dir (user_rcdir, LAUNCHINFO_FILE);
1175
1176 f = fopen (fn, "w");
1177 if (f) {
1178
1179 temp_name = s->name;
1180 temp_game = s->game;
1181 temp_mod = s->gametype;
1182
1183 if (!temp_name) {
1184 temp_name = "";
1185 }
1186
1187 fprintf (f, "GameType %s\n", games[s->type].name);
1188 fprintf (f, "ServerName %s\n", temp_name);
1189 fprintf (f, "ServerAddr %s:%d\n", inet_ntoa (s->host->ip),
1190 s->port);
1191
1192 fprintf (f, "ServerMod ");
1193 if (temp_game) {
1194 fprintf (f, "%s", temp_game);
1195 }
1196 if (temp_game&&temp_mod) {
1197 fprintf (f, ", ");
1198 }
1199 if (temp_mod) {
1200 fprintf (f, "%s", temp_mod);
1201 }
1202 fprintf (f, "\n");
1203
1204 fclose (f);
1205 }
1206 g_free (fn);
1207 }
1208
1209 // Launch pre-launch script
1210 if (default_prelaunchexec) {
1211 if (fork() == 0) {
1212 char *launchargv[4];
1213 launchargv[0] = g_strdup_printf("%s/PreLaunch",user_rcdir);
1214 launchargv[1] = games[s->type].qstat_str;
1215 launchargv[2] = g_strdup_printf("%s:%d", inet_ntoa (s->host->ip), s->port);
1216 launchargv[3] = NULL;
1217 execv(launchargv[0],launchargv);
1218 xqf_error("PreLaunch failed");
1219 _exit(EXIT_FAILURE);
1220 }
1221 }
1222
1223 if (main_window && default_iconify && !default_terminate) {
1224 iconify_window (main_window->window);
1225 }
1226
1227 if (main_window && default_terminate) {
1228 gtk_widget_destroy (main_window);
1229 }
1230 }
1231
1232
launch_server_handler(struct stat_job * job,struct server * s)1233 static void launch_server_handler (struct stat_job *job, struct server *s) {
1234
1235 server_clist_refresh_server (s);
1236
1237 if (s == cur_server) {
1238 player_clist_set_server (s);
1239 srvinf_ctree_set_server (s);
1240 }
1241
1242 // no connection defined, maybe because of a hostname instead of ip specified
1243 // on command line. just take first server to launch
1244 if (!job->data) {
1245 job->data = condef_new (s);
1246 }
1247
1248 /* Don't spend time on host name lookups */
1249
1250 if (job->hosts) {
1251 host_list_free (job->hosts);
1252 job->hosts = NULL;
1253 }
1254 }
1255
1256
1257
launch_callback(GtkWidget * widget,enum launch_mode mode)1258 static void launch_callback (GtkWidget *widget, enum launch_mode mode) {
1259 int spectate = FALSE;
1260 char *demo = NULL;
1261 struct condef *con = NULL;
1262
1263 debug (6, "launc_callback() --");
1264 if (stat_process || !cur_server ||
1265 (games[cur_server->type].flags & GAME_CONNECT) == 0) {
1266 return;
1267 }
1268 if (games[cur_server->type].config_is_valid &&
1269 !(*games[cur_server->type].config_is_valid) (cur_server)) {
1270 start_preferences_dialog (NULL, PREF_PAGE_GAMES + cur_server->type * 256);
1271 return;
1272 }
1273
1274 switch (mode) {
1275
1276 case LAUNCH_NORMAL:
1277 break;
1278
1279 case LAUNCH_SPECTATE:
1280 if ((cur_server->flags & SERVER_SPECTATE) == 0) {
1281 return;
1282 }
1283
1284 spectate = TRUE;
1285 break;
1286
1287 case LAUNCH_RECORD:
1288 if ((games[cur_server->type].flags & GAME_RECORD) == 0) {
1289 return;
1290 }
1291
1292 if ((games[cur_server->type].flags & GAME_SPECTATE) != 0) {
1293 demo = enter_string_with_option_dialog (TRUE, _("Spectator"), &spectate, _("Demo name:"));
1294 }
1295 else {
1296 demo = enter_string_dialog (TRUE, _("Demo name:"));
1297 }
1298
1299 if (!demo) {
1300 return;
1301 }
1302
1303 break;
1304
1305 }
1306
1307 con = condef_new (cur_server);
1308 con->demo = demo;
1309 con->spectate = spectate;
1310
1311 stat_process = stat_job_create (NULL, NULL, server_list_prepend (NULL, cur_server), NULL);
1312 stat_process->data = con;
1313
1314 stat_process->state_handlers = g_slist_prepend (
1315 stat_process->state_handlers, stat_lists_state_handler);
1316 stat_process->close_handlers = g_slist_prepend (
1317 stat_process->close_handlers, stat_lists_close_handler);
1318
1319 stat_process->server_handlers = g_slist_append (
1320 stat_process->server_handlers, launch_server_handler);
1321
1322 /* run last!!! */
1323 stat_process->close_handlers = g_slist_append (
1324 stat_process->close_handlers, launch_close_handler);
1325
1326 stat_start (stat_process);
1327 set_widgets_sensitivity ();
1328 }
1329
1330 static int server_clist_sort_mode = SORT_SERVER_PING;
1331
server_clist_set_sort_mode(enum ssort_mode mode)1332 void server_clist_set_sort_mode(enum ssort_mode mode) {
1333 server_clist_sort_mode = mode;
1334 }
1335
server_clist_compare_func(GtkCList * clist,gconstpointer ptr1,gconstpointer ptr2)1336 static int server_clist_compare_func (GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2) {
1337 int res, mode;
1338 GtkCListRow *row1 = (GtkCListRow *) ptr1;
1339 GtkCListRow *row2 = (GtkCListRow *) ptr2;
1340 struct server *s1 = (struct server *) row1->data;
1341 struct server *s2 = (struct server *) row2->data;
1342 debug (7, "");
1343
1344 mode = server_clist_def.cols[clist->sort_column].sort_mode[server_clist_def.cols[clist->sort_column].current_sort_mode];
1345 res = compare_servers (s1, s2, mode);
1346
1347 // fallback
1348 if (res == 0 && mode != SORT_SERVER_PING) {
1349 res = compare_servers(s1, s2, SORT_SERVER_PING);
1350 }
1351
1352 return res;
1353 }
1354
1355
player_clist_compare_func(GtkCList * clist,gconstpointer ptr1,gconstpointer ptr2)1356 static int player_clist_compare_func (GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2) {
1357 GtkCListRow *row1 = (GtkCListRow *) ptr1;
1358 GtkCListRow *row2 = (GtkCListRow *) ptr2;
1359 struct player *p1 = (struct player *) row1->data;
1360 struct player *p2 = (struct player *) row2->data;
1361
1362 return compare_players (p1, p2, clist->sort_column);
1363 }
1364
1365
srvinf_clist_compare_func(GtkCList * clist,gconstpointer ptr1,gconstpointer ptr2)1366 static int srvinf_clist_compare_func (GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2) {
1367 GtkCListRow *row1 = (GtkCListRow *) ptr1;
1368 GtkCListRow *row2 = (GtkCListRow *) ptr2;
1369 const char **i1 = (const char **) row1->data;
1370 const char **i2 = (const char **) row2->data;
1371
1372 return compare_srvinfo (i1, i2, clist->sort_column);
1373 }
1374
1375
update_source_callback(GtkWidget * widget,gpointer data)1376 void update_source_callback (GtkWidget *widget, gpointer data) {
1377 GSList *masters = NULL;
1378 GSList *servers = NULL;
1379 GSList *uservers = NULL;
1380
1381 event_type=EVENT_UPDATE;
1382
1383 debug_increase_indent();
1384 debug (6, "update_source_callback() -- ");
1385 if (stat_process || !cur_source) {
1386 return;
1387 }
1388
1389 master_selection_to_lists (cur_source, &masters, &servers, &uservers);
1390 if (masters || servers || uservers) {
1391 stat_lists (masters, uservers, servers, NULL);
1392 }
1393 debug_decrease_indent();
1394
1395 }
1396
1397
refresh_selected_callback(GtkWidget * widget,gpointer data)1398 static void refresh_selected_callback (GtkWidget *widget, gpointer data) {
1399 GSList *list;
1400
1401 if (stat_process) {
1402 debug(1,"nope");
1403 return;
1404 }
1405
1406 event_type=EVENT_REFRESH_SELECTED;
1407
1408 list = server_clist_selected_servers ();
1409
1410 if (list) {
1411 stat_lists (NULL, NULL, list, NULL);
1412 }
1413 }
1414
1415
refresh_callback(GtkWidget * widget,gpointer data)1416 static void refresh_callback (GtkWidget *widget, gpointer data) {
1417 GSList *servers;
1418 GSList *uservers;
1419
1420 if (stat_process) {
1421 return;
1422 }
1423
1424 event_type=EVENT_REFRESH;
1425
1426 debug (7, "refresh_callback() -- Get Server List");
1427
1428 servers = server_clist_all_servers ();
1429 uservers = userver_list_copy (cur_userver_list);
1430
1431 debug (7, "refresh_callback() -- server list %lx", servers);
1432
1433 if (servers || uservers) {
1434 stat_lists (NULL, uservers, servers, NULL);
1435 }
1436 }
1437
refresh_n_server(GtkWidget * button,gpointer * data)1438 void refresh_n_server (GtkWidget * button, gpointer *data) {
1439 GSList *list;
1440 gint number;
1441
1442 if (stat_process)
1443 return;
1444
1445 event_type = EVENT_REFRESH;
1446 number=GPOINTER_TO_INT(data);
1447
1448 list = server_clist_get_n_servers(number);
1449
1450 if (list) {
1451 stat_lists(NULL, NULL, list, NULL);
1452 }
1453 }
1454
stop_callback(GtkWidget * widget,gpointer data)1455 void stop_callback (GtkWidget *widget, gpointer data) {
1456
1457 event_type = 0; // To prevent sound from stopped action from playing
1458
1459 if (stat_process) {
1460 stat_stop (stat_process);
1461 stat_process = NULL;
1462 }
1463 redialserver = 0; // Reset redialserver so prompt comes up next time
1464 play_sound(sound_stop, 0);
1465 event_type = 0; // To prevent sound from stopped action from playing
1466 }
1467
1468
add_to_favorites_callback(GtkWidget * widget,gpointer data)1469 static void add_to_favorites_callback (GtkWidget *widget, gpointer data) {
1470 GList *selected = server_clist->selection;
1471 GSList *list;
1472 GSList *tmp;
1473 enum { buflen = 256 };
1474 char buf[buflen]; /* if you change this, change the statement below */
1475 int server_list_size;
1476
1477 debug (7, "add_to_favorites_callback() -- ");
1478 if (stat_process || !selected) {
1479 return;
1480 }
1481
1482 list = server_clist_selected_servers ();
1483 if (list) {
1484 for (tmp = list; tmp; tmp = tmp->next) {
1485 server_list_size = g_slist_length (favorites->servers);
1486 favorites->servers =
1487 server_list_append (favorites->servers, (struct server *) tmp->data);
1488 if (server_list_size < g_slist_length (favorites->servers)){
1489 snprintf(buf, buflen, "Added Server #%d: '%s'",
1490 g_slist_length (favorites->servers),
1491 ((struct server *)tmp->data)->name);
1492 } else {
1493 snprintf(buf, buflen, "Server '%s' Already In Favorites",
1494 ((struct server *)tmp->data)->name);
1495 }
1496 print_status (main_status_bar, buf);
1497
1498 }
1499 debug (7, "add_to_favorites_callback() -- Saving To Favorites");
1500 save_favorites ();
1501 server_list_free (list);
1502 }
1503 }
1504
1505 // add a server to favorites
new_server_to_favorites(struct stat_job * job,struct server * s)1506 static void new_server_to_favorites (struct stat_job *job, struct server *s) {
1507 int row;
1508
1509 debug (6, "Server %lx, job %p", s, job);
1510 favorites->servers = server_list_append (favorites->servers, s);
1511 save_favorites ();
1512
1513 source_ctree_select_source (favorites);
1514
1515 if (cur_filter != 0) {
1516 set_filters (0); /* turn off filters */
1517 if (job) {
1518 job->need_redraw = FALSE;
1519 }
1520 }
1521
1522 row = gtk_clist_find_row_from_data (server_clist, s);
1523 if (row >= 0) {
1524 server_clist_select_one (row);
1525 server_clist_selection_visible ();
1526 }
1527 }
1528
1529
add_server_name_handler(struct stat_job * job,struct userver * us,enum dns_status status)1530 static void add_server_name_handler (struct stat_job *job, struct userver *us,
1531 enum dns_status status) {
1532 if (us->s) {
1533 new_server_to_favorites (job, us->s);
1534 }
1535 else {
1536 progress_bar_reset (main_progress_bar);
1537 dialog_ok (NULL, _("Host %s not found"), us->hostname);
1538 }
1539 }
1540
1541 /** check specified address is valid, resolve hostname if needed, stat server,
1542 * finally call new_server_to_favorites
1543 * calls free(str)!!!
1544 */
prepare_new_server_to_favorites(enum server_type type,char * str,gboolean dolaunch)1545 static void prepare_new_server_to_favorites(enum server_type type, char* str, gboolean dolaunch) {
1546 char *addr;
1547 unsigned short port;
1548 struct host *h;
1549 struct server *s = NULL;
1550 struct userver *us = NULL;
1551
1552 if (!str || !*str) {
1553 return;
1554 }
1555
1556 if (!parse_address (str, &addr, &port)) {
1557 dialog_ok (NULL, _("\"%s\" is not valid host[:port] combination."), str);
1558 g_free (str);
1559 return;
1560 }
1561
1562 g_free (str);
1563
1564 h = host_add (addr);
1565 if (h) { /* IP address */
1566 host_ref (h);
1567 s = server_add (h, port, type);
1568 if (s) {
1569 new_server_to_favorites (NULL, s);
1570 }
1571 host_unref (h);
1572 }
1573 else { /* hostname */
1574 us = userver_add (g_ascii_strdown(addr, -1), port, type);
1575 }
1576 g_free (addr);
1577
1578 if (s || us) {
1579 stat_process = stat_job_create (NULL,
1580 (us)? userver_list_add (NULL, us) : NULL,
1581 (s)? server_list_prepend (NULL, s) : NULL,
1582 NULL);
1583
1584 stat_process->state_handlers = g_slist_prepend (
1585 stat_process->state_handlers, stat_lists_state_handler);
1586 stat_process->close_handlers = g_slist_prepend (
1587 stat_process->close_handlers, stat_lists_close_handler);
1588
1589 // stat_process->server_handlers = g_slist_append (stat_process->server_handlers, stat_lists_server_handler);
1590
1591 stat_process->name_handlers = g_slist_prepend (
1592 stat_process->name_handlers, add_server_name_handler);
1593
1594 if (dolaunch) {
1595 if (s) {
1596 struct condef* con = condef_new (s);
1597 stat_process->data = con;
1598 }
1599
1600 stat_process->server_handlers = g_slist_append (
1601 stat_process->server_handlers, launch_server_handler);
1602
1603 stat_process->close_handlers = g_slist_append (
1604 stat_process->close_handlers, launch_close_handler);
1605 }
1606
1607 stat_start (stat_process);
1608 set_widgets_sensitivity ();
1609 }
1610 }
1611
add_server_callback(GtkWidget * widget,gpointer data)1612 static void add_server_callback (GtkWidget *widget, gpointer data) {
1613 char *str = NULL;
1614 enum server_type type = UNKNOWN_SERVER;
1615
1616 if (stat_process) {
1617 return;
1618 }
1619
1620 str = add_server_dialog (&type, NULL);
1621
1622 if (!str) {
1623 return;
1624 }
1625
1626 prepare_new_server_to_favorites(type, str, FALSE);
1627
1628 return;
1629 }
1630
del_server_callback(GtkWidget * widget,gpointer data)1631 static void del_server_callback (GtkWidget *widget, gpointer data) {
1632 GSList *selected;
1633 GSList *l, *c;
1634 int is_favorites = 0;
1635 int delete_from_all = 0;
1636
1637 debug(3, "--");
1638
1639 if (stat_process || !cur_source) {
1640 return;
1641 }
1642
1643 selected = server_clist_selected_servers();
1644
1645 if (!selected) {
1646 return;
1647 }
1648
1649 for (c = cur_source; c; c = c->next) {
1650 struct master* m = (struct master *) c->data;
1651
1652 if (m == favorites) {
1653 is_favorites = 1;
1654 }
1655
1656 if (!delete_from_all && m->isgroup) {
1657 delete_from_all = dialog_yesno (NULL, 1, _("Yes"), _("No"), _("Remove selected servers from all lists?"));
1658 }
1659 }
1660
1661 for (l = selected; l; l = l->next) {
1662 struct server* s = (struct server*) l->data;
1663
1664 if (delete_from_all) {
1665 server_remove_from_all(s);
1666 master_remove_server(favorites, s);
1667 }
1668 else {
1669 for (c = cur_source; c; c = c->next) {
1670 struct master* m = (struct master *) c->data;
1671
1672 master_remove_server(m, s);
1673 }
1674 }
1675 }
1676
1677 if (is_favorites) {
1678 save_favorites();
1679 }
1680
1681 g_slist_free(selected);
1682
1683 update_server_lists_from_selected_source ();
1684 server_clist_build_filtered (cur_server_list, FALSE);
1685 }
1686
1687
copy_server_callback(GtkWidget * widget,gpointer data)1688 static void copy_server_callback (GtkWidget *widget, gpointer data) {
1689 GList *selection = server_clist->selection;
1690 struct server *s;
1691 char buf[256];
1692 int pos = 0;
1693
1694 gtk_editable_delete_text (selection_manager, 0, -1);
1695
1696 switch (g_list_length (selection)) {
1697
1698 case 0:
1699 gtk_editable_select_region (selection_manager, 0, 0);
1700 break;
1701
1702 default:
1703 for (; selection; selection = selection->next) {
1704 s = (struct server *) gtk_clist_get_row_data (
1705 server_clist, GPOINTER_TO_INT(selection->data));
1706 g_snprintf (buf, 256, "%s:%d%s", inet_ntoa (s->host->ip), s->port, selection->next?"\n":"");
1707 gtk_editable_insert_text (selection_manager, buf, strlen (buf), &pos);
1708 }
1709 gtk_editable_select_region (selection_manager, 0, -1);
1710 break;
1711
1712 }
1713 gtk_editable_copy_clipboard(selection_manager);
1714 }
1715
copy_server_info_callback(GtkWidget * widget,gpointer data)1716 static void copy_server_info_callback (GtkWidget *widget, gpointer data) {
1717 GList *selection = GTK_CLIST(srvinf_ctree)->selection;
1718 int pos = 0;
1719
1720 gtk_editable_delete_text (selection_manager, 0, -1);
1721
1722 if (!g_list_length (selection)) {
1723 gtk_editable_select_region (selection_manager, 0, 0);
1724 }
1725 else {
1726 for (; selection; selection = selection->next) {
1727 GtkCTreeNode* node = GTK_CTREE_NODE(selection->data);
1728 char* txt = NULL;
1729
1730 gtk_ctree_node_get_text(GTK_CTREE(srvinf_ctree), node, 1, &txt);
1731 gtk_editable_insert_text (selection_manager, txt, strlen (txt), &pos);
1732 }
1733 gtk_editable_select_region (selection_manager, 0, -1);
1734 }
1735 gtk_editable_copy_clipboard(selection_manager);
1736 }
1737
copy_text_to_clipboard(const char * text)1738 static void copy_text_to_clipboard(const char* text) {
1739 int pos = 0;
1740 gtk_editable_delete_text (selection_manager, 0, -1);
1741 if (text && *text) {
1742 gtk_editable_insert_text (selection_manager, text, strlen (text), &pos);
1743 }
1744 gtk_editable_select_region (selection_manager, 0, pos);
1745 gtk_editable_copy_clipboard(selection_manager);
1746 }
1747
copy_server_callback_plus(GtkWidget * widget,gpointer data)1748 static void copy_server_callback_plus (GtkWidget *widget, gpointer data) {
1749 GList *selection = server_clist->selection;
1750 struct server *s;
1751 char buf[256];
1752 int pos = 0;
1753 unsigned players;
1754
1755 gtk_editable_delete_text (selection_manager, 0, -1);
1756
1757 switch (g_list_length (selection)) {
1758
1759 case 0:
1760 gtk_editable_select_region (selection_manager, 0, 0);
1761 break;
1762
1763 default:
1764 for (; selection; selection = selection->next) {
1765 s = (struct server *) gtk_clist_get_row_data (
1766 server_clist, GPOINTER_TO_INT(selection->data));
1767 players = s->curplayers;
1768 if (serverlist_countbots && s->curbots <= players) {
1769 players-=s->curbots;
1770 }
1771
1772 g_snprintf (buf, 256, "%i %s:%d %s %s %i of %i%s", s->ping, inet_ntoa
1773 (s->host->ip), s->port, s->name, s->map, players, s->maxplayers, selection->next?"\n":"");
1774 gtk_editable_insert_text (selection_manager, buf, strlen (buf), &pos);
1775 }
1776 gtk_editable_select_region (selection_manager, 0, -1);
1777 break;
1778
1779 }
1780
1781 gtk_editable_copy_clipboard(selection_manager);
1782 }
1783
update_master_builtin_callback(GtkWidget * widget,gpointer data)1784 static void update_master_builtin_callback (GtkWidget *widget, gpointer data) {
1785
1786 update_master_list_builtin();
1787
1788 }
1789
update_master_gslist_callback(GtkWidget * widget,gpointer data)1790 static void update_master_gslist_callback (GtkWidget *widget, gpointer data) {
1791 if (!have_gslist_installed()) {
1792 // translator: %s == url
1793 dialog_ok(NULL, _("For Gslist support you must install the 'gslist' program available from\n%s\n"
1794 "Don't forget that you need to run 'gslist -u' before you can use it."), gslisthome);
1795 copy_text_to_clipboard(gslisthome);
1796 return;
1797 }
1798 update_master_gslist_builtin();
1799 }
1800
add_master_callback(GtkWidget * widget,gpointer data)1801 static void add_master_callback (GtkWidget *widget, gpointer data) {
1802 struct master *m;
1803
1804 if (stat_process) {
1805 return;
1806 }
1807
1808 m = add_master_dialog(NULL);
1809
1810 if (m) {
1811 source_ctree_add_master (source_ctree, m);
1812 source_ctree_select_source (m);
1813 }
1814 }
1815
1816 // does only work with one master selected
edit_master_callback(GtkWidget * widget,gpointer data)1817 static void edit_master_callback (GtkWidget *widget, gpointer data) {
1818 struct master *master_to_edit, *master_to_add;
1819
1820 if (!cur_source) {
1821 return;
1822 }
1823
1824 master_to_edit = (struct master *) cur_source->data;
1825 source_ctree_select_source (master_to_edit);
1826 master_to_add = add_master_dialog(master_to_edit);
1827 if (master_to_add) {
1828 source_ctree_add_master (source_ctree, master_to_add);
1829 source_ctree_select_source (master_to_add);
1830 }
1831 }
1832
del_master_callback(GtkWidget * widget,gpointer data)1833 static void del_master_callback (GtkWidget *widget, gpointer data) {
1834 struct master *m;
1835 GSList *masters = NULL;
1836 char *master_names = NULL;
1837 GSList *list;
1838 int delete;
1839 char *s1;
1840 char *s2;
1841
1842 if (stat_process) {
1843 return;
1844 }
1845
1846 for (list = cur_source; list; list = list->next) {
1847 m = (struct master *) list->data;
1848 if (m != favorites && !m->isgroup) {
1849
1850 masters = g_slist_append (masters, m);
1851 s1 = g_strdup_printf ("%s (%s)", m->name, games[m->type].name);
1852
1853 if (!master_names) {
1854 master_names = s1;
1855 }
1856 else {
1857 s2= master_names;
1858 master_names = g_strconcat (s2, "\n", s1, NULL);
1859 g_free (s1);
1860 g_free (s2);
1861 }
1862
1863 }
1864 }
1865
1866 if (!masters) {
1867 dialog_ok(NULL,_("You have to select the server you want to delete"));
1868 return;
1869 }
1870
1871 // FIXME: plural
1872 delete = dialog_yesno (NULL, 1, _("Delete"), _("Cancel"),
1873 _("Master%s to delete:\n\n%s"),
1874 (g_slist_length (masters) > 1)? "s" : "",
1875 master_names);
1876
1877 if (delete) {
1878 for (list = masters; list; list = list->next) {
1879 m = (struct master *) list->data;
1880 source_ctree_delete_master (source_ctree, m);
1881 free_master (m);
1882 }
1883 }
1884
1885 g_free (master_names);
1886 g_slist_free (masters);
1887 }
1888
1889
find_player_callback(GtkWidget * widget,int find_next)1890 static void find_player_callback (GtkWidget *widget, int find_next) {
1891 char *pattern;
1892
1893 if (find_next || find_player_dialog ()) {
1894 if (!psearch_data_is_empty ()) {
1895 pattern = psearch_lookup_pattern ();
1896 print_status (main_status_bar, _("Find Player: %s"), pattern);
1897 g_free (pattern);
1898
1899 find_player (find_next);
1900 }
1901 }
1902 }
1903
1904
show_hostnames_callback(GtkWidget * widget,gpointer data)1905 static void show_hostnames_callback (GtkWidget *widget, gpointer data) {
1906
1907 if (stat_process || !server_clist || server_clist->rows == 0) {
1908 return;
1909 }
1910
1911 if (GTK_CHECK_MENU_ITEM (view_hostnames_menu_item)->active != show_hostnames) {
1912 show_hostnames = GTK_CHECK_MENU_ITEM (view_hostnames_menu_item)->active;
1913 server_clist_redraw ();
1914 config_set_bool ("/" CONFIG_FILE "/Appearance/show hostnames", show_hostnames);
1915 }
1916 }
1917
1918
show_default_port_callback(GtkWidget * widget,gpointer data)1919 static void show_default_port_callback (GtkWidget *widget, gpointer data) {
1920
1921 if (stat_process || !server_clist || server_clist->rows == 0) {
1922 return;
1923 }
1924
1925 if (GTK_CHECK_MENU_ITEM (view_defport_menu_item)->active != show_default_port) {
1926 show_default_port = GTK_CHECK_MENU_ITEM (view_defport_menu_item)->active;
1927 server_clist_redraw ();
1928 config_set_bool ("/" CONFIG_FILE "/Appearance/show default port", show_default_port);
1929 }
1930 }
1931
1932
resolve_callback(GtkWidget * widget,gpointer data)1933 static void resolve_callback (GtkWidget *widget, gpointer data) {
1934 GSList *selected;
1935 GSList *hosts;
1936 struct server *s;
1937
1938 debug (7, "resolve_callback() --");
1939 if (stat_process) {
1940 return;
1941 }
1942
1943 if (!show_hostnames) {
1944 gtk_check_menu_item_set_active (
1945 GTK_CHECK_MENU_ITEM (view_hostnames_menu_item), TRUE);
1946 }
1947
1948 selected = server_clist_selected_servers ();
1949 if (!selected) {
1950 return;
1951 }
1952
1953 if (selected->next) {
1954 hosts = merge_hosts_to_resolve (NULL, selected);
1955 }
1956 else {
1957
1958 /* always resolve if only one host is asked to */
1959
1960 s = (struct server *) selected->data;
1961 hosts = host_list_add (NULL, s->host);
1962 }
1963
1964 server_list_free (selected);
1965
1966 stat_lists (NULL, NULL, NULL, hosts);
1967 }
1968
1969
properties_callback(GtkWidget * widget,gpointer data)1970 static void properties_callback (GtkWidget *widget, gpointer data) {
1971
1972 if (stat_process) {
1973 return;
1974 }
1975
1976 if (cur_server) {
1977 properties_dialog (cur_server);
1978 set_widgets_sensitivity ();
1979 }
1980 }
1981
1982 #if 0
1983 static void cancelredial_callback (GtkWidget *widget, gpointer data) {
1984
1985 if (stat_process) {
1986 return;
1987 }
1988
1989 redialserver = 0;
1990 print_status (main_status_bar, _("Done."));
1991 progress_bar_reset (main_progress_bar);
1992
1993 }
1994 #endif
1995
rcon_callback(GtkWidget * widget,gpointer data)1996 static void rcon_callback (GtkWidget *widget, gpointer data) {
1997 struct server_props *sp;
1998 char *passwd = NULL;
1999 int save = 0;
2000
2001 if (stat_process || !cur_server ||
2002 (games[cur_server->type].flags & GAME_RCON) == 0) {
2003 return;
2004 }
2005
2006 sp = properties (cur_server);
2007
2008 if (!sp || !sp->rcon_password) {
2009 passwd = enter_string_with_option_dialog (FALSE,
2010 _("Save Password"), &save, _("Server Password:"));
2011
2012 if (!passwd) /* canceled */
2013 return;
2014
2015 if (save) {
2016 if (!sp) {
2017 sp = properties_new (cur_server->host, cur_server->port);
2018 }
2019 sp->rcon_password = passwd;
2020 props_save ();
2021 passwd = NULL;
2022 }
2023 }
2024
2025 rcon_dialog (cur_server, (passwd)? passwd : sp->rcon_password);
2026
2027 if (passwd) {
2028 g_free (passwd);
2029 }
2030 }
2031
2032
server_clist_select_callback(GtkWidget * widget,int row,int column,GdkEvent * event,GtkWidget * button)2033 static void server_clist_select_callback (GtkWidget *widget, int row,
2034 int column, GdkEvent *event, GtkWidget *button) {
2035 GdkEventButton *bevent = (GdkEventButton *) event;
2036 debug (7, "server_clist_select_callback() -- Row %d", row);
2037 server_clist_sync_selection ();
2038
2039 if (bevent && bevent->type == GDK_2BUTTON_PRESS && bevent->button == 1 &&
2040 !((column == 6) && cur_server && (games[cur_server->type].get_mapshot))) // not for map preview
2041 {
2042 launch_callback (NULL, LAUNCH_NORMAL);
2043 }
2044 }
2045
2046
server_clist_unselect_callback(GtkWidget * widget,int row,int column,GdkEvent * event,GtkWidget * button)2047 static void server_clist_unselect_callback (GtkWidget *widget, int row,
2048 int column, GdkEvent *event, GtkWidget *button) {
2049 debug (7, "server_clist_uselect_callback() -- Row %d", row);
2050 server_clist_sync_selection ();
2051 }
2052
2053
2054 /* Deal with key-presses in the server pane */
server_clist_keypress_callback(GtkWidget * widget,GdkEventKey * event)2055 static gboolean server_clist_keypress_callback (GtkWidget *widget, GdkEventKey *event) {
2056
2057 debug (7, "server_clist_keypress_callback() -- CLIST Key %x", event->keyval);
2058 if (event->keyval == GDK_Delete) {
2059 del_server_callback(widget, event);
2060 return TRUE;
2061 } else if (event->keyval == GDK_Insert) {
2062 if (event->state & GDK_SHIFT_MASK){
2063 add_to_favorites_callback(widget, event);
2064 } else {
2065 add_server_callback (widget, event);
2066 }
2067 return TRUE;
2068 } else if (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter) {
2069 launch_callback(widget, LAUNCH_NORMAL);
2070 return TRUE;
2071 }
2072 return FALSE;
2073 }
2074
source_ctree_event_callback(GtkWidget * widget,GdkEvent * event)2075 static int source_ctree_event_callback (GtkWidget *widget, GdkEvent *event) {
2076 GdkEventButton *bevent = (GdkEventButton *) event;
2077 GList *selection;
2078 int row;
2079 GtkCTreeNode *node, *node_under_mouse;
2080 int node_is_in_selection = 0;
2081
2082 if (event->type == GDK_BUTTON_PRESS &&
2083 bevent->window == GTK_CLIST(source_ctree)->clist_window) {
2084
2085 switch (bevent->button) {
2086
2087 case 3:
2088 // lets see which row the cursor is on
2089 if (gtk_clist_get_selection_info (GTK_CLIST(source_ctree),
2090 bevent->x, bevent->y, &row, NULL)) {
2091 // list of selected items
2092 selection = GTK_CLIST(source_ctree)->selection;
2093 // XXX: what is the first part of the && good for?
2094 if (!g_list_find (selection, GINT_TO_POINTER(row)) &&
2095 (bevent->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == 0) {
2096 node_under_mouse = gtk_ctree_node_nth(GTK_CTREE (source_ctree),row);
2097 if (node_under_mouse) {
2098 // go through all selected masters and search if the one under the
2099 // cursor is among them
2100 while (selection) {
2101 node = GTK_CTREE_NODE(selection->data);
2102 if (node == node_under_mouse) {
2103 node_is_in_selection = 1;
2104 break;
2105 }
2106 selection = selection->next;
2107 }
2108
2109 // clear selection and only select the one under the curser
2110 if (!node_is_in_selection) {
2111 gtk_ctree_unselect_recursive(GTK_CTREE(source_ctree),NULL);
2112 gtk_ctree_select (GTK_CTREE (source_ctree), node_under_mouse);
2113 }
2114 }
2115 }
2116
2117 }
2118
2119 gtk_menu_popup (GTK_MENU (source_menu), NULL, NULL, NULL, NULL,
2120 bevent->button, bevent->time);
2121 return TRUE;
2122
2123 default:
2124 return FALSE;
2125 }
2126
2127 }
2128 return FALSE;
2129 }
2130
2131 static GtkWidget *server_mapshot_popup = NULL;
2132 static GtkWidget *server_mapshot_popup_pixmap = NULL;
2133
server_mapshot_preview_popup_show(guchar * imagedata,size_t len,int x,int y)2134 static void server_mapshot_preview_popup_show (guchar *imagedata, size_t len, int x, int y) {
2135 GtkWidget *frame;
2136 int win_x, win_y, scr_w, scr_h;
2137 guint w = 0, h = 0;
2138 GdkPixmap *pix = NULL;
2139 GdkBitmap *mask = NULL;
2140
2141 renderMemToGtkPixmap(imagedata,len,&pix,&mask,&w,&h, 64);
2142
2143 if (!pix || !w || !h) {
2144 if (pix) gdk_pixmap_unref(pix);
2145 if (mask) gdk_bitmap_unref(mask);
2146 pix=stop_pix.pix;
2147 mask=stop_pix.mask;
2148 }
2149
2150 if (!server_mapshot_popup) {
2151 server_mapshot_popup = gtk_window_new (GTK_WINDOW_POPUP);
2152 gtk_window_set_policy (GTK_WINDOW (server_mapshot_popup), FALSE, FALSE, TRUE);
2153
2154 frame = gtk_frame_new (NULL);
2155 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
2156 gtk_container_add (GTK_CONTAINER (server_mapshot_popup), frame);
2157 gtk_widget_show (frame);
2158
2159 server_mapshot_popup_pixmap = gtk_pixmap_new(pix,mask);
2160 gtk_container_add (GTK_CONTAINER (frame), server_mapshot_popup_pixmap);
2161 // gtk_preview_size (GTK_PREVIEW (pixmap), 320, 200);
2162 gtk_widget_show (server_mapshot_popup_pixmap);
2163 }
2164 else {
2165 gtk_widget_hide (server_mapshot_popup);
2166 gtk_pixmap_set(GTK_PIXMAP(server_mapshot_popup_pixmap),pix,mask);
2167 }
2168
2169 gdk_window_get_origin (server_clist->clist_window, &win_x, &win_y);
2170 x += win_x;
2171 y += win_y;
2172 scr_w = gdk_screen_width ();
2173 scr_h = gdk_screen_height ();
2174 x = (x + w > scr_w)? scr_w - w : x;
2175 y = (y + h > scr_h)? scr_h - h : y;
2176
2177 // debug(0,"%d %d %d %d %d %d",scr_w,scr_h,x,y,w,h);
2178
2179 gtk_widget_set_uposition (server_mapshot_popup, x, y);
2180 gtk_widget_show(server_mapshot_popup);
2181 }
2182
server_clist_event_callback(GtkWidget * widget,GdkEvent * event)2183 static int server_clist_event_callback (GtkWidget *widget, GdkEvent *event) {
2184 GdkEventButton *bevent = (GdkEventButton *) event;
2185 GList *selection;
2186 int row, column;
2187
2188 debug (7, "server_clist_event_callback() -- ");
2189 if (event->type == GDK_BUTTON_PRESS &&
2190 bevent->window == server_clist->clist_window) {
2191
2192 switch (bevent->button) {
2193 case 1:
2194 if (gtk_clist_get_selection_info (server_clist,
2195 bevent->x, bevent->y, &row, &column)) {
2196 server_clist_select_one (row);
2197 if ((column == 6) && cur_server && (games[cur_server->type].get_mapshot)) {
2198 size_t buflen;
2199 guchar* buf = NULL;
2200
2201 buflen = games[cur_server->type].get_mapshot(cur_server,&buf);
2202
2203 gdk_pointer_grab (server_clist->clist_window, FALSE,
2204 GDK_POINTER_MOTION_HINT_MASK |
2205 GDK_BUTTON1_MOTION_MASK |
2206 GDK_BUTTON_RELEASE_MASK,
2207 NULL, NULL, bevent->time);
2208
2209 server_mapshot_preview_popup_show (buf, buflen, bevent->x, bevent->y);
2210
2211 g_free (buf);
2212 return TRUE;
2213 }
2214 }
2215 break;
2216
2217 case 2:
2218 if (gtk_clist_get_selection_info (server_clist, bevent->x, bevent->y, &row, NULL)) {
2219 server_clist_select_one (row);
2220 stat_one_server (cur_server);
2221 }
2222 return TRUE;
2223
2224 case 3:
2225 if (gtk_clist_get_selection_info (server_clist, bevent->x, bevent->y, &row, NULL)) {
2226 selection = server_clist->selection;
2227 if (!g_list_find (selection, GINT_TO_POINTER(row)) && (bevent->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == 0) {
2228 server_clist_select_one (row);
2229 }
2230 }
2231 gtk_menu_popup (GTK_MENU (server_menu), NULL, NULL, NULL, NULL,
2232 bevent->button, bevent->time);
2233 return TRUE;
2234
2235 default:
2236 return FALSE;
2237 }
2238
2239 }
2240
2241 if (event->type == GDK_BUTTON_RELEASE &&
2242 bevent->window == server_clist->clist_window) {
2243 if (server_mapshot_popup) {
2244 gdk_pointer_ungrab (bevent->time);
2245 gtk_widget_hide (server_mapshot_popup);
2246 }
2247 }
2248
2249 return FALSE;
2250 }
2251
server_info_clist_event_callback(GtkWidget * widget,GdkEvent * event)2252 static int server_info_clist_event_callback (GtkWidget *widget, GdkEvent *event) {
2253 GdkEventButton *bevent = (GdkEventButton *) event;
2254 GList *selection;
2255 GtkCTreeNode *node, *node_under_mouse;
2256 int row = -1;
2257 int node_is_in_selection = 0;
2258
2259 if (event->type == GDK_BUTTON_PRESS
2260 && bevent->window == GTK_CLIST(srvinf_ctree)->clist_window
2261 && bevent->button == 3) {
2262
2263 if (gtk_clist_get_selection_info (GTK_CLIST(srvinf_ctree), bevent->x, bevent->y, &row, NULL)) {
2264
2265 selection = GTK_CLIST(srvinf_ctree)->selection;
2266 if (!g_list_find (selection, GINT_TO_POINTER(row)) && (bevent->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == 0) {
2267 node_under_mouse = gtk_ctree_node_nth(GTK_CTREE (srvinf_ctree),row);
2268 if (node_under_mouse) {
2269 // go through all selected masters and search if the one under the
2270 // cursor is among them
2271 while (selection) {
2272 node = GTK_CTREE_NODE(selection->data);
2273 if (node == node_under_mouse) {
2274 node_is_in_selection = 1;
2275 break;
2276 }
2277 selection = selection->next;
2278 }
2279
2280 // clear selection and only select the one under the curser
2281 if (!node_is_in_selection) {
2282 gtk_ctree_unselect_recursive(GTK_CTREE(srvinf_ctree),NULL);
2283 gtk_ctree_select (GTK_CTREE (srvinf_ctree), node_under_mouse);
2284 }
2285 }
2286 }
2287 }
2288 gtk_menu_popup (GTK_MENU (server_info_menu), NULL, NULL, NULL, NULL,
2289 bevent->button, bevent->time);
2290
2291 return TRUE;
2292 }
2293
2294 return FALSE;
2295 }
2296
2297
source_selection_changed(void)2298 static void source_selection_changed (void) {
2299 GList *selection = GTK_CLIST (source_ctree)->selection;
2300 GtkCTreeNode *node;
2301 struct master *m;
2302
2303 debug (6, "souce_selection_changed() --");
2304 if (cur_source) {
2305 g_slist_free (cur_source);
2306 cur_source = NULL;
2307 }
2308
2309 while (selection) {
2310 node = (GtkCTreeNode *) selection->data;
2311 m = (struct master *) gtk_ctree_node_get_row_data (
2312 GTK_CTREE (source_ctree), node);
2313 cur_source = g_slist_append (cur_source, m);
2314 selection = selection->next;
2315 }
2316
2317 update_server_lists_from_selected_source ();
2318 server_clist_set_list (cur_server_list);
2319
2320 reset_main_status_bar();
2321 }
2322
2323
source_ctree_selection_changed_callback(GtkWidget * widget,int row,int column,GdkEvent * event,GtkWidget * button)2324 static void source_ctree_selection_changed_callback (GtkWidget *widget,
2325 int row, int column, GdkEvent *event, GtkWidget *button) {
2326 debug(6,"source_ctree_selection_changed_callback(%p,%d,%d,%p,%p)",widget,row,column,event,button);
2327 source_selection_changed ();
2328 }
2329
source_selection_clear_master_servers(void)2330 static void source_selection_clear_master_servers (void) {
2331 struct master *m;
2332 GSList* source = NULL;
2333
2334 for (source = cur_source; source; source=source->next) {
2335 m = (struct master *) source->data;
2336
2337 if (m == favorites || m->isgroup) {
2338 continue;
2339 }
2340
2341 server_list_free(m->servers);
2342 m->servers = NULL;
2343 }
2344
2345 update_server_lists_from_selected_source ();
2346 server_clist_set_list (cur_server_list);
2347
2348 reset_main_status_bar();
2349 }
2350
clear_master_servers_callback(GtkWidget * widget,int row,int column,GdkEvent * event,GtkWidget * button)2351 static void clear_master_servers_callback (GtkWidget *widget,
2352 int row, int column, GdkEvent *event, GtkWidget *button) {
2353 source_selection_clear_master_servers ();
2354 }
2355
add_to_player_filter_callback(GtkWidget * widget,unsigned mask)2356 static void add_to_player_filter_callback (GtkWidget *widget, unsigned mask) {
2357 GList *selection = player_clist->selection;
2358 struct player *p;
2359 int row;
2360
2361 if (!selection || !cur_server || stat_process) {
2362 return;
2363 }
2364
2365 row = GPOINTER_TO_INT(selection->data);
2366 p = (struct player *) gtk_clist_get_row_data (player_clist, row);
2367
2368 if (player_filter_add_player (p->name, mask)) {
2369 server_clist_build_filtered (cur_server_list, TRUE);
2370 player_clist_redraw ();
2371 }
2372 }
2373
2374
player_skin_preview_popup_show(guchar * skin,int top,int bottom,int x,int y)2375 static void player_skin_preview_popup_show (guchar *skin,
2376 int top, int bottom, int x, int y) {
2377 GtkWidget *frame;
2378 int win_x, win_y, scr_w, scr_h;
2379
2380 if (!player_skin_popup) {
2381 player_skin_popup = gtk_window_new (GTK_WINDOW_POPUP);
2382 gtk_window_set_policy (GTK_WINDOW (player_skin_popup), FALSE, FALSE, TRUE);
2383
2384 frame = gtk_frame_new (NULL);
2385 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
2386 gtk_container_add (GTK_CONTAINER (player_skin_popup), frame);
2387 gtk_widget_show (frame);
2388
2389 player_skin_popup_preview = gtk_preview_new (GTK_PREVIEW_COLOR);
2390 gtk_container_add (GTK_CONTAINER (frame), player_skin_popup_preview);
2391 gtk_preview_size (GTK_PREVIEW (player_skin_popup_preview), 320, 200);
2392 gtk_widget_show (player_skin_popup_preview);
2393 }
2394 else {
2395 gtk_widget_hide (player_skin_popup);
2396 }
2397
2398 gdk_window_get_origin (player_clist->clist_window, &win_x, &win_y);
2399 x += win_x;
2400 y += win_y;
2401 scr_w = gdk_screen_width ();
2402 scr_h = gdk_screen_height ();
2403 x = (x + 320 > scr_w)? scr_w - 320 : x;
2404 y = (y + 200 > scr_h)? scr_h - 200 : y;
2405
2406 gtk_widget_set_uposition (player_skin_popup, x, y);
2407 gtk_widget_show(player_skin_popup);
2408
2409 draw_qw_skin (player_skin_popup_preview, skin, top, bottom);
2410 }
2411
2412
player_clist_event_callback(GtkWidget * widget,GdkEvent * event)2413 static int player_clist_event_callback (GtkWidget *widget, GdkEvent *event) {
2414 GdkEventButton *bevent = (GdkEventButton *) event;
2415 guchar *skindata;
2416 int row, column;
2417 struct player *p;
2418
2419 switch (event->type) {
2420
2421 case GDK_BUTTON_PRESS:
2422 if (bevent->window == player_clist->clist_window) {
2423 if (gtk_clist_get_selection_info (player_clist, bevent->x, bevent->y, &row, &column)) {
2424 if (row >= 0 && row < g_slist_length (cur_server->players)) {
2425
2426 if ((column == 2 || column == 3) && cur_server &&
2427 (games[cur_server->type].flags & GAME_QUAKE1_SKIN) != 0) {
2428
2429 p = (struct player *) gtk_clist_get_row_data (player_clist, row);
2430
2431 skindata = get_qw_skin (p->skin, games[QW_SERVER].real_dir);
2432
2433 gdk_pointer_grab (player_clist->clist_window, FALSE,
2434 GDK_POINTER_MOTION_HINT_MASK |
2435 GDK_BUTTON1_MOTION_MASK |
2436 GDK_BUTTON_RELEASE_MASK,
2437 NULL, NULL, bevent->time);
2438
2439 player_skin_preview_popup_show (skindata, p->shirt, p->pants, bevent->x, bevent->y);
2440 if (skindata) {
2441 g_free (skindata);
2442 }
2443
2444 return TRUE;
2445
2446 }
2447 else {
2448 if (bevent->button == 3) {
2449 gtk_clist_select_row (player_clist, row, column);
2450 gtk_menu_popup (GTK_MENU (player_menu), NULL, NULL, NULL, NULL, bevent->button, bevent->time);
2451 return TRUE;
2452 }
2453 }
2454
2455 }
2456 }
2457 }
2458 break;
2459
2460 case GDK_2BUTTON_PRESS:
2461 case GDK_3BUTTON_PRESS:
2462 return TRUE;
2463
2464 case GDK_BUTTON_RELEASE:
2465 if (player_skin_popup) {
2466 gdk_pointer_ungrab (bevent->time);
2467 gtk_widget_hide (player_skin_popup);
2468 }
2469 break;
2470
2471 default:
2472 break;
2473 }
2474
2475 return FALSE;
2476 }
2477
2478
statistics_callback(GtkWidget * widget,gpointer data)2479 static void statistics_callback (GtkWidget *widget, gpointer data) {
2480
2481 if (stat_process) {
2482 return;
2483 }
2484
2485 statistics_dialog ();
2486 }
2487
2488
2489
2490 struct __menuitem {
2491 char *label;
2492 char accel_key;
2493 int accel_mods;
2494 GtkWidget **widget;
2495 GtkSignalFunc callback;
2496 gpointer user_data;
2497 };
2498
2499
2500
2501
2502 static const struct menuitem srvopt_menu_items[] = {
2503 {
2504 MENU_ITEM,
2505 N_("Connect"),
2506 0,
2507 0,
2508 GTK_SIGNAL_FUNC (launch_callback),
2509 (gpointer) LAUNCH_NORMAL,
2510 &connect_menu_item
2511 },
2512 {
2513 MENU_ITEM,
2514 N_("Observe"),
2515 0,
2516 0,
2517 GTK_SIGNAL_FUNC (launch_callback),
2518 (gpointer) LAUNCH_SPECTATE,
2519 &observe_menu_item
2520 },
2521 {
2522 MENU_ITEM,
2523 N_("Record Demo"),
2524 0,
2525 0,
2526 GTK_SIGNAL_FUNC (launch_callback),
2527 (gpointer) LAUNCH_RECORD,
2528 &record_menu_item
2529 },
2530 /*
2531 {
2532 MENU_ITEM,
2533 N_("Cancel Redial"),
2534 0,
2535 0,
2536 GTK_SIGNAL_FUNC (cancelredial_callback),
2537 NULL,
2538 &cancel_redial_menu_item
2539 },
2540 */
2541 {
2542 MENU_SEPARATOR,
2543 NULL,
2544 0,
2545 0,
2546 NULL,
2547 NULL,
2548 NULL
2549 },
2550 {
2551 MENU_ITEM,
2552 N_("Add new Server"),
2553 0,
2554 0,
2555 GTK_SIGNAL_FUNC (add_server_callback),
2556 NULL,
2557 &add_menu_item
2558 },
2559 {
2560 MENU_ITEM,
2561 N_("Add to Favorites"),
2562 0,
2563 0,
2564 GTK_SIGNAL_FUNC (add_to_favorites_callback),
2565 NULL,
2566 &favadd_menu_item
2567 },
2568 {
2569 MENU_ITEM,
2570 N_("Remove"),
2571 0,
2572 0,
2573 GTK_SIGNAL_FUNC (del_server_callback),
2574 NULL,
2575 &delete_menu_item
2576 },
2577 {
2578 MENU_ITEM,
2579 N_("Copy"),
2580 0,
2581 0,
2582 GTK_SIGNAL_FUNC (copy_server_callback),
2583 NULL,
2584 NULL
2585 },
2586 {
2587 MENU_ITEM,
2588 N_("Copy+"),
2589 0,
2590 0,
2591 GTK_SIGNAL_FUNC (copy_server_callback_plus),
2592 NULL,
2593 NULL
2594 },
2595 { MENU_SEPARATOR,
2596 NULL,
2597 0,
2598 0,
2599 NULL,
2600 NULL,
2601 NULL
2602 },
2603 {
2604 MENU_ITEM,
2605 N_("Refresh"),
2606 0,
2607 0,
2608 GTK_SIGNAL_FUNC (refresh_callback),
2609 NULL,
2610 &refresh_menu_item
2611 },
2612 {
2613 MENU_ITEM,
2614 N_("Refresh Selected"),
2615 0,
2616 0,
2617 GTK_SIGNAL_FUNC (refresh_selected_callback),
2618 NULL,
2619 &refrsel_menu_item
2620 },
2621 {
2622 MENU_SEPARATOR,
2623 NULL,
2624 0,
2625 0,
2626 NULL,
2627 NULL,
2628 NULL
2629 },
2630 {
2631 MENU_ITEM,
2632 N_("DNS Lookup"),
2633 0,
2634 0,
2635 GTK_SIGNAL_FUNC (resolve_callback),
2636 NULL,
2637 &resolve_menu_item
2638 },
2639 {
2640 MENU_SEPARATOR,
2641 NULL,
2642 0,
2643 0,
2644 NULL,
2645 NULL,
2646 NULL
2647 },
2648 {
2649 MENU_ITEM,
2650 N_("RCon"),
2651 0,
2652 0,
2653 GTK_SIGNAL_FUNC (rcon_callback),
2654 NULL,
2655 &rcon_menu_item
2656 },
2657 {
2658 MENU_ITEM,
2659 N_("Properties"),
2660 0,
2661 0,
2662 GTK_SIGNAL_FUNC (properties_callback),
2663 NULL,
2664 &properties_menu_item
2665 },
2666 {
2667 MENU_END,
2668 NULL,
2669 0,
2670 0,
2671 NULL,
2672 NULL,
2673 NULL
2674 }
2675 };
2676
2677 static const struct menuitem srvinfo_menu_items[] = {
2678 {
2679 MENU_ITEM,
2680 N_("Copy"),
2681 0,
2682 0,
2683 GTK_SIGNAL_FUNC (copy_server_info_callback), NULL,
2684 NULL
2685 },
2686 {
2687 MENU_END,
2688 NULL,
2689 0,
2690 0,
2691 NULL,
2692 NULL,
2693 NULL
2694 }
2695 };
2696 static const struct menuitem file_menu_items[] = {
2697 {
2698 MENU_ITEM,
2699 N_("_Statistics"),
2700 0,
2701 0,
2702 GTK_SIGNAL_FUNC (statistics_callback),
2703 NULL,
2704 &file_statistics_menu_item
2705 },
2706 {
2707 MENU_SEPARATOR,
2708 NULL,
2709 0,
2710 0,
2711 NULL,
2712 NULL,
2713 NULL
2714 },
2715 {
2716 MENU_ITEM,
2717 N_("_Exit"),
2718 'Q',
2719 GDK_CONTROL_MASK,
2720 NULL,
2721 NULL,
2722 &file_quit_menu_item
2723 },
2724 {
2725 MENU_END,
2726 NULL,
2727 0,
2728 0,
2729 NULL,
2730 NULL,
2731 NULL
2732 }
2733 };
2734
2735 // appears on right click on a master server
2736 static const struct menuitem source_ctree_popup_menu[] = {
2737 {
2738 MENU_ITEM,
2739 N_("Add _Master"),
2740 'M',
2741 GDK_CONTROL_MASK,
2742 GTK_SIGNAL_FUNC (add_master_callback),
2743 NULL,
2744 &source_add_master_menu_item
2745 },
2746 {
2747 MENU_ITEM,
2748 N_("_Rename Master"),
2749 0,
2750 0,
2751 GTK_SIGNAL_FUNC (edit_master_callback),
2752 NULL,
2753 &source_edit_master_menu_item
2754 },
2755 {
2756 MENU_ITEM,
2757 N_("D_elete Master"),
2758 0, 0,
2759 GTK_SIGNAL_FUNC (del_master_callback),
2760 NULL,
2761 &source_delete_master_menu_item
2762 },
2763 {
2764 MENU_ITEM,
2765 N_("_Clear Servers"),
2766 0, 0,
2767 GTK_SIGNAL_FUNC (clear_master_servers_callback),
2768 NULL,
2769 &source_clear_master_servers_menu_item
2770 },
2771 {MENU_END,
2772 NULL,
2773 0,
2774 0,
2775 NULL,
2776 NULL,
2777 NULL
2778 }
2779 };
2780
2781 static const struct menuitem edit_menu_items[] = {
2782 {
2783 MENU_ITEM,
2784 N_("_Add new Server"),
2785 'N',
2786 GDK_CONTROL_MASK,
2787 GTK_SIGNAL_FUNC (add_server_callback),
2788 NULL,
2789 &edit_add_menu_item
2790 },
2791 {
2792 MENU_ITEM,
2793 N_("Add to _Favorites"),
2794 0,
2795 0,
2796 GTK_SIGNAL_FUNC (add_to_favorites_callback),
2797 NULL,
2798 &edit_favadd_menu_item
2799 },
2800 {
2801 MENU_ITEM,
2802 N_("_Remove"),
2803 'D',
2804 GDK_CONTROL_MASK,
2805 GTK_SIGNAL_FUNC (del_server_callback),
2806 NULL,
2807 &edit_delete_menu_item
2808 },
2809 {
2810 MENU_ITEM,
2811 N_("_Copy"),
2812 'C',
2813 GDK_CONTROL_MASK,
2814 GTK_SIGNAL_FUNC (copy_server_callback),
2815 NULL,
2816 NULL
2817 },
2818 {
2819 MENU_ITEM,
2820 N_("_Copy+"),
2821 'O',
2822 GDK_CONTROL_MASK,
2823 GTK_SIGNAL_FUNC (copy_server_callback_plus),
2824 NULL,
2825 NULL
2826 },
2827 {
2828 MENU_SEPARATOR,
2829 NULL,
2830 0,
2831 0,
2832 NULL,
2833 NULL,
2834 NULL
2835 },
2836 {
2837 MENU_ITEM,
2838 N_("Add Default Masters"),
2839 0,
2840 GDK_CONTROL_MASK,
2841 GTK_SIGNAL_FUNC (update_master_builtin_callback),
2842 NULL,
2843 &edit_update_master_builtin_menu_item
2844 },
2845 {
2846 MENU_ITEM,
2847 N_("Add Gslist Masters"),
2848 0,
2849 GDK_CONTROL_MASK,
2850 GTK_SIGNAL_FUNC (update_master_gslist_callback),
2851 NULL,
2852 &edit_update_master_gslist_menu_item
2853 },
2854 {
2855 MENU_ITEM,
2856 N_("Add _Master"),
2857 'M',
2858 GDK_CONTROL_MASK,
2859 GTK_SIGNAL_FUNC (add_master_callback),
2860 NULL,
2861 &edit_add_master_menu_item
2862 },
2863 {
2864 MENU_ITEM,
2865 N_("_Rename Master"),
2866 0,
2867 0,
2868 GTK_SIGNAL_FUNC (edit_master_callback),
2869 NULL,
2870 &edit_edit_master_menu_item
2871 },
2872 {
2873 MENU_ITEM,
2874 N_("D_elete Master"),
2875 0,
2876 0,
2877 GTK_SIGNAL_FUNC (del_master_callback),
2878 NULL,
2879 &edit_delete_master_menu_item
2880 },
2881 {
2882 MENU_ITEM,
2883 N_("_Clear Servers"),
2884 0,
2885 0,
2886 GTK_SIGNAL_FUNC (clear_master_servers_callback),
2887 NULL,
2888 &edit_clear_master_servers_menu_item
2889 },
2890 {
2891 MENU_SEPARATOR,
2892 NULL,
2893 0,
2894 0,
2895 NULL,
2896 NULL,
2897 NULL
2898 },
2899 {
2900 MENU_ITEM,
2901 N_("_Find Player"),
2902 'F',
2903 GDK_CONTROL_MASK,
2904 GTK_SIGNAL_FUNC (find_player_callback),
2905 (gpointer) FALSE,
2906 &edit_find_player_menu_item
2907 },
2908 {
2909 MENU_ITEM,
2910 N_("Find A_gain"),
2911 'G',
2912 GDK_CONTROL_MASK,
2913 GTK_SIGNAL_FUNC (find_player_callback),
2914 (gpointer) TRUE,
2915 &edit_find_again_menu_item
2916 },
2917 {
2918 MENU_SEPARATOR,
2919 NULL,
2920 0,
2921 0,
2922 NULL,
2923 NULL,
2924 NULL
2925 },
2926 {
2927 MENU_ITEM,
2928 N_("Properties"),
2929 0,
2930 0,
2931 GTK_SIGNAL_FUNC (properties_callback),
2932 NULL,
2933 &properties_menu_item
2934 },
2935 {
2936 MENU_END,
2937 NULL,
2938 0,
2939 0,
2940 NULL,
2941 NULL,
2942 NULL
2943 }
2944 };
2945
2946 static const struct menuitem view_menu_items[] = {
2947 {
2948 MENU_ITEM,
2949 N_("_Refresh"),
2950 'R', GDK_CONTROL_MASK,
2951 GTK_SIGNAL_FUNC (refresh_callback), NULL,
2952 &view_refresh_menu_item
2953 },
2954 {
2955 MENU_ITEM,
2956 N_("Refresh _Selected"),
2957 'S', GDK_CONTROL_MASK,
2958 GTK_SIGNAL_FUNC (refresh_selected_callback),
2959 NULL,
2960 &view_refrsel_menu_item
2961 },
2962 {
2963 MENU_ITEM,
2964 N_("_Update From Master"),
2965 'U',
2966 GDK_CONTROL_MASK,
2967 GTK_SIGNAL_FUNC (update_source_callback),
2968 NULL,
2969 &view_update_menu_item
2970 },
2971 {
2972 MENU_SEPARATOR,
2973 NULL,
2974 0,
2975 0,
2976 NULL,
2977 NULL,
2978 NULL
2979 },
2980 {
2981 MENU_CHECK_ITEM,
2982 N_("Show _Host Names"),
2983 'H',
2984 GDK_CONTROL_MASK,
2985 GTK_SIGNAL_FUNC (show_hostnames_callback),
2986 NULL,
2987 &view_hostnames_menu_item
2988 },
2989 {
2990 MENU_CHECK_ITEM,
2991 N_("Show Default _Port"),
2992 0,
2993 0,
2994 GTK_SIGNAL_FUNC (show_default_port_callback),
2995 NULL,
2996 &view_defport_menu_item
2997 },
2998 {
2999 MENU_END,
3000 NULL,
3001 0,
3002 0,
3003 NULL,
3004 NULL,
3005 NULL
3006 }
3007 };
3008
3009
3010 /*
3011 baa -- Oh, this is kind of bad. In order to allow
3012 the number of menus to be changed at compile (and in
3013 the future, run) time, I have to allocate and set
3014 up each of the filter menu items. But that makes
3015 it no longer a const.
3016 */
3017
3018 static const struct menuitem server_menu_items[] = {
3019 /*
3020 {
3021 MENU_ITEM,
3022 N_("_Server Filters"),
3023 0,
3024 0,
3025 NULL,
3026 0,
3027 &server_serverfilter_menu_item
3028 },
3029 */
3030 {
3031 MENU_ITEM,
3032 N_("_Connect"),
3033 0,
3034 0,
3035 GTK_SIGNAL_FUNC (launch_callback),
3036 (gpointer) LAUNCH_NORMAL,
3037 &server_connect_menu_item
3038 },
3039 {
3040 MENU_ITEM,
3041 N_("_Observe"),
3042 0,
3043 0,
3044 GTK_SIGNAL_FUNC (launch_callback),
3045 (gpointer) LAUNCH_SPECTATE,
3046 &server_observe_menu_item
3047 },
3048 {
3049 MENU_ITEM,
3050 N_("Record _Demo"),
3051 0,
3052 0,
3053 GTK_SIGNAL_FUNC (launch_callback),
3054 (gpointer) LAUNCH_RECORD,
3055 &server_record_menu_item
3056 },
3057 /*
3058 {
3059 MENU_ITEM,
3060 N_("Cancel Redial"),
3061 0,
3062 0,
3063 GTK_SIGNAL_FUNC (cancelredial_callback),
3064 NULL,
3065 &server_cancel_redial_menu_item
3066 },
3067 */
3068 {
3069 MENU_SEPARATOR,
3070 NULL,
3071 0,
3072 0,
3073 NULL,
3074 NULL,
3075 NULL
3076 },
3077 {
3078 MENU_ITEM,
3079 N_("_Add new Server"),
3080 0,
3081 0,
3082 GTK_SIGNAL_FUNC (add_server_callback),
3083 NULL,
3084 &edit_add_menu_item
3085 },
3086 {
3087 MENU_ITEM,
3088 N_("Add to _Favorites"),
3089 0,
3090 0,
3091 GTK_SIGNAL_FUNC (add_to_favorites_callback),
3092 NULL,
3093 &server_favadd_menu_item
3094 },
3095 {
3096 MENU_ITEM,
3097 N_("_Remove"),
3098 0,
3099 0,
3100 GTK_SIGNAL_FUNC (del_server_callback),
3101 NULL,
3102 &server_delete_menu_item
3103 },
3104 {
3105 MENU_ITEM,
3106 N_("DNS _Lookup"),
3107 'L',
3108 GDK_CONTROL_MASK,
3109 GTK_SIGNAL_FUNC (resolve_callback),
3110 NULL,
3111 &server_resolve_menu_item
3112 },
3113 {
3114 MENU_SEPARATOR,
3115 NULL,
3116 0,
3117 0,
3118 NULL,
3119 NULL,
3120 NULL
3121 },
3122 {
3123 MENU_ITEM,
3124 N_("_RCon"),
3125 0,
3126 0,
3127 GTK_SIGNAL_FUNC (rcon_callback),
3128 NULL,
3129 &server_rcon_menu_item
3130 },
3131 {
3132 MENU_ITEM,
3133 N_("_Properties"),
3134 0,
3135 0,
3136 GTK_SIGNAL_FUNC (properties_callback),
3137 NULL,
3138 &server_properties_menu_item
3139 },
3140 {
3141 MENU_END,
3142 NULL,
3143 0,
3144 0,
3145 NULL,
3146 NULL,
3147 NULL
3148 }
3149 };
3150
3151 static const struct menuitem preferences_menu_items[] = {
3152 {
3153 MENU_ITEM,
3154 N_("_General"),
3155 0,
3156 0,
3157 GTK_SIGNAL_FUNC (start_preferences_dialog),
3158 (gpointer) (PREF_PAGE_GENERAL + UNKNOWN_SERVER * 256),
3159 NULL
3160 },
3161 {
3162 MENU_ITEM,
3163 N_("_Games"),
3164 0,
3165 0,
3166 GTK_SIGNAL_FUNC (start_preferences_dialog),
3167 (gpointer) (PREF_PAGE_GAMES + UNKNOWN_SERVER * 256),
3168 NULL
3169 },
3170 {
3171 MENU_ITEM,
3172 N_("_Appearance"),
3173 0,
3174 0,
3175 GTK_SIGNAL_FUNC (start_preferences_dialog),
3176 (gpointer) (PREF_PAGE_APPEARANCE + UNKNOWN_SERVER * 256),
3177 NULL
3178 },
3179 {
3180 MENU_ITEM,
3181 N_("_QStat"),
3182 0,
3183 0,
3184 GTK_SIGNAL_FUNC (start_preferences_dialog),
3185 (gpointer) (PREF_PAGE_QSTAT + UNKNOWN_SERVER * 256),
3186 NULL
3187 },
3188 {
3189 MENU_ITEM,
3190 N_("_Sounds"),
3191 0,
3192 0,
3193 GTK_SIGNAL_FUNC (start_preferences_dialog),
3194 (gpointer) (PREF_PAGE_SOUNDS + UNKNOWN_SERVER * 256),
3195 NULL
3196 },
3197 {
3198 MENU_ITEM,
3199 N_("S_cripts"),
3200 0,
3201 0,
3202 GTK_SIGNAL_FUNC (start_preferences_dialog),
3203 (gpointer) (PREF_PAGE_SCRIPTS + UNKNOWN_SERVER * 256),
3204 NULL
3205 },
3206 {
3207 MENU_SEPARATOR,
3208 NULL,
3209 0,
3210 0,
3211 NULL,
3212 NULL,
3213 NULL
3214 },
3215 {
3216 MENU_ITEM,
3217 N_("_Server Filter"),
3218 0,
3219 0,
3220 GTK_SIGNAL_FUNC (start_filters_cfg_dialog),
3221 (gpointer) FILTER_SERVER,
3222 NULL
3223 },
3224 {
3225 MENU_ITEM,
3226 N_("Player _Filter"),
3227 0,
3228 0,
3229 GTK_SIGNAL_FUNC (start_filters_cfg_dialog),
3230 (gpointer) FILTER_PLAYER,
3231 NULL
3232 },
3233 {
3234 MENU_END,
3235 NULL,
3236 0,
3237 0,
3238 NULL,
3239 NULL,
3240 NULL
3241 }
3242 };
3243
3244 static const struct menuitem help_menu_items[] = {
3245 {
3246 MENU_ITEM,
3247 N_("_About"),
3248 0,
3249 0,
3250 GTK_SIGNAL_FUNC (about_dialog),
3251 NULL,
3252 NULL
3253 },
3254 {
3255 MENU_END,
3256 NULL,
3257 0,
3258 0,
3259 NULL,
3260 NULL,
3261 NULL
3262 }
3263 };
3264
3265
3266 static const struct menuitem menubar_menu_items[] = {
3267 {
3268 MENU_BRANCH,
3269 N_("_File"),
3270 0,
3271 0,
3272 NULL,
3273 &file_menu_items,
3274 NULL
3275 },
3276 {
3277 MENU_BRANCH,
3278 N_("_Edit"),
3279 0,
3280 0,
3281 NULL,
3282 &edit_menu_items,
3283 NULL
3284 },
3285 {
3286 MENU_BRANCH,
3287 N_("_View"),
3288 0,
3289 0,
3290 NULL,
3291 &view_menu_items,
3292 NULL
3293 },
3294 {
3295 MENU_BRANCH,
3296 N_("_Server"),
3297 0,
3298 0,
3299 NULL,
3300 &server_menu_items,
3301 NULL
3302 },
3303 {
3304 MENU_BRANCH,
3305 N_("_Preferences"),
3306 0,
3307 0,
3308 NULL,
3309 &preferences_menu_items,
3310 NULL
3311 },
3312 {
3313 MENU_ITEM,
3314 N_("_Server Filters"),
3315 0,
3316 0,
3317 NULL,
3318 0,
3319 &server_serverfilter_menu_item
3320 },
3321 {
3322 MENU_BRANCH,
3323 N_("_Help"),
3324 0,
3325 0,
3326 NULL,
3327 &help_menu_items,
3328 NULL
3329 },
3330 {
3331 MENU_END,
3332 NULL,
3333 0,
3334 0,
3335 NULL,
3336 NULL,
3337 NULL
3338 }
3339 };
3340
3341
create_player_menu_item(char * str,int i)3342 static GtkWidget *create_player_menu_item (char *str, int i) {
3343 GtkWidget *menu_item;
3344 GtkWidget *hbox;
3345 GtkWidget *label;
3346 GtkWidget *pixmap;
3347
3348 menu_item = gtk_menu_item_new ();
3349
3350 hbox = gtk_hbox_new (FALSE, 4);
3351 gtk_container_add (GTK_CONTAINER (menu_item), hbox);
3352
3353 label = gtk_label_new (str);
3354 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
3355 gtk_widget_show (label);
3356
3357 pixmap = gtk_pixmap_new (group_pix[i].pix, group_pix[i].mask);
3358 gtk_box_pack_end (GTK_BOX (hbox), pixmap, FALSE, FALSE, 0);
3359 gtk_widget_show (pixmap);
3360
3361 gtk_widget_show (hbox);
3362
3363 return menu_item;
3364 }
3365
3366
create_player_menu(GtkAccelGroup * accel_group)3367 static GtkWidget *create_player_menu (GtkAccelGroup *accel_group) {
3368 GtkWidget *menu;
3369 GtkWidget *marker_menu;
3370 GtkWidget *menu_item;
3371
3372 menu = gtk_menu_new ();
3373
3374 marker_menu = gtk_menu_new ();
3375
3376 menu_item = create_player_menu_item (_("Mark as Red"), 0);
3377 gtk_menu_append (GTK_MENU (marker_menu), menu_item);
3378 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
3379 GTK_SIGNAL_FUNC (add_to_player_filter_callback),
3380 (gpointer) PLAYER_GROUP_RED);
3381 gtk_widget_show (menu_item);
3382
3383 menu_item = create_player_menu_item (_("Mark as Green"), 1);
3384 gtk_menu_append (GTK_MENU (marker_menu), menu_item);
3385 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
3386 GTK_SIGNAL_FUNC (add_to_player_filter_callback),
3387 (gpointer) PLAYER_GROUP_GREEN);
3388 gtk_widget_show (menu_item);
3389
3390 menu_item = create_player_menu_item (_("Mark as Blue"), 2);
3391 gtk_menu_append (GTK_MENU (marker_menu), menu_item);
3392 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
3393 GTK_SIGNAL_FUNC (add_to_player_filter_callback),
3394 (gpointer) PLAYER_GROUP_BLUE);
3395 gtk_widget_show (menu_item);
3396
3397 menu_item = gtk_menu_item_new_with_label (_("Add to Player Filter"));
3398 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), marker_menu);
3399 gtk_menu_append (GTK_MENU (menu), menu_item);
3400 gtk_widget_show (menu_item);
3401
3402 player_filter_menu_item = menu_item;
3403
3404 return menu;
3405 }
3406
3407
populate_main_toolbar(void)3408 static void populate_main_toolbar (void) {
3409 GtkWidget *pixmap;
3410 char buf[128];
3411 unsigned mask;
3412 int i;
3413
3414 pixmap = gtk_pixmap_new (update_pix.pix, update_pix.mask);
3415 gtk_widget_show (pixmap);
3416
3417 update_button = gtk_toolbar_append_item (GTK_TOOLBAR (main_toolbar),
3418 _("Update"), _("Update from master"), NULL,
3419 pixmap,
3420 GTK_SIGNAL_FUNC (update_source_callback), NULL);
3421
3422 pixmap = gtk_pixmap_new (refresh_pix.pix, refresh_pix.mask);
3423 gtk_widget_show (pixmap);
3424
3425 refresh_button = gtk_toolbar_append_item (GTK_TOOLBAR (main_toolbar),
3426 _("Refresh"), _("Refresh current list"), NULL,
3427 pixmap,
3428 GTK_SIGNAL_FUNC (refresh_callback), NULL);
3429
3430 pixmap = gtk_pixmap_new (refrsel_pix.pix, refrsel_pix.mask);
3431 gtk_widget_show (pixmap);
3432
3433 refrsel_button = gtk_toolbar_append_item (GTK_TOOLBAR (main_toolbar),
3434 _("Ref.Sel."), _("Refresh selected servers"), NULL,
3435 pixmap,
3436 GTK_SIGNAL_FUNC (refresh_selected_callback), NULL);
3437
3438 pixmap = gtk_pixmap_new (stop_pix.pix, stop_pix.mask);
3439 gtk_widget_show (pixmap);
3440
3441 stop_button = gtk_toolbar_append_item (GTK_TOOLBAR (main_toolbar),
3442 _("Stop"), _("Stop"), NULL,
3443 pixmap,
3444 GTK_SIGNAL_FUNC (stop_callback), NULL);
3445
3446 gtk_toolbar_append_space (GTK_TOOLBAR (main_toolbar));
3447
3448 pixmap = gtk_pixmap_new (connect_pix.pix, connect_pix.mask);
3449 gtk_widget_show (pixmap);
3450
3451 connect_button = gtk_toolbar_append_item (GTK_TOOLBAR (main_toolbar),
3452 _("Connect"), _("Connect"), NULL,
3453 pixmap,
3454 GTK_SIGNAL_FUNC (launch_callback), (gpointer) LAUNCH_NORMAL);
3455
3456 #if 0
3457 pixmap = gtk_pixmap_new (observe_pix.pix, observe_pix.mask);
3458 gtk_widget_show (pixmap);
3459
3460 observe_button = gtk_toolbar_append_item (GTK_TOOLBAR (main_toolbar),
3461 _("Observe"), _("Observe"), NULL,
3462 pixmap,
3463 GTK_SIGNAL_FUNC (launch_callback), (gpointer) LAUNCH_SPECTATE);
3464
3465 pixmap = gtk_pixmap_new (record_pix.pix, record_pix.mask);
3466 gtk_widget_show (pixmap);
3467
3468 record_button = gtk_toolbar_append_item (GTK_TOOLBAR (main_toolbar),
3469 _("Record"), _("Record Demo"), NULL,
3470 pixmap,
3471 GTK_SIGNAL_FUNC (launch_callback), (gpointer) LAUNCH_RECORD);
3472 #endif
3473
3474 gtk_toolbar_append_space (GTK_TOOLBAR (main_toolbar));
3475 /*
3476 * Filter buttons
3477 */
3478
3479 for (i = 0, mask = 1; i < FILTERS_TOTAL; i++, mask <<= 1) {
3480 if (!filters[i].pix) {
3481 filter_buttons[i] = NULL;
3482 continue;
3483 }
3484 // Translators: e.g. Server Filter
3485 g_snprintf (buf, 128, _("%s Filter Enable / Disable"), _(filters[i].name));
3486
3487 pixmap = gtk_pixmap_new (filters[i].pix->pix, filters[i].pix->mask);
3488 gtk_widget_show (pixmap);
3489
3490 filter_buttons[i] = gtk_toolbar_append_element (
3491 GTK_TOOLBAR (main_toolbar),
3492 GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL,
3493 _(filters[i].short_name), buf, NULL,
3494 pixmap,
3495 GTK_SIGNAL_FUNC (filter_toggle_callback), GINT_TO_POINTER(mask));
3496
3497 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (filter_buttons[i]), ((cur_filter & mask) != 0)? TRUE : FALSE);
3498 }
3499
3500 #if 0
3501 gtk_toolbar_append_space (GTK_TOOLBAR (main_toolbar));
3502
3503 for (i = 0, mask = 1; i < FILTERS_TOTAL; i++, mask <<= 1) {
3504 // Translators: e.g. Server Filter Configuration
3505 g_snprintf (buf, 128, _("%s Filter Configuration"), _(filters[i].name));
3506
3507 pixmap = gtk_pixmap_new (filter_cfg_pix[i].pix, filter_cfg_pix[i].mask);
3508 gtk_widget_show (pixmap);
3509
3510 gtk_toolbar_append_item (GTK_TOOLBAR (main_toolbar),
3511 _(filters[i].short_cfg_name), buf, NULL,
3512 pixmap,
3513 GTK_SIGNAL_FUNC (start_filters_cfg_dialog), (gpointer) i);
3514 }
3515
3516 gtk_toolbar_append_space (GTK_TOOLBAR (main_toolbar));
3517
3518 /* filter option menu for toolbar */
3519
3520 filter_toolbar_label = gtk_label_new ("Filter: ");
3521 gtk_toolbar_append_widget(GTK_TOOLBAR (main_toolbar),
3522 filter_toolbar_label,
3523 "Select a server filter",
3524 "Private");
3525 gtk_widget_show(filter_toolbar_label);
3526
3527 filter_option_menu_toolbar = gtk_option_menu_new ();
3528 gtk_option_menu_set_menu (GTK_OPTION_MENU (filter_option_menu_toolbar), create_filter_menu_toolbar());
3529
3530 gtk_toolbar_append_widget(GTK_TOOLBAR (main_toolbar),
3531 filter_option_menu_toolbar,
3532 "Select a server filter",
3533 "Private");
3534
3535 gtk_widget_show (filter_option_menu_toolbar);
3536 #endif
3537
3538 set_toolbar_appearance (GTK_TOOLBAR (main_toolbar), default_toolbar_style, default_toolbar_tips);
3539 }
3540
3541 /** build server filter menu for menubar */
3542 #if 0
3543 static GtkWidget* create_filter_menu_toolbar() {
3544 unsigned int i;
3545 GtkWidget *menu;
3546 GtkWidget *menu_item;
3547
3548 struct server_filter_vars* filter = NULL;
3549
3550 menu = gtk_menu_new();
3551
3552
3553 for (i = 0;i<=server_filters->len;i++) {
3554 char* name = NULL;
3555 if (i == 0) {
3556 filter = NULL;
3557 name = _("None");
3558 }
3559 else {
3560 filter = g_array_index (server_filters, struct server_filter_vars*, i-1);
3561 name = filter->filter_name;
3562 }
3563
3564 menu_item = gtk_menu_item_new_with_label(name);
3565 gtk_menu_append (GTK_MENU (menu), menu_item);
3566 gtk_widget_show (menu_item);
3567
3568 gtk_signal_connect (GTK_OBJECT (menu_item), "activate", GTK_SIGNAL_FUNC (server_filter_select_callback_toolbar), (gpointer)i); // array starts from zero but filters from 1
3569
3570 }
3571
3572 gtk_widget_show (menu);
3573 return menu;
3574 }
3575 #endif
3576
3577 /** build server filter menu for toolbar */
create_filter_menu()3578 static GtkWidget* create_filter_menu() {
3579 unsigned int i;
3580 GtkWidget *menu;
3581 GtkWidget *menu_item;
3582 struct server_filter_vars* filter = NULL;
3583 GSList* rbgroup = NULL;
3584
3585 filter_menu_radio_buttons = NULL;
3586
3587 menu = gtk_menu_new();
3588
3589 menu_item = gtk_menu_item_new_with_label (_("Configure"));
3590 gtk_menu_append (GTK_MENU (menu), menu_item);
3591 gtk_widget_show (menu_item);
3592
3593 gtk_signal_connect (GTK_OBJECT (menu_item), "activate", GTK_SIGNAL_FUNC (start_filters_cfg_dialog), (gpointer) FILTER_SERVER);
3594
3595 menu_item = gtk_menu_item_new ();
3596 gtk_widget_set_sensitive (menu_item, FALSE);
3597 gtk_menu_append (GTK_MENU (menu), menu_item);
3598 gtk_widget_show (menu_item);
3599
3600 for (i = 0;i<=server_filters->len;i++) {
3601 char* name = NULL;
3602 if (i == 0) {
3603 filter = NULL;
3604 name = _("None");
3605 }
3606 else {
3607 filter = g_array_index (server_filters, struct server_filter_vars*, i-1);
3608 name = filter->filter_name;
3609 }
3610
3611 menu_item = gtk_radio_menu_item_new_with_label(rbgroup,name);
3612 rbgroup = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menu_item));
3613 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_item), FALSE);
3614 filter_menu_radio_buttons = g_slist_append(filter_menu_radio_buttons,menu_item);
3615
3616 gtk_menu_append (GTK_MENU (menu), menu_item);
3617 gtk_widget_show (menu_item);
3618
3619 // array starts from zero but filters from 1
3620 gtk_signal_connect (GTK_OBJECT (menu_item), "activate", GTK_SIGNAL_FUNC (server_filter_select_callback), GINT_TO_POINTER(i));
3621
3622 /*
3623 // add separator
3624 if (i == 0) {
3625 menu_item = gtk_menu_item_new ();
3626 gtk_widget_set_sensitive (menu_item, FALSE);
3627 gtk_menu_append (GTK_MENU (menu), menu_item);
3628 gtk_widget_show (menu_item);
3629 }
3630 */
3631 }
3632
3633 // filter_menu = menu;
3634 return menu;
3635 }
3636
quick_filter_entry_changed(GtkWidget * entry,gpointer data)3637 static void quick_filter_entry_changed(GtkWidget* entry, gpointer data) {
3638 const char* text = gtk_entry_get_text(GTK_ENTRY(entry));
3639 int mask = 0;
3640
3641 debug(3,"%d <%s>", strlen(text), text);
3642
3643 if (!text || !*text) {
3644 if (filter_quick_get()) {
3645 mask = FILTER_QUICK_MASK;
3646 }
3647 filter_quick_set(NULL);
3648 }
3649 else {
3650 if (!filter_quick_get()) {
3651 mask = FILTER_QUICK_MASK;
3652 }
3653 filter_quick_set(text);
3654 }
3655
3656 filters[FILTER_QUICK].last_changed = filter_time_inc();
3657
3658 filter_toggle_callback(NULL, mask);
3659 }
3660
quickfilter_delete_button_clicked(GtkWidget * widget,GtkWidget * entry)3661 void quickfilter_delete_button_clicked (GtkWidget *widget, GtkWidget* entry) {
3662 gtk_editable_delete_text(GTK_EDITABLE(entry), 0, -1);
3663 gtk_widget_grab_focus(entry);
3664 }
3665
create_main_window(void)3666 static void create_main_window (void) {
3667 main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3668 gtk_signal_connect (GTK_OBJECT (main_window), "delete_event",
3669 GTK_SIGNAL_FUNC (window_delete_event_callback), NULL);
3670 gtk_signal_connect (GTK_OBJECT (main_window), "destroy",
3671 GTK_SIGNAL_FUNC (ui_done), NULL);
3672 gtk_signal_connect (GTK_OBJECT (main_window), "destroy",
3673 GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
3674 gtk_window_set_title (GTK_WINDOW (main_window), "XQF");
3675
3676 register_window (main_window);
3677
3678 gtk_widget_realize (main_window);
3679 }
3680
populate_main_window(void)3681 static void populate_main_window (void) {
3682 GtkWidget *main_vbox;
3683 GtkWidget *vbox;
3684 GtkWidget *vbox2;
3685 GtkWidget *hbox;
3686 GtkWidget *hpaned;
3687 GtkWidget *hpaned2;
3688 GtkWidget *vpaned;
3689 GtkWidget *menu_bar;
3690 GtkWidget *handlebox;
3691 GtkWidget *scrollwin;
3692 GtkWidget *entry;
3693 GtkWidget *label;
3694 GtkWidget *button;
3695 GtkWidget *pixmap;
3696 GtkAccelGroup *accel_group;
3697 int i;
3698 // char *buf;
3699
3700 accel_group = gtk_accel_group_new ();
3701
3702 /*
3703 Before we create the right-click server menu, we
3704 need to set up all of the needed filter entries. This
3705 is a terrible thing to do because in menus.c, the function
3706 that builds the menu expects a const. However, we are not going
3707 go g_free or otherwise reuse the memory we g_malloc so we should be
3708 okay.
3709
3710 If you change the number of menu items before the various filters,
3711 you need to change the server_filter_widget line in xqf.h.
3712 */
3713
3714 #if 0
3715 if ((server_filter_menu_items = g_malloc(sizeof(struct menuitem) * (MAX_SERVER_FILTERS + 4)))) {
3716 i = 0;
3717 j = 0;
3718 server_filter_menu_items[i].type = MENU_ITEM;
3719 server_filter_menu_items[i].label = _("Filters");
3720 server_filter_menu_items[i].accel_key = 0;
3721 server_filter_menu_items[i].accel_mods = 0;
3722 server_filter_menu_items[i].callback = NULL;
3723 server_filter_menu_items[i].user_data = NULL;
3724 server_filter_menu_items[i].widget = &server_filter_widget[i];
3725 i++;
3726
3727 server_filter_menu_items[i].type = MENU_SEPARATOR;
3728 server_filter_menu_items[i].label = NULL;
3729 server_filter_menu_items[i].accel_key = 0;
3730 server_filter_menu_items[i].accel_mods = 0;
3731 server_filter_menu_items[i].callback = NULL;
3732 server_filter_menu_items[i].user_data = NULL;
3733 server_filter_menu_items[i].widget = &server_filter_widget[i];
3734 i++;
3735
3736 /* Start of the filters */
3737 filter_start_index = i;
3738 server_filter_menu_items[i].type = MENU_ITEM;
3739 server_filter_menu_items[i].label = _("None");
3740 server_filter_menu_items[i].accel_key = 0;
3741 server_filter_menu_items[i].accel_mods = 0;
3742 server_filter_menu_items[i].callback = GTK_SIGNAL_FUNC (server_filter_select_callback);
3743 server_filter_menu_items[i].user_data = (gpointer) j;
3744 server_filter_menu_items[i].widget = &server_filter_widget[i];
3745
3746 i++;
3747 j++;
3748
3749 for (; i < (MAX_SERVER_FILTERS + filter_start_index); i++, j++){
3750 buf = g_malloc(sizeof(char) * (16));
3751 sprintf(buf, "Filter %d", j);
3752 server_filter_menu_items[i].type = MENU_ITEM;
3753 server_filter_menu_items[i].label = buf;
3754 server_filter_menu_items[i].accel_key = 0;
3755 server_filter_menu_items[i].accel_mods = 0;
3756 server_filter_menu_items[i].callback = GTK_SIGNAL_FUNC (server_filter_select_callback);
3757 server_filter_menu_items[i].user_data = (gpointer) j;
3758 server_filter_menu_items[i].widget = &server_filter_widget[i];
3759 }
3760
3761 server_filter_menu_items[i].type = MENU_END;
3762 server_filter_menu_items[i].label = NULL;
3763 server_filter_menu_items[i].accel_key = 0;
3764 server_filter_menu_items[i].accel_mods = 0;
3765 server_filter_menu_items[i].callback = NULL;
3766 server_filter_menu_items[i].user_data = NULL;
3767 server_filter_menu_items[i].widget = NULL;
3768 }
3769
3770 /* Depeding on where you want the filters to appear... */
3771 #if 0
3772 srvopt_menu_items[0].user_data = &server_filter_menu_items[0];
3773 #else
3774 server_menu_items[0].user_data = &server_filter_menu_items[0];
3775 #endif
3776 #endif
3777
3778 server_menu = create_menu (srvopt_menu_items, accel_group);
3779
3780 server_info_menu = create_menu (srvinfo_menu_items, accel_group);
3781
3782 source_menu = create_menu (source_ctree_popup_menu, accel_group);
3783
3784 /* We will call set_server_filter_menu_list_text (); below after we
3785 have the filter status bar. It used to be here -baa
3786 */
3787
3788 player_menu = create_player_menu (accel_group);
3789
3790 main_vbox = gtk_vbox_new (FALSE, 0);
3791 gtk_container_add (GTK_CONTAINER (main_window), main_vbox);
3792
3793 /* Lazy way to get `copy to clipboard' feature working.
3794 * Don't gtk_widget_show() selection_manager widget!
3795 */
3796
3797 selection_manager = GTK_EDITABLE (gtk_text_new (NULL, NULL));
3798 gtk_box_pack_start (GTK_BOX (main_vbox), GTK_WIDGET (selection_manager), FALSE, FALSE, 0);
3799 gtk_widget_realize (GTK_WIDGET (selection_manager));
3800
3801 handlebox = gtk_handle_box_new ();
3802 gtk_box_pack_start (GTK_BOX (main_vbox), handlebox, FALSE, FALSE, 0);
3803
3804 menu_bar = create_menubar (menubar_menu_items, accel_group);
3805
3806 // add server filters to menu
3807 server_filter_menu_items = g_array_new(FALSE,FALSE,sizeof(GtkWidget*));
3808 gtk_menu_item_set_submenu (GTK_MENU_ITEM (server_serverfilter_menu_item), create_filter_menu());
3809
3810 gtk_signal_connect_object (GTK_OBJECT (file_quit_menu_item), "activate", GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (main_window));
3811
3812 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_hostnames_menu_item), show_hostnames);
3813
3814 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_defport_menu_item), show_default_port);
3815
3816 gtk_container_add (GTK_CONTAINER (handlebox), menu_bar);
3817 gtk_widget_show (menu_bar);
3818
3819 gtk_widget_show (handlebox);
3820
3821 vbox = gtk_vbox_new (FALSE, 4);
3822 gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
3823 gtk_box_pack_start (GTK_BOX (main_vbox), vbox, TRUE, TRUE, 0);
3824
3825 main_toolbar = gtk_toolbar_new ();
3826 gtk_toolbar_set_orientation (GTK_TOOLBAR(main_toolbar),GTK_ORIENTATION_HORIZONTAL);
3827 gtk_toolbar_set_style (GTK_TOOLBAR(main_toolbar),GTK_TOOLBAR_BOTH);
3828 gtk_box_pack_start (GTK_BOX (main_vbox), main_toolbar, FALSE, FALSE, 0);
3829
3830 // FIXME GTK2
3831 gtk_box_reorder_child(GTK_BOX (main_vbox), main_toolbar, 2);
3832 populate_main_toolbar ();
3833 gtk_widget_show (main_toolbar);
3834
3835 pane1_widget = hpaned = gtk_hpaned_new ();
3836 gtk_box_pack_start (GTK_BOX (vbox), hpaned, TRUE, TRUE, 0);
3837
3838 /*
3839 * Sources CTree
3840 */
3841
3842 scrollwin = gtk_scrolled_window_new (NULL, NULL);
3843 gtk_paned_add1 (GTK_PANED (hpaned), scrollwin);
3844
3845 source_ctree = create_source_ctree (scrollwin);
3846
3847 gtk_widget_show (source_ctree);
3848
3849 gtk_signal_connect (GTK_OBJECT (source_ctree), "tree_select_row", GTK_SIGNAL_FUNC (source_ctree_selection_changed_callback), NULL);
3850 gtk_signal_connect (GTK_OBJECT (source_ctree), "tree_unselect_row", GTK_SIGNAL_FUNC (source_ctree_selection_changed_callback), NULL);
3851 gtk_signal_connect (GTK_OBJECT (source_ctree), "event", GTK_SIGNAL_FUNC (source_ctree_event_callback), NULL);
3852
3853 gtk_widget_show (scrollwin);
3854
3855 pane2_widget = vpaned = gtk_vpaned_new ();
3856 gtk_paned_add2 (GTK_PANED (hpaned), vpaned);
3857
3858 /*
3859 * Server CList
3860 */
3861
3862 vbox2 = gtk_vbox_new (FALSE, 4);
3863 gtk_paned_add1 (GTK_PANED (vpaned), vbox2);
3864
3865 hbox = gtk_hbox_new (FALSE, 4);
3866
3867 button = gtk_button_new();
3868 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
3869 pixmap = gtk_pixmap_new (delete_pix.pix, delete_pix.mask);
3870 gtk_container_add(GTK_CONTAINER(button), pixmap);
3871 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
3872
3873 gtk_widget_show_all(button);
3874
3875 label = gtk_label_new(_("Quick Filter:"));
3876 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
3877 gtk_widget_show (label);
3878
3879 entry = gtk_entry_new();
3880 gtk_signal_connect(GTK_OBJECT(entry), "changed", G_CALLBACK(quick_filter_entry_changed), NULL);
3881 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
3882 gtk_widget_show (entry);
3883
3884 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (quickfilter_delete_button_clicked), entry);
3885
3886 gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0);
3887 gtk_widget_show (hbox);
3888
3889 scrollwin = gtk_scrolled_window_new (NULL, NULL);
3890
3891 gtk_box_pack_start (GTK_BOX (vbox2), scrollwin, TRUE, TRUE, 0);
3892 gtk_widget_show (vbox2);
3893
3894 server_clist = GTK_CLIST (create_cwidget (scrollwin, &server_clist_def));
3895
3896 gtk_signal_connect (GTK_OBJECT (server_clist), "click_column", GTK_SIGNAL_FUNC (clist_set_sort_column), &server_clist_def);
3897 gtk_signal_connect (GTK_OBJECT (server_clist), "event", GTK_SIGNAL_FUNC (server_clist_event_callback), NULL);
3898 gtk_signal_connect (GTK_OBJECT (server_clist), "select_row", GTK_SIGNAL_FUNC (server_clist_select_callback), NULL);
3899 gtk_signal_connect (GTK_OBJECT (server_clist), "unselect_row", GTK_SIGNAL_FUNC (server_clist_unselect_callback), NULL);
3900 gtk_signal_connect (GTK_OBJECT (server_clist), "key_press_event", GTK_SIGNAL_FUNC (server_clist_keypress_callback), NULL);
3901
3902 gtk_clist_set_compare_func (server_clist, (GtkCListCompareFunc) server_clist_compare_func);
3903
3904 gtk_widget_show (GTK_WIDGET (server_clist));
3905 gtk_widget_show (scrollwin);
3906
3907 pane3_widget = hpaned2 = gtk_hpaned_new ();
3908 gtk_paned_add2 (GTK_PANED (vpaned), hpaned2);
3909
3910 /*
3911 * Player CList
3912 */
3913
3914 scrollwin = gtk_scrolled_window_new (NULL, NULL);
3915 gtk_paned_add1 (GTK_PANED (hpaned2), scrollwin);
3916
3917 player_clist = GTK_CLIST (create_cwidget (scrollwin, &player_clist_def));
3918
3919 gtk_signal_connect (GTK_OBJECT (player_clist), "click_column", GTK_SIGNAL_FUNC (clist_set_sort_column), &player_clist_def);
3920 gtk_signal_connect (GTK_OBJECT (player_clist), "event", GTK_SIGNAL_FUNC (player_clist_event_callback), NULL);
3921
3922 gtk_clist_set_compare_func (player_clist, (GtkCListCompareFunc) player_clist_compare_func);
3923
3924 gtk_widget_show (GTK_WIDGET (player_clist));
3925 gtk_widget_show (scrollwin);
3926
3927 /*
3928 * Server Info CList
3929 */
3930
3931 scrollwin = gtk_scrolled_window_new (NULL, NULL);
3932 gtk_paned_add2 (GTK_PANED (hpaned2), scrollwin);
3933
3934 srvinf_ctree = GTK_CTREE (create_cwidget (scrollwin, &srvinf_clist_def));
3935
3936 gtk_signal_connect (GTK_OBJECT (srvinf_ctree), "click_column", GTK_SIGNAL_FUNC (clist_set_sort_column), &srvinf_clist_def);
3937
3938 gtk_signal_connect (GTK_OBJECT (srvinf_ctree), "event", GTK_SIGNAL_FUNC (server_info_clist_event_callback), NULL);
3939
3940 gtk_clist_set_compare_func (GTK_CLIST (srvinf_ctree), (GtkCListCompareFunc) srvinf_clist_compare_func);
3941
3942 gtk_widget_show (GTK_WIDGET (srvinf_ctree));
3943 gtk_widget_show (scrollwin);
3944
3945 gtk_widget_show (hpaned2);
3946 gtk_widget_show (vpaned);
3947 gtk_widget_show (hpaned);
3948
3949 gtk_widget_ensure_style (GTK_WIDGET (server_clist));
3950 i = calculate_clist_row_height (GTK_WIDGET (server_clist), games[Q1_SERVER].pix->pix);
3951 gtk_clist_set_row_height (server_clist, i);
3952 gtk_clist_set_row_height (player_clist, i);
3953 gtk_clist_set_row_height (GTK_CLIST (srvinf_ctree), i);
3954 gtk_clist_set_row_height (GTK_CLIST (source_ctree), i);
3955
3956 /*
3957 * Status Bar & Progress Bar
3958 */
3959
3960 hbox = gtk_hbox_new (FALSE, 4);
3961 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
3962
3963 main_status_bar = gtk_statusbar_new ();
3964 gtk_box_pack_start (GTK_BOX (hbox), main_status_bar, TRUE, TRUE, 0);
3965 gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(main_status_bar), FALSE);
3966 gtk_widget_show (main_status_bar);
3967
3968 main_filter_status_bar = gtk_statusbar_new ();
3969 gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(main_filter_status_bar), FALSE);
3970 gtk_widget_set_usize (main_filter_status_bar, 100, -1);
3971 gtk_box_pack_start (GTK_BOX (hbox), main_filter_status_bar, TRUE, TRUE, 0);
3972 gtk_widget_show (main_filter_status_bar);
3973
3974 main_progress_bar = create_progress_bar ();
3975 gtk_widget_set_usize (main_progress_bar, 200, -1);
3976 gtk_box_pack_end (GTK_BOX (hbox), main_progress_bar, FALSE, FALSE, 0);
3977 gtk_widget_show (main_progress_bar);
3978
3979 /* Make sure the current filter is dispalyed and applied if needed */
3980 set_server_filter_menu_list_text ();
3981
3982 /* Refresh optionmenu on toolbar */
3983
3984 set_filter_option_menu_toolbar();
3985
3986 gtk_widget_show (hbox);
3987
3988 gtk_widget_show (vbox);
3989
3990 gtk_widget_show (main_vbox);
3991
3992 restore_main_window_geometry ();
3993
3994 window_set_icon(main_window);
3995
3996 gtk_window_add_accel_group (GTK_WINDOW (main_window), accel_group);
3997 gtk_accel_group_unref (accel_group);
3998
3999 // Set tooltips - also in prefs_load
4000 tooltips = gtk_tooltips_new ();
4001 if (default_toolbar_tips) {
4002 gtk_tooltips_enable(tooltips);
4003 }
4004 else {
4005 gtk_tooltips_disable(tooltips);
4006 }
4007
4008 gtk_widget_grab_focus(entry);
4009 }
4010
play_sound(const char * sound,gboolean override)4011 void play_sound (const char *sound, gboolean override) {
4012 play_sound_with(sound_player, sound, override);
4013 }
4014
play_sound_with(const char * player,const char * sound,gboolean override)4015 void play_sound_with (const char* player, const char *sound, gboolean override) {
4016 int pid;
4017
4018 if (!sound || !*sound) {
4019 return;
4020 }
4021
4022 if (!sound_enable && !override) {
4023 debug(2,"sound disabled - not playing");
4024 return;
4025 }
4026
4027 if (!player || !*player) {
4028 xqf_warning(_("no sound player configured"));
4029 return;
4030 }
4031
4032 pid = fork();
4033 if (pid == 0) {
4034 char *argv[3];
4035
4036 argv[0] = g_strdup(player);
4037
4038 if (sound[0] != '/') {
4039 // Does not start with a / so prepend user_rcdir
4040 debug(1,"Prepending user_rcdir to sound file");
4041 argv[1] = file_in_dir(user_rcdir, sound);
4042 }
4043 else {
4044 argv[1] = g_strdup(sound);
4045 }
4046
4047 argv[2] = NULL;
4048
4049 debug(1,"sound player (program): %s",argv[0]);
4050 debug(1,"sound to play: %s",argv[1]);
4051 execvp(argv[0],argv);
4052
4053 g_free (argv[1]);
4054
4055 _exit (1);
4056 }
4057 }
4058
cmdlinehelp()4059 static void cmdlinehelp() {
4060 puts("XQF Version " PACKAGE_VERSION);
4061 puts(_(
4062 "Usage:\n"
4063 "\txqf [OPTIONS]\n"
4064 "\n"
4065 "OPTIONS:\n"
4066 "\t--launch \"[SERVERTYPE] IP\"\tlaunch game on specified server\n"
4067 "\t--add \"[SERVERTYPE] IP\"\tadd specified server to favorites\n"
4068 "\t--debug <level>\t\t\tset debug level\n"
4069 "\t--version\t\t\tprint version and exit\n"));
4070 exit(0);
4071 }
4072
4073 static char* cmdline_add_server = NULL;
4074 static gboolean cmdline_launch = FALSE;
4075 static gboolean cmdline_newversion = FALSE;
4076
4077 // must always return FALSE to stop g_timeout
check_cmdline_launch(gpointer nothing)4078 gboolean check_cmdline_launch(gpointer nothing) {
4079 char* token[2] = {0};
4080 enum server_type type = UNKNOWN_SERVER;
4081 unsigned n = 0;
4082 char* addrstring = NULL; // must point to a copy
4083
4084 if (!cmdline_add_server) {
4085 return FALSE;
4086 }
4087
4088 n = tokenize_bychar(cmdline_add_server, token, 2, ' ');
4089
4090 if (n == 2) // type and address given
4091 {
4092 type = id2type(token[0]);
4093
4094 if (type == UNKNOWN_SERVER) {
4095 addrstring = add_server_dialog (&type, token[1]);
4096 }
4097 else {
4098 addrstring = g_strdup(token[1]);
4099 }
4100 }
4101 else if (n == 1) // only address
4102 {
4103 char *addr;
4104 unsigned short port;
4105 unsigned matches = 0;
4106
4107 if (!parse_address (token[0], &addr, &port)) {
4108 dialog_ok (NULL, _("\"%s\" is not valid host[:port] combination."), token[0]);
4109 g_free(cmdline_add_server);
4110 return FALSE;
4111 }
4112
4113 if (port) // guess the type from the port
4114 {
4115 unsigned i = 0;
4116 for (i = 0; i < GAMES_TOTAL; i++) {
4117 if (games[i].default_port == port) {
4118 ++matches;
4119 if (type == UNKNOWN_SERVER) type = i;
4120 }
4121 }
4122 }
4123
4124 if (!port || type == UNKNOWN_SERVER || matches > 1) {
4125 addrstring = add_server_dialog (&type, token[0]);
4126 }
4127 else {
4128 addrstring = g_strdup(cmdline_add_server);
4129 }
4130 }
4131
4132 prepare_new_server_to_favorites(type, addrstring, cmdline_launch);
4133
4134 g_free(cmdline_add_server);
4135 return FALSE;
4136 }
4137
4138 static struct option long_options[] =
4139 {
4140 {"launch", 1, 0, 'l'},
4141 {"add", 1, 0, 'a'},
4142 {"debug", 1, 0, 'd'},
4143 {"dontlaunch", 0, 0, 128},
4144 {"version", 0, 0, 'v'},
4145 {"help", 0, 0, 'h'},
4146 {"newversion", 0, 0, 129},
4147 {"nomapscan", 0, 0, 130},
4148 {0, 0, 0, 0}
4149 };
4150
parse_commandline(int argc,char * argv[])4151 static void parse_commandline(int argc, char* argv[]) {
4152 while (1) {
4153 int c;
4154 int option_index = 0;
4155
4156 c = getopt_long (argc, argv, "d:l:h", long_options, &option_index);
4157 if (c == -1) {
4158 break;
4159 }
4160
4161 switch(c) {
4162 case 'd':
4163 set_debug_level(atoi(optarg));
4164 break;
4165 case 'l':
4166 g_free(cmdline_add_server);
4167 cmdline_add_server = g_strdup(optarg);
4168 cmdline_launch = TRUE;
4169 break;
4170 case 'a':
4171 g_free(cmdline_add_server);
4172 cmdline_add_server = g_strdup(optarg);
4173 break;
4174 case 'h':
4175 cmdlinehelp();
4176 break;
4177 case 'v':
4178 puts("XQF Version " PACKAGE_VERSION);
4179 exit(0);
4180 break;
4181 case 128:
4182 dontlaunch = TRUE;
4183 break;
4184 case 129:
4185 cmdline_newversion = TRUE;
4186 break;
4187 case 130:
4188 skip_startup_mapscan = TRUE;
4189 break;
4190 case '?':
4191 case ':':
4192 exit(1);
4193 break;
4194 default:
4195 xqf_warning("getopt error, starting anyway ...");
4196 return;
4197 }
4198 }
4199 }
4200
add_pixmap_path_for_theme(const char * theme)4201 void add_pixmap_path_for_theme(const char* theme) {
4202 char dir[PATH_MAX];
4203 snprintf(dir, sizeof(dir), "%s/%s", xqf_PACKAGE_DATA_DIR, theme);
4204 add_pixmap_directory (dir);
4205 snprintf(dir, sizeof(dir), "%s/.local/share/xqf/%s", g_get_home_dir(), theme);
4206 add_pixmap_directory (dir);
4207 }
4208
init_config_path()4209 static void init_config_path() {
4210 char dir[PATH_MAX];
4211 config_add_dir (xqf_PACKAGE_DATA_DIR);
4212 snprintf(dir, sizeof(dir), "%s/.local/share/xqf", g_get_home_dir());
4213 config_add_dir (dir);
4214 config_add_dir (user_rcdir);
4215 }
4216
init_scripts_path()4217 static void init_scripts_path() {
4218 char dir[PATH_MAX];
4219 snprintf(dir, sizeof(dir), "%s/scripts", xqf_PACKAGE_DATA_DIR);
4220 scripts_add_dir (dir);
4221 snprintf(dir, sizeof(dir), "%s/.local/share/xqf/scripts", g_get_home_dir());
4222 scripts_add_dir (dir);
4223 snprintf(dir, sizeof(dir), "%s/scripts", user_rcdir);
4224 scripts_add_dir (dir);
4225 }
4226
main(int argc,char * argv[])4227 int main (int argc, char *argv[]) {
4228 char *gtk_config;
4229 char* var = NULL;
4230 int newversion = FALSE;
4231
4232 xqf_start_time = time (NULL);
4233
4234 redialserver=0;
4235
4236 var = getenv("xqf_PACKAGE_DATA_DIR");
4237 if (var) {
4238 xqf_PACKAGE_DATA_DIR = var;
4239 }
4240
4241 var = getenv("xqf_LOCALEDIR");
4242 if (var) {
4243 xqf_LOCALEDIR = var;
4244 }
4245
4246 #ifdef ENABLE_NLS
4247 setlocale(LC_ALL, "");
4248 bindtextdomain(PACKAGE, xqf_LOCALEDIR);
4249 bind_textdomain_codeset(PACKAGE, "UTF-8");
4250 textdomain(PACKAGE);
4251 #endif
4252
4253 set_debug_level (DEFAULT_DEBUG_LEVEL);
4254 debug (5, "main() -- Debug Level Default Set at %d", DEFAULT_DEBUG_LEVEL);
4255
4256 /* migrate config directory to follow XDG Base Directory Specification
4257 * http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
4258 * https://developer.gnome.org/basedir-spec/
4259 * https://developer.gnome.org/glib/2.37/glib-Miscellaneous-Utility-Functions.html#g-get-user-config-dir
4260 */
4261 if (!rc_migrate_dir()) {
4262 return 1;
4263 }
4264
4265 if (!init_user_info ()) {
4266 return 1;
4267 }
4268
4269 gtk_config = file_in_dir (user_rcdir, "gtkrc");
4270 gtk_rc_add_default_file (gtk_config);
4271 g_free (gtk_config);
4272
4273 gtk_init (&argc, &argv);
4274
4275 parse_commandline(argc,argv);
4276
4277 if (!GDK_PIXBUF_INSTALLED) {
4278 xqf_warning(_("gdk-pixbuf is not installed. Some icons may not be displayed"));
4279 }
4280
4281 if (dns_spawn_helper () < 0) {
4282 xqf_error ("Unable to start DNS helper");
4283 return 1;
4284 }
4285
4286 add_pixmap_path_for_theme("default");
4287 add_pixmap_directory(xqf_PACKAGE_DATA_DIR);
4288
4289 qstat_configfile = g_strconcat(xqf_PACKAGE_DATA_DIR, "/qstat.cfg", NULL);
4290
4291 dns_gtk_init ();
4292
4293 rc_check_dir ();
4294
4295 init_games();
4296
4297 init_config_path();
4298
4299 newversion = prefs_load () | cmdline_newversion;
4300
4301 if (default_icontheme) {
4302 add_pixmap_path_for_theme(default_icontheme);
4303 }
4304
4305 init_scripts_path();
4306 scripts_load();
4307
4308 #ifdef USE_GEOIP
4309 geoip_init();
4310 #endif
4311
4312 gtk_preview_set_gamma (1.5);
4313
4314 props_load ();
4315 filters_init ();
4316
4317 host_cache_load ();
4318 splash_increase_progress(_("Reading server lists"),10);
4319 init_masters (newversion);
4320
4321 client_init ();
4322 ignore_sigpipe ();
4323
4324 on_sig(SIGUSR1, sighandler_debug);
4325 on_sig(SIGUSR2, sighandler_debug);
4326
4327 add_server_init ();
4328 add_master_init ();
4329 psearch_init ();
4330 rcon_init ();
4331
4332 if (check_qstat_version() == FALSE) {
4333 dialog_ok(NULL, _("You need at least qstat version %s for xqf to function properly"), required_qstat_version);
4334 }
4335
4336 splash_increase_progress(_("Loading icons ..."),10);
4337
4338 create_main_window ();
4339
4340 init_pixmaps (main_window);
4341
4342 splash_set_progress(_("Starting ..."),100);
4343
4344 play_sound(sound_xqf_start, 0);
4345
4346 script_action_start();
4347
4348 populate_main_window();
4349
4350 if (default_show_tray_icon) {
4351 tray_init(main_window);
4352 }
4353 else {
4354 gtk_widget_show (main_window);
4355 }
4356
4357 source_ctree_select_source (favorites);
4358 filter_menu_activate_current();
4359
4360 print_status (main_status_bar, NULL);
4361
4362 if (default_auto_favorites && !cmdline_add_server) refresh_callback (NULL, NULL);
4363
4364 destroy_splashscreen();
4365
4366 g_timeout_add(0, check_cmdline_launch, NULL);
4367
4368 debug(1,"startup time %ds", time(NULL)-xqf_start_time);
4369
4370 // tray_icon_set_tooltip(_("nothing yet..."));
4371
4372 gtk_main ();
4373
4374 play_sound(sound_xqf_quit, 0);
4375 script_action_quit();
4376
4377 if (default_show_tray_icon) {
4378 tray_done();
4379 }
4380
4381 unregister_window (main_window);
4382 main_window = NULL;
4383
4384 if (stat_process) {
4385 stop_callback (NULL, NULL);
4386 }
4387
4388 debug (1, "total servers: %d", servers_total ());
4389 debug (1, "total uservers: %d", uservers_total ());
4390 debug (1, "total hosts: %d", hosts_total ());
4391 #if 0
4392 if (servers_total () > 0) {
4393 GSList *list = all_servers (); /* Debug code, free done in two lines */
4394
4395 server_list_fprintf (stderr, list);
4396 server_list_free (list);
4397 }
4398 #endif
4399
4400
4401 if (server_menu) {
4402 debug(6, "EXIT: destroy server_menu");
4403 gtk_widget_destroy (server_menu);
4404 server_menu = NULL;
4405 }
4406
4407 if (player_menu) {
4408 debug(6, "EXIT: destroy player_menu");
4409 gtk_widget_destroy (player_menu);
4410 player_menu = NULL;
4411 }
4412
4413 if (player_skin_popup) {
4414 gtk_widget_destroy (player_skin_popup);
4415 player_skin_popup = NULL;
4416 }
4417
4418 if (server_mapshot_popup) {
4419 gtk_widget_destroy (server_mapshot_popup);
4420 server_mapshot_popup = NULL;
4421 }
4422
4423 pixmap_cache_clear (&qw_colors_pixmap_cache, 0);
4424 pixmap_cache_clear (&server_pixmap_cache, 0);
4425 free_pixmaps ();
4426
4427 filters_done ();
4428 props_free_all ();
4429
4430 debug(6, "EXIT: Free Server Lists");
4431 g_slist_free (cur_source);
4432 server_list_free (cur_server_list);
4433 userver_list_free (cur_userver_list);
4434
4435 if (cur_server) {
4436 server_unref (cur_server);
4437 cur_server = NULL;
4438 }
4439
4440 host_cache_save ();
4441 host_cache_clear ();
4442
4443 debug(6, "EXIT: Free Master Lists");
4444 free_masters ();
4445
4446 debug(6, "EXIT: Call rcon_done.");
4447 rcon_done ();
4448 psearch_done ();
4449 add_server_done ();
4450 add_master_done ();
4451 client_detach_all ();
4452 free_user_info ();
4453
4454 dns_helper_shutdown ();
4455
4456 config_sync ();
4457 config_drop_all ();
4458
4459 #ifdef USE_GEOIP
4460 geoip_done();
4461 #endif
4462
4463 games_done();
4464
4465 debug(6, "EXIT: Done.");
4466
4467 return 0;
4468 }
4469