Add Compile BPF to the capture options dialog description.
[obnox/wireshark/wip.git] / gtk / find_dlg.c
1 /* find_dlg.c
2  * Routines for "find frame" window
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <string.h>
30 #include <ctype.h>
31
32 #include <gtk/gtk.h>
33
34 #include <epan/proto.h>
35 #include <epan/dfilter/dfilter.h>
36 #include <epan/strutil.h>
37 #include <epan/prefs.h>
38
39 #include "../globals.h"
40 #include "../alert_box.h"
41 #include "../simple_dialog.h"
42 #include "../main_statusbar.h"
43
44 #include "gtk/gui_utils.h"
45 #include "gtk/find_dlg.h"
46 #include "gtk/filter_dlg.h"
47 #include "gtk/dlg_utils.h"
48 #include "gtk/stock_icons.h"
49 #include "gtk/prefs_dlg.h"
50 #include "gtk/keys.h"
51 #include "gtk/help_dlg.h"
52 #include "gtk/filter_autocomplete.h"
53
54 /* Capture callback data keys */
55 #define E_FIND_FILT_KEY       "find_filter_te"
56 #define E_FIND_BACKWARD_KEY   "find_backward"
57 #define E_FIND_HEXDATA_KEY    "find_hex"
58 #define E_FIND_STRINGDATA_KEY "find_string"
59 #define E_FIND_FILTERDATA_KEY "find_filter"
60 #define E_FIND_STRINGTYPE_KEY "find_string_type"
61 #define E_FIND_STRINGTYPE_LABEL_KEY "find_string_type_label"
62 #define E_CASE_SEARCH_KEY     "case_insensitive_search"
63 #define E_SOURCE_HEX_KEY      "hex_data_source"
64 #define E_SOURCE_DECODE_KEY   "decode_data_source"
65 #define E_SOURCE_SUMMARY_KEY  "summary_data_source"
66 #define E_FILT_TE_BUTTON_KEY  "find_filter_button"
67
68 static gboolean case_type = TRUE;
69 static gboolean summary_data = FALSE;
70 static gboolean decode_data = FALSE;
71
72 static void
73 find_filter_te_syntax_check_cb(GtkWidget *w, gpointer parent_w);
74
75 static void
76 find_frame_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
77
78 static void
79 find_frame_close_cb(GtkWidget *close_bt, gpointer parent_w);
80
81 static void
82 find_frame_destroy_cb(GtkWidget *win, gpointer user_data);
83
84 static void
85 hex_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w);
86
87 static void
88 string_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w);
89
90 static void
91 filter_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w);
92
93 /*
94  * Keep a static pointer to the current "Find Packet" window, if any, so
95  * that if somebody tries to do "Find Packet" while there's already a
96  * "Find Packet" window up, we just pop up the existing one, rather than
97  * creating a new one.
98  */
99 static GtkWidget *find_frame_w;
100 static GtkWidget *filter_text_box;
101
102 /*
103  * Save the presskey handlers to be able to dissable the auto-completion 
104  * feature for hex and string searches.
105  */
106 static gulong te_presskey_handler_id;
107 static gulong win_presskey_handler_id;
108
109 void
110 find_frame_cb(GtkWidget *w _U_, gpointer d _U_)
111 {
112   GtkWidget     *main_vb, *main_find_hb, *main_options_hb,
113
114                 *find_type_frame, *find_type_vb,
115                 *find_type_hb, *find_type_lb, *hex_rb, *string_rb, *filter_rb,
116                 *filter_hb, *filter_bt,
117
118                 *direction_frame, *direction_vb,
119                 *up_rb, *down_rb,
120
121                 *data_frame, *data_vb,
122                 *hex_data_rb, *decode_data_rb, *summary_data_rb,
123
124                 *string_opt_frame, *string_opt_vb,
125                 *case_cb, *combo_lb, *combo_cb,
126
127                 *bbox, *ok_bt, *cancel_bt, *help_bt;
128   GtkTooltips   *tooltips;
129
130
131   /* No Apply button, but "OK" not only sets our text widget, it
132      activates it (i.e., it causes us to do the search). */
133   static construct_args_t args = {
134         "Wireshark: Search Filter",
135         FALSE,
136         TRUE,
137     FALSE
138   };
139
140   if (find_frame_w != NULL) {
141     /* There's already a "Find Packet" dialog box; reactivate it. */
142     reactivate_window(find_frame_w);
143     return;
144   }
145
146   find_frame_w = dlg_window_new("Wireshark: Find Packet");
147   tooltips = gtk_tooltips_new ();
148
149   /* Container for each row of widgets */
150   main_vb = gtk_vbox_new(FALSE, 3);
151   gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
152   gtk_container_add(GTK_CONTAINER(find_frame_w), main_vb);
153   gtk_widget_show(main_vb);
154
155
156   /* */
157   main_find_hb = gtk_hbox_new(FALSE, 3);
158   gtk_container_add(GTK_CONTAINER(main_vb), main_find_hb);
159   gtk_widget_show(main_find_hb);
160
161
162   /* find frame */
163   find_type_frame = gtk_frame_new("Find");
164   gtk_box_pack_start(GTK_BOX(main_find_hb), find_type_frame, TRUE, TRUE, 0);
165   gtk_widget_show(find_type_frame);
166
167   find_type_vb = gtk_vbox_new(FALSE, 3);
168   gtk_container_set_border_width(GTK_CONTAINER(find_type_vb), 3);
169   gtk_container_add(GTK_CONTAINER(find_type_frame), find_type_vb);
170   gtk_widget_show(find_type_vb);
171
172   /* find type row */
173   find_type_hb = gtk_hbox_new(FALSE, 3);
174   gtk_container_add(GTK_CONTAINER(find_type_vb), find_type_hb);
175   gtk_widget_show(find_type_hb);
176
177   find_type_lb = gtk_label_new("By:");
178   gtk_box_pack_start(GTK_BOX(find_type_hb), find_type_lb, FALSE, FALSE, 0);
179   gtk_widget_show(find_type_lb);
180
181   /* Filter */
182   filter_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "_Display filter");
183   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filter_rb), !cfile.hex && !cfile.string);
184   gtk_box_pack_start(GTK_BOX(find_type_hb), filter_rb, FALSE, FALSE, 0);
185   gtk_tooltips_set_tip (tooltips, filter_rb, ("Search for data by display filter syntax.\ne.g. ip.addr==10.1.1.1"), NULL);
186   gtk_widget_show(filter_rb);
187
188   /* Hex */
189   hex_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(filter_rb), "_Hex value");
190   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hex_rb), cfile.hex);
191   gtk_box_pack_start(GTK_BOX(find_type_hb), hex_rb, FALSE, FALSE, 0);
192   gtk_tooltips_set_tip (tooltips, hex_rb, ("Search for data by hex string.\ne.g. fffffda5"), NULL);
193   gtk_widget_show(hex_rb);
194
195   /* ASCII Search */
196   string_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(filter_rb), "_String");
197   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(string_rb), cfile.string);
198   gtk_box_pack_start(GTK_BOX(find_type_hb), string_rb, FALSE, FALSE, 0);
199   gtk_tooltips_set_tip (tooltips, string_rb, ("Search for data by string value.\ne.g. My String"), NULL);
200   gtk_widget_show(string_rb);
201
202   /* Filter row */
203   filter_hb = gtk_hbox_new(FALSE, 3);
204   gtk_box_pack_start(GTK_BOX(find_type_vb), filter_hb, FALSE, FALSE, 0);
205   gtk_widget_show(filter_hb);
206
207   filter_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
208   g_signal_connect(filter_bt, "clicked", G_CALLBACK(display_filter_construct_cb), &args);
209   g_signal_connect(filter_bt, "destroy", G_CALLBACK(filter_button_destroy_cb), NULL);
210   g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_BUTTON_KEY, filter_bt);
211   gtk_box_pack_start(GTK_BOX(filter_hb), filter_bt, FALSE, TRUE, 0);
212   gtk_tooltips_set_tip (tooltips, filter_bt, ("Click on the filter button to select a display filter,\nor enter your search criteria into the text box"), NULL);
213   gtk_widget_show(filter_bt);
214
215   filter_text_box = gtk_entry_new();
216   if (cfile.sfilter) gtk_entry_set_text(GTK_ENTRY(filter_text_box), cfile.sfilter);
217   g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_text_box);
218   g_object_set_data(G_OBJECT(find_frame_w), E_FILT_TE_PTR_KEY, filter_text_box);
219   gtk_box_pack_start(GTK_BOX(filter_hb), filter_text_box, TRUE, TRUE, 0);
220   g_signal_connect(filter_text_box, "changed", G_CALLBACK(find_filter_te_syntax_check_cb), find_frame_w);
221   g_object_set_data(G_OBJECT(find_frame_w), E_FILT_AUTOCOMP_PTR_KEY, NULL);
222   te_presskey_handler_id = g_signal_connect(filter_text_box, "key-press-event", G_CALLBACK (filter_string_te_key_pressed_cb), NULL);
223   win_presskey_handler_id = g_signal_connect(find_frame_w, "key-press-event", G_CALLBACK (filter_parent_dlg_key_pressed_cb), NULL);
224   gtk_widget_show(filter_text_box);
225
226
227   /* */
228   main_options_hb = gtk_hbox_new(FALSE, 3);
229   gtk_container_add(GTK_CONTAINER(main_vb), main_options_hb);
230   gtk_widget_show(main_options_hb);
231
232
233   /* search in frame */
234   data_frame = gtk_frame_new("Search In");
235   gtk_box_pack_start(GTK_BOX(main_options_hb), data_frame, TRUE, TRUE, 0);
236   gtk_widget_show(data_frame);
237
238   /* search in row */
239   data_vb = gtk_vbox_new(TRUE, 0);
240   gtk_container_set_border_width(GTK_CONTAINER(data_vb), 3);
241   gtk_container_add(GTK_CONTAINER(data_frame), data_vb);
242   gtk_widget_show(data_vb);
243
244   /* Packet list */
245   summary_data_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "Packet list");
246   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(summary_data_rb), summary_data);
247   gtk_box_pack_start(GTK_BOX(data_vb), summary_data_rb, TRUE, TRUE, 0);
248   gtk_tooltips_set_tip (tooltips, summary_data_rb, ("Search for string in the Info column of the packet summary (top pane)"), NULL);
249   gtk_widget_show(summary_data_rb);
250
251   /* Packet details */
252   decode_data_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(summary_data_rb), "Packet details");
253   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(decode_data_rb), decode_data);
254   gtk_box_pack_start(GTK_BOX(data_vb), decode_data_rb, TRUE, TRUE, 0);
255   gtk_tooltips_set_tip (tooltips, decode_data_rb, ("Search for string in the decoded packet display (middle pane)"), NULL);
256   gtk_widget_show(decode_data_rb);
257
258   /* Packet bytes */
259   hex_data_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(summary_data_rb), "Packet bytes");
260   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hex_data_rb), !decode_data && !summary_data);
261   gtk_box_pack_start(GTK_BOX(data_vb), hex_data_rb, TRUE, TRUE, 0);
262   gtk_tooltips_set_tip (tooltips, hex_data_rb, ("Search for string in the packet data"), NULL);
263   gtk_widget_show(hex_data_rb);
264
265   /* string options frame */
266   string_opt_frame = gtk_frame_new("String Options");
267   gtk_box_pack_start(GTK_BOX(main_options_hb), string_opt_frame, TRUE, TRUE, 0);
268   gtk_widget_show(string_opt_frame);
269
270   string_opt_vb = gtk_vbox_new(FALSE, 0);
271   gtk_container_add(GTK_CONTAINER(string_opt_frame), string_opt_vb);
272   gtk_container_set_border_width(GTK_CONTAINER(string_opt_vb), 3);
273   gtk_widget_show(string_opt_vb);
274
275   case_cb = gtk_check_button_new_with_mnemonic("Case sensitive");
276   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(case_cb), !case_type);
277   gtk_container_add(GTK_CONTAINER(string_opt_vb), case_cb);
278   gtk_tooltips_set_tip (tooltips, case_cb, ("Search by mixed upper/lower case?"), NULL);
279   gtk_widget_show(case_cb);
280
281   combo_lb = gtk_label_new("Character set:");
282   gtk_container_add(GTK_CONTAINER(string_opt_vb), combo_lb);
283   gtk_misc_set_alignment(GTK_MISC(combo_lb), 0.0f, 0.5f);
284   gtk_widget_show(combo_lb);
285
286   /* Character Type Selection Dropdown Box
287      These only apply to the string find option */
288   /* Create Combo Box */
289  
290   combo_cb = gtk_combo_box_new_text();
291
292   gtk_combo_box_append_text(GTK_COMBO_BOX(combo_cb), "ASCII Unicode & Non-Unicode");
293   gtk_combo_box_append_text(GTK_COMBO_BOX(combo_cb), "ASCII Non-Unicode");
294   gtk_combo_box_append_text(GTK_COMBO_BOX(combo_cb), "ASCII Unicode");
295
296   gtk_combo_box_set_active(GTK_COMBO_BOX(combo_cb),0);
297   gtk_container_add(GTK_CONTAINER(string_opt_vb), combo_cb);
298
299   gtk_widget_show(combo_cb);
300
301
302   /* direction frame */
303   direction_frame = gtk_frame_new("Direction");
304   gtk_box_pack_start(GTK_BOX(main_options_hb), direction_frame, FALSE, FALSE, 0);
305   gtk_widget_show(direction_frame);
306
307   /* Direction row: Forward and reverse radio buttons */
308   direction_vb = gtk_vbox_new(FALSE, 0);
309   gtk_container_set_border_width(GTK_CONTAINER(direction_vb), 3);
310   gtk_container_add(GTK_CONTAINER(direction_frame), direction_vb);
311   gtk_widget_show(direction_vb);
312
313   up_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "_Up");
314   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(up_rb), cfile.dir == SD_BACKWARD);
315   gtk_box_pack_start(GTK_BOX(direction_vb), up_rb, FALSE, FALSE, 0);
316   gtk_widget_show(up_rb);
317
318   down_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(up_rb), "_Down");
319   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(down_rb), cfile.dir == SD_FORWARD);
320   gtk_box_pack_start(GTK_BOX(direction_vb), down_rb, FALSE, FALSE, 0);
321   gtk_widget_show(down_rb);
322
323
324   /* Button row */
325   bbox = dlg_button_row_new(GTK_STOCK_FIND, GTK_STOCK_CANCEL, GTK_STOCK_HELP, NULL);
326   gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
327   gtk_widget_show(bbox);
328
329   ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_FIND);
330   g_signal_connect(ok_bt, "clicked", G_CALLBACK(find_frame_ok_cb), find_frame_w);
331
332   cancel_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
333   g_signal_connect(cancel_bt, "clicked", G_CALLBACK(find_frame_close_cb), find_frame_w);
334
335   help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
336   g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_FIND_DIALOG);
337
338   /* Attach pointers to needed widgets to the capture prefs window/object */
339   g_object_set_data(G_OBJECT(find_frame_w), E_FIND_FILT_KEY, filter_text_box);
340   g_object_set_data(G_OBJECT(find_frame_w), E_FIND_BACKWARD_KEY, up_rb);
341   g_object_set_data(G_OBJECT(find_frame_w), E_FIND_FILTERDATA_KEY, filter_rb);
342   g_object_set_data(G_OBJECT(find_frame_w), E_FIND_HEXDATA_KEY, hex_rb);
343   g_object_set_data(G_OBJECT(find_frame_w), E_FIND_STRINGDATA_KEY, string_rb);
344   g_object_set_data(G_OBJECT(find_frame_w), E_FIND_STRINGTYPE_LABEL_KEY, combo_lb);
345   g_object_set_data(G_OBJECT(find_frame_w), E_FIND_STRINGTYPE_KEY, combo_cb);
346   g_object_set_data(G_OBJECT(find_frame_w), E_CASE_SEARCH_KEY, case_cb);
347   g_object_set_data(G_OBJECT(find_frame_w), E_SOURCE_HEX_KEY, hex_data_rb);
348   g_object_set_data(G_OBJECT(find_frame_w), E_SOURCE_DECODE_KEY, decode_data_rb);
349   g_object_set_data(G_OBJECT(find_frame_w), E_SOURCE_SUMMARY_KEY, summary_data_rb);
350   g_object_set_data(G_OBJECT(find_frame_w), E_FILT_TE_BUTTON_KEY, filter_bt);
351
352   /*
353    * Now that we've attached the pointers, connect the signals - if
354    * we do so before we've attached the pointers, the signals may
355    * be delivered before the pointers are attached; the signal
356    * handlers expect the pointers to be attached, and won't be happy.
357    */
358   g_signal_connect(hex_rb, "clicked", G_CALLBACK(hex_selected_cb), find_frame_w);
359   g_signal_connect(string_rb, "clicked", G_CALLBACK(string_selected_cb), find_frame_w);
360   g_signal_connect(filter_rb, "clicked", G_CALLBACK(filter_selected_cb), find_frame_w);
361
362   string_selected_cb(NULL, find_frame_w);
363   filter_selected_cb(NULL, find_frame_w);
364
365   window_set_cancel_button(find_frame_w, cancel_bt, window_cancel_button_cb);
366
367   gtk_widget_grab_default(ok_bt);
368
369   /* Catch the "activate" signal on the filter text entry, so that
370      if the user types Return there, we act as if the "OK" button
371      had been selected, as happens if Return is typed if some widget
372      that *doesn't* handle the Return key has the input focus. */
373   dlg_set_activate(filter_text_box, ok_bt);
374
375   /* Give the initial focus to the "Filter" entry box. */
376   gtk_widget_grab_focus(filter_text_box);
377
378   g_signal_connect(find_frame_w, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
379   g_signal_connect(find_frame_w, "destroy", G_CALLBACK(find_frame_destroy_cb), NULL);
380
381   gtk_widget_show(find_frame_w);
382   window_present(find_frame_w);
383 }
384
385 /* this function opens the find frame dialogue and sets the filter string */
386 void
387 find_frame_with_filter(char *filter)
388 {
389         find_frame_cb(NULL, NULL);
390         gtk_entry_set_text(GTK_ENTRY(filter_text_box), filter);
391 }
392
393 /*
394  * Check the filter syntax based on the type of search we're doing.
395  */
396 static void
397 find_filter_te_syntax_check_cb(GtkWidget *w, gpointer parent_w)
398 {
399   const gchar     *strval;
400   GtkWidget       *hex_rb, *string_rb;
401   guint8          *bytes = NULL;
402   size_t           nbytes;
403
404   hex_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_HEXDATA_KEY);
405   string_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_STRINGDATA_KEY);
406
407   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (hex_rb))) {
408     /*
409      * Hex search - scan the search string to make sure it's valid hex.
410      */
411     strval = gtk_entry_get_text(GTK_ENTRY(w));
412     if (strval == NULL) {
413       /* XXX - can this happen? */
414       colorize_filter_te_as_invalid(w);
415     } else {
416       bytes = convert_string_to_hex(strval, &nbytes);
417       if (bytes == NULL)
418         colorize_filter_te_as_invalid(w);
419       else {
420         g_free(bytes);
421         colorize_filter_te_as_valid(w);
422       }
423     }
424   } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (string_rb))) {
425     /*
426      * String search.  Make sure the string isn't empty.
427      */
428     strval = gtk_entry_get_text(GTK_ENTRY(w));
429     if (strval == NULL) {
430       /* XXX - can this happen? */
431       colorize_filter_te_as_invalid(w);
432     } else {
433       if (strcmp(strval, "") == 0)
434         colorize_filter_te_as_invalid(w);
435       else
436         colorize_filter_te_as_valid(w);
437     }
438   } else {
439     /*
440      * Display filter search; check it with "filter_te_syntax_check_cb()".
441      */
442       filter_te_syntax_check_cb(w, NULL);
443   }
444 }
445
446 /*
447  *  This function will re-check the search text syntax.
448  */
449 static void
450 hex_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w)
451 {
452     GtkWidget   *filter_tb, *hex_rb;
453
454     filter_tb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_FILT_TE_PTR_KEY);
455     hex_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_HEXDATA_KEY);
456
457     /* Disable AutoCompletion feature */
458     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hex_rb)) && g_signal_handler_is_connected(filter_tb, te_presskey_handler_id)) {
459       g_signal_handler_disconnect(filter_tb, te_presskey_handler_id);
460       g_signal_handler_disconnect(parent_w, win_presskey_handler_id);
461     }
462
463     /* Re-check the display filter. */
464     find_filter_te_syntax_check_cb(filter_tb, parent_w);
465     return;
466 }
467
468 /*
469  *  This function will disable the string options until
470  *  the string search is selected.
471  */
472 static void
473 string_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w)
474 {
475     GtkWidget   *string_rb, *hex_data_rb, *decode_data_rb, *summary_data_rb,
476                 *data_combo_lb, *data_combo_cb, *data_case_cb, *filter_tb;
477
478     string_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_STRINGDATA_KEY);
479     hex_data_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_SOURCE_HEX_KEY);
480     decode_data_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_SOURCE_DECODE_KEY);
481     summary_data_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_SOURCE_SUMMARY_KEY);
482
483     data_combo_lb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_STRINGTYPE_LABEL_KEY);
484     data_combo_cb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_STRINGTYPE_KEY);
485     data_case_cb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_CASE_SEARCH_KEY);
486     filter_tb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_FILT_TE_PTR_KEY);
487
488     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(string_rb))) {
489         gtk_widget_set_sensitive(GTK_WIDGET(hex_data_rb), TRUE);
490         gtk_widget_set_sensitive(GTK_WIDGET(decode_data_rb), TRUE);
491         gtk_widget_set_sensitive(GTK_WIDGET(summary_data_rb), TRUE);
492         gtk_widget_set_sensitive(GTK_WIDGET(data_combo_lb), TRUE);
493         gtk_widget_set_sensitive(GTK_WIDGET(data_combo_cb), TRUE);
494         gtk_widget_set_sensitive(GTK_WIDGET(data_case_cb), TRUE);
495
496         /* Disable AutoCompletion feature */
497         if(g_signal_handler_is_connected(filter_tb, te_presskey_handler_id)) {
498           g_signal_handler_disconnect(filter_tb, te_presskey_handler_id);
499           g_signal_handler_disconnect(parent_w, win_presskey_handler_id);
500         }
501
502     } else {
503         gtk_widget_set_sensitive(GTK_WIDGET(hex_data_rb), FALSE);
504         gtk_widget_set_sensitive(GTK_WIDGET(decode_data_rb), FALSE);
505         gtk_widget_set_sensitive(GTK_WIDGET(summary_data_rb), FALSE);
506         gtk_widget_set_sensitive(GTK_WIDGET(data_combo_lb), FALSE);
507         gtk_widget_set_sensitive(GTK_WIDGET(data_combo_cb), FALSE);
508         gtk_widget_set_sensitive(GTK_WIDGET(data_case_cb), FALSE);
509     }
510     /* Re-check the display filter. */
511     find_filter_te_syntax_check_cb(filter_tb, parent_w);
512     return;
513 }
514
515 /*
516  *  This function will disable the filter button until
517  *  the filter search is selected.
518  */
519 static void
520 filter_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w)
521 {
522     GtkWidget   *filter_bt, *filter_rb, *filter_te;
523
524     filter_bt = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FILT_TE_BUTTON_KEY);
525     filter_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_FILTERDATA_KEY);
526     filter_te = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FILT_TE_PTR_KEY);
527
528     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(filter_rb)))
529     {
530         gtk_widget_set_sensitive(GTK_WIDGET(filter_bt), TRUE);
531         /* Enable AutoCompletion feature */
532         if(!g_signal_handler_is_connected(filter_te, te_presskey_handler_id)) {
533           te_presskey_handler_id = g_signal_connect(filter_te, "key-press-event", G_CALLBACK (filter_string_te_key_pressed_cb), NULL);
534           win_presskey_handler_id = g_signal_connect(parent_w, "key-press-event", G_CALLBACK (filter_parent_dlg_key_pressed_cb), NULL);
535         }
536     }
537     else
538     {
539         gtk_widget_set_sensitive(GTK_WIDGET(filter_bt), FALSE);
540     }
541     return;
542 }
543
544 static void
545 find_frame_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
546 {
547   GtkWidget       *filter_te, *up_rb, *hex_rb, *string_rb, *combo_cb,
548                   *case_cb, *decode_data_rb, *summary_data_rb;
549   const gchar     *filter_text;
550   search_charset_t scs_type = SCS_ASCII_AND_UNICODE;
551   guint8          *bytes = NULL;
552   size_t           nbytes = 0;
553   char            *string = NULL;
554   dfilter_t       *sfcode = NULL;
555   gboolean        found_packet=FALSE;
556   int                     string_type;
557
558   filter_te = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_FILT_KEY);
559   up_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_BACKWARD_KEY);
560   hex_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_HEXDATA_KEY);
561   string_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_STRINGDATA_KEY);
562   combo_cb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_STRINGTYPE_KEY);
563   case_cb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_CASE_SEARCH_KEY);
564   decode_data_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_SOURCE_DECODE_KEY);
565   summary_data_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_SOURCE_SUMMARY_KEY);
566
567   filter_text = gtk_entry_get_text(GTK_ENTRY(filter_te));
568
569   /* Corresponds to the enum in file.c
570    * Character set for text search. 
571    * typedef enum {
572    *   SCS_ASCII_AND_UNICODE,
573    *   SCS_ASCII,
574    *   SCS_UNICODE
575    *   / * add EBCDIC when it's implemented * /
576    * } search_charset_t;
577    */
578   string_type = gtk_combo_box_get_active (GTK_COMBO_BOX(combo_cb));
579
580   case_type = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(case_cb));
581   decode_data = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(decode_data_rb));
582   summary_data = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(summary_data_rb));
583
584   /*
585    * Process the search criterion.
586    */
587   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (hex_rb))) {
588     /*
589      * Hex search - scan the search string to make sure it's valid hex
590      * and to find out how many bytes there are.
591      */
592     bytes = convert_string_to_hex(filter_text, &nbytes);
593     if (bytes == NULL) {
594       statusbar_push_temporary_msg("That's not a valid hex string.");
595       return;
596     }
597   } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (string_rb))) {
598     /*
599      * String search.
600      * Make sure we're searching for something, first.
601      */
602     if (strcmp(filter_text, "") == 0) {
603       statusbar_push_temporary_msg("You didn't specify any text for which to search.");
604       return;
605     }
606
607     /*
608      * We are - get the character set type.
609      */
610     if (string_type == SCS_ASCII_AND_UNICODE)
611       scs_type = SCS_ASCII_AND_UNICODE;
612     else if (string_type == SCS_ASCII)
613       scs_type = SCS_ASCII;
614     else if (string_type == SCS_UNICODE)
615       scs_type = SCS_UNICODE;
616     else {
617       statusbar_push_temporary_msg("You didn't choose a valid character set.");
618       return;
619     }
620     string = convert_string_case(filter_text, case_type);
621   } else {
622     /*
623      * Display filter search - try to compile the filter.
624      */
625     if (!dfilter_compile(filter_text, &sfcode)) {
626       /* The attempt failed; report an error. */
627       bad_dfilter_alert_box(filter_text);
628       return;
629     }
630
631     /* Was it empty? */
632     if (sfcode == NULL) {
633       /* Yes - complain. */
634       statusbar_push_temporary_msg("That filter doesn't test anything.");
635       return;
636     }
637   }
638
639   /*
640    * Remember the search parameters.
641    */
642   g_free(cfile.sfilter);
643   cfile.sfilter = g_strdup(filter_text);
644   cfile.dir = GTK_TOGGLE_BUTTON (up_rb)->active ? SD_BACKWARD : SD_FORWARD;
645   cfile.hex = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (hex_rb));
646   cfile.string = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (string_rb));
647   cfile.scs_type = scs_type;
648   cfile.case_type = case_type;
649   cfile.decode_data = decode_data;
650   cfile.summary_data = summary_data;
651
652   if (cfile.hex) {
653     found_packet = cf_find_packet_data(&cfile, bytes, nbytes, cfile.dir);
654     g_free(bytes);
655     if (!found_packet) {
656       /* We didn't find a packet */
657       statusbar_push_temporary_msg("No packet contained those bytes.");
658       return;
659     }
660   } else if (cfile.string) {
661     /* OK, what are we searching? */
662     if (cfile.decode_data) {
663       /* The text in the protocol tree */
664       if(string){
665         found_packet = cf_find_packet_protocol_tree(&cfile, string, cfile.dir);
666         g_free(string);
667       }
668       if (!found_packet) {
669         /* We didn't find the packet. */
670         statusbar_push_temporary_msg("No packet contained that string in its dissected display.");
671         return;
672       }
673     } else if (cfile.summary_data) {
674       /* The text in the summary line */
675       if(string){
676         found_packet = cf_find_packet_summary_line(&cfile, string, cfile.dir);
677         g_free(string);
678       }
679       if (!found_packet) {
680         /* We didn't find the packet. */
681         simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
682             "%sNo match found!%s\n\n"
683             "No packet contained that string in its Info column.",
684             simple_dialog_primary_start(), simple_dialog_primary_end());
685         return;
686       }
687     } else {
688       /* The raw packet data */
689       if(string){
690         found_packet = cf_find_packet_data(&cfile, string, strlen(string),
691                                            cfile.dir);
692         g_free(string);
693       }
694       if (!found_packet) {
695         /* We didn't find the packet. */
696         statusbar_push_temporary_msg("No packet contained that string in its data.");
697         return;
698       }
699     }
700   } else {
701     found_packet = cf_find_packet_dfilter(&cfile, sfcode, cfile.dir);
702     dfilter_free(sfcode);
703     if (!found_packet) {
704       /* We didn't find a packet */
705       statusbar_push_temporary_msg("No packet matched that filter.");
706       g_free(bytes);
707       return;
708     }
709   }
710   window_destroy(GTK_WIDGET(parent_w));
711 }
712
713 static void
714 find_frame_close_cb(GtkWidget *close_bt _U_, gpointer parent_w)
715 {
716   gtk_grab_remove(GTK_WIDGET(parent_w));
717   window_destroy(GTK_WIDGET(parent_w));
718 }
719
720 static void
721 find_frame_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
722 {
723   /* Note that we no longer have a "Find Packet" dialog box. */
724   find_frame_w = NULL;
725 }
726
727 static void
728 find_previous_next(GtkWidget *w, gpointer d, search_direction dir)
729 {
730   guint8    *bytes;
731   size_t     nbytes;
732   char      *string;
733   dfilter_t *sfcode;
734
735   if (cfile.sfilter) {
736     cfile.dir = dir;
737     if (cfile.hex) {
738       bytes = convert_string_to_hex(cfile.sfilter, &nbytes);
739       if (bytes == NULL) {
740         /*
741          * XXX - this shouldn't happen, as we've already successfully
742          * translated the string once.
743          */
744         return;
745       }
746       cf_find_packet_data(&cfile, bytes, nbytes, dir);
747       g_free(bytes);
748     } else if (cfile.string) {
749       string = convert_string_case(cfile.sfilter, cfile.case_type);
750       /* OK, what are we searching? */
751       if (cfile.decode_data) {
752         /* The text in the protocol tree */
753         cf_find_packet_protocol_tree(&cfile, string, dir);
754       } else if (cfile.summary_data) {
755         /* The text in the summary line */
756         cf_find_packet_summary_line(&cfile, string, dir);
757       } else {
758         /* The raw packet data */
759         cf_find_packet_data(&cfile, string, strlen(string), dir);
760       }
761       g_free(string);
762     } else {
763       if (!dfilter_compile(cfile.sfilter, &sfcode)) {
764         /*
765          * XXX - this shouldn't happen, as we've already successfully
766          * translated the string once.
767          */
768         return;
769       }
770       if (sfcode == NULL) {
771         /*
772          * XXX - this shouldn't happen, as we've already found that the
773          * string wasn't null.
774          */
775         return;
776       }
777       cf_find_packet_dfilter(&cfile, sfcode, dir);
778       dfilter_free(sfcode);
779     }
780   } else
781      find_frame_cb(w, d);
782 }
783
784 void
785 find_next_cb(GtkWidget *w , gpointer d)
786 {
787   find_previous_next(w, d, SD_FORWARD);
788 }
789
790 void
791 find_previous_cb(GtkWidget *w , gpointer d)
792 {
793   find_previous_next(w, d, SD_BACKWARD);
794 }