We always HAVE_CONFIG_H so don't bother checking whether we have it or not.
[metze/wireshark/wip.git] / ui / 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #include "config.h"
27
28 #include <stdio.h>
29 #include <string.h>
30
31 #include <gtk/gtk.h>
32
33 #include <epan/stat_cmd_args.h>
34
35 #include "ui/simple_dialog.h"
36 #include "../file.h"
37 #include "../globals.h"
38 #include "../stat_menu.h"
39
40 #include "ui/gtk/stock_icons.h"
41 #include "ui/gtk/dlg_utils.h"
42 #include "ui/gtk/filter_dlg.h"
43 #include "ui/gtk/gui_stat_menu.h"
44 #include "ui/gtk/tap_param_dlg.h"
45 #include "ui/gtk/gui_utils.h"
46 #include "ui/gtk/gtkglobals.h"
47 #include "ui/gtk/filter_autocomplete.h"
48
49 #include "ui/gtk/old-gtk-compat.h"
50
51 typedef struct _tap_param_dlg_list_item {
52     GtkWidget *dlg;
53     tap_param_dlg cont;
54     construct_args_t args;
55     GtkWidget **param_items;    /* items for params */
56     struct _tap_param_dlg_list_item *next;
57 } tap_param_dlg_list_item;
58
59 static tap_param_dlg_list_item *start_dlg_list=NULL;
60 static tap_param_dlg_list_item *end_dlg_list=NULL;
61 static tap_param_dlg_list_item *current_dlg = NULL;
62
63 /*
64  * Register a stat that has a parameter dialog.
65  * We register it both as a command-line stat and a menu item stat.
66  */
67 void
68 register_dfilter_stat(tap_param_dlg *info, const char *name _U_,
69     register_stat_group_t group _U_ )
70 {
71     register_stat_cmd_arg(info->init_string, info->tap_init_cb, NULL);
72 }
73
74 void tap_param_dlg_update (void)
75 {
76     tap_param_dlg_list_item *dialog = start_dlg_list;
77     char *display_name;
78     char *title;
79
80     while(dialog != NULL) {
81         if(dialog->dlg) {
82             display_name = cf_get_display_name(&cfile);
83             title = g_strdup_printf("Wireshark: %s: %s", dialog->cont.win_title , display_name);
84             g_free(display_name);
85             gtk_window_set_title(GTK_WINDOW(dialog->dlg), title);
86             g_free(title);
87         }
88         dialog = dialog->next;
89     }
90 }
91
92 static void
93 dlg_destroy_cb(GtkWidget *item _U_, gpointer dialog_data)
94 {
95     tap_param_dlg_list_item *dlg_data = (tap_param_dlg_list_item *) dialog_data;
96     dlg_data->dlg = NULL;
97 }
98
99 static void
100 tap_param_dlg_start_button_clicked(GtkWidget *item _U_, gpointer dialog_data)
101 {
102     GString *params;
103     size_t i;
104     gint j;
105
106     tap_param_dlg_list_item *dlg_data = (tap_param_dlg_list_item *) dialog_data;
107
108     params = g_string_new(dlg_data->cont.init_string);
109     for(i=0;i<dlg_data->cont.nparams;i++) {
110         g_string_append_c(params, ',');
111         switch (dlg_data->cont.params[i].type) {
112
113         case PARAM_ENUM:
114             j = gtk_combo_box_get_active(GTK_COMBO_BOX(dlg_data->param_items[i]));
115             g_string_append_printf(params,"%d",
116                                    dlg_data->cont.params[i].enum_vals[j].value);
117             break;
118
119         case PARAM_UINT:
120         case PARAM_STRING:
121         case PARAM_FILTER:
122             g_string_append(params,
123                             gtk_entry_get_text(GTK_ENTRY(dlg_data->param_items[i])));
124             break;
125         }
126     }
127     (dlg_data->cont.tap_init_cb)(params->str,NULL);
128     g_string_free(params, TRUE);
129 }
130
131 void
132 tap_param_dlg_cb(GtkAction *action _U_, gpointer data)
133 {
134     const char *filter;
135     char *display_name;
136     char *title;
137     GtkWidget *dlg_box;
138     GtkWidget *item_box, *item, *label, *filter_bt;
139     GtkWidget *bbox, *start_button, *cancel_button;
140     size_t i, j;
141     char *label_with_colon;
142
143     tap_param_dlg *dlg_data = (tap_param_dlg *) data;
144
145     if(dlg_data==NULL)
146         return;
147
148     if(dlg_data->index==-1) {
149         /* Dialog is not registered */
150         if(start_dlg_list==NULL) {
151             start_dlg_list = (tap_param_dlg_list_item *) g_malloc(sizeof (tap_param_dlg_list_item));
152             end_dlg_list = start_dlg_list;
153             end_dlg_list->cont.index = 0; /* first entry in list -> index = 0 */
154         } else {
155             end_dlg_list->next = (tap_param_dlg_list_item *) g_malloc(sizeof (tap_param_dlg_list_item));
156             end_dlg_list->next->cont.index = end_dlg_list->cont.index + 1;
157             end_dlg_list = end_dlg_list->next;
158         }
159         end_dlg_list->dlg = NULL;
160         end_dlg_list->param_items = g_malloc(dlg_data->nparams * sizeof (GtkWidget *));
161         end_dlg_list->cont.win_title = dlg_data->win_title;
162         end_dlg_list->cont.init_string = dlg_data->init_string;
163         end_dlg_list->cont.tap_init_cb = dlg_data->tap_init_cb;
164         end_dlg_list->cont.nparams = dlg_data->nparams;
165         end_dlg_list->cont.params = dlg_data->params;
166         end_dlg_list->args.title = g_strdup_printf("%s Filter", dlg_data->win_title);
167         end_dlg_list->args.wants_apply_button = TRUE;
168         end_dlg_list->args.activate_on_ok = FALSE;
169         end_dlg_list->args.modal_and_transient = FALSE;
170         end_dlg_list->next = NULL;
171         dlg_data->index = end_dlg_list->cont.index;
172         current_dlg = end_dlg_list;
173     } else {
174         /* Dialog is registered, find it */
175         current_dlg = start_dlg_list;
176         while(dlg_data->index != current_dlg->cont.index)
177         {
178             if(current_dlg->next == NULL) {
179                 /* could not find any dialog */
180                 return;
181             }
182             current_dlg = current_dlg->next;
183         }
184     }
185
186     /* if the window is already open, bring it to front */
187     if(current_dlg->dlg){
188         gdk_window_raise(gtk_widget_get_window(current_dlg->dlg));
189         return;
190     }
191
192     display_name = cf_get_display_name(&cfile);
193     title = g_strdup_printf("Wireshark: %s: %s", current_dlg->cont.win_title , display_name);
194     g_free(display_name);
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=ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 10, FALSE);
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=ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3, FALSE);
209
210         switch (current_dlg->cont.params[i].type) {
211
212         case PARAM_UINT:
213         case PARAM_STRING:
214             /* Label */
215             label_with_colon=g_strdup_printf("%s:", current_dlg->cont.params[i].title);
216             label=gtk_label_new(label_with_colon);
217             g_free(label_with_colon);
218             gtk_box_pack_start(GTK_BOX(item_box), label, FALSE, TRUE, 0);
219             gtk_widget_show(label);
220
221             /* Entry */
222             item=gtk_entry_new();
223             break;
224
225         case PARAM_ENUM:
226             /* Label */
227             label_with_colon=g_strdup_printf("%s:", current_dlg->cont.params[i].title);
228             label=gtk_label_new(label_with_colon);
229             g_free(label_with_colon);
230             gtk_box_pack_start(GTK_BOX(item_box), label, FALSE, TRUE, 0);
231             gtk_widget_show(label);
232
233             /* Combo box */
234             item=gtk_combo_box_text_new();
235             for (j = 0; current_dlg->cont.params[i].enum_vals[j].name != NULL;
236                  j++)
237                  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(item),
238                                           current_dlg->cont.params[i].enum_vals[j].description);
239             gtk_combo_box_set_active(GTK_COMBO_BOX(item), 0);
240             break;
241
242         case PARAM_FILTER:
243             /* Filter button */
244             filter_bt=gtk_button_new_from_stock(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
245             g_signal_connect(filter_bt, "clicked", G_CALLBACK(display_filter_construct_cb), &(current_dlg->args));
246             gtk_box_pack_start(GTK_BOX(item_box), filter_bt, FALSE, TRUE, 0);
247             gtk_widget_show(filter_bt);
248
249             /* Entry */
250             item=gtk_entry_new();
251             g_signal_connect(item, "changed", G_CALLBACK(filter_te_syntax_check_cb), NULL);
252             g_object_set_data(G_OBJECT(item_box), E_FILT_AUTOCOMP_PTR_KEY, NULL);
253             g_signal_connect(item, "key-press-event", G_CALLBACK (filter_string_te_key_pressed_cb), NULL);
254             g_signal_connect(current_dlg->dlg, "key-press-event", G_CALLBACK (filter_parent_dlg_key_pressed_cb), NULL);
255             g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, item);
256
257             filter=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
258             if(filter){
259                 gtk_entry_set_text(GTK_ENTRY(item), filter);
260             } else {
261                 colorize_filter_te_as_empty(item);
262             }
263             break;
264
265         default:
266             g_assert_not_reached();
267             item=NULL;
268             break;
269         }
270
271         gtk_box_pack_start(GTK_BOX(item_box), item, TRUE, TRUE, 0);
272         current_dlg->param_items[i]=item;
273         gtk_widget_show(item);
274
275         gtk_box_pack_start(GTK_BOX(dlg_box), item_box, TRUE, TRUE, 0);
276         gtk_widget_show(item_box);
277     }
278
279     /* button box */
280     bbox = dlg_button_row_new(WIRESHARK_STOCK_CREATE_STAT, GTK_STOCK_CANCEL, NULL);
281     gtk_box_pack_start(GTK_BOX(dlg_box), bbox, FALSE, FALSE, 0);
282     gtk_widget_show(bbox);
283
284     start_button = g_object_get_data(G_OBJECT(bbox), WIRESHARK_STOCK_CREATE_STAT);
285     g_signal_connect(start_button, "clicked",
286                      G_CALLBACK(tap_param_dlg_start_button_clicked), current_dlg);
287
288     cancel_button = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
289     window_set_cancel_button(current_dlg->dlg, cancel_button, window_cancel_button_cb);
290
291     /* Catch the "activate" signal on all the text entries, so that
292        if the user types Return there, we act as if the "Create Stat"
293        button had been selected, as happens if Return is typed if
294        some widget that *doesn't* handle the Return key has the input
295        focus. */
296     for(i=0;i<current_dlg->cont.nparams;i++){
297         switch (current_dlg->cont.params[i].type) {
298
299         case PARAM_ENUM:
300             break;
301
302         case PARAM_UINT:
303         case PARAM_STRING:
304         case PARAM_FILTER:
305             dlg_set_activate(current_dlg->param_items[i], start_button);
306             break;
307         }
308     }
309
310     /* Give the initial focus to the first entry box. */
311     if(current_dlg->cont.nparams>0){
312         gtk_widget_grab_focus(current_dlg->param_items[0]);
313     }
314
315     gtk_widget_grab_default(start_button );
316
317     g_signal_connect(current_dlg->dlg, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
318     g_signal_connect(current_dlg->dlg, "destroy", G_CALLBACK(dlg_destroy_cb), current_dlg);
319
320     gtk_widget_show_all(current_dlg->dlg);
321     window_present(current_dlg->dlg);
322 }