Add a REGISTER_STAT_GROUP_TELEPHONY_LTE for the Telephony/LTE menu, and
[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 "../file.h"
36 #include "../globals.h"
37 #include "../stat_menu.h"
38
39 #include "ui/gtk/stock_icons.h"
40 #include "ui/gtk/dlg_utils.h"
41 #include "ui/gtk/filter_dlg.h"
42 #include "ui/gtk/gui_stat_menu.h"
43 #include "ui/gtk/tap_param_dlg.h"
44 #include "ui/gtk/gui_utils.h"
45 #include "ui/gtk/gtkglobals.h"
46 #include "ui/gtk/filter_autocomplete.h"
47
48 #include "ui/gtk/old-gtk-compat.h"
49
50 typedef struct _tap_param_dlg_list_item {
51     GtkWidget *dlg;
52     tap_param_dlg cont;
53     construct_args_t args;
54     GtkWidget **param_items;    /* items for params */
55     struct _tap_param_dlg_list_item *next;
56 } tap_param_dlg_list_item;
57
58 static tap_param_dlg_list_item *start_dlg_list=NULL;
59 static tap_param_dlg_list_item *end_dlg_list=NULL;
60 static tap_param_dlg_list_item *current_dlg = NULL;
61
62 /*
63  * Register a stat that has a parameter dialog.
64  * We register it both as a command-line stat and a menu item stat.
65  */
66 void
67 register_param_stat(tap_param_dlg *info, const char *name,
68     register_stat_group_t group)
69 {
70     gchar *full_name;
71     const gchar *stock_id = NULL;
72
73     register_stat_cmd_arg(info->init_string, info->tap_init_cb, NULL);
74
75     /*
76      * This menu item will pop up a dialog box, so append "..."
77      * to it.
78      */
79     full_name = g_strdup_printf("%s...", name);
80
81     switch (group) {
82
83     case REGISTER_ANALYZE_GROUP_UNSORTED:
84     case REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER:
85     case REGISTER_STAT_GROUP_UNSORTED:
86     case REGISTER_STAT_GROUP_GENERIC:
87         break;
88
89     case REGISTER_STAT_GROUP_CONVERSATION_LIST:
90         stock_id = WIRESHARK_STOCK_CONVERSATIONS;
91         break;
92
93     case REGISTER_STAT_GROUP_ENDPOINT_LIST:
94         stock_id = WIRESHARK_STOCK_ENDPOINTS;
95         break;
96
97     case REGISTER_STAT_GROUP_RESPONSE_TIME:
98         stock_id = WIRESHARK_STOCK_TIME;
99         break;
100
101     case REGISTER_STAT_GROUP_TELEPHONY:
102     case REGISTER_STAT_GROUP_TELEPHONY_GSM:
103     case REGISTER_STAT_GROUP_TELEPHONY_LTE:
104         break;
105
106     case REGISTER_TOOLS_GROUP_UNSORTED:
107         break;
108     }
109
110     register_menu_bar_menu_items(
111         stat_group_name(group), /* GUI path to the place holder in the menu */
112         name,                   /* Action name */
113         stock_id,               /* Stock id */
114         full_name,              /* label */
115         NULL,                   /* Accelerator */
116         NULL,                   /* Tooltip */
117         tap_param_dlg_cb,       /* Callback */
118         info,                   /* Callback data */
119         TRUE,                   /* Enabled */
120         NULL,
121         NULL);
122 }
123
124 void tap_param_dlg_update (void)
125 {
126     tap_param_dlg_list_item *dialog = start_dlg_list;
127     char *display_name;
128     char *title;
129
130     while(dialog != NULL) {
131         if(dialog->dlg) {
132             display_name = cf_get_display_name(&cfile);
133             title = g_strdup_printf("Wireshark: %s: %s", dialog->cont.win_title , display_name);
134             g_free(display_name);
135             gtk_window_set_title(GTK_WINDOW(dialog->dlg), title);
136             g_free(title);
137         }
138         dialog = dialog->next;
139     }
140 }
141
142 static void
143 dlg_destroy_cb(GtkWidget *item _U_, gpointer dialog_data)
144 {
145     tap_param_dlg_list_item *dlg_data = (tap_param_dlg_list_item *) dialog_data;
146     dlg_data->dlg = NULL;
147 }
148
149 static void
150 tap_param_dlg_start_button_clicked(GtkWidget *item _U_, gpointer dialog_data)
151 {
152     GString *params;
153     size_t i;
154     gint j;
155
156     tap_param_dlg_list_item *dlg_data = (tap_param_dlg_list_item *) dialog_data;
157
158     params = g_string_new(dlg_data->cont.init_string);
159     for(i=0;i<dlg_data->cont.nparams;i++) {
160         g_string_append_c(params, ',');
161         switch (dlg_data->cont.params[i].type) {
162
163         case PARAM_ENUM:
164             j = gtk_combo_box_get_active(GTK_COMBO_BOX(dlg_data->param_items[i]));
165             g_string_append_printf(params,"%d",
166                                    dlg_data->cont.params[i].enum_vals[j].value);
167             break;
168
169         case PARAM_UINT:
170         case PARAM_STRING:
171         case PARAM_FILTER:
172             g_string_append(params,
173                             gtk_entry_get_text(GTK_ENTRY(dlg_data->param_items[i])));
174             break;
175         }
176     }
177     (dlg_data->cont.tap_init_cb)(params->str,NULL);
178     g_string_free(params, TRUE);
179 }
180
181 void
182 tap_param_dlg_cb(GtkAction *action _U_, gpointer data)
183 {
184     const char *filter;
185     char *display_name;
186     char *title;
187     GtkWidget *dlg_box;
188     GtkWidget *item_box, *item, *label, *filter_bt;
189     GtkWidget *bbox, *start_button, *cancel_button;
190     size_t i, j;
191     char *label_with_colon;
192
193     tap_param_dlg *dlg_data = (tap_param_dlg *) data;
194
195     if(dlg_data==NULL)
196         return;
197
198     if(dlg_data->index==-1) {
199         /* Dialog is not registered */
200         if(start_dlg_list==NULL) {
201             start_dlg_list = (tap_param_dlg_list_item *) g_malloc(sizeof (tap_param_dlg_list_item));
202             end_dlg_list = start_dlg_list;
203             end_dlg_list->cont.index = 0; /* first entry in list -> index = 0 */
204         } else {
205             end_dlg_list->next = (tap_param_dlg_list_item *) g_malloc(sizeof (tap_param_dlg_list_item));
206             end_dlg_list->next->cont.index = end_dlg_list->cont.index + 1;
207             end_dlg_list = end_dlg_list->next;
208         }
209         end_dlg_list->dlg = NULL;
210         end_dlg_list->param_items = (GtkWidget **)g_malloc(dlg_data->nparams * sizeof (GtkWidget *));
211         end_dlg_list->cont.win_title = dlg_data->win_title;
212         end_dlg_list->cont.init_string = dlg_data->init_string;
213         end_dlg_list->cont.tap_init_cb = dlg_data->tap_init_cb;
214         end_dlg_list->cont.nparams = dlg_data->nparams;
215         end_dlg_list->cont.params = dlg_data->params;
216         end_dlg_list->args.title = g_strdup_printf("%s Filter", dlg_data->win_title);
217         end_dlg_list->args.wants_apply_button = TRUE;
218         end_dlg_list->args.activate_on_ok = FALSE;
219         end_dlg_list->args.modal_and_transient = FALSE;
220         end_dlg_list->next = NULL;
221         dlg_data->index = end_dlg_list->cont.index;
222         current_dlg = end_dlg_list;
223     } else {
224         /* Dialog is registered, find it */
225         current_dlg = start_dlg_list;
226         while(dlg_data->index != current_dlg->cont.index)
227         {
228             if(current_dlg->next == NULL) {
229                 /* could not find any dialog */
230                 return;
231             }
232             current_dlg = current_dlg->next;
233         }
234     }
235
236     /* if the window is already open, bring it to front */
237     if(current_dlg->dlg){
238         gdk_window_raise(gtk_widget_get_window(current_dlg->dlg));
239         return;
240     }
241
242     display_name = cf_get_display_name(&cfile);
243     title = g_strdup_printf("Wireshark: %s: %s", current_dlg->cont.win_title , display_name);
244     g_free(display_name);
245
246     current_dlg->dlg=dlg_window_new(title);
247     gtk_window_set_default_size(GTK_WINDOW(current_dlg->dlg), 300, -1);
248     g_free(title);
249
250     dlg_box=ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 10, FALSE);
251     gtk_container_set_border_width(GTK_CONTAINER(dlg_box), 10);
252     gtk_container_add(GTK_CONTAINER(current_dlg->dlg), dlg_box);
253     gtk_widget_show(dlg_box);
254
255     /* Parameter items */
256     for(i=0;i<current_dlg->cont.nparams;i++) {
257         /* Item box */
258         item_box=ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3, FALSE);
259
260         switch (current_dlg->cont.params[i].type) {
261
262         case PARAM_UINT:
263         case PARAM_STRING:
264             /* Label */
265             label_with_colon=g_strdup_printf("%s:", current_dlg->cont.params[i].title);
266             label=gtk_label_new(label_with_colon);
267             g_free(label_with_colon);
268             gtk_box_pack_start(GTK_BOX(item_box), label, FALSE, TRUE, 0);
269             gtk_widget_show(label);
270
271             /* Entry */
272             item=gtk_entry_new();
273             break;
274
275         case PARAM_ENUM:
276             /* Label */
277             label_with_colon=g_strdup_printf("%s:", current_dlg->cont.params[i].title);
278             label=gtk_label_new(label_with_colon);
279             g_free(label_with_colon);
280             gtk_box_pack_start(GTK_BOX(item_box), label, FALSE, TRUE, 0);
281             gtk_widget_show(label);
282
283             /* Combo box */
284             item=gtk_combo_box_text_new();
285             for (j = 0; current_dlg->cont.params[i].enum_vals[j].name != NULL;
286                  j++)
287                  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(item),
288                                           current_dlg->cont.params[i].enum_vals[j].description);
289             gtk_combo_box_set_active(GTK_COMBO_BOX(item), 0);
290             break;
291
292         case PARAM_FILTER:
293             /* Filter button */
294             filter_bt=gtk_button_new_from_stock(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
295             g_signal_connect(filter_bt, "clicked", G_CALLBACK(display_filter_construct_cb), &(current_dlg->args));
296             gtk_box_pack_start(GTK_BOX(item_box), filter_bt, FALSE, TRUE, 0);
297             gtk_widget_show(filter_bt);
298
299             /* Entry */
300             item=gtk_entry_new();
301             g_signal_connect(item, "changed", G_CALLBACK(filter_te_syntax_check_cb), NULL);
302             g_object_set_data(G_OBJECT(item_box), E_FILT_AUTOCOMP_PTR_KEY, NULL);
303             g_signal_connect(item, "key-press-event", G_CALLBACK (filter_string_te_key_pressed_cb), NULL);
304             g_signal_connect(current_dlg->dlg, "key-press-event", G_CALLBACK (filter_parent_dlg_key_pressed_cb), NULL);
305             g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, item);
306
307             filter=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
308             if(filter){
309                 gtk_entry_set_text(GTK_ENTRY(item), filter);
310             } else {
311                 colorize_filter_te_as_empty(item);
312             }
313             break;
314
315         default:
316             g_assert_not_reached();
317             item=NULL;
318             break;
319         }
320
321         gtk_box_pack_start(GTK_BOX(item_box), item, TRUE, TRUE, 0);
322         current_dlg->param_items[i]=item;
323         gtk_widget_show(item);
324
325         gtk_box_pack_start(GTK_BOX(dlg_box), item_box, TRUE, TRUE, 0);
326         gtk_widget_show(item_box);
327     }
328
329     /* button box */
330     bbox = dlg_button_row_new(WIRESHARK_STOCK_CREATE_STAT, GTK_STOCK_CANCEL, NULL);
331     gtk_box_pack_start(GTK_BOX(dlg_box), bbox, FALSE, FALSE, 0);
332     gtk_widget_show(bbox);
333
334     start_button = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), WIRESHARK_STOCK_CREATE_STAT);
335     g_signal_connect(start_button, "clicked",
336                      G_CALLBACK(tap_param_dlg_start_button_clicked), current_dlg);
337
338     cancel_button = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
339     window_set_cancel_button(current_dlg->dlg, cancel_button, window_cancel_button_cb);
340
341     /* Catch the "activate" signal on all the text entries, so that
342        if the user types Return there, we act as if the "Create Stat"
343        button had been selected, as happens if Return is typed if
344        some widget that *doesn't* handle the Return key has the input
345        focus. */
346     for(i=0;i<current_dlg->cont.nparams;i++){
347         switch (current_dlg->cont.params[i].type) {
348
349         case PARAM_ENUM:
350             break;
351
352         case PARAM_UINT:
353         case PARAM_STRING:
354         case PARAM_FILTER:
355             dlg_set_activate(current_dlg->param_items[i], start_button);
356             break;
357         }
358     }
359
360     /* Give the initial focus to the first entry box. */
361     if(current_dlg->cont.nparams>0){
362         gtk_widget_grab_focus(current_dlg->param_items[0]);
363     }
364
365     gtk_widget_grab_default(start_button );
366
367     g_signal_connect(current_dlg->dlg, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
368     g_signal_connect(current_dlg->dlg, "destroy", G_CALLBACK(dlg_destroy_cb), current_dlg);
369
370     gtk_widget_show_all(current_dlg->dlg);
371     window_present(current_dlg->dlg);
372 }