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