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