Microsoft Credential Security Support Provider (CredSSP) support.
[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 #include "gtk/old-gtk-compat.h"
54
55 /* Capture callback data keys */
56 #define E_FIND_FILT_KEY       "find_filter_te"
57 #define E_FIND_BACKWARD_KEY   "find_backward"
58 #define E_FIND_HEXDATA_KEY    "find_hex"
59 #define E_FIND_STRINGDATA_KEY "find_string"
60 #define E_FIND_FILTERDATA_KEY "find_filter"
61 #define E_FIND_STRINGTYPE_KEY "find_string_type"
62 #define E_FIND_STRINGTYPE_LABEL_KEY "find_string_type_label"
63 #define E_CASE_SEARCH_KEY     "case_insensitive_search"
64 #define E_SOURCE_DATA_KEY     "packet_data_source"
65 #define E_SOURCE_DECODE_KEY   "decode_data_source"
66 #define E_SOURCE_SUMMARY_KEY  "summary_data_source"
67 #define E_FILT_TE_BUTTON_KEY  "find_filter_button"
68
69 static gboolean case_type = TRUE;
70 static gboolean summary_data = FALSE;
71 static gboolean decode_data = FALSE;
72 static gboolean packet_data = FALSE;
73
74 static void
75 find_filter_te_syntax_check_cb(GtkWidget *w, gpointer parent_w);
76
77 static void
78 find_frame_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
79
80 static void
81 find_frame_close_cb(GtkWidget *close_bt, gpointer parent_w);
82
83 static void
84 find_frame_destroy_cb(GtkWidget *win, gpointer user_data);
85
86 static void
87 hex_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w);
88
89 static void
90 string_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w);
91
92 static void
93 filter_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w);
94
95 /*
96  * Keep a static pointer to the current "Find Packet" window, if any, so
97  * that if somebody tries to do "Find Packet" while there's already a
98  * "Find Packet" window up, we just pop up the existing one, rather than
99  * creating a new one.
100  */
101 static GtkWidget *find_frame_w;
102 static GtkWidget *filter_text_box;
103
104 /*
105  * Save the presskey handlers to be able to dissable the auto-completion
106  * feature for hex and string searches.
107  */
108 static gulong te_presskey_handler_id;
109 static gulong win_presskey_handler_id;
110
111 void
112 find_frame_cb(GtkWidget *w _U_, gpointer d _U_)
113 {
114   GtkWidget     *main_vb, *main_find_hb, *main_options_hb,
115
116                 *find_type_frame, *find_type_vb,
117                 *find_type_hb, *find_type_lb, *hex_rb, *string_rb, *filter_rb,
118                 *filter_hb, *filter_bt,
119
120                 *direction_frame, *direction_vb,
121                 *up_rb, *down_rb,
122
123                 *data_frame, *data_vb,
124                 *packet_data_rb, *decode_data_rb, *summary_data_rb,
125
126                 *string_opt_frame, *string_opt_vb,
127                 *case_cb, *combo_lb, *combo_cb,
128
129                 *bbox, *ok_bt, *cancel_bt, *help_bt;
130
131
132   /* No Apply button, but "OK" not only sets our text widget, it
133      activates it (i.e., it causes us to do the search). */
134   static construct_args_t args = {
135         "Wireshark: Search Filter",
136         FALSE,
137         TRUE,
138     FALSE
139   };
140
141   if (find_frame_w != NULL) {
142     /* There's already a "Find Packet" dialog box; reactivate it. */
143     reactivate_window(find_frame_w);
144     return;
145   }
146
147   find_frame_w = dlg_window_new("Wireshark: Find Packet");
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_widget_set_tooltip_text(filter_rb, "Search for data by display filter syntax.\ne.g. ip.addr==10.1.1.1");
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_widget_set_tooltip_text(hex_rb, "Search for data by hex string.\ne.g. fffffda5");
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_widget_set_tooltip_text(string_rb, "Search for data by string value.\ne.g. My String");
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_widget_set_tooltip_text(filter_bt, "Click on the filter button to select a display filter,\nor enter your search criteria into the text box");
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_widget_set_tooltip_text(summary_data_rb, "Search for string in the Info column of the packet summary (summary pane)");
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_widget_set_tooltip_text(decode_data_rb, "Search for string among the decoded packet display labels (tree view pane)");
256   gtk_widget_show(decode_data_rb);
257
258   /* Packet bytes */
259   packet_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(packet_data_rb), packet_data);
261   gtk_box_pack_start(GTK_BOX(data_vb), packet_data_rb, TRUE, TRUE, 0);
262   gtk_widget_set_tooltip_text(packet_data_rb, "Search for string in the ASCII-converted packet data (hex view pane)");
263   gtk_widget_show(packet_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_widget_set_tooltip_text(case_cb, "Search by mixed upper/lower case?");
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_text_new();
291
292   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(combo_cb), "ASCII Unicode & Non-Unicode");
293   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(combo_cb), "ASCII Non-Unicode");
294   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(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_DATA_KEY, packet_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, *packet_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     packet_data_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_SOURCE_DATA_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(packet_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(packet_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, *packet_data_rb, *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   gboolean         hex_search;
557   gboolean         string_search;
558   int              string_type;
559
560   filter_te = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_FILT_KEY);
561   up_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_BACKWARD_KEY);
562   hex_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_HEXDATA_KEY);
563   string_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_STRINGDATA_KEY);
564   combo_cb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_STRINGTYPE_KEY);
565   case_cb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_CASE_SEARCH_KEY);
566   packet_data_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_SOURCE_DATA_KEY);
567   decode_data_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_SOURCE_DECODE_KEY);
568   summary_data_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_SOURCE_SUMMARY_KEY);
569
570   filter_text = gtk_entry_get_text(GTK_ENTRY(filter_te));
571
572   /* Corresponds to the enum in file.c
573    * Character set for text search.
574    * typedef enum {
575    *   SCS_ASCII_AND_UNICODE,
576    *   SCS_ASCII,
577    *   SCS_UNICODE
578    *   / * add EBCDIC when it's implemented * /
579    * } search_charset_t;
580    */
581   string_type = gtk_combo_box_get_active (GTK_COMBO_BOX(combo_cb));
582
583   case_type     = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(case_cb));
584   packet_data   =  gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(packet_data_rb));
585   decode_data   =  gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(decode_data_rb));
586   summary_data  =  gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(summary_data_rb));
587   hex_search    =  gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (hex_rb));
588   string_search =  gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (string_rb));
589   /*
590    * Process the search criterion.
591    */
592   if (hex_search) {
593     /*
594      * Hex search - scan the search string to make sure it's valid hex
595      * and to find out how many bytes there are.
596      */
597     bytes = convert_string_to_hex(filter_text, &nbytes);
598     if (bytes == NULL) {
599       statusbar_push_temporary_msg("That's not a valid hex string.");
600       return;
601     }
602   } else if (string_search) {
603     /*
604      * String search.
605      * Make sure we're searching for something, first.
606      */
607     if (strcmp(filter_text, "") == 0) {
608       statusbar_push_temporary_msg("You didn't specify any text for which to search.");
609       return;
610     }
611
612     /*
613      * We are - get the character set type.
614      */
615     if (string_type == SCS_ASCII_AND_UNICODE)
616       scs_type = SCS_ASCII_AND_UNICODE;
617     else if (string_type == SCS_ASCII)
618       scs_type = SCS_ASCII;
619     else if (string_type == SCS_UNICODE)
620       scs_type = SCS_UNICODE;
621     else {
622       statusbar_push_temporary_msg("You didn't choose a valid character set.");
623       return;
624     }
625     string = convert_string_case(filter_text, case_type);
626   } else {
627     /*
628      * Display filter search - try to compile the filter.
629      */
630     if (!dfilter_compile(filter_text, &sfcode)) {
631       /* The attempt failed; report an error. */
632       bad_dfilter_alert_box(filter_text);
633       return;
634     }
635
636     /* Was it empty? */
637     if (sfcode == NULL) {
638       /* Yes - complain. */
639       statusbar_push_temporary_msg("That filter doesn't test anything.");
640       return;
641     }
642   }
643
644   /*
645    * Remember the search parameters.
646    */
647   g_free(cfile.sfilter);
648   cfile.sfilter = g_strdup(filter_text);
649   cfile.dir          = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (up_rb)) ? SD_BACKWARD : SD_FORWARD;
650   cfile.hex          = hex_search;
651   cfile.string       = string_search;
652   cfile.scs_type     = scs_type;
653   cfile.case_type    = case_type;
654   cfile.packet_data  = packet_data;
655   cfile.decode_data  = decode_data;
656   cfile.summary_data = summary_data;
657
658   if (cfile.hex) {
659     /* Hex value in packet data */
660     found_packet = cf_find_packet_data(&cfile, bytes, nbytes, cfile.dir);
661     g_free(bytes);
662     if (!found_packet) {
663       /* We didn't find a packet */
664       statusbar_push_temporary_msg("No packet contained those bytes.");
665       return;
666     }
667   } else if (cfile.string) {
668     if (cfile.summary_data) {
669       /* String in the Info column of the summary line */
670       found_packet = cf_find_packet_summary_line(&cfile, string, cfile.dir);
671       g_free(string);
672       if (!found_packet) {
673         statusbar_push_temporary_msg("No packet contained that string in its Info column.");
674         return;
675       }
676     } else if (cfile.decode_data) {
677       /* String in the protocol tree headings */
678       found_packet = cf_find_packet_protocol_tree(&cfile, string, cfile.dir);
679       g_free(string);
680       if (!found_packet) {
681         statusbar_push_temporary_msg("No packet contained that string in its dissected display.");
682         return;
683       }
684     } else if (cfile.packet_data && string) {
685       /* String in the ASCII-converted packet data */
686       found_packet = cf_find_packet_data(&cfile, string, strlen(string), cfile.dir);
687       g_free(string);
688       if (!found_packet) {
689         statusbar_push_temporary_msg("No packet contained that string in its ASCII-converted data.");
690         return;
691       }
692     }
693   } else {
694     /* Search via display filter */
695     found_packet = cf_find_packet_dfilter(&cfile, sfcode, cfile.dir);
696     dfilter_free(sfcode);
697     if (!found_packet) {
698       statusbar_push_temporary_msg("No packet matched that filter.");
699       g_free(bytes);
700       return;
701     }
702   }
703   window_destroy(GTK_WIDGET(parent_w));
704 }
705
706 static void
707 find_frame_close_cb(GtkWidget *close_bt _U_, gpointer parent_w)
708 {
709   gtk_grab_remove(GTK_WIDGET(parent_w));
710   window_destroy(GTK_WIDGET(parent_w));
711 }
712
713 static void
714 find_frame_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
715 {
716   /* Note that we no longer have a "Find Packet" dialog box. */
717   find_frame_w = NULL;
718 }
719
720 static void
721 find_previous_next(GtkWidget *w, gpointer d, search_direction dir)
722 {
723   guint8    *bytes;
724   size_t     nbytes;
725   char      *string;
726   dfilter_t *sfcode;
727
728   if (cfile.sfilter) {
729     cfile.dir = dir;
730     if (cfile.hex) {
731       bytes = convert_string_to_hex(cfile.sfilter, &nbytes);
732       if (bytes == NULL) {
733         /*
734          * XXX - this shouldn't happen, as we've already successfully
735          * translated the string once.
736          */
737         return;
738       }
739       cf_find_packet_data(&cfile, bytes, nbytes, dir);
740       g_free(bytes);
741     } else if (cfile.string) {
742       string = convert_string_case(cfile.sfilter, cfile.case_type);
743       /* OK, what are we searching? */
744       if (cfile.decode_data) {
745         /* The text in the protocol tree */
746         cf_find_packet_protocol_tree(&cfile, string, dir);
747       } else if (cfile.summary_data) {
748         /* The text in the summary line */
749         cf_find_packet_summary_line(&cfile, string, dir);
750       } else {
751         /* The raw packet data */
752         cf_find_packet_data(&cfile, string, strlen(string), dir);
753       }
754       g_free(string);
755     } else {
756       if (!dfilter_compile(cfile.sfilter, &sfcode)) {
757         /*
758          * XXX - this shouldn't happen, as we've already successfully
759          * translated the string once.
760          */
761         return;
762       }
763       if (sfcode == NULL) {
764         /*
765          * XXX - this shouldn't happen, as we've already found that the
766          * string wasn't null.
767          */
768         return;
769       }
770       cf_find_packet_dfilter(&cfile, sfcode, dir);
771       dfilter_free(sfcode);
772     }
773   } else
774      find_frame_cb(w, d);
775 }
776
777 void
778 find_next_cb(GtkWidget *w , gpointer d)
779 {
780   find_previous_next(w, d, SD_FORWARD);
781 }
782
783 void
784 find_previous_cb(GtkWidget *w , gpointer d)
785 {
786   find_previous_next(w, d, SD_BACKWARD);
787 }