05d32b8c74411705e6ccec354c7dd30e1837e077
[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
56 typedef struct _tap_param_dlg_list_item {
57     GtkWidget *dlg;
58     tap_param_dlg cont;
59     construct_args_t args;
60     GtkWidget **param_entries;    /* items for params */
61     struct _tap_param_dlg_list_item *next;
62 } tap_param_dlg_list_item;
63
64 static tap_param_dlg_list_item *start_dlg_list=NULL;
65 static tap_param_dlg_list_item *end_dlg_list=NULL;
66 static tap_param_dlg_list_item *current_dlg = NULL;
67
68 static void
69 tap_param_dlg_cb(GtkWidget *w, gpointer data);
70
71 /*
72  * Register a stat that has a parameter dialog.
73  * We register it both as a command-line stat and a menu item stat.
74  */
75 void
76 register_dfilter_stat(tap_param_dlg *info, const char *name,
77     register_stat_group_t group)
78 {
79     char *full_name;
80
81     register_stat_cmd_arg(info->init_string, info->tap_init_cb, NULL);
82
83     /*
84      * This menu item will pop up a dialog box, so append "..."
85      * to it.
86      */
87     full_name = g_strdup_printf("%s...", name);
88     register_stat_menu_item(full_name, group, tap_param_dlg_cb, NULL,
89                             NULL, info);
90     g_free(full_name);
91 }              
92
93 void tap_param_dlg_update (void)
94 {
95     tap_param_dlg_list_item *dialog = start_dlg_list;
96     char *title;
97     
98     while(dialog != NULL) {
99         if(dialog->dlg) {
100             title = g_strdup_printf("Wireshark: %s: %s", dialog->cont.win_title , cf_get_display_name(&cfile));
101             gtk_window_set_title(GTK_WINDOW(dialog->dlg), title);
102             g_free(title);
103         }
104         dialog = dialog->next;
105     }
106 }
107
108 static void
109 dlg_destroy_cb(GtkWidget *item _U_, gpointer dialog_data)
110 {
111     tap_param_dlg_list_item *dlg_data = (tap_param_dlg_list_item *) dialog_data;
112     dlg_data->dlg = NULL;
113 }
114
115 static void
116 tap_param_dlg_start_button_clicked(GtkWidget *item _U_, gpointer dialog_data)
117 {
118     const char *value;
119     GString *params;
120     size_t i;
121     
122     tap_param_dlg_list_item *dlg_data = (tap_param_dlg_list_item *) dialog_data;
123
124     params = g_string_new(dlg_data->cont.init_string);
125     for(i=0;i<dlg_data->cont.nparams;i++) {
126         value=gtk_entry_get_text(GTK_ENTRY(dlg_data->param_entries[i]));
127         params=g_string_append_c(params, ',');
128         params=g_string_append(params, value);
129     }
130     (dlg_data->cont.tap_init_cb)(params->str,NULL);
131     g_string_free(params, TRUE);
132 }
133
134
135 static void
136 tap_param_dlg_cb(GtkWidget *w _U_, gpointer data)
137 {
138     const char *filter;
139     char *title;
140     GtkWidget *dlg_box;
141     GtkWidget *item_box, *item_entry, *label, *filter_bt;
142     GtkWidget *bbox, *start_button, *cancel_button;
143     size_t i;
144     
145     tap_param_dlg *dlg_data = (tap_param_dlg *) data;
146
147     if(dlg_data==NULL)
148         return;
149         
150     if(dlg_data->index==-1) {
151         /* Dialog is not registered */
152         if(start_dlg_list==NULL) {
153             start_dlg_list = (tap_param_dlg_list_item *) g_malloc(sizeof (tap_param_dlg_list_item));
154             end_dlg_list = start_dlg_list;
155             end_dlg_list->cont.index = 0; /* first entry in list -> index = 0 */
156         } else {
157             end_dlg_list->next = (tap_param_dlg_list_item *) g_malloc(sizeof (tap_param_dlg_list_item));
158             end_dlg_list->next->cont.index = end_dlg_list->cont.index + 1;
159             end_dlg_list = end_dlg_list->next;
160         }
161         end_dlg_list->dlg = NULL;
162         end_dlg_list->param_entries = g_malloc(dlg_data->nparams * sizeof (GtkWidget *));
163         end_dlg_list->cont.win_title = dlg_data->win_title;
164         end_dlg_list->cont.init_string = dlg_data->init_string;
165         end_dlg_list->cont.tap_init_cb = dlg_data->tap_init_cb;
166         end_dlg_list->cont.nparams = dlg_data->nparams;
167         end_dlg_list->cont.params = dlg_data->params;
168         end_dlg_list->args.title = g_strdup_printf("%s Filter", dlg_data->win_title);
169         end_dlg_list->args.wants_apply_button = TRUE;
170         end_dlg_list->args.activate_on_ok = FALSE;
171         end_dlg_list->args.modal_and_transient = FALSE;
172         end_dlg_list->next = NULL;
173         dlg_data->index = end_dlg_list->cont.index;
174         current_dlg = end_dlg_list;
175     } else {
176         /* Dialog is registered, find it */
177         current_dlg = start_dlg_list;
178         while(dlg_data->index != current_dlg->cont.index)
179         {
180             if(current_dlg->next == NULL) {
181                 /* could not find any dialog */
182                 return;
183             }
184             current_dlg = current_dlg->next;
185         }
186     }
187
188     /* if the window is already open, bring it to front */
189     if(current_dlg->dlg){
190         gdk_window_raise(current_dlg->dlg->window);
191         return;
192     }
193
194     title = g_strdup_printf("Wireshark: %s: %s", current_dlg->cont.win_title , cf_get_display_name(&cfile));
195
196     current_dlg->dlg=dlg_window_new(title);
197     gtk_window_set_default_size(GTK_WINDOW(current_dlg->dlg), 300, -1);
198     g_free(title);
199
200     dlg_box=gtk_vbox_new(FALSE, 10);
201     gtk_container_set_border_width(GTK_CONTAINER(dlg_box), 10);
202     gtk_container_add(GTK_CONTAINER(current_dlg->dlg), dlg_box);
203     gtk_widget_show(dlg_box);
204
205     /* Parameter items */
206     for(i=0;i<current_dlg->cont.nparams;i++) {
207         /* Item box */
208         item_box=gtk_hbox_new(FALSE, 3);
209
210         /* Item entry */
211         item_entry=gtk_entry_new();
212         current_dlg->param_entries[i] = item_entry;
213
214         switch (current_dlg->cont.params[i].type) {
215
216         case PARAM_UINT:
217         case PARAM_STRING:
218             /* Label */
219             label=gtk_label_new(current_dlg->cont.params[i].title);
220             gtk_box_pack_start(GTK_BOX(item_box), label, FALSE, TRUE, 0);
221             gtk_widget_show(label);
222             break;
223
224         case PARAM_FILTER:
225             /* Filter button */
226             filter_bt=gtk_button_new_from_stock(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
227             g_signal_connect(filter_bt, "clicked", G_CALLBACK(display_filter_construct_cb), &(current_dlg->args));
228             gtk_box_pack_start(GTK_BOX(item_box), filter_bt, FALSE, TRUE, 0);
229             gtk_widget_show(filter_bt);
230             g_signal_connect(item_entry, "changed", G_CALLBACK(filter_te_syntax_check_cb), NULL);
231             g_object_set_data(G_OBJECT(item_box), E_FILT_AUTOCOMP_PTR_KEY, NULL);
232             g_signal_connect(item_entry, "key-press-event", G_CALLBACK (filter_string_te_key_pressed_cb), NULL);
233             g_signal_connect(current_dlg->dlg, "key-press-event", G_CALLBACK (filter_parent_dlg_key_pressed_cb), NULL);
234
235             /* prefs dialog */
236             g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, item_entry);
237             /* prefs dialog */
238             break;
239
240         default:
241             /* XXX - fill me in */
242             break;
243         }
244     
245         gtk_box_pack_start(GTK_BOX(item_box), item_entry, TRUE, TRUE, 0);
246
247         switch(current_dlg->cont.params[i].type){
248
249         case PARAM_FILTER:
250             filter=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
251             if(filter){
252                 gtk_entry_set_text(GTK_ENTRY(item_entry), filter);
253             } else {
254                 colorize_filter_te_as_empty(item_entry);
255             }
256             break;
257
258         default:
259             /* XXX - anything to do here? */
260             break;
261         }
262         gtk_widget_show(item_entry);
263
264         gtk_box_pack_start(GTK_BOX(dlg_box), item_box, TRUE, TRUE, 0);
265         gtk_widget_show(item_box);
266     }
267
268     /* button box */
269     bbox = dlg_button_row_new(WIRESHARK_STOCK_CREATE_STAT, GTK_STOCK_CANCEL, NULL);
270     gtk_box_pack_start(GTK_BOX(dlg_box), bbox, FALSE, FALSE, 0);
271     gtk_widget_show(bbox);
272
273     start_button = g_object_get_data(G_OBJECT(bbox), WIRESHARK_STOCK_CREATE_STAT);
274     g_signal_connect(start_button, "clicked",
275                      G_CALLBACK(tap_param_dlg_start_button_clicked), current_dlg);
276
277     cancel_button = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
278     window_set_cancel_button(current_dlg->dlg, cancel_button, window_cancel_button_cb);
279
280     /* Catch the "activate" signal on all the text entries, so that
281        if the user types Return there, we act as if the "Create Stat"
282        button had been selected, as happens if Return is typed if
283        some widget that *doesn't* handle the Return key has the input
284        focus. */
285     for(i=0;i<current_dlg->cont.nparams;i++){
286         dlg_set_activate(current_dlg->param_entries[i], start_button);
287     }
288
289     /* Give the initial focus to the first entry box. */
290     if(current_dlg->cont.nparams>0){
291         gtk_widget_grab_focus(current_dlg->param_entries[0]);
292     }
293
294     gtk_widget_grab_default(start_button );
295
296     g_signal_connect(current_dlg->dlg, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
297     g_signal_connect(current_dlg->dlg, "destroy", G_CALLBACK(dlg_destroy_cb), current_dlg);
298
299     gtk_widget_show_all(current_dlg->dlg);
300     window_present(current_dlg->dlg);
301 }