Make register_dfilter_stat work for MAIN_MENU_USE_UIMANAGER
[obnox/wireshark/wip.git] / gtk / tap_param_dlg.c
1 /* tap_param_dlg.c
2  * Routines for parameter dialog used by gui taps
3  * Copyright 2003 Lars Roland
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdio.h>
31 #include <string.h>
32
33 #ifdef HAVE_SYS_TYPES_H
34 # include <sys/types.h>
35 #endif
36
37 #include <gtk/gtk.h>
38
39 #include <epan/stat_cmd_args.h>
40
41 #include "../simple_dialog.h"
42 #include "../file.h"
43 #include "../globals.h"
44 #include "../stat_menu.h"
45
46 #include "gtk/stock_icons.h"
47 #include "gtk/dlg_utils.h"
48 #include "gtk/filter_dlg.h"
49 #include "gtk/gui_stat_menu.h"
50 #include "gtk/tap_param_dlg.h"
51 #include "gtk/gui_utils.h"
52 #include "gtk/gtkglobals.h"
53 #include "gtk/filter_autocomplete.h"
54
55 #include "gtk/old-gtk-compat.h"
56
57 typedef struct _tap_param_dlg_list_item {
58     GtkWidget *dlg;
59     tap_param_dlg cont;
60     construct_args_t args;
61     GtkWidget **param_items;    /* items for params */
62     struct _tap_param_dlg_list_item *next;
63 } tap_param_dlg_list_item;
64
65 static tap_param_dlg_list_item *start_dlg_list=NULL;
66 static tap_param_dlg_list_item *end_dlg_list=NULL;
67 static tap_param_dlg_list_item *current_dlg = NULL;
68
69 #ifdef MAIN_MENU_USE_UIMANAGER
70 #else
71 static void tap_param_dlg_cb(GtkWidget *w, gpointer data);
72 #endif
73 /*
74  * Register a stat that has a parameter dialog.
75  * We register it both as a command-line stat and a menu item stat.
76  */
77 void
78 register_dfilter_stat(tap_param_dlg *info, const char *name,
79     register_stat_group_t group)
80 {
81 #ifdef MAIN_MENU_USE_UIMANAGER
82     register_stat_cmd_arg(info->init_string, info->tap_init_cb, NULL);
83 #else
84     char *full_name;
85
86     register_stat_cmd_arg(info->init_string, info->tap_init_cb, NULL);
87     /*
88      * This menu item will pop up a dialog box, so append "..."
89      * to it.
90      */
91     full_name = g_strdup_printf("%s...", name);
92     register_stat_menu_item(full_name, group, tap_param_dlg_cb, NULL,
93                             NULL, info);
94     /* tap_menu_item_add() uses the name later on. Leave it allocated. */
95 #endif
96 }
97
98 void tap_param_dlg_update (void)
99 {
100     tap_param_dlg_list_item *dialog = start_dlg_list;
101     char *title;
102
103     while(dialog != NULL) {
104         if(dialog->dlg) {
105             title = g_strdup_printf("Wireshark: %s: %s", dialog->cont.win_title , cf_get_display_name(&cfile));
106             gtk_window_set_title(GTK_WINDOW(dialog->dlg), title);
107             g_free(title);
108         }
109         dialog = dialog->next;
110     }
111 }
112
113 static void
114 dlg_destroy_cb(GtkWidget *item _U_, gpointer dialog_data)
115 {
116     tap_param_dlg_list_item *dlg_data = (tap_param_dlg_list_item *) dialog_data;
117     dlg_data->dlg = NULL;
118 }
119
120 static void
121 tap_param_dlg_start_button_clicked(GtkWidget *item _U_, gpointer dialog_data)
122 {
123     GString *params;
124     size_t i;
125     gint j;
126
127     tap_param_dlg_list_item *dlg_data = (tap_param_dlg_list_item *) dialog_data;
128
129     params = g_string_new(dlg_data->cont.init_string);
130     for(i=0;i<dlg_data->cont.nparams;i++) {
131         g_string_append_c(params, ',');
132         switch (dlg_data->cont.params[i].type) {
133
134         case PARAM_ENUM:
135             j = gtk_combo_box_get_active(GTK_COMBO_BOX(dlg_data->param_items[i]));
136             g_string_append_printf(params,"%d",
137                                    dlg_data->cont.params[i].enum_vals[j].value);
138             break;
139
140         case PARAM_UINT:
141         case PARAM_STRING:
142         case PARAM_FILTER:
143             g_string_append(params,
144                             gtk_entry_get_text(GTK_ENTRY(dlg_data->param_items[i])));
145             break;
146         }
147     }
148     (dlg_data->cont.tap_init_cb)(params->str,NULL);
149     g_string_free(params, TRUE);
150 }
151
152 #ifdef MAIN_MENU_USE_UIMANAGER
153 void
154 tap_param_dlg_cb(GtkAction *action _U_, gpointer data)
155 #else
156 static void
157 tap_param_dlg_cb(GtkWidget *w _U_, gpointer data)
158 #endif
159 {
160     const char *filter;
161     char *title;
162     GtkWidget *dlg_box;
163     GtkWidget *item_box, *item, *label, *filter_bt;
164     GtkWidget *bbox, *start_button, *cancel_button;
165     size_t i, j;
166     char *label_with_colon;
167
168     tap_param_dlg *dlg_data = (tap_param_dlg *) data;
169
170     if(dlg_data==NULL)
171         return;
172
173     if(dlg_data->index==-1) {
174         /* Dialog is not registered */
175         if(start_dlg_list==NULL) {
176             start_dlg_list = (tap_param_dlg_list_item *) g_malloc(sizeof (tap_param_dlg_list_item));
177             end_dlg_list = start_dlg_list;
178             end_dlg_list->cont.index = 0; /* first entry in list -> index = 0 */
179         } else {
180             end_dlg_list->next = (tap_param_dlg_list_item *) g_malloc(sizeof (tap_param_dlg_list_item));
181             end_dlg_list->next->cont.index = end_dlg_list->cont.index + 1;
182             end_dlg_list = end_dlg_list->next;
183         }
184         end_dlg_list->dlg = NULL;
185         end_dlg_list->param_items = g_malloc(dlg_data->nparams * sizeof (GtkWidget *));
186         end_dlg_list->cont.win_title = dlg_data->win_title;
187         end_dlg_list->cont.init_string = dlg_data->init_string;
188         end_dlg_list->cont.tap_init_cb = dlg_data->tap_init_cb;
189         end_dlg_list->cont.nparams = dlg_data->nparams;
190         end_dlg_list->cont.params = dlg_data->params;
191         end_dlg_list->args.title = g_strdup_printf("%s Filter", dlg_data->win_title);
192         end_dlg_list->args.wants_apply_button = TRUE;
193         end_dlg_list->args.activate_on_ok = FALSE;
194         end_dlg_list->args.modal_and_transient = FALSE;
195         end_dlg_list->next = NULL;
196         dlg_data->index = end_dlg_list->cont.index;
197         current_dlg = end_dlg_list;
198     } else {
199         /* Dialog is registered, find it */
200         current_dlg = start_dlg_list;
201         while(dlg_data->index != current_dlg->cont.index)
202         {
203             if(current_dlg->next == NULL) {
204                 /* could not find any dialog */
205                 return;
206             }
207             current_dlg = current_dlg->next;
208         }
209     }
210
211     /* if the window is already open, bring it to front */
212     if(current_dlg->dlg){
213         gdk_window_raise(gtk_widget_get_window(current_dlg->dlg));
214         return;
215     }
216
217     title = g_strdup_printf("Wireshark: %s: %s", current_dlg->cont.win_title , cf_get_display_name(&cfile));
218
219     current_dlg->dlg=dlg_window_new(title);
220     gtk_window_set_default_size(GTK_WINDOW(current_dlg->dlg), 300, -1);
221     g_free(title);
222
223     dlg_box=gtk_vbox_new(FALSE, 10);
224     gtk_container_set_border_width(GTK_CONTAINER(dlg_box), 10);
225     gtk_container_add(GTK_CONTAINER(current_dlg->dlg), dlg_box);
226     gtk_widget_show(dlg_box);
227
228     /* Parameter items */
229     for(i=0;i<current_dlg->cont.nparams;i++) {
230         /* Item box */
231         item_box=gtk_hbox_new(FALSE, 3);
232
233         switch (current_dlg->cont.params[i].type) {
234
235         case PARAM_UINT:
236         case PARAM_STRING:
237             /* Label */
238             label_with_colon=g_strdup_printf("%s:", current_dlg->cont.params[i].title);
239             label=gtk_label_new(label_with_colon);
240             g_free(label_with_colon);
241             gtk_box_pack_start(GTK_BOX(item_box), label, FALSE, TRUE, 0);
242             gtk_widget_show(label);
243
244             /* Entry */
245             item=gtk_entry_new();
246             break;
247
248         case PARAM_ENUM:
249             /* Label */
250             label_with_colon=g_strdup_printf("%s:", current_dlg->cont.params[i].title);
251             label=gtk_label_new(label_with_colon);
252             g_free(label_with_colon);
253             gtk_box_pack_start(GTK_BOX(item_box), label, FALSE, TRUE, 0);
254             gtk_widget_show(label);
255
256             /* Combo box */
257             item=gtk_combo_box_text_new();
258             for (j = 0; current_dlg->cont.params[i].enum_vals[j].name != NULL;
259                  j++)
260                  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(item),
261                                           current_dlg->cont.params[i].enum_vals[j].description);
262             gtk_combo_box_set_active(GTK_COMBO_BOX(item), 0);
263             break;
264
265         case PARAM_FILTER:
266             /* Filter button */
267             filter_bt=gtk_button_new_from_stock(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
268             g_signal_connect(filter_bt, "clicked", G_CALLBACK(display_filter_construct_cb), &(current_dlg->args));
269             gtk_box_pack_start(GTK_BOX(item_box), filter_bt, FALSE, TRUE, 0);
270             gtk_widget_show(filter_bt);
271
272             /* Entry */
273             item=gtk_entry_new();
274             filter=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
275             if(filter){
276                 gtk_entry_set_text(GTK_ENTRY(item), filter);
277             } else {
278                 colorize_filter_te_as_empty(item);
279             }
280             g_signal_connect(item, "changed", G_CALLBACK(filter_te_syntax_check_cb), NULL);
281             g_object_set_data(G_OBJECT(item_box), E_FILT_AUTOCOMP_PTR_KEY, NULL);
282             g_signal_connect(item, "key-press-event", G_CALLBACK (filter_string_te_key_pressed_cb), NULL);
283             g_signal_connect(current_dlg->dlg, "key-press-event", G_CALLBACK (filter_parent_dlg_key_pressed_cb), NULL);
284             g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, item);
285             break;
286
287         default:
288             g_assert_not_reached();
289             item=NULL;
290             break;
291         }
292
293         gtk_box_pack_start(GTK_BOX(item_box), item, TRUE, TRUE, 0);
294         current_dlg->param_items[i]=item;
295         gtk_widget_show(item);
296
297         gtk_box_pack_start(GTK_BOX(dlg_box), item_box, TRUE, TRUE, 0);
298         gtk_widget_show(item_box);
299     }
300
301     /* button box */
302     bbox = dlg_button_row_new(WIRESHARK_STOCK_CREATE_STAT, GTK_STOCK_CANCEL, NULL);
303     gtk_box_pack_start(GTK_BOX(dlg_box), bbox, FALSE, FALSE, 0);
304     gtk_widget_show(bbox);
305
306     start_button = g_object_get_data(G_OBJECT(bbox), WIRESHARK_STOCK_CREATE_STAT);
307     g_signal_connect(start_button, "clicked",
308                      G_CALLBACK(tap_param_dlg_start_button_clicked), current_dlg);
309
310     cancel_button = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
311     window_set_cancel_button(current_dlg->dlg, cancel_button, window_cancel_button_cb);
312
313     /* Catch the "activate" signal on all the text entries, so that
314        if the user types Return there, we act as if the "Create Stat"
315        button had been selected, as happens if Return is typed if
316        some widget that *doesn't* handle the Return key has the input
317        focus. */
318     for(i=0;i<current_dlg->cont.nparams;i++){
319         switch (current_dlg->cont.params[i].type) {
320
321         case PARAM_ENUM:
322             break;
323
324         case PARAM_UINT:
325         case PARAM_STRING:
326         case PARAM_FILTER:
327             dlg_set_activate(current_dlg->param_items[i], start_button);
328             break;
329         }
330     }
331
332     /* Give the initial focus to the first entry box. */
333     if(current_dlg->cont.nparams>0){
334         gtk_widget_grab_focus(current_dlg->param_items[0]);
335     }
336
337     gtk_widget_grab_default(start_button );
338
339     g_signal_connect(current_dlg->dlg, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
340     g_signal_connect(current_dlg->dlg, "destroy", G_CALLBACK(dlg_destroy_cb), current_dlg);
341
342     gtk_widget_show_all(current_dlg->dlg);
343     window_present(current_dlg->dlg);
344 }