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 <string.h>
24 #include <stdlib.h>
25
26 #include <glib.h>
27 #include <gtk/gtk.h>
28
29 #include "i18n.h"
30 #include "xqf.h"
31 #include "xqf-ui.h"
32 #include "dialogs.h"
33 #include "server.h"
34 #include "config.h"
35 #include "filter.h"
36 #include "flt-player.h"
37 #include "utils.h"
38 #include "pref.h"
39
40 #ifdef USE_GEOIP
41 #include "country-filter.h"
42
43 static void country_select_button_pressed (GtkWidget * widget, gpointer data);
44 static void country_add_button (GtkWidget * widget, gpointer data);
45 static void country_delete_button (GtkWidget * widget, gpointer data);
46 static void country_clear_list (GtkWidget * widget, gpointer data);
47 static void country_create_popup_window (void);
48
49 // TODO: get rid of global variables
50 static gint selected_row_left_list=-1;
51 static gint selected_row_right_list=-1;
52 static int last_row_right_list = 0;
53 static int last_row_country_list = 0;
54 #endif
55
56 static void server_filter_vars_free (struct server_filter_vars* v);
57
58 static int server_pass_filter (struct server *s);
59 static void server_filter_init (void);
60
61 static void server_filter_on_ok ();
62 static void server_filter_on_cancel ();
63 static void server_filter_fill_widgets (guint num);
64
65 static void server_filter_save_settings (int number, struct server_filter_vars* oldfilter, struct server_filter_vars* newfilter);
66
67 static void filter_select_callback (GtkWidget *widget, guint number);
68
69 void server_filter_print (struct server_filter_vars* f);
70
71 // whether the currently displayed filter page has been altered
72 static gboolean server_filter_changed = FALSE;
73 static gboolean server_filter_deleted = FALSE;
74
75 GArray* server_filters;
76
77 static GArray* backup_server_filters; // copy of server_filters, for restoring on cancel
78
79 static gboolean cleaned_up = FALSE;
80
81 /* QUICK FILTER */
82
83 static char* quick_filter_token[8];
84 static char quick_filter_str[512] = {0};
85
86 static int quick_filter (struct server *s);
87 void filter_quick_set (const char* str);
88 const char* filter_quick_get(void);
89 void filter_quick_unset (void);
90
91 /* /QUICK FILTER */
92
93 struct filter filters[FILTERS_TOTAL] = {
94 {
95 N_("Server"),
96 N_("S Filter"),
97 N_("SF Cfg"),
98 server_pass_filter,
99 server_filter_init,
100 NULL,
101 server_filter_on_ok,
102 server_filter_on_cancel,
103 1,
104 FILTER_NOT_CHANGED,
105 &sfilter_pix,
106 &sfilter_cfg_pix,
107 },
108 {
109 N_("Player"),
110 N_("P Filter"),
111 N_("PF Cfg"),
112 player_filter,
113 player_filter_init,
114 player_filter_done,
115 player_filter_new_defaults,
116 NULL,
117 1,
118 FILTER_NOT_CHANGED,
119 &pfilter_pix,
120 &pfilter_cfg_pix,
121 },
122 {
123 "not visible",
124 "not visible",
125 "not visible",
126 quick_filter,
127 NULL,
128 NULL,
129 NULL,
130 NULL,
131 1,
132 FILTER_NOT_CHANGED,
133 NULL,
134 NULL,
135 }
136 };
137
138
139 unsigned char cur_filter = 0;
140
141 static unsigned filter_current_time = 1;
142
143 unsigned server_filter_dialog_current_filter = 0;
144
145 unsigned current_server_filter;
146
147 static GtkWidget *filter_option_menu;
148 static GtkWidget *filter_retries_spinner;
149 static GtkWidget *filter_ping_spinner;
150 static GtkWidget *filter_not_full_check_button;
151 static GtkWidget *filter_not_empty_check_button;
152 static GtkWidget *filter_no_cheats_check_button;
153 static GtkWidget *filter_no_password_check_button;
154 static GtkWidget *game_contains_entry;
155 static GtkWidget *filter_game_type_entry;
156 static GtkWidget *version_contains_entry;
157 static GtkWidget *map_contains_entry;
158 static GtkWidget *server_name_contains_entry;
159 #ifdef USE_GEOIP
160 static GtkWidget *country_left_list;
161 static GtkWidget *country_right_list;
162 static GtkWidget *country_filter_list;
163 static GtkWidget *scrolledwindow_fcountry;
164 static GtkWidget *country_selection_button;
165 static GtkWidget *country_clear_button;
166 static GtkWidget *country_show_all_check_button;
167 #endif
168
server_filter_vars_new()169 static struct server_filter_vars* server_filter_vars_new() {
170 struct server_filter_vars* f = g_malloc(sizeof(struct server_filter_vars));
171 if (!f) return NULL;
172
173 f->filter_retries = 2;
174 f->filter_ping = 9999;
175 f->filter_not_full = 0;
176 f->filter_not_empty = 0;
177 f->filter_no_cheats = 0;
178 f->filter_no_password = 0;
179 f->filter_name = NULL;
180 f->game_contains = NULL;
181 f->version_contains = NULL;
182 f->game_type = NULL;
183 f->map_contains = NULL;
184 f->server_name_contains=NULL;
185 #ifdef USE_GEOIP
186 f->countries = g_array_new(FALSE, FALSE, sizeof(int));
187 #endif
188
189 return f;
190 }
191
server_filter_vars_free(struct server_filter_vars * v)192 static void server_filter_vars_free(struct server_filter_vars* v) {
193 if (!v) return;
194
195 g_free(v->filter_name);
196 g_free(v->game_contains);
197 g_free(v->version_contains);
198 g_free(v->map_contains);
199 g_free(v->server_name_contains);
200 g_free(v->game_type);
201 #ifdef USE_GEOIP
202 g_array_free(v->countries,TRUE);
203 v->countries=NULL;
204 #endif
205 }
206
207 // deep copy of server_filter_vars
server_filter_vars_copy(struct server_filter_vars * v)208 static struct server_filter_vars* server_filter_vars_copy(struct server_filter_vars* v) {
209 struct server_filter_vars* f;
210 unsigned i;
211
212 if (!v) return NULL;
213
214 f = server_filter_vars_new();
215 if (!f) return NULL;
216
217 f->filter_retries = v->filter_retries;
218 f->filter_ping = v->filter_ping;
219 f->filter_not_full = v->filter_not_full;
220 f->filter_not_empty = v->filter_not_empty;
221 f->filter_no_cheats = v->filter_no_cheats;
222 f->filter_no_password = v->filter_no_password;
223 f->filter_name = g_strdup(v->filter_name);
224 f->game_contains = g_strdup(v->game_contains);
225 f->version_contains = g_strdup(v->version_contains);
226 f->game_type = g_strdup(v->game_type);
227 f->map_contains = g_strdup(v->map_contains);
228 f->server_name_contains = g_strdup(v->server_name_contains);
229 #ifdef USE_GEOIP
230
231 //FIXME reserve space first, then insert
232 for (i =0; i< v->countries->len;i++)
233 g_array_append_val(f->countries,g_array_index(v->countries,int,i));
234
235 #endif
236
237 return f;
238 }
239
server_filter_print(struct server_filter_vars * f)240 void server_filter_print(struct server_filter_vars* f) {
241 #ifdef USE_GEOIP
242 unsigned i;
243 #endif
244
245 printf("Filter: %s\n",f->filter_name);
246 printf(" retries: %d\n",f->filter_retries);
247 printf(" ping: %d\n",f->filter_ping);
248 printf(" not full: %d\n",f->filter_not_full);
249 printf(" not empty: %d\n",f->filter_not_empty);
250 printf(" no cheats: %d\n",f->filter_no_cheats);
251 printf(" no password: %d\n",f->filter_no_password);
252 printf(" game: %s\n",f->game_contains);
253 printf(" version: %s\n",f->version_contains);
254 printf(" game type: %s\n",f->game_type);
255 printf(" map: %s\n",f->map_contains);
256 printf(" server name: %s\n",f->server_name_contains);
257 #ifdef USE_GEOIP
258
259 for (i =0; i< f->countries->len;i++)
260 printf("country id: %d ",g_array_index(f->countries,int,i));
261 printf("\n");
262
263 #endif
264 }
265
apply_filters(unsigned mask,struct server * s)266 void apply_filters (unsigned mask, struct server *s) {
267 /* This function gets called once per server */
268
269 unsigned flt_time;
270 unsigned i;
271 int n;
272
273 flt_time = s->flt_last;
274
275 for (n = 0, i = 1; n < FILTERS_TOTAL; n++, i <<= 1) {
276 if ((mask & i) == i && ((filters[n].last_changed > s->flt_last) || ((s->flt_mask & i) != i))) {
277
278 /* baa --
279 The 'vars' (second param to the func) only matters
280 with the server filter call. It gets passed to the
281 player filter call but not used.
282 */
283 /* if ((*filters[n].func)(s, vars)) */
284 //if ((*filters[n].func)(s, &server_filters[current_server_filter]))
285 if ((*filters[n].func)(s))
286 s->filters |= i;
287 else
288 s->filters &= ~i;
289
290 if (flt_time < filters[n].last_changed)
291 flt_time = filters[n].last_changed;
292 }
293 }
294
295
296 s->flt_mask |= mask;
297 s->flt_last = flt_time;
298 }
299
300
301 /*
302 build_filtered_list -- Return a list of servers that pass the filter
303 requirements. Called from server_clist_setlist() and
304 server_clist_build_filtered().
305 */
306
build_filtered_list(unsigned mask,GSList * server_list)307 GSList *build_filtered_list (unsigned mask, GSList *server_list) {
308 struct server *server;
309 GSList *list = NULL;
310
311 while (server_list) {
312 server =(struct server *) server_list->data;
313 apply_filters(mask | FILTER_PLAYER_MASK, server); /* in filter.c */
314
315 if ((server->filters & mask) == mask) {
316 list = g_slist_prepend(list, server);
317 debug(6, "build_filtered_list() -- Server %lx added to list", server);
318 server_ref(server);
319 }
320
321 server_list = server_list->next;
322 }
323
324 list = g_slist_reverse(list);
325 return list;
326 }
327
328 /*
329 This applies a filter's attributes to a server entry and returns true if it
330 passes the filter or false if not.
331 */
server_pass_filter(struct server * s)332 static int server_pass_filter (struct server *s){
333 char **info_ptr;
334 struct server_filter_vars* filter;
335 int players = s->curplayers;
336
337 /* Filter Zero is No Filter */
338 if (current_server_filter == 0){ return TRUE; }
339
340 filter = g_array_index(server_filters, struct server_filter_vars*, current_server_filter-1);
341
342 // server_filter_print(filter);
343
344 if (s->ping == -1) /* no information */
345 return FALSE;
346
347 if (s->retries >= filter->filter_retries)
348 return FALSE;
349
350 if (s->ping >= filter->filter_ping)
351 return FALSE;
352
353 if (serverlist_countbots && s->curbots <= players)
354 players-=s->curbots;
355
356 if (filter->filter_not_full && (players >= s->maxplayers))
357 return FALSE;
358
359 if (filter->filter_not_empty && (players == 0))
360 return FALSE;
361
362 if (filter->filter_no_cheats && ((s->flags & SERVER_CHEATS) != 0))
363 return FALSE;
364
365 if (filter->filter_no_password && ((s->flags & SERVER_PASSWORD) != 0))
366 return FALSE;
367
368 if (filter->game_contains && *filter->game_contains) {
369 if (!s->game)
370 return FALSE;
371 else if (!lowcasestrstr(s->game,filter->game_contains))
372 return FALSE;
373 }
374
375 if (filter->game_type && *filter->game_type) {
376 if (!s->gametype)
377 return FALSE;
378 else if (!lowcasestrstr(s->gametype, filter->game_type))
379 return FALSE;
380 }
381
382 if (filter->map_contains && *filter->map_contains) {
383 if (!s->map)
384 return FALSE;
385 else if (!lowcasestrstr(s->map, filter->map_contains))
386 return FALSE;
387 }
388
389
390 if (filter->version_contains && *filter->version_contains) {
391 const char* version = NULL;
392 /* Filter for the version */
393 for (info_ptr = s->info; info_ptr && *info_ptr; info_ptr += 2) {
394 if (strcmp(*info_ptr, "version") == 0) {
395 version=info_ptr[1];
396 }
397 }
398 if (!version) {
399 return FALSE;
400 }
401 else if (!lowcasestrstr(version, filter->version_contains)) {
402 return FALSE;
403 }
404 } /*end version check */
405
406 #ifdef USE_GEOIP
407 if (filter->countries->len > 0) {
408 gboolean have_country=FALSE;
409 unsigned i;
410
411 if (!s->country_id) {
412 return FALSE;
413 }
414 else {
415 for (i = 0; i < filter->countries->len; ++i) {
416 if (g_array_index(filter->countries,int,i) == s->country_id) {
417 have_country=TRUE;
418 }
419 }
420
421 if (!have_country) {
422 return FALSE;
423 }
424 }
425 }
426
427 #endif
428
429 if (filter->server_name_contains && *filter->server_name_contains) {
430 if (!s->name) {
431 return FALSE;
432 }
433 else if (!lowcasestrstr(s->name, filter->server_name_contains)) {
434 return FALSE;
435 }
436 }
437
438
439
440 return TRUE;
441 }
442
443 /** initialize server_filters array from config file */
server_filter_init(void)444 static void server_filter_init (void) {
445 int i;
446 char config_section[64];
447 int isdefault = FALSE; // used to determine whether key exists in config
448 char* filtername;
449
450 #ifdef USE_GEOIP
451 char *str = NULL;
452 #endif
453
454
455 struct server_filter_vars* filter;
456
457 /* This is called before the window has been created so
458 we cannot set the filter names in the pulldown yet. */
459
460 server_filters = g_array_new(FALSE,FALSE, sizeof(struct server_filter_vars*));
461 if (!server_filters) return;
462
463 i = 1;
464 snprintf(config_section, 64, "/" CONFIG_FILE "/Server Filter/%d", i);
465 config_push_prefix(config_section);
466
467 filtername = config_get_string_with_default("filter_name",&isdefault);
468
469 while (!isdefault) {
470 filter = server_filter_vars_new();
471 if (!filter) break;
472
473 filter->filter_name = filtername;
474 filter->filter_retries = config_get_int("retries=2");
475 filter->filter_ping = config_get_int("ping=9999");
476 filter->filter_not_full = config_get_bool("not full=false");
477 filter->filter_not_empty = config_get_bool("not empty=false");
478 filter->filter_no_cheats = config_get_bool("no cheats=false");
479 filter->filter_no_password = config_get_bool("no password=false");
480 filter->game_contains = config_get_string("game_contains");
481 filter->version_contains = config_get_string("version_contains");
482 filter->game_type = config_get_string("game_type");
483 filter->map_contains = config_get_string("map_contains");
484 filter->server_name_contains = config_get_string("server_name_contains");
485 #ifdef USE_GEOIP
486
487 /*country filter ids*/
488 str = config_get_string("server_country_contains");
489 if (str) {
490 int nr;
491 gchar **buf = NULL;
492 buf = g_strsplit(str," ",0);
493
494 for (nr = 0; buf && buf[nr]; ++nr) {
495 int flag_nr = geoip_id_by_code(buf[nr]);
496 if (flag_nr > 0)
497 g_array_append_val(filter->countries,flag_nr);
498 }
499
500 g_strfreev(buf);
501 }
502
503 #endif
504 g_array_append_val(server_filters,filter);
505
506 config_pop_prefix();
507
508 i++;
509 snprintf(config_section, 64, "/" CONFIG_FILE "/Server Filter/%d", i);
510 config_push_prefix(config_section);
511 filtername = config_get_string_with_default("filter_name",&isdefault);
512
513 }
514
515 config_pop_prefix();
516
517 debug(3,"number of server filters: %d",server_filters->len);
518
519 sprintf(config_section, "/" CONFIG_FILE "/Server Filter");
520 config_push_prefix(config_section);
521 current_server_filter = config_get_int("current_server_filter=0");
522
523 if (current_server_filter<0 || current_server_filter>server_filters->len)
524 current_server_filter = 0;
525
526 config_pop_prefix();
527 }
528
server_filter_on_cancel()529 static void server_filter_on_cancel() {
530 // restore server filter array
531 unsigned i;
532 struct server_filter_vars* filter;
533
534 for (i=0;i<server_filters->len;++i) {
535 filter = g_array_index(server_filters, struct server_filter_vars*, i);
536 server_filter_vars_free(filter);
537 }
538 g_array_free(server_filters, FALSE);
539
540 server_filters = backup_server_filters;
541
542 filters[FILTER_SERVER].changed = FILTER_CHANGED;
543
544 }
545
546 // query widgets and put values in a new struct
server_filter_new_from_widgets()547 static struct server_filter_vars* server_filter_new_from_widgets() {
548 #ifdef USE_GEOIP
549 int country_nr;
550 int i;
551 #endif
552
553 struct server_filter_vars* filter = server_filter_vars_new();
554 if (!filter) return NULL;
555
556 filter->filter_retries = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(filter_retries_spinner));
557 filter->filter_ping = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(filter_ping_spinner));
558 filter->filter_not_full = GTK_TOGGLE_BUTTON(filter_not_full_check_button)->active;
559 filter->filter_not_empty = GTK_TOGGLE_BUTTON(filter_not_empty_check_button)->active;
560 filter->filter_no_password = GTK_TOGGLE_BUTTON(filter_no_password_check_button)->active;
561 filter->filter_no_cheats = GTK_TOGGLE_BUTTON(filter_no_cheats_check_button)->active;
562 filter->game_type = gtk_editable_get_chars(GTK_EDITABLE(filter_game_type_entry), 0, -1);
563 filter->version_contains = gtk_editable_get_chars(GTK_EDITABLE(version_contains_entry), 0, -1);
564 filter->game_contains = gtk_editable_get_chars(GTK_EDITABLE(game_contains_entry), 0, -1);
565 filter->map_contains = gtk_editable_get_chars(GTK_EDITABLE(map_contains_entry), 0, -1);
566 filter->server_name_contains = gtk_editable_get_chars(GTK_EDITABLE(server_name_contains_entry), 0, -1);
567
568 #ifdef USE_GEOIP
569
570 for (i = 0; i < last_row_country_list; ++i) {
571 country_nr=GPOINTER_TO_INT(gtk_clist_get_row_data(GTK_CLIST(country_filter_list), i));
572 g_array_append_val(filter->countries,country_nr);
573 }
574
575 #endif
576
577 return filter;
578 }
579
server_filter_on_ok()580 static void server_filter_on_ok() {
581 // struct server_filter_vars** oldfilter = NULL;
582 // struct server_filter_vars* newfilter = NULL;
583
584 unsigned i;
585 struct server_filter_vars* filter;
586
587 if (server_filter_dialog_current_filter == 0 && server_filter_deleted == FALSE) {
588 return;
589 }
590 /*
591 oldfilter = &g_array_index(server_filters, struct server_filter_vars*, server_filter_dialog_current_filter-1);
592 if(!oldfilter || !*oldfilter) {
593 debug(0,"Bug: filter is NULL");
594 return;
595 }
596 */
597 filter_select_callback(NULL,server_filter_dialog_current_filter);
598
599 /*
600 newfilter = server_filter_vars_new();
601 if(!newfilter)
602 return;
603
604 filters[FILTER_SERVER].changed = FILTER_CHANGED;
605
606 newfilter = server_filter_new_from_widgets();
607 newfilter->filter_name = g_strdup((*oldfilter)->filter_name);
608
609 server_filter_save_settings(server_filter_dialog_current_filter, *oldfilter, newfilter);
610
611 server_filter_vars_free(*oldfilter);
612 *oldfilter = newfilter;
613
614 if (server_filter_deleted == TRUE)
615 */
616
617 { /* as some filter in the middle could have changed, clear all of them and
618 set all new
619 */
620 guint i;
621 config_clean_section("/" CONFIG_FILE "/Server Filter");
622
623 for (i=0;i<server_filters->len;i++) {
624 struct server_filter_vars* newfilter = NULL;
625 struct server_filter_vars* oldfilter = server_filter_vars_new();
626
627 newfilter = g_array_index(server_filters, struct server_filter_vars*, i);
628 server_filter_save_settings(i+1,oldfilter,newfilter);
629
630 server_filter_vars_free(oldfilter);
631 }
632 }
633
634 current_server_filter = server_filter_dialog_current_filter;
635
636 #ifdef DEBUG
637 {
638 unsigned i;
639 struct server_filter_vars* filter = NULL;
640 for (i=0;i<server_filters->len;i++) {
641 filter = g_array_index(server_filters, struct server_filter_vars*, i);
642 server_filter_print(filter);
643 }
644 }
645 #endif
646
647 { // save number of current server filters
648 enum { buflen = 64 };
649 char config_section[buflen];
650 sprintf(config_section, "/" CONFIG_FILE "/Server Filter");
651 config_push_prefix(config_section);
652 config_set_int("current_server_filter", current_server_filter);
653 config_pop_prefix();
654 }
655
656
657 for (i=0;i<backup_server_filters->len;i++) {
658 filter = g_array_index(backup_server_filters, struct server_filter_vars*, i);
659 server_filter_vars_free(filter);
660 }
661 g_array_free(backup_server_filters,FALSE);
662 }
663
664 /** save settings of current server filter and detect if filter has changed
665 * oldfilter is currently dummy
666 * modifies oldfilter
667 */
server_filter_save_settings(int number,struct server_filter_vars * oldfilter,struct server_filter_vars * newfilter)668 static void server_filter_save_settings (int number,
669 struct server_filter_vars* oldfilter,
670 struct server_filter_vars* newfilter) {
671 int text_changed;
672 enum { buflen = 64 };
673 char config_section[buflen];
674
675 if (number == 0) {
676 return;
677 }
678
679 snprintf(config_section, buflen, "/" CONFIG_FILE "/Server Filter/%d", number);
680 config_push_prefix(config_section);
681
682 config_set_string("filter_name", newfilter->filter_name);
683
684
685 if (oldfilter->filter_retries != newfilter->filter_retries) {
686 config_set_int("retries", oldfilter->filter_retries = newfilter->filter_retries);
687 filters[FILTER_SERVER].changed = FILTER_CHANGED;
688 }
689
690 if (oldfilter->filter_ping != newfilter->filter_ping) {
691 config_set_int("ping", oldfilter->filter_ping = newfilter->filter_ping);
692 filters[FILTER_SERVER].changed = FILTER_CHANGED;
693 }
694
695 /* GAMECONTAINS string values -- baa */
696 text_changed = 0;
697 if (newfilter->game_contains && strlen(newfilter->game_contains)){
698 /*
699 First case, the user entered something. See if the value
700 is different
701 */
702 if (oldfilter->game_contains){
703 if (strcmp(newfilter->game_contains, oldfilter->game_contains)) text_changed = 1;
704 g_free(oldfilter->game_contains);
705 } else {
706 text_changed = 1;
707 }
708 oldfilter->game_contains = g_strdup(newfilter->game_contains);
709 if (text_changed) {
710 config_set_string("game_contains", oldfilter->game_contains);
711 filters[FILTER_SERVER].changed = FILTER_CHANGED;
712 }
713 } else {
714 if (oldfilter->game_contains){
715 text_changed = 1; /* From something to nothing */
716 g_free(oldfilter->game_contains);
717 config_set_string("game_contains", "");
718 filters[FILTER_SERVER].changed = FILTER_CHANGED;
719 }
720 oldfilter->game_contains = NULL;
721 }
722
723
724 /* Version string values -- baa */
725 text_changed = 0;
726 if (newfilter->version_contains && strlen(newfilter->version_contains)){
727 /*
728 First case, the user entered something. See if the value
729 is different
730 */
731 if (oldfilter->version_contains){
732 if (strcmp(newfilter->version_contains, oldfilter->version_contains)) text_changed = 1;
733 g_free(oldfilter->version_contains);
734 } else {
735 text_changed = 1;
736 }
737 oldfilter->version_contains = g_strdup(newfilter->version_contains);
738 if (text_changed) {
739 config_set_string("version_contains", oldfilter->version_contains);
740 filters[FILTER_SERVER].changed = FILTER_CHANGED;
741 }
742 } else {
743 if (oldfilter->version_contains){
744 text_changed = 1; /* From something to nothing */
745 g_free(oldfilter->version_contains);
746 config_set_string("version_contains", "");
747 filters[FILTER_SERVER].changed = FILTER_CHANGED;
748 }
749 oldfilter->version_contains = NULL;
750 }
751
752
753 /* GAMETYPE string values -- baa */
754 text_changed = 0;
755 if (newfilter->game_type && strlen(newfilter->game_type)){
756 /*
757 First case, the user entered something. See if the value
758 is different
759 */
760 if (oldfilter->game_type){
761 if (strcmp(newfilter->game_type, oldfilter->game_type)) text_changed = 1;
762 g_free(oldfilter->game_type);
763 } else {
764 text_changed = 1;
765 }
766 oldfilter->game_type = g_strdup(newfilter->game_type);
767 if (text_changed) {
768 config_set_string("game_type", oldfilter->game_type);
769 filters[FILTER_SERVER].changed = FILTER_CHANGED;
770 }
771 } else {
772 if (oldfilter->game_type){
773 text_changed = 1; /* From something to nothing */
774 g_free(oldfilter->game_type);
775 config_set_string("game_type", "");
776 filters[FILTER_SERVER].changed = FILTER_CHANGED;
777 }
778 oldfilter->game_type = NULL;
779 }
780 /* end game_type filter */
781
782
783 /* map string values */
784 text_changed = 0;
785 if (newfilter->map_contains && strlen(newfilter->map_contains)){
786 /*
787 First case, the user entered something. See if the value
788 is different
789 */
790 if (oldfilter->map_contains){
791 if (strcmp(newfilter->map_contains, oldfilter->map_contains)) text_changed = 1;
792 g_free(oldfilter->map_contains);
793 } else {
794 text_changed = 1;
795 }
796 oldfilter->map_contains = g_strdup(newfilter->map_contains);
797 if (text_changed) {
798 config_set_string("map_contains", oldfilter->map_contains);
799 filters[FILTER_SERVER].changed = FILTER_CHANGED;
800 }
801 } else {
802 if (oldfilter->map_contains){
803 text_changed = 1; /* From something to nothing */
804 g_free(oldfilter->map_contains);
805 config_set_string("map_contains", "");
806 filters[FILTER_SERVER].changed = FILTER_CHANGED;
807 }
808 oldfilter->map_contains= NULL;
809 } /* end of map filter */
810
811 /* servername string values */
812 text_changed = 0;
813 if (newfilter->server_name_contains && strlen(newfilter->server_name_contains)){
814 /*
815 First case, the user entered something. See if the value
816 is different
817 */
818 if (oldfilter->server_name_contains){
819 if (strcmp(newfilter->server_name_contains, oldfilter->server_name_contains)) text_changed = 1;
820 g_free(oldfilter->server_name_contains);
821 } else {
822 text_changed = 1;
823 }
824 oldfilter->server_name_contains = g_strdup(newfilter->server_name_contains);
825 if (text_changed) {
826 config_set_string("server_name_contains", oldfilter->server_name_contains);
827 filters[FILTER_SERVER].changed = FILTER_CHANGED;
828 }
829 } else {
830 if (oldfilter->server_name_contains){
831 text_changed = 1; /* From something to nothing */
832 g_free(oldfilter->server_name_contains);
833 config_set_string("server_name_contains", "");
834 filters[FILTER_SERVER].changed = FILTER_CHANGED;
835 }
836 oldfilter->server_name_contains = NULL;
837 } /* end of server filter */
838
839 #ifdef USE_GEOIP
840
841 /* country string values */
842
843 if (newfilter->countries->len > 0) {
844 unsigned i;
845 char* buf = NULL;
846 buf = g_new(char,newfilter->countries->len*3);
847
848 for (i = 0; i < newfilter->countries->len; ++i) {
849 const char* code = geoip_code_by_id(g_array_index(newfilter->countries,int,i));
850 if (strlen(code)!=2) code = " "; // may not happen
851 buf[i*3]=code[0];
852 buf[i*3+1]=code[1];
853 buf[i*3+2]=' ';
854 }
855 buf[i*3-1]='\0';
856
857 config_set_string("server_country_contains", buf);
858
859 g_free(buf);
860
861 filters[FILTER_SERVER].changed = FILTER_CHANGED;
862 }
863
864 #endif
865
866
867 if (oldfilter->filter_not_full != newfilter->filter_not_full) {
868 config_set_bool("not full", oldfilter->filter_not_full = newfilter->filter_not_full);
869 filters[FILTER_SERVER].changed = FILTER_CHANGED;
870 }
871
872 if (oldfilter->filter_not_empty != newfilter->filter_not_empty) {
873 config_set_bool("not empty", oldfilter->filter_not_empty = newfilter->filter_not_empty);
874 filters[FILTER_SERVER].changed = FILTER_CHANGED;
875 }
876
877 if (oldfilter->filter_no_cheats != newfilter->filter_no_cheats) {
878 config_set_bool("no cheats", oldfilter->filter_no_cheats = newfilter->filter_no_cheats);
879 filters[FILTER_SERVER].changed = FILTER_CHANGED;
880 }
881
882 if (oldfilter->filter_no_password != newfilter->filter_no_password) {
883 config_set_bool("no password", oldfilter->filter_no_password = newfilter->filter_no_password);
884 filters[FILTER_SERVER].changed = FILTER_CHANGED;
885 }
886 #if 0
887 /* This from the Gtk FAQ, mostly. */
888 if (server_filter_widget[current_server_filter + filter_start_index] &&
889 GTK_BIN(server_filter_widget[current_server_filter + filter_start_index])->child) {
890 GtkWidget *child = GTK_BIN(server_filter_widget[current_server_filter + filter_start_index])->child;
891
892 /* do stuff with child */
893 if (GTK_IS_LABEL(child)) {
894 if (filter->filter_name != NULL && strlen(filter->filter_name)) {
895 gtk_label_set(GTK_LABEL(child), filter->filter_name);
896 } else {
897 /* Reuse the config_secion var */
898 sprintf(config_section, "Filter %d", current_server_filter);
899 gtk_label_set(GTK_LABEL(child), config_section);
900 }
901 }
902 }
903 #endif
904
905 config_pop_prefix ();
906
907 if (filters[FILTER_SERVER].changed == FILTER_CHANGED)
908 filters[FILTER_SERVER].last_changed = filter_time_inc();
909 }
910
911 // store changed widget values
filter_select_callback(GtkWidget * widget,guint number)912 static void filter_select_callback(GtkWidget *widget, guint number) {
913 struct server_filter_vars** filter = NULL;
914 char* name;
915
916 if (server_filter_changed && server_filter_dialog_current_filter > 0) {
917 /*
918 int cont = dialog_yesno(_("Server filter changed"), 1,
919 _("Continue"),
920 _("Cancel"),
921 _("Your changes will be lost if you change server filters now"));
922 if (!cont) {
923 gtk_option_menu_set_history(GTK_OPTION_MENU(filter_option_menu), server_filter_dialog_current_filter-1);
924 return FALSE;
925 }
926 */
927 filter = &g_array_index(server_filters,
928 struct server_filter_vars*, server_filter_dialog_current_filter-1);
929 name = g_strdup((*filter)->filter_name);
930 server_filter_vars_free(*filter);
931 *filter = server_filter_new_from_widgets();
932 (*filter)->filter_name = name;
933 }
934 server_filter_dialog_current_filter = number;
935 server_filter_fill_widgets(number);
936 return;
937 }
938
create_filter_menu()939 static GtkWidget *create_filter_menu() {
940 GtkWidget *menu;
941 GtkWidget *menu_item;
942 guint i;
943 struct server_filter_vars* filter;
944
945 menu = gtk_menu_new();
946
947 // gtk_signal_connect(GTK_OBJECT(menu_item), "activate",
948 // GTK_SIGNAL_FUNC(callback), (gpointer) 0);
949
950 for (i = 0;i<server_filters->len;i++) {
951 filter = g_array_index(server_filters, struct server_filter_vars*, i);
952 if (!filter) {
953 debug(0,"Bug: filter is NULL");
954 continue;
955 }
956 menu_item = gtk_menu_item_new_with_label(filter->filter_name?filter->filter_name:"(null)");
957 gtk_menu_append(GTK_MENU(menu), menu_item);
958 gtk_widget_show(menu_item);
959
960 gtk_signal_connect(GTK_OBJECT(menu_item), "activate",
961 GTK_SIGNAL_FUNC(filter_select_callback), GINT_TO_POINTER(i+1)); // array starts from zero but filters from 1
962 }
963
964 gtk_widget_show (menu);
965
966 return menu;
967 }
968
969 /** create new filter if number == 0, rename current filter number if number >0
970 */
filter_new_rename_callback(int number)971 static void filter_new_rename_callback (int number) {
972 char *str = NULL;
973 struct server_filter_vars* filter = NULL;
974
975 debug(3,"%s %d",str, number);
976
977 // renaming the none filter is not possible
978 if (number && server_filter_dialog_current_filter < 1) return;
979
980 // remember changes
981 if (!number) {
982 filter_select_callback(NULL,server_filter_dialog_current_filter);
983 }
984
985 str = enter_string_dialog(TRUE,_("Enter filter name"));
986
987 if (str && *str) {
988 filters[FILTER_SERVER].changed = FILTER_CHANGED;
989 if (!number) {
990 filter = server_filter_vars_new();
991 filter->filter_name = str;
992 g_array_append_val(server_filters,filter);
993 server_filter_dialog_current_filter = server_filters->len;
994 gtk_widget_grab_focus(GTK_WIDGET(game_contains_entry));
995 }
996 else {
997 filter = g_array_index(server_filters, struct server_filter_vars*, server_filter_dialog_current_filter-1);
998 filter->filter_name = str;
999 }
1000
1001 gtk_option_menu_set_menu(GTK_OPTION_MENU(filter_option_menu), create_filter_menu());
1002
1003 gtk_option_menu_set_history(GTK_OPTION_MENU(filter_option_menu), server_filter_dialog_current_filter-1);
1004 server_filter_fill_widgets(server_filter_dialog_current_filter);
1005
1006 server_filter_changed = TRUE;
1007 }
1008 }
1009
filter_delete_callback(void * dummy)1010 static void filter_delete_callback (void* dummy) {
1011 struct server_filter_vars* filter = NULL;
1012 int cont = 0;
1013
1014 if (server_filter_dialog_current_filter == 0) return;
1015
1016 filter = g_array_index(server_filters, struct server_filter_vars*, server_filter_dialog_current_filter-1);
1017 if (!filter) return;
1018
1019 cont = dialog_yesno(_("Delete server filter"), 1,
1020 _("Yes"),
1021 _("No"),
1022 _("Really delete server filter \"%s\"?"),filter->filter_name);
1023
1024 if (!cont)
1025 return;
1026
1027 filters[FILTER_SERVER].changed = FILTER_CHANGED;
1028 server_filter_deleted = TRUE;
1029
1030 server_filter_vars_free(filter);
1031 g_array_remove_index(server_filters,server_filter_dialog_current_filter-1);
1032 server_filter_dialog_current_filter = server_filters->len;
1033 debug(3,"number of filters: %d",server_filter_dialog_current_filter);
1034
1035 gtk_option_menu_set_menu(GTK_OPTION_MENU(filter_option_menu), create_filter_menu());
1036 gtk_option_menu_set_history(GTK_OPTION_MENU(filter_option_menu), server_filter_dialog_current_filter-1);
1037 server_filter_fill_widgets(server_filter_dialog_current_filter);
1038 /*
1039 for(cont=0;cont<server_filters->len;cont++) {
1040 filter = g_array_index(server_filters, struct server_filter_vars*, cont);
1041 server_filter_print(filter);
1042 }
1043 */
1044 }
1045
1046 /** set all server filter widgets sensitive
1047 */
server_filter_set_widgets_sensitive(gboolean sensitive)1048 static void server_filter_set_widgets_sensitive(gboolean sensitive) {
1049 gtk_widget_set_sensitive(filter_game_type_entry,sensitive);
1050 gtk_widget_set_sensitive(version_contains_entry,sensitive);
1051 gtk_widget_set_sensitive(game_contains_entry,sensitive);
1052 gtk_widget_set_sensitive(map_contains_entry,sensitive);
1053 gtk_widget_set_sensitive(server_name_contains_entry,sensitive);
1054 gtk_widget_set_sensitive(filter_ping_spinner,sensitive);
1055 gtk_widget_set_sensitive(filter_retries_spinner,sensitive);
1056 gtk_widget_set_sensitive(filter_not_full_check_button,sensitive);
1057 gtk_widget_set_sensitive(filter_not_empty_check_button,sensitive);
1058 gtk_widget_set_sensitive(filter_not_full_check_button,sensitive);
1059 gtk_widget_set_sensitive(filter_no_cheats_check_button,sensitive);
1060 gtk_widget_set_sensitive(filter_no_password_check_button,sensitive);
1061 #ifdef USE_GEOIP
1062 if (geoip_is_working()) {
1063 gtk_widget_set_sensitive(country_filter_list, sensitive);
1064 gtk_widget_set_sensitive(scrolledwindow_fcountry, sensitive);
1065 gtk_widget_set_sensitive(country_selection_button, sensitive);
1066 gtk_widget_set_sensitive(country_clear_button, sensitive);
1067 if (!sensitive) {
1068 gtk_clist_clear(GTK_CLIST(country_filter_list));
1069 }
1070 }
1071 #endif
1072 }
1073
server_filter_fill_widgets(guint num)1074 static void server_filter_fill_widgets(guint num) {
1075 struct server_filter_vars* filter = NULL;
1076
1077 gboolean dofree = FALSE;
1078 #ifdef USE_GEOIP
1079 int f_number;
1080 int rw = 0;
1081
1082 struct pixmap* countrypix = NULL;
1083 #endif
1084
1085 if (num > 0) {
1086 filter = g_array_index(server_filters, struct server_filter_vars*, num-1);
1087 if (!filter) {
1088 debug(0,"Bug: filter is NULL");
1089 filter = server_filter_vars_new();
1090 dofree = TRUE;
1091 }
1092 server_filter_set_widgets_sensitive(TRUE);
1093 }
1094 else {
1095 server_filter_set_widgets_sensitive(FALSE);
1096 filter = server_filter_vars_new();
1097 dofree = TRUE;
1098 }
1099
1100 gtk_entry_set_text(GTK_ENTRY(filter_game_type_entry), filter->game_type?filter->game_type:"");
1101 gtk_entry_set_text(GTK_ENTRY(version_contains_entry), filter->version_contains?filter->version_contains:"");
1102 gtk_entry_set_text(GTK_ENTRY(game_contains_entry), filter->game_contains?filter->game_contains:"");
1103 gtk_entry_set_text(GTK_ENTRY(map_contains_entry), filter->map_contains?filter->map_contains:"");
1104 gtk_entry_set_text(GTK_ENTRY(server_name_contains_entry), filter->server_name_contains?filter->server_name_contains:"");
1105 #ifdef USE_GEOIP
1106 gtk_clist_clear(GTK_CLIST(country_filter_list));
1107
1108 last_row_country_list=0;
1109
1110 /*fill the country_filter_list from filter->countries*/
1111 if (geoip_is_working()) {
1112 unsigned i;
1113 gchar buf[64] = {0};
1114 gchar *text[1] = {buf};
1115
1116 if (filter->countries != NULL) {
1117
1118 for (i = 0; i < filter->countries->len; ++i) {
1119
1120 f_number=g_array_index(filter->countries,int,i);
1121
1122 // gtk_clist_insert third parameter is not const!
1123 strncpy(buf,geoip_name_by_id(f_number),sizeof(buf));
1124 gtk_clist_insert(GTK_CLIST(country_filter_list), rw, text);
1125 countrypix = get_pixmap_for_country_with_fallback(f_number);
1126 if (countrypix) {
1127 gtk_clist_set_pixtext(GTK_CLIST(country_filter_list), rw, 0,geoip_name_by_id(f_number), 4,
1128 countrypix->pix, countrypix->mask);
1129 }
1130 gtk_clist_set_row_data(GTK_CLIST(country_filter_list),rw,GINT_TO_POINTER(f_number));
1131
1132 last_row_country_list++;
1133 ++rw;
1134 }
1135 }
1136 }
1137
1138 #endif
1139
1140 gtk_adjustment_set_value(gtk_spin_button_get_adjustment(
1141 GTK_SPIN_BUTTON(filter_ping_spinner)),filter->filter_ping);
1142 gtk_adjustment_set_value(gtk_spin_button_get_adjustment(
1143 GTK_SPIN_BUTTON(filter_retries_spinner)),filter->filter_retries);
1144
1145 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filter_not_full_check_button), filter->filter_not_full);
1146 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filter_not_empty_check_button), filter->filter_not_empty);
1147 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filter_no_cheats_check_button), filter->filter_no_cheats);
1148 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filter_no_password_check_button), filter->filter_no_password);
1149
1150 server_filter_changed = FALSE;
1151
1152 if (dofree == TRUE)
1153 server_filter_vars_free(filter);
1154 }
1155
1156 // set changed flag to status
server_filter_set_changed_callback(int status)1157 static void server_filter_set_changed_callback(int status) {
1158 server_filter_changed = status;
1159 }
1160
server_filter_page(GtkWidget * notebook)1161 static void server_filter_page (GtkWidget *notebook) {
1162 GtkWidget *page_vbox;
1163 GtkWidget *alignment;
1164 GtkWidget *frame;
1165 GtkWidget *table;
1166 GtkWidget *label;
1167 GtkWidget *hbox;
1168 GtkWidget *button;
1169 GtkObject *adj;
1170
1171 #ifdef USE_GEOIP
1172 GtkWidget *vbuttonbox1;
1173 #endif
1174
1175
1176 // char label_buf[64];
1177 int row = 0; /* for auto inserting entry boxes */
1178
1179 cleaned_up = FALSE;
1180
1181 /* One cannot edit the "None" filter */
1182 if (current_server_filter < 0) {
1183 current_server_filter = 0;
1184 debug(0,"invalid filter nr %d", server_filter_dialog_current_filter);
1185 }
1186 else if (current_server_filter > server_filters->len) {
1187 current_server_filter = 1;
1188 debug(0,"invalid filter nr %d", server_filter_dialog_current_filter);
1189 }
1190
1191 server_filter_deleted = FALSE;
1192
1193 server_filter_dialog_current_filter = current_server_filter;
1194
1195 { // back up server filter array
1196 unsigned i;
1197 struct server_filter_vars* filter;
1198 backup_server_filters = g_array_new(FALSE,FALSE, sizeof(struct server_filter_vars*));
1199 // g_array_set_size(backup_server_filters,server_filters->len);
1200
1201 for (i=0;i<server_filters->len;i++) {
1202 filter = server_filter_vars_copy(g_array_index(server_filters, struct server_filter_vars*, i));
1203 g_array_append_val(backup_server_filters, filter);
1204 }
1205 }
1206
1207 page_vbox = gtk_vbox_new(FALSE, 8);
1208 gtk_container_set_border_width(GTK_CONTAINER(page_vbox), 8);
1209
1210 label = gtk_label_new(_("Server Filter"));
1211 gtk_widget_show(label);
1212
1213 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_vbox, label);
1214
1215 hbox = gtk_hbox_new(FALSE, 8);
1216 gtk_box_pack_start(GTK_BOX(page_vbox), hbox, FALSE, FALSE, 0);
1217 gtk_widget_show(hbox);
1218
1219 filter_option_menu = gtk_option_menu_new();
1220 gtk_box_pack_start(GTK_BOX(hbox), filter_option_menu, FALSE, FALSE, 0);
1221 gtk_option_menu_set_menu(GTK_OPTION_MENU(filter_option_menu), create_filter_menu());
1222 gtk_widget_show(filter_option_menu);
1223
1224 button = gtk_button_new_with_label(_("New"));
1225 gtk_widget_set_usize(button, 80, -1);
1226 gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
1227 GTK_SIGNAL_FUNC(filter_new_rename_callback), (gpointer)0);
1228 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1229 gtk_widget_show(button);
1230
1231 button = gtk_button_new_with_label(_("Rename"));
1232 gtk_widget_set_usize(button, 80, -1);
1233 gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
1234 GTK_SIGNAL_FUNC(filter_new_rename_callback), (gpointer)1);
1235 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1236 gtk_widget_show(button);
1237
1238 button = gtk_button_new_with_label(_("Delete"));
1239 gtk_widget_set_usize(button, 80, -1);
1240 gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
1241 GTK_SIGNAL_FUNC(filter_delete_callback), NULL);
1242 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1243 gtk_widget_show(button);
1244
1245 frame = gtk_frame_new(_("Server would pass filter if"));
1246 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
1247 gtk_box_pack_start(GTK_BOX(page_vbox), frame, FALSE, FALSE, 0);
1248
1249 alignment = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
1250 gtk_container_add(GTK_CONTAINER(frame), alignment);
1251
1252 #ifdef USE_GEOIP
1253 table = gtk_table_new(8, 5, FALSE);
1254 #else
1255 table = gtk_table_new(6, 5, FALSE);
1256 #endif
1257
1258 gtk_table_set_row_spacings(GTK_TABLE(table), 2);
1259 gtk_table_set_col_spacings(GTK_TABLE(table), 4);
1260 gtk_container_set_border_width(GTK_CONTAINER(table), 6);
1261 gtk_container_add(GTK_CONTAINER(alignment), table);
1262
1263 /* row=0..1 */
1264
1265 /* max ping */
1266 label = gtk_label_new(_("ping is less than"));
1267 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
1268 gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_FILL, GTK_FILL, 0, 0);
1269 gtk_widget_show(label);
1270
1271 adj = gtk_adjustment_new(MAX_PING, 0.0, MAX_PING, 100.0, 1000.0, 0.0);
1272
1273 filter_ping_spinner = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0, 0);
1274 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(filter_ping_spinner),
1275 GTK_UPDATE_ALWAYS);
1276 gtk_widget_set_usize(filter_ping_spinner, 64, -1);
1277 gtk_signal_connect_object(GTK_OBJECT(filter_ping_spinner), "changed",
1278 GTK_SIGNAL_FUNC(server_filter_set_changed_callback),(gpointer) TRUE);
1279 gtk_table_attach_defaults(GTK_TABLE(table), filter_ping_spinner, 1, 2, row, row+1);
1280 gtk_widget_show(filter_ping_spinner);
1281
1282
1283 /* GAMECONTAINS Filter -- baa */
1284 /* http://developer.gnome.org/doc/API/gtk/gtktable.html */
1285
1286 label = gtk_label_new(_("the game contains the string"));
1287 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
1288 gtk_table_attach(GTK_TABLE(table), label, 3, 4, row, row+1, GTK_FILL, GTK_FILL, 0, 0);
1289 gtk_widget_show(label);
1290 game_contains_entry = gtk_entry_new_with_max_length(32);
1291 gtk_widget_set_usize(game_contains_entry, 64, -1);
1292 gtk_entry_set_editable(GTK_ENTRY(game_contains_entry), TRUE);
1293 gtk_signal_connect_object(GTK_OBJECT(game_contains_entry), "changed",
1294 GTK_SIGNAL_FUNC(server_filter_set_changed_callback), (gpointer) TRUE);
1295
1296 gtk_table_attach_defaults(GTK_TABLE(table), game_contains_entry, 4, 5, row, row+1);
1297 gtk_widget_show(game_contains_entry);
1298 row++;
1299
1300
1301 /* row=1..2*/
1302
1303 /* max timeouts */
1304 label = gtk_label_new(_("the number of retries is fewer than"));
1305 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
1306 gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_FILL, GTK_FILL,
1307 0, 0);
1308 gtk_widget_show(label);
1309
1310 adj = gtk_adjustment_new(2, 0.0, MAX_RETRIES, 1.0, 1.0, 0.0);
1311
1312 filter_retries_spinner = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0, 0);
1313 gtk_widget_set_usize(filter_retries_spinner, 64, -1);
1314 gtk_signal_connect_object(GTK_OBJECT(filter_retries_spinner), "changed",
1315 GTK_SIGNAL_FUNC(server_filter_set_changed_callback), (gpointer) TRUE);
1316 gtk_table_attach_defaults(GTK_TABLE(table), filter_retries_spinner,
1317 1, 2, row, row+1);
1318 gtk_widget_show(filter_retries_spinner);
1319
1320 /* GAMETYPE Filter -- baa */
1321 /* http://developer.gnome.org/doc/API/gtk/gtktable.html */
1322
1323 label = gtk_label_new(_("the game type contains the string"));
1324 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
1325 gtk_table_attach(GTK_TABLE(table), label, 3, 4, row, row+1, GTK_FILL, GTK_FILL, 0, 0);
1326 gtk_widget_show(label);
1327 filter_game_type_entry = gtk_entry_new_with_max_length(32);
1328 gtk_widget_set_usize(filter_game_type_entry, 64, -1);
1329 gtk_entry_set_editable(GTK_ENTRY(filter_game_type_entry), TRUE);
1330 gtk_signal_connect_object(GTK_OBJECT(filter_game_type_entry), "changed",
1331 GTK_SIGNAL_FUNC(server_filter_set_changed_callback), (gpointer) TRUE);
1332
1333 gtk_table_attach_defaults(GTK_TABLE(table), filter_game_type_entry, 4, 5, row, row+1);
1334 gtk_widget_show(filter_game_type_entry);
1335 row++;
1336
1337 /*row=2..3*/
1338
1339 /*not full */
1340 filter_not_full_check_button =gtk_check_button_new_with_label(_("it is not full"));
1341 gtk_signal_connect_object(GTK_OBJECT(filter_not_full_check_button),"toggled",
1342 GTK_SIGNAL_FUNC(server_filter_set_changed_callback), (gpointer) TRUE);
1343 gtk_table_attach_defaults(GTK_TABLE(table),filter_not_full_check_button, 0, 2, row, row+1);
1344 gtk_widget_show(filter_not_full_check_button);
1345
1346 /* Version Filter -- baa */
1347 label = gtk_label_new(_("the version contains the string"));
1348 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
1349 gtk_table_attach(GTK_TABLE(table), label, 3, 4, row, row+1, GTK_FILL, GTK_FILL,
1350 0, 0);
1351 gtk_widget_show(label);
1352 version_contains_entry = gtk_entry_new_with_max_length(32);
1353 gtk_widget_set_usize(version_contains_entry, 64, -1);
1354 gtk_entry_set_editable(GTK_ENTRY(version_contains_entry), TRUE);
1355 gtk_signal_connect_object(GTK_OBJECT(version_contains_entry), "changed",
1356 GTK_SIGNAL_FUNC(server_filter_set_changed_callback), (gpointer) TRUE);
1357
1358 gtk_table_attach_defaults(GTK_TABLE(table), version_contains_entry, 4, 5, row, row+1);
1359 gtk_widget_show(version_contains_entry);
1360 row++;
1361
1362 /*row=3..4*/
1363
1364 /* not empty */
1365 filter_not_empty_check_button =
1366 gtk_check_button_new_with_label(_("it is not empty"));
1367 gtk_signal_connect_object(GTK_OBJECT(filter_not_empty_check_button), "toggled",
1368 GTK_SIGNAL_FUNC(server_filter_set_changed_callback), (gpointer) TRUE);
1369 gtk_table_attach_defaults(GTK_TABLE(table), filter_not_empty_check_button,
1370 0, 2, row, row+1);
1371 gtk_widget_show(filter_not_empty_check_button);
1372
1373
1374 /* Map filter*/
1375 label = gtk_label_new(_("the map contains the string"));
1376 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
1377 gtk_table_attach(GTK_TABLE(table), label, 3, 4, row, row+1, GTK_FILL, GTK_FILL, 0, 0);
1378 gtk_widget_show(label);
1379 map_contains_entry = gtk_entry_new_with_max_length(32);
1380 gtk_widget_set_usize(map_contains_entry, 64, -1);
1381 gtk_entry_set_editable(GTK_ENTRY(map_contains_entry), TRUE);
1382 gtk_signal_connect_object(GTK_OBJECT(map_contains_entry), "changed",
1383 GTK_SIGNAL_FUNC(server_filter_set_changed_callback), (gpointer) TRUE);
1384
1385 gtk_table_attach_defaults(GTK_TABLE(table), map_contains_entry, 4, 5, row, row+1);
1386 gtk_widget_show(map_contains_entry);
1387 row++;
1388
1389 /*row=4..5*/
1390
1391 /* no cheats */
1392 filter_no_cheats_check_button =
1393 gtk_check_button_new_with_label(_("cheats are not allowed"));
1394 gtk_signal_connect_object(GTK_OBJECT(filter_no_cheats_check_button), "toggled",
1395 GTK_SIGNAL_FUNC(server_filter_set_changed_callback), (gpointer) TRUE);
1396 gtk_table_attach_defaults(GTK_TABLE(table), filter_no_cheats_check_button, 0, 2, row, row+1);
1397 gtk_widget_show(filter_no_cheats_check_button);
1398
1399
1400 /* Server name filter*/
1401 label = gtk_label_new(_("the server name contains the string"));
1402 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
1403 gtk_table_attach(GTK_TABLE(table), label, 3, 4, row, row+1, GTK_FILL, GTK_FILL, 0, 0);
1404 gtk_widget_show(label);
1405 server_name_contains_entry = gtk_entry_new_with_max_length(32);
1406 gtk_widget_set_usize(server_name_contains_entry, 64, -1);
1407 gtk_entry_set_editable(GTK_ENTRY(server_name_contains_entry), TRUE);
1408 gtk_signal_connect_object(GTK_OBJECT(server_name_contains_entry), "changed",
1409 GTK_SIGNAL_FUNC(server_filter_set_changed_callback), (gpointer) TRUE);
1410
1411 gtk_table_attach_defaults(GTK_TABLE(table),server_name_contains_entry , 4, 5, row, row+1);
1412 gtk_widget_show(server_name_contains_entry);
1413 row++;
1414
1415 /*row=5..6*/
1416
1417 /* no password */
1418 filter_no_password_check_button =
1419 gtk_check_button_new_with_label(_("no password required"));
1420 gtk_signal_connect_object(GTK_OBJECT(filter_no_password_check_button), "toggled",
1421 GTK_SIGNAL_FUNC(server_filter_set_changed_callback), (gpointer) TRUE);
1422 gtk_table_attach_defaults(GTK_TABLE(table), filter_no_password_check_button, 0, 2, row, row+1);
1423 gtk_widget_show(filter_no_password_check_button);
1424
1425 row++;
1426
1427 /*country list */
1428 #ifdef USE_GEOIP
1429 label = gtk_label_new(_("Country filter:"));
1430 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 6, 7);
1431 gtk_misc_set_padding(GTK_MISC(label), 0, 15);
1432 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
1433 gtk_widget_show(label);
1434
1435 scrolledwindow_fcountry = gtk_scrolled_window_new(NULL, NULL);
1436 gtk_widget_set_sensitive(scrolledwindow_fcountry,FALSE);
1437 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW
1438 (scrolledwindow_fcountry),
1439 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1440
1441 country_filter_list = gtk_clist_new(1);
1442 gtk_clist_set_shadow_type(GTK_CLIST(country_filter_list),GTK_SHADOW_NONE);
1443 gtk_widget_set_sensitive(country_filter_list,FALSE);
1444
1445
1446 gtk_clist_set_column_justification(GTK_CLIST(country_filter_list), 0,
1447 GTK_JUSTIFY_LEFT);
1448 gtk_clist_set_column_width(GTK_CLIST(country_filter_list), 0, 100);
1449 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW
1450 (scrolledwindow_fcountry),
1451 country_filter_list);
1452
1453 gtk_widget_set_usize(scrolledwindow_fcountry, 100, 100);
1454
1455 gtk_table_attach_defaults(GTK_TABLE(table), scrolledwindow_fcountry, 0, 1, 7, 8);
1456 gtk_widget_show(scrolledwindow_fcountry);
1457 gtk_widget_show(country_filter_list);
1458
1459 /*select and clear buttons */
1460 vbuttonbox1 = gtk_vbutton_box_new();
1461 gtk_widget_show(vbuttonbox1);
1462 gtk_table_attach_defaults(GTK_TABLE(table), vbuttonbox1, 1, 2, 7, 8);
1463 gtk_button_box_set_layout(GTK_BUTTON_BOX(vbuttonbox1),
1464 GTK_BUTTONBOX_START);
1465 gtk_button_box_set_spacing(GTK_BUTTON_BOX(vbuttonbox1), 1);
1466 gtk_button_box_set_child_size(GTK_BUTTON_BOX(vbuttonbox1), 80, 0);
1467 gtk_button_box_set_child_ipadding(GTK_BUTTON_BOX(vbuttonbox1), 5, -1);
1468
1469 country_selection_button = gtk_button_new_with_label(_("select..."));
1470 gtk_widget_set_sensitive(country_selection_button,FALSE);
1471 gtk_widget_show(country_selection_button);
1472 gtk_container_add(GTK_CONTAINER(vbuttonbox1),
1473 country_selection_button);
1474 gtk_widget_set_usize(country_selection_button, 80, -1);
1475 gtk_signal_connect(GTK_OBJECT(country_selection_button), "clicked",
1476 GTK_SIGNAL_FUNC(country_select_button_pressed), NULL);
1477
1478 gtk_signal_connect_object(GTK_OBJECT(country_selection_button), "clicked",
1479 GTK_SIGNAL_FUNC(server_filter_set_changed_callback), (gpointer) TRUE);
1480
1481
1482 country_clear_button = gtk_button_new_with_label(_("clear"));
1483 gtk_widget_set_sensitive(country_clear_button,FALSE);
1484 gtk_signal_connect(GTK_OBJECT(country_clear_button), "clicked",
1485 GTK_SIGNAL_FUNC(country_clear_list), NULL);
1486 gtk_signal_connect_object(GTK_OBJECT(country_clear_button), "clicked",
1487 GTK_SIGNAL_FUNC(server_filter_set_changed_callback), (gpointer) TRUE);
1488
1489
1490 gtk_widget_show(country_clear_button);
1491 gtk_container_add(GTK_CONTAINER(vbuttonbox1), country_clear_button);
1492 gtk_widget_set_usize(country_clear_button, 80, -1);
1493 #endif
1494
1495 gtk_widget_show(table);
1496 gtk_widget_show(alignment);
1497 gtk_widget_show(frame);
1498 gtk_widget_show(page_vbox);
1499
1500 gtk_option_menu_set_history(GTK_OPTION_MENU(filter_option_menu), server_filter_dialog_current_filter-1);
1501 server_filter_fill_widgets(server_filter_dialog_current_filter);
1502 }
1503
filters_on_ok(void)1504 static void filters_on_ok (void) {
1505 int i;
1506 cleaned_up = TRUE;
1507 for (i = 0; i < FILTERS_TOTAL; i++) {
1508 if (filters[i].filter_on_ok)
1509 (*filters[i].filter_on_ok)();
1510 }
1511 }
1512
filters_on_cancel(void)1513 static void filters_on_cancel (void) {
1514 int i;
1515
1516 // ok was pressed
1517 if (cleaned_up) return;
1518
1519 for (i = 0; i < FILTERS_TOTAL; i++) {
1520 if (filters[i].filter_on_cancel)
1521 (*filters[i].filter_on_cancel)();
1522 }
1523 }
1524
filters_cfg_dialog(int page_num)1525 int filters_cfg_dialog (int page_num) {
1526 GtkWidget *vbox;
1527 GtkWidget *hbox;
1528 GtkWidget *notebook;
1529 GtkWidget *button;
1530 GtkWidget *window;
1531 int changed = FALSE;
1532 int i;
1533
1534 #ifdef DEBUG
1535 const char *flt_status[3] = { "not changed", "changed", "data changed" };
1536 #endif
1537
1538 window = dialog_create_modal_transient_window(_("XQF: Filters"),
1539 TRUE, TRUE, filters_on_cancel);
1540 vbox = gtk_vbox_new(FALSE, 8);
1541 gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
1542 gtk_container_add(GTK_CONTAINER(window), vbox);
1543
1544 /*
1545 * Notebook
1546 */
1547
1548 notebook = gtk_notebook_new();
1549 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
1550 gtk_notebook_set_tab_hborder(GTK_NOTEBOOK(notebook), 4);
1551 gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
1552
1553 server_filter_page(notebook);
1554
1555 player_filter_page(notebook);
1556
1557 gtk_widget_show(notebook);
1558
1559 /*
1560 * Buttons at the bottom
1561 */
1562
1563 hbox = gtk_hbox_new(FALSE, 8);
1564 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1565
1566 button = gtk_button_new_with_label(_("Cancel"));
1567 gtk_widget_set_usize(button, 80, -1);
1568 /* gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
1569 GTK_SIGNAL_FUNC(filters_on_cancel), NULL);
1570 */
1571 gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
1572 GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(window));
1573 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1574 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1575 gtk_widget_show(button);
1576
1577 button = gtk_button_new_with_label(_("OK"));
1578 gtk_widget_set_usize(button, 80, -1);
1579 gtk_signal_connect(GTK_OBJECT(button), "clicked",
1580 GTK_SIGNAL_FUNC(filters_on_ok), NULL);
1581 gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
1582 GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(window));
1583 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1584 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1585 gtk_widget_grab_default(button);
1586 gtk_widget_show(button);
1587
1588 gtk_widget_show(hbox);
1589
1590 gtk_widget_show(vbox);
1591
1592 gtk_widget_show(window);
1593
1594 for (i = 0; i < FILTERS_TOTAL; i++)
1595 filters[i].changed = FILTER_NOT_CHANGED;
1596
1597 gtk_notebook_set_page(GTK_NOTEBOOK(notebook), page_num);
1598
1599 gtk_main();
1600
1601 unregister_window(window);
1602
1603 player_filter_cfg_clean_up();
1604
1605 #ifdef DEBUG
1606 for (i = 0; i < FILTERS_TOTAL; i++) {
1607 fprintf (stderr, "%s Filter (%d): %s\n", filters[i].name, i,
1608 flt_status[filters[i].changed]);
1609 }
1610 #endif
1611
1612 for (i = 0; i < FILTERS_TOTAL; i++) {
1613 if (filters[i].changed == FILTER_CHANGED) {
1614 changed = TRUE;
1615 break;
1616 }
1617 }
1618
1619 return changed;
1620 }
1621
1622
filters_init(void)1623 void filters_init (void) {
1624 int i;
1625
1626 for (i = 0; i < FILTERS_TOTAL; i++) {
1627 if (filters[i].filter_init)
1628 (*filters[i].filter_init)();
1629 }
1630 }
1631
1632
filters_done(void)1633 void filters_done (void) {
1634 int i;
1635
1636 for (i = 0; i < FILTERS_TOTAL; i++) {
1637 if (filters[i].filter_done)
1638 (*filters[i].filter_done)();
1639 }
1640 }
1641
1642 #ifdef USE_GEOIP
1643 /*
1644 *
1645 * country filter stuff
1646 *
1647 */
1648
1649 /* callback: row selection left list*/
country_selection_left_list(GtkWidget * list,gint row_select,gint column,GdkEventButton * event,gpointer data)1650 void country_selection_left_list(GtkWidget * list,
1651 gint row_select,
1652 gint column,
1653 GdkEventButton * event, gpointer data) {
1654 selected_row_left_list = row_select;
1655 return;
1656 }
1657
1658 /* callback: row selection right list*/
country_selection_right_list(GtkWidget * list,gint row_select,gint column,GdkEventButton * event,gpointer data)1659 void country_selection_right_list(GtkWidget * list,
1660 gint row_select,
1661 gint column,
1662 GdkEventButton * event, gpointer data) {
1663 selected_row_right_list = row_select;
1664 return;
1665 }
1666
1667 /* callback: no row is selected*/
country_unselection_right_list(GtkWidget * list,gint row_select,gint column,GdkEventButton * event,gpointer data)1668 void country_unselection_right_list(GtkWidget * list,
1669 gint row_select,
1670 gint column,
1671 GdkEventButton * event, gpointer data) {
1672 selected_row_right_list = -1;
1673 return;
1674 }
1675
1676 /* show the country selection popup window*/
country_select_button_pressed(GtkWidget * widget,gpointer data)1677 static void country_select_button_pressed(GtkWidget * widget, gpointer data) {
1678 country_create_popup_window();
1679 }
1680
1681 /* callback: clear button*/
country_clear_list(GtkWidget * widget,gpointer data)1682 static void country_clear_list(GtkWidget * widget, gpointer data) {
1683 gtk_clist_clear(GTK_CLIST(country_filter_list));
1684 last_row_country_list=0;
1685 }
1686
1687 /** add the country selected in the left list to the right list */
country_add_selection_to_right_list()1688 static void country_add_selection_to_right_list() {
1689 gint i;
1690 gint flag_id;
1691 gchar buf[64] = {0};
1692 gchar *text[1] = {buf};
1693 struct pixmap* countrypix = NULL;
1694
1695 if (selected_row_left_list < 0)
1696 return;
1697
1698 flag_id = GPOINTER_TO_INT(gtk_clist_get_row_data(GTK_CLIST(country_left_list),
1699 selected_row_left_list));
1700
1701 /* do nothing if country is already in right list */
1702 for (i = 0; i < last_row_right_list; i++)
1703 if (flag_id == GPOINTER_TO_INT(gtk_clist_get_row_data(GTK_CLIST(country_right_list), i)))
1704 return;
1705
1706 countrypix = get_pixmap_for_country(flag_id);
1707
1708 // gtk_clist_insert third parameter is not const!
1709 strncpy(buf,geoip_name_by_id(flag_id),sizeof(buf));
1710 gtk_clist_append(GTK_CLIST(country_right_list), text);
1711 if (countrypix) {
1712 gtk_clist_set_pixtext(GTK_CLIST(country_right_list), last_row_right_list, 0,
1713 geoip_name_by_id(flag_id), 4, countrypix->pix, countrypix->mask);
1714 }
1715
1716 gtk_clist_set_row_data(GTK_CLIST(country_right_list), last_row_right_list,
1717 GINT_TO_POINTER(flag_id));
1718
1719 ++last_row_right_list;
1720 }
1721
1722 /* callback: >> button*/
country_add_button(GtkWidget * widget,gpointer data)1723 static void country_add_button(GtkWidget * widget, gpointer data) {
1724 country_add_selection_to_right_list();
1725 }
1726
1727 /* callback: << button*/
country_delete_button(GtkWidget * widget,gpointer data)1728 static void country_delete_button(GtkWidget * widget, gpointer data) {
1729
1730 if ((selected_row_right_list != -1) && (last_row_right_list > 0)) {
1731 gtk_clist_remove(GTK_CLIST(country_right_list), selected_row_right_list);
1732 last_row_right_list--;
1733 }
1734 }
1735
1736
1737 /** callback: double click on row */
country_mouse_click_left_list(GtkWidget * widget,GdkEventButton * event,gpointer func_data)1738 gint country_mouse_click_left_list(GtkWidget * widget,
1739 GdkEventButton * event,
1740 gpointer func_data) {
1741 if ((event->type == GDK_2BUTTON_PRESS) && (event->button==1)) {
1742 country_add_selection_to_right_list();
1743 }
1744
1745 return FALSE;
1746 }
1747
1748 /** callback: double click on row*/
country_mouse_click_right_list(GtkWidget * widget,GdkEventButton * event,gpointer func_data)1749 gint country_mouse_click_right_list(GtkWidget * widget,
1750 GdkEventButton * event,
1751 gpointer func_data) {
1752
1753 if ((event->type == GDK_2BUTTON_PRESS) && (event->button==1)) {
1754 country_delete_button(NULL,NULL);
1755 }
1756
1757 return FALSE;
1758 }
1759
1760 /* callback: ready with country selection*/
country_selection_on_ok(void)1761 static void country_selection_on_ok(void) {
1762 int i;
1763 gint country_nr;
1764 gchar buf[64] = {0};
1765 gchar *text[1] = {buf};
1766
1767 struct pixmap* countrypix = NULL;
1768
1769 selected_row_right_list=-1;
1770 gtk_clist_freeze(GTK_CLIST(country_filter_list));
1771 gtk_clist_clear(GTK_CLIST(country_filter_list));
1772
1773 for (i = 0; i < last_row_right_list; ++i) {
1774 country_nr = GPOINTER_TO_INT(gtk_clist_get_row_data(GTK_CLIST(country_right_list), i));
1775
1776 countrypix = get_pixmap_for_country(country_nr);
1777
1778 // gtk_clist_insert third parameter is not const!
1779 strncpy(buf,geoip_name_by_id(country_nr),sizeof(buf));
1780 gtk_clist_insert(GTK_CLIST(country_filter_list), i, text);
1781 if (countrypix) {
1782 gtk_clist_set_pixtext(GTK_CLIST(country_filter_list), i, 0,
1783 text[0], 4,countrypix->pix,countrypix->mask);
1784 }
1785 gtk_clist_set_row_data(GTK_CLIST(country_filter_list),i,GINT_TO_POINTER(country_nr));
1786
1787 }
1788 gtk_clist_thaw(GTK_CLIST(country_filter_list));
1789 last_row_country_list=last_row_right_list;
1790 }
1791
country_selection_on_cancel(void)1792 static void country_selection_on_cancel(void) {
1793 selected_row_right_list=-1;
1794 }
1795
1796 /** populate a clist with country names&flags
1797 * @param clist the clist
1798 * @param all if false only show countries that have a flag
1799 */
populate_country_clist(GtkWidget * clist,gboolean all)1800 static void populate_country_clist(GtkWidget* clist, gboolean all) {
1801 struct pixmap* countrypix = NULL;
1802 int row_number = -1;
1803 unsigned i;
1804 gchar buf[64] = {0};
1805 gchar *text[1] = {buf};
1806
1807 g_return_if_fail(GTK_IS_CLIST(clist));
1808
1809 gtk_clist_freeze(GTK_CLIST(clist));
1810
1811 gtk_clist_clear(GTK_CLIST(clist));
1812
1813 for (i = 0; i <= geoip_num_countries(); ++i) {
1814 if (all)
1815 countrypix = get_pixmap_for_country_with_fallback(i);
1816 else
1817 countrypix = get_pixmap_for_country(i);
1818
1819 if (!all && !countrypix)
1820 continue;
1821
1822 ++row_number;
1823
1824 // gtk_clist_insert third parameter is not const!
1825 strncpy(buf,geoip_name_by_id(i),sizeof(buf));
1826 gtk_clist_insert(GTK_CLIST(clist), row_number, text);
1827 if (countrypix) {
1828 gtk_clist_set_pixtext(GTK_CLIST(clist), row_number, 0,
1829 geoip_name_by_id(i), 4,
1830 countrypix->pix,
1831 countrypix->mask);
1832 }
1833
1834 /* save the flag number */
1835 gtk_clist_set_row_data(GTK_CLIST(clist),
1836 row_number, GINT_TO_POINTER(i));
1837 }
1838
1839 gtk_clist_thaw(GTK_CLIST(clist));
1840 }
1841
country_show_all_changed_callback(GtkWidget * widget,GtkWidget * clist)1842 static void country_show_all_changed_callback (GtkWidget *widget, GtkWidget *clist) {
1843 populate_country_clist(clist,gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1844 }
1845
1846 /* country selection window */
country_create_popup_window(void)1847 static void country_create_popup_window(void) {
1848 GtkWidget *country_popup_window;
1849 GtkWidget *vbox1;
1850 GtkWidget *vbox2;
1851 GtkWidget *frame1;
1852 GtkWidget *hbox1;
1853 GtkWidget *scrolledwindow1;
1854
1855
1856 GtkWidget *vbuttonbox1;
1857 GtkWidget *button3;
1858 GtkWidget *button4;
1859 GtkWidget *scrolledwindow2;
1860
1861
1862 GtkWidget *hbuttonbox1;
1863 GtkWidget *button1;
1864 GtkWidget *button2;
1865
1866 int i;
1867 int flag_nr;
1868 gchar buf[64] = {0};
1869 gchar *text[1] = {buf};
1870
1871 struct pixmap* countrypix = NULL;
1872
1873 /* window caption for country filter */
1874 country_popup_window = dialog_create_modal_transient_window(_("Configure Country Filter"),
1875 TRUE, TRUE,
1876 country_selection_on_cancel);
1877 gtk_widget_set_usize(GTK_WIDGET(country_popup_window), 480, 320);
1878
1879 vbox1 = gtk_vbox_new(FALSE, 0);
1880 gtk_widget_show(vbox1);
1881 gtk_container_add(GTK_CONTAINER(country_popup_window), vbox1);
1882
1883 frame1 = gtk_frame_new(_("Country filter:"));
1884 gtk_widget_show(frame1);
1885 gtk_box_pack_start(GTK_BOX(vbox1), frame1, TRUE, TRUE, 0);
1886 gtk_container_set_border_width(GTK_CONTAINER(frame1), 4);
1887
1888 vbox2 = gtk_vbox_new(FALSE, 0);
1889 gtk_widget_show(vbox2);
1890 gtk_container_add(GTK_CONTAINER(frame1), vbox2);
1891 gtk_container_set_border_width(GTK_CONTAINER(frame1), 4);
1892
1893
1894 hbox1 = gtk_hbox_new(FALSE, 0);
1895 gtk_widget_show(hbox1);
1896 gtk_box_pack_start(GTK_BOX(vbox2), hbox1, TRUE, TRUE, 0);
1897
1898 /* left clist */
1899 scrolledwindow1 = gtk_scrolled_window_new(NULL, NULL);
1900 gtk_container_set_border_width(GTK_CONTAINER(scrolledwindow1), 8);
1901 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow1),
1902 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
1903 country_left_list = gtk_clist_new(1);
1904 gtk_clist_set_shadow_type(GTK_CLIST(country_left_list),GTK_SHADOW_NONE);
1905 gtk_clist_set_selection_mode(GTK_CLIST(country_left_list), GTK_SELECTION_SINGLE);
1906 gtk_clist_set_column_justification(GTK_CLIST(country_left_list), 0,
1907 GTK_JUSTIFY_LEFT);
1908 gtk_clist_set_column_width(GTK_CLIST(country_left_list), 0, 100);
1909
1910
1911 gtk_signal_connect(GTK_OBJECT(country_left_list), "select_row",
1912 GTK_SIGNAL_FUNC(country_selection_left_list),
1913 NULL);
1914
1915
1916 gtk_signal_connect(GTK_OBJECT(country_left_list), "button_press_event",
1917 GTK_SIGNAL_FUNC(country_mouse_click_left_list),
1918 NULL);
1919
1920 /* fill the list with all countries if the flag is available*/
1921
1922 populate_country_clist(country_left_list, FALSE);
1923
1924 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolledwindow1),
1925 GTK_WIDGET(country_left_list));
1926 gtk_box_pack_start(GTK_BOX(hbox1), scrolledwindow1, TRUE, TRUE, 0);
1927 gtk_widget_show(scrolledwindow1);
1928 gtk_widget_show(country_left_list);
1929
1930 /* >> and << buttons */
1931
1932 /* >> */
1933 vbuttonbox1 = gtk_vbutton_box_new();
1934 gtk_widget_show(vbuttonbox1);
1935 gtk_box_pack_start(GTK_BOX(hbox1), vbuttonbox1, FALSE, TRUE, 0);
1936 gtk_button_box_set_layout(GTK_BUTTON_BOX(vbuttonbox1),
1937 GTK_BUTTONBOX_SPREAD);
1938 gtk_button_box_set_spacing(GTK_BUTTON_BOX(vbuttonbox1), 0);
1939 // gtk_button_box_set_child_size(GTK_BUTTON_BOX(vbuttonbox1), 63, -1);
1940
1941 button3 = gtk_button_new_with_label(">>");
1942 gtk_signal_connect(GTK_OBJECT(button3), "clicked",
1943 GTK_SIGNAL_FUNC(country_add_button), NULL);
1944 gtk_widget_show(button3);
1945 gtk_container_add(GTK_CONTAINER(vbuttonbox1), button3);
1946 GTK_WIDGET_SET_FLAGS(button3, GTK_CAN_DEFAULT);
1947
1948
1949 /* << */
1950 button4 = gtk_button_new_with_label("<<");
1951 gtk_signal_connect(GTK_OBJECT(button4), "clicked",
1952 GTK_SIGNAL_FUNC(country_delete_button), NULL);
1953 gtk_widget_show(button4);
1954 gtk_container_add(GTK_CONTAINER(vbuttonbox1), button4);
1955 GTK_WIDGET_SET_FLAGS(button4, GTK_CAN_DEFAULT);
1956
1957
1958 /* right clist */
1959 scrolledwindow2 = gtk_scrolled_window_new(NULL, NULL);
1960 gtk_container_set_border_width(GTK_CONTAINER(scrolledwindow2), 8);
1961 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow2),
1962 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1963 country_right_list = gtk_clist_new(1);
1964 gtk_clist_set_shadow_type(GTK_CLIST(country_right_list),GTK_SHADOW_NONE);
1965 gtk_clist_set_selection_mode(GTK_CLIST(country_right_list), GTK_SELECTION_SINGLE);
1966
1967 gtk_clist_set_column_justification(GTK_CLIST(country_right_list), 0,
1968 GTK_JUSTIFY_LEFT);
1969 gtk_clist_set_column_width(GTK_CLIST(country_right_list), 0, 100);
1970
1971
1972 gtk_signal_connect(GTK_OBJECT(country_right_list), "select_row",
1973 GTK_SIGNAL_FUNC(country_selection_right_list),
1974 NULL);
1975
1976 gtk_signal_connect(GTK_OBJECT(country_right_list), "unselect_row",
1977 GTK_SIGNAL_FUNC(country_unselection_right_list),
1978 NULL);
1979
1980 gtk_signal_connect(GTK_OBJECT(country_right_list), "button_press_event",
1981 GTK_SIGNAL_FUNC(country_mouse_click_right_list),
1982 NULL);
1983
1984
1985 /* fill the clist with the same countries as in country_filter_list */
1986
1987 for (i = 0; i<last_row_country_list;i++) {
1988
1989 flag_nr=GPOINTER_TO_INT(gtk_clist_get_row_data(GTK_CLIST(country_filter_list), i));
1990
1991 countrypix = get_pixmap_for_country_with_fallback(flag_nr);
1992
1993 // gtk_clist_insert third parameter is not const!
1994 strncpy(buf,geoip_name_by_id(flag_nr),sizeof(buf));
1995 gtk_clist_insert(GTK_CLIST(country_right_list),i, text);
1996 if (countrypix) {
1997 gtk_clist_set_pixtext(GTK_CLIST(country_right_list),i, 0,
1998 geoip_name_by_id(flag_nr), 4,
1999 countrypix->pix,countrypix->mask);
2000 }
2001
2002 gtk_clist_set_row_data(GTK_CLIST(country_right_list),i,GINT_TO_POINTER(flag_nr));
2003
2004 }
2005
2006 last_row_right_list=last_row_country_list;
2007
2008
2009 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW
2010 (scrolledwindow2), country_right_list);
2011 gtk_box_pack_start(GTK_BOX(hbox1), scrolledwindow2, TRUE, TRUE, 0);
2012 gtk_widget_show(scrolledwindow2);
2013 gtk_widget_show(country_right_list);
2014
2015 country_show_all_check_button = gtk_check_button_new_with_label(_("Show all countries"));
2016 gtk_signal_connect(GTK_OBJECT(country_show_all_check_button),"toggled",
2017 GTK_SIGNAL_FUNC(country_show_all_changed_callback), (gpointer) country_left_list);
2018 gtk_widget_show(country_show_all_check_button);
2019 gtk_box_pack_start(GTK_BOX(vbox2), country_show_all_check_button, FALSE, FALSE, 0);
2020 gtk_container_set_border_width(GTK_CONTAINER(country_show_all_check_button), 4);
2021
2022 /* OK and Cancel buttons */
2023 hbuttonbox1 = gtk_hbutton_box_new();
2024
2025
2026 gtk_widget_show(hbuttonbox1);
2027 gtk_box_pack_start(GTK_BOX(vbox1), hbuttonbox1, FALSE, TRUE, 0);
2028 gtk_container_set_border_width(GTK_CONTAINER(hbuttonbox1), 4);
2029 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbuttonbox1),
2030 GTK_BUTTONBOX_END);
2031 gtk_button_box_set_spacing(GTK_BUTTON_BOX(hbuttonbox1), 1);
2032 // gtk_button_box_set_child_size(GTK_BUTTON_BOX(hbuttonbox1), 79, 38);
2033
2034 button1 = gtk_button_new_with_label(_("OK"));
2035 // gtk_widget_set_usize(button1, 80, -1);
2036 gtk_signal_connect(GTK_OBJECT(button1), "clicked",
2037 GTK_SIGNAL_FUNC(country_selection_on_ok), NULL);
2038 gtk_signal_connect_object(GTK_OBJECT(button1), "clicked",
2039 GTK_SIGNAL_FUNC(gtk_widget_destroy),
2040 GTK_OBJECT(country_popup_window));
2041
2042 gtk_widget_show(button1);
2043 gtk_container_add(GTK_CONTAINER(hbuttonbox1), button1);
2044 GTK_WIDGET_SET_FLAGS(button1, GTK_CAN_DEFAULT);
2045
2046 button2 = gtk_button_new_with_label(_("Cancel"));
2047 // gtk_widget_set_usize(button2, 80, -1);
2048 gtk_signal_connect_object(GTK_OBJECT(button2), "clicked",
2049 GTK_SIGNAL_FUNC(gtk_widget_destroy),
2050 GTK_OBJECT(country_popup_window));
2051
2052 gtk_widget_show(button2);
2053 gtk_container_add(GTK_CONTAINER(hbuttonbox1), button2);
2054 GTK_WIDGET_SET_FLAGS(button2, GTK_CAN_DEFAULT);
2055
2056 gtk_widget_show(country_popup_window);
2057
2058 gtk_main();
2059
2060 unregister_window(country_popup_window);
2061
2062 }
2063 #endif
2064
filter_time_inc()2065 unsigned filter_time_inc() {
2066 ++filter_current_time;
2067 if (!filter_current_time) {
2068 struct server* s;
2069 GSList* list = all_servers();
2070 printf("CONGRATULATION! You managed to filter more than %u times\n", UINT_MAX);
2071 for (;list; list = list->next) {
2072 s = (struct server *) list->data;
2073 s->flt_last = 0;
2074 }
2075 ++filter_current_time;
2076 }
2077 return filter_current_time;
2078 }
2079
quick_filter(struct server * s)2080 static int quick_filter (struct server *s) {
2081 unsigned i;
2082 size_t max = sizeof(quick_filter_token)/sizeof(quick_filter_token[0]);
2083
2084 if (!s || !*quick_filter_str) return TRUE;
2085
2086 for (i = 0; i < max && quick_filter_token[i]; ++i) {
2087 if (s->map && strstr(s->map, quick_filter_token[i]))
2088 continue;
2089
2090 if (s->game && lowcasestrstr(s->game, quick_filter_token[i]))
2091 continue;
2092
2093 if (s->gametype && lowcasestrstr(s->gametype, quick_filter_token[i]))
2094 continue;
2095
2096 if (s->name && lowcasestrstr(s->name, quick_filter_token[i]))
2097 continue;
2098
2099 if (s->host && s->host->name && lowcasestrstr(s->host->name, quick_filter_token[i]))
2100 continue;
2101
2102 {
2103 gboolean match = FALSE;
2104 char **info_ptr;
2105 for (info_ptr = s->info; info_ptr && *info_ptr; info_ptr += 2) {
2106 if (lowcasestrstr(info_ptr[1], quick_filter_token[i])) {
2107 match = TRUE;
2108 break;
2109 }
2110 }
2111 if (!match)
2112 return FALSE;
2113 }
2114 }
2115
2116 return TRUE;
2117 }
2118
filter_quick_set(const char * str)2119 void filter_quick_set (const char* str) {
2120 if (str) {
2121 unsigned num;
2122 size_t max = sizeof(quick_filter_token)/sizeof(quick_filter_token[0]);
2123 strncpy(quick_filter_str, str, sizeof(quick_filter_str));
2124 num = tokenize(quick_filter_str, quick_filter_token, max, " ");
2125 if (num < max)
2126 quick_filter_token[num] = NULL;
2127 }
2128 else {
2129 quick_filter_str[0] = '\0';
2130 quick_filter_token[0] = NULL;
2131 }
2132 }
2133
filter_quick_get(void)2134 const char* filter_quick_get(void) {
2135 if (!*quick_filter_token)
2136 return NULL;
2137 return quick_filter_str;
2138 }
2139
filter_quick_unset(void)2140 void filter_quick_unset (void) {
2141 quick_filter_str[0] = '\0';
2142 quick_filter_token[0] = NULL;
2143 }
2144
2145