HACK: 1. try to match RowsetProperties
[wireshark-wip.git] / ui / gtk / find_dlg.c
blob08a4b5501b29b62c9b167fc8b9b649a0f4d0e74e
1 /* find_dlg.c
2 * Routines for "find frame" window
4 * $Id$
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "config.h"
27 #include <string.h>
28 #include <ctype.h>
30 #include <gtk/gtk.h>
32 #include <epan/proto.h>
33 #include <epan/dfilter/dfilter.h>
34 #include <epan/strutil.h>
35 #include <epan/prefs.h>
37 #include "../globals.h"
38 #include "ui/alert_box.h"
39 #include "ui/main_statusbar.h"
41 #include "ui/gtk/gui_utils.h"
42 #include "ui/gtk/find_dlg.h"
43 #include "ui/gtk/filter_dlg.h"
44 #include "ui/gtk/dlg_utils.h"
45 #include "ui/gtk/stock_icons.h"
46 #include "ui/gtk/prefs_dlg.h"
47 #include "ui/gtk/keys.h"
48 #include "ui/gtk/help_dlg.h"
49 #include "ui/gtk/filter_autocomplete.h"
50 #include "ui/gtk/old-gtk-compat.h"
52 /* Capture callback data keys */
53 #define E_FIND_FILT_KEY "find_filter_te"
54 #define E_FIND_BACKWARD_KEY "find_backward"
55 #define E_FIND_HEXDATA_KEY "find_hex"
56 #define E_FIND_STRINGDATA_KEY "find_string"
57 #define E_FIND_FILTERDATA_KEY "find_filter"
58 #define E_FIND_STRINGTYPE_KEY "find_string_type"
59 #define E_FIND_STRINGTYPE_LABEL_KEY "find_string_type_label"
60 #define E_CASE_SEARCH_KEY "case_insensitive_search"
61 #define E_SOURCE_DATA_KEY "packet_data_source"
62 #define E_SOURCE_DECODE_KEY "decode_data_source"
63 #define E_SOURCE_SUMMARY_KEY "summary_data_source"
64 #define E_FILT_TE_BUTTON_KEY "find_filter_button"
66 static gboolean case_type = TRUE;
67 static gboolean summary_data = FALSE;
68 static gboolean decode_data = FALSE;
69 static gboolean packet_data = FALSE;
71 static void
72 find_filter_te_syntax_check_cb(GtkWidget *w, gpointer parent_w);
74 static void
75 find_frame_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
77 static void
78 find_frame_close_cb(GtkWidget *close_bt, gpointer parent_w);
80 static void
81 find_frame_destroy_cb(GtkWidget *win, gpointer user_data);
83 static void
84 hex_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w);
86 static void
87 string_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w);
89 static void
90 filter_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w);
93 * Keep a static pointer to the current "Find Packet" window, if any, so
94 * that if somebody tries to do "Find Packet" while there's already a
95 * "Find Packet" window up, we just pop up the existing one, rather than
96 * creating a new one.
98 static GtkWidget *find_frame_w;
99 static GtkWidget *filter_text_box;
102 * Save the presskey handlers to be able to dissable the auto-completion
103 * feature for hex and string searches.
105 static gulong te_presskey_handler_id;
106 static gulong win_presskey_handler_id;
108 void
109 find_frame_cb(GtkWidget *w _U_, gpointer d _U_)
111 GtkWidget *main_vb, *main_find_hb, *main_options_hb,
113 *find_type_frame, *find_type_vb,
114 *find_type_hb, *find_type_lb, *hex_rb, *string_rb, *filter_rb,
115 *filter_hb, *filter_bt,
117 *direction_frame, *direction_vb,
118 *up_rb, *down_rb,
120 *data_frame, *data_vb,
121 *packet_data_rb, *decode_data_rb, *summary_data_rb,
123 *string_opt_frame, *string_opt_vb,
124 *case_cb, *combo_lb, *combo_cb,
126 *bbox, *ok_bt, *cancel_bt, *help_bt;
129 /* No Apply button, but "OK" not only sets our text widget, it
130 activates it (i.e., it causes us to do the search). */
131 static construct_args_t args = {
132 "Wireshark: Search Filter",
133 FALSE,
134 TRUE,
135 FALSE
138 if (find_frame_w != NULL) {
139 /* There's already a "Find Packet" dialog box; reactivate it. */
140 reactivate_window(find_frame_w);
141 return;
144 find_frame_w = dlg_window_new("Wireshark: Find Packet");
146 /* Container for each row of widgets */
147 main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 3, FALSE);
148 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
149 gtk_container_add(GTK_CONTAINER(find_frame_w), main_vb);
150 gtk_widget_show(main_vb);
153 /* */
154 main_find_hb = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3, FALSE);
155 gtk_box_pack_start(GTK_BOX (main_vb), main_find_hb, TRUE, TRUE, 0);
156 gtk_widget_show(main_find_hb);
159 /* find frame */
160 find_type_frame = gtk_frame_new("Find");
161 gtk_box_pack_start(GTK_BOX(main_find_hb), find_type_frame, TRUE, TRUE, 0);
162 gtk_widget_show(find_type_frame);
164 find_type_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 3, FALSE);
165 gtk_container_set_border_width(GTK_CONTAINER(find_type_vb), 3);
166 gtk_container_add(GTK_CONTAINER(find_type_frame), find_type_vb);
167 gtk_widget_show(find_type_vb);
169 /* find type row */
170 find_type_hb = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3, FALSE);
171 gtk_box_pack_start(GTK_BOX (find_type_vb), find_type_hb, TRUE, TRUE, 0);
172 gtk_widget_show(find_type_hb);
174 find_type_lb = gtk_label_new("By:");
175 gtk_box_pack_start(GTK_BOX(find_type_hb), find_type_lb, FALSE, FALSE, 0);
176 gtk_widget_show(find_type_lb);
178 /* Filter */
179 filter_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "_Display filter");
180 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filter_rb), !cfile.hex && !cfile.string);
181 gtk_box_pack_start(GTK_BOX(find_type_hb), filter_rb, FALSE, FALSE, 0);
182 gtk_widget_set_tooltip_text(filter_rb, "Search for data by display filter syntax.\ne.g. ip.addr==10.1.1.1");
183 gtk_widget_show(filter_rb);
185 /* Hex */
186 hex_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(filter_rb), "_Hex value");
187 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hex_rb), cfile.hex);
188 gtk_box_pack_start(GTK_BOX(find_type_hb), hex_rb, FALSE, FALSE, 0);
189 gtk_widget_set_tooltip_text(hex_rb, "Search for data by hex string.\ne.g. fffffda5");
190 gtk_widget_show(hex_rb);
192 /* ASCII Search */
193 string_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(filter_rb), "_String");
194 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(string_rb), cfile.string);
195 gtk_box_pack_start(GTK_BOX(find_type_hb), string_rb, FALSE, FALSE, 0);
196 gtk_widget_set_tooltip_text(string_rb, "Search for data by string value.\ne.g. My String");
197 gtk_widget_show(string_rb);
199 /* Filter row */
200 filter_hb = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3, FALSE);
201 gtk_box_pack_start(GTK_BOX(find_type_vb), filter_hb, FALSE, FALSE, 0);
202 gtk_widget_show(filter_hb);
204 filter_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
205 g_signal_connect(filter_bt, "clicked", G_CALLBACK(display_filter_construct_cb), &args);
206 g_signal_connect(filter_bt, "destroy", G_CALLBACK(filter_button_destroy_cb), NULL);
207 g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_BUTTON_KEY, filter_bt);
208 gtk_box_pack_start(GTK_BOX(filter_hb), filter_bt, FALSE, TRUE, 0);
209 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");
210 gtk_widget_show(filter_bt);
212 filter_text_box = gtk_entry_new();
213 if (cfile.sfilter) gtk_entry_set_text(GTK_ENTRY(filter_text_box), cfile.sfilter);
214 g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_text_box);
215 g_object_set_data(G_OBJECT(find_frame_w), E_FILT_TE_PTR_KEY, filter_text_box);
216 gtk_box_pack_start(GTK_BOX(filter_hb), filter_text_box, TRUE, TRUE, 0);
217 g_signal_connect(filter_text_box, "changed", G_CALLBACK(find_filter_te_syntax_check_cb), find_frame_w);
218 g_object_set_data(G_OBJECT(find_frame_w), E_FILT_AUTOCOMP_PTR_KEY, NULL);
219 te_presskey_handler_id = g_signal_connect(filter_text_box, "key-press-event", G_CALLBACK (filter_string_te_key_pressed_cb), NULL);
220 win_presskey_handler_id = g_signal_connect(find_frame_w, "key-press-event", G_CALLBACK (filter_parent_dlg_key_pressed_cb), NULL);
221 gtk_widget_show(filter_text_box);
224 /* */
225 main_options_hb = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3, FALSE);
226 gtk_box_pack_start(GTK_BOX (main_vb), main_options_hb, TRUE, TRUE, 0);
227 gtk_widget_show(main_options_hb);
230 /* search in frame */
231 data_frame = gtk_frame_new("Search In");
232 gtk_box_pack_start(GTK_BOX(main_options_hb), data_frame, TRUE, TRUE, 0);
233 gtk_widget_show(data_frame);
235 /* search in row */
236 data_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 0, FALSE);
237 gtk_container_set_border_width(GTK_CONTAINER(data_vb), 3);
238 gtk_container_add(GTK_CONTAINER(data_frame), data_vb);
239 gtk_widget_show(data_vb);
241 /* Packet list */
242 summary_data_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "Packet list");
243 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(summary_data_rb), summary_data);
244 gtk_box_pack_start(GTK_BOX(data_vb), summary_data_rb, TRUE, TRUE, 0);
245 gtk_widget_set_tooltip_text(summary_data_rb, "Search for string in the Info column of the packet summary (summary pane)");
246 gtk_widget_show(summary_data_rb);
248 /* Packet details */
249 decode_data_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(summary_data_rb), "Packet details");
250 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(decode_data_rb), decode_data);
251 gtk_box_pack_start(GTK_BOX(data_vb), decode_data_rb, TRUE, TRUE, 0);
252 gtk_widget_set_tooltip_text(decode_data_rb, "Search for string among the decoded packet display labels (tree view pane)");
253 gtk_widget_show(decode_data_rb);
255 /* Packet bytes */
256 packet_data_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(summary_data_rb), "Packet bytes");
257 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(packet_data_rb), packet_data);
258 gtk_box_pack_start(GTK_BOX(data_vb), packet_data_rb, TRUE, TRUE, 0);
259 gtk_widget_set_tooltip_text(packet_data_rb, "Search for string in the ASCII-converted packet data (hex view pane)");
260 gtk_widget_show(packet_data_rb);
262 /* string options frame */
263 string_opt_frame = gtk_frame_new("String Options");
264 gtk_box_pack_start(GTK_BOX(main_options_hb), string_opt_frame, TRUE, TRUE, 0);
265 gtk_widget_show(string_opt_frame);
267 string_opt_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 0, FALSE);
268 gtk_container_add(GTK_CONTAINER(string_opt_frame), string_opt_vb);
269 gtk_container_set_border_width(GTK_CONTAINER(string_opt_vb), 3);
270 gtk_widget_show(string_opt_vb);
272 case_cb = gtk_check_button_new_with_mnemonic("Case sensitive");
273 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(case_cb), !case_type);
274 gtk_box_pack_start(GTK_BOX (string_opt_vb), case_cb, TRUE, TRUE, 0);
275 gtk_widget_set_tooltip_text(case_cb, "Search by mixed upper/lower case?");
276 gtk_widget_show(case_cb);
278 combo_lb = gtk_label_new("Character width:");
279 gtk_box_pack_start(GTK_BOX (string_opt_vb), combo_lb, TRUE, TRUE, 0);
280 gtk_misc_set_alignment(GTK_MISC(combo_lb), 0.0f, 0.5f);
281 gtk_widget_show(combo_lb);
283 /* Character Type Selection Dropdown Box
284 These only apply to the string find option */
285 /* Create Combo Box */
287 combo_cb = gtk_combo_box_text_new();
289 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(combo_cb), "Narrow & wide");
290 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(combo_cb), "Narrow (UTF-8 / ASCII)");
291 /* UCS-2 might be more accurate but then we'd have to explain why we don't support UTF-16 */
292 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(combo_cb), "Wide (UTF-16)");
294 gtk_combo_box_set_active(GTK_COMBO_BOX(combo_cb),0);
295 gtk_box_pack_start(GTK_BOX (string_opt_vb), combo_cb, TRUE, TRUE, 0);
297 gtk_widget_show(combo_cb);
300 /* direction frame */
301 direction_frame = gtk_frame_new("Direction");
302 gtk_box_pack_start(GTK_BOX(main_options_hb), direction_frame, FALSE, FALSE, 0);
303 gtk_widget_show(direction_frame);
305 /* Direction row: Forward and reverse radio buttons */
306 direction_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 0, FALSE);
307 gtk_container_set_border_width(GTK_CONTAINER(direction_vb), 3);
308 gtk_container_add(GTK_CONTAINER(direction_frame), direction_vb);
309 gtk_widget_show(direction_vb);
311 up_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "_Up");
312 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(up_rb), cfile.dir == SD_BACKWARD);
313 gtk_box_pack_start(GTK_BOX(direction_vb), up_rb, FALSE, FALSE, 0);
314 gtk_widget_show(up_rb);
316 down_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(up_rb), "_Down");
317 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(down_rb), cfile.dir == SD_FORWARD);
318 gtk_box_pack_start(GTK_BOX(direction_vb), down_rb, FALSE, FALSE, 0);
319 gtk_widget_show(down_rb);
322 /* Button row */
323 bbox = dlg_button_row_new(GTK_STOCK_FIND, GTK_STOCK_CANCEL, GTK_STOCK_HELP, NULL);
324 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
325 gtk_widget_show(bbox);
327 ok_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_FIND);
328 g_signal_connect(ok_bt, "clicked", G_CALLBACK(find_frame_ok_cb), find_frame_w);
330 cancel_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
331 g_signal_connect(cancel_bt, "clicked", G_CALLBACK(find_frame_close_cb), find_frame_w);
333 help_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
334 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_FIND_DIALOG);
336 /* Attach pointers to needed widgets to the capture prefs window/object */
337 g_object_set_data(G_OBJECT(find_frame_w), E_FIND_FILT_KEY, filter_text_box);
338 g_object_set_data(G_OBJECT(find_frame_w), E_FIND_BACKWARD_KEY, up_rb);
339 g_object_set_data(G_OBJECT(find_frame_w), E_FIND_FILTERDATA_KEY, filter_rb);
340 g_object_set_data(G_OBJECT(find_frame_w), E_FIND_HEXDATA_KEY, hex_rb);
341 g_object_set_data(G_OBJECT(find_frame_w), E_FIND_STRINGDATA_KEY, string_rb);
342 g_object_set_data(G_OBJECT(find_frame_w), E_FIND_STRINGTYPE_LABEL_KEY, combo_lb);
343 g_object_set_data(G_OBJECT(find_frame_w), E_FIND_STRINGTYPE_KEY, combo_cb);
344 g_object_set_data(G_OBJECT(find_frame_w), E_CASE_SEARCH_KEY, case_cb);
345 g_object_set_data(G_OBJECT(find_frame_w), E_SOURCE_DATA_KEY, packet_data_rb);
346 g_object_set_data(G_OBJECT(find_frame_w), E_SOURCE_DECODE_KEY, decode_data_rb);
347 g_object_set_data(G_OBJECT(find_frame_w), E_SOURCE_SUMMARY_KEY, summary_data_rb);
348 g_object_set_data(G_OBJECT(find_frame_w), E_FILT_TE_BUTTON_KEY, filter_bt);
351 * Now that we've attached the pointers, connect the signals - if
352 * we do so before we've attached the pointers, the signals may
353 * be delivered before the pointers are attached; the signal
354 * handlers expect the pointers to be attached, and won't be happy.
356 g_signal_connect(hex_rb, "clicked", G_CALLBACK(hex_selected_cb), find_frame_w);
357 g_signal_connect(string_rb, "clicked", G_CALLBACK(string_selected_cb), find_frame_w);
358 g_signal_connect(filter_rb, "clicked", G_CALLBACK(filter_selected_cb), find_frame_w);
360 string_selected_cb(NULL, find_frame_w);
361 filter_selected_cb(NULL, find_frame_w);
363 window_set_cancel_button(find_frame_w, cancel_bt, window_cancel_button_cb);
365 gtk_widget_grab_default(ok_bt);
367 /* Catch the "activate" signal on the filter text entry, so that
368 if the user types Return there, we act as if the "OK" button
369 had been selected, as happens if Return is typed if some widget
370 that *doesn't* handle the Return key has the input focus. */
371 dlg_set_activate(filter_text_box, ok_bt);
373 /* Give the initial focus to the "Filter" entry box. */
374 gtk_widget_grab_focus(filter_text_box);
376 g_signal_connect(find_frame_w, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
377 g_signal_connect(find_frame_w, "destroy", G_CALLBACK(find_frame_destroy_cb), NULL);
379 gtk_widget_show(find_frame_w);
380 window_present(find_frame_w);
383 /* this function opens the find frame dialogue and sets the filter string */
384 void
385 find_frame_with_filter(char *filter)
387 find_frame_cb(NULL, NULL);
388 gtk_entry_set_text(GTK_ENTRY(filter_text_box), filter);
392 * Check the filter syntax based on the type of search we're doing.
394 static void
395 find_filter_te_syntax_check_cb(GtkWidget *w, gpointer parent_w)
397 const gchar *strval;
398 GtkWidget *hex_rb, *string_rb;
399 guint8 *bytes = NULL;
400 size_t nbytes;
402 hex_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_HEXDATA_KEY);
403 string_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_STRINGDATA_KEY);
405 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (hex_rb))) {
407 * Hex search - scan the search string to make sure it's valid hex.
409 strval = gtk_entry_get_text(GTK_ENTRY(w));
410 if (strval == NULL) {
411 /* XXX - can this happen? */
412 colorize_filter_te_as_invalid(w);
413 } else {
414 bytes = convert_string_to_hex(strval, &nbytes);
415 if (bytes == NULL)
416 colorize_filter_te_as_invalid(w);
417 else {
418 g_free(bytes);
419 colorize_filter_te_as_valid(w);
422 } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (string_rb))) {
424 * String search. Make sure the string isn't empty.
426 strval = gtk_entry_get_text(GTK_ENTRY(w));
427 if (strval == NULL) {
428 /* XXX - can this happen? */
429 colorize_filter_te_as_invalid(w);
430 } else {
431 if (strcmp(strval, "") == 0)
432 colorize_filter_te_as_invalid(w);
433 else
434 colorize_filter_te_as_valid(w);
436 } else {
438 * Display filter search; check it with "filter_te_syntax_check_cb()".
440 filter_te_syntax_check_cb(w, NULL);
445 * This function will re-check the search text syntax.
447 static void
448 hex_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w)
450 GtkWidget *filter_tb, *hex_rb, *filter_entry;
452 filter_tb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_FILT_TE_PTR_KEY);
453 hex_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_HEXDATA_KEY);
455 filter_entry = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w),E_FIND_FILT_KEY);
456 gtk_widget_grab_focus(filter_entry);
458 /* Disable AutoCompletion feature */
459 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hex_rb)) && g_signal_handler_is_connected(filter_tb, te_presskey_handler_id)) {
460 g_signal_handler_disconnect(filter_tb, te_presskey_handler_id);
461 g_signal_handler_disconnect(parent_w, win_presskey_handler_id);
464 /* Re-check the display filter. */
465 find_filter_te_syntax_check_cb(filter_tb, parent_w);
466 return;
470 * This function will disable the string options until
471 * the string search is selected.
473 static void
474 string_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w)
476 GtkWidget *string_rb, *packet_data_rb, *decode_data_rb, *summary_data_rb,
477 *data_combo_lb, *data_combo_cb, *data_case_cb, *filter_tb, *filter_entry;
479 string_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_STRINGDATA_KEY);
480 packet_data_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_SOURCE_DATA_KEY);
481 decode_data_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_SOURCE_DECODE_KEY);
482 summary_data_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_SOURCE_SUMMARY_KEY);
484 data_combo_lb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_STRINGTYPE_LABEL_KEY);
485 data_combo_cb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_STRINGTYPE_KEY);
486 data_case_cb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_CASE_SEARCH_KEY);
487 filter_tb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_FILT_TE_PTR_KEY);
489 filter_entry = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w),E_FIND_FILT_KEY);
490 gtk_widget_grab_focus(filter_entry);
492 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(string_rb))) {
493 gtk_widget_set_sensitive(GTK_WIDGET(packet_data_rb), TRUE);
494 gtk_widget_set_sensitive(GTK_WIDGET(decode_data_rb), TRUE);
495 gtk_widget_set_sensitive(GTK_WIDGET(summary_data_rb), TRUE);
496 gtk_widget_set_sensitive(GTK_WIDGET(data_combo_lb), TRUE);
497 gtk_widget_set_sensitive(GTK_WIDGET(data_combo_cb), TRUE);
498 gtk_widget_set_sensitive(GTK_WIDGET(data_case_cb), TRUE);
500 /* Disable AutoCompletion feature */
501 if(g_signal_handler_is_connected(filter_tb, te_presskey_handler_id)) {
502 g_signal_handler_disconnect(filter_tb, te_presskey_handler_id);
503 g_signal_handler_disconnect(parent_w, win_presskey_handler_id);
506 } else {
507 gtk_widget_set_sensitive(GTK_WIDGET(packet_data_rb), FALSE);
508 gtk_widget_set_sensitive(GTK_WIDGET(decode_data_rb), FALSE);
509 gtk_widget_set_sensitive(GTK_WIDGET(summary_data_rb), FALSE);
510 gtk_widget_set_sensitive(GTK_WIDGET(data_combo_lb), FALSE);
511 gtk_widget_set_sensitive(GTK_WIDGET(data_combo_cb), FALSE);
512 gtk_widget_set_sensitive(GTK_WIDGET(data_case_cb), FALSE);
514 /* Re-check the display filter. */
515 find_filter_te_syntax_check_cb(filter_tb, parent_w);
516 return;
520 * This function will disable the filter button until
521 * the filter search is selected.
523 static void
524 filter_selected_cb(GtkWidget *button_rb _U_, gpointer parent_w)
526 GtkWidget *filter_bt, *filter_rb, *filter_te, *filter_entry;
528 filter_bt = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FILT_TE_BUTTON_KEY);
529 filter_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_FILTERDATA_KEY);
530 filter_te = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FILT_TE_PTR_KEY);
532 filter_entry = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w),E_FIND_FILT_KEY);
533 gtk_widget_grab_focus(filter_entry);
535 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(filter_rb)))
537 gtk_widget_set_sensitive(GTK_WIDGET(filter_bt), TRUE);
538 /* Enable AutoCompletion feature */
539 if(!g_signal_handler_is_connected(filter_te, te_presskey_handler_id)) {
540 te_presskey_handler_id = g_signal_connect(filter_te, "key-press-event", G_CALLBACK (filter_string_te_key_pressed_cb), NULL);
541 win_presskey_handler_id = g_signal_connect(parent_w, "key-press-event", G_CALLBACK (filter_parent_dlg_key_pressed_cb), NULL);
544 else
546 gtk_widget_set_sensitive(GTK_WIDGET(filter_bt), FALSE);
548 return;
551 static void
552 find_frame_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
554 GtkWidget *filter_te, *up_rb, *hex_rb, *string_rb, *combo_cb,
555 *case_cb, *packet_data_rb, *decode_data_rb, *summary_data_rb;
556 const gchar *filter_text;
557 search_charset_t scs_type = SCS_NARROW_AND_WIDE;
558 guint8 *bytes = NULL;
559 size_t nbytes = 0;
560 char *string = NULL;
561 dfilter_t *sfcode = NULL;
562 gboolean found_packet=FALSE;
563 gboolean hex_search;
564 gboolean string_search;
565 int string_type;
567 filter_te = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_FILT_KEY);
568 up_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_BACKWARD_KEY);
569 hex_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_HEXDATA_KEY);
570 string_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_STRINGDATA_KEY);
571 combo_cb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_FIND_STRINGTYPE_KEY);
572 case_cb = (GtkWidget *) g_object_get_data(G_OBJECT(parent_w), E_CASE_SEARCH_KEY);
573 packet_data_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_SOURCE_DATA_KEY);
574 decode_data_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_SOURCE_DECODE_KEY);
575 summary_data_rb = (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_SOURCE_SUMMARY_KEY);
577 filter_text = gtk_entry_get_text(GTK_ENTRY(filter_te));
579 /* Corresponds to the enum in file.c
580 * Character set for text search.
581 * typedef enum {
582 * SCS_NARROW_AND_WIDE,
583 * SCS_NARROW,
584 * SCS_WIDE
585 * / * add EBCDIC when it's implemented * /
586 * } search_charset_t;
588 string_type = gtk_combo_box_get_active (GTK_COMBO_BOX(combo_cb));
590 case_type = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(case_cb));
591 packet_data = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(packet_data_rb));
592 decode_data = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(decode_data_rb));
593 summary_data = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(summary_data_rb));
594 hex_search = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (hex_rb));
595 string_search = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (string_rb));
597 * Process the search criterion.
599 if (hex_search) {
601 * Hex search - scan the search string to make sure it's valid hex
602 * and to find out how many bytes there are.
604 bytes = convert_string_to_hex(filter_text, &nbytes);
605 if (bytes == NULL) {
606 statusbar_push_temporary_msg("That's not a valid hex string.");
607 return;
609 } else if (string_search) {
611 * String search.
612 * Make sure we're searching for something, first.
614 if (strcmp(filter_text, "") == 0) {
615 statusbar_push_temporary_msg("You didn't specify any text for which to search.");
616 return;
620 * We are - get the character set type.
622 if (string_type == SCS_NARROW_AND_WIDE)
623 scs_type = SCS_NARROW_AND_WIDE;
624 else if (string_type == SCS_NARROW)
625 scs_type = SCS_NARROW;
626 else if (string_type == SCS_WIDE)
627 scs_type = SCS_WIDE;
628 else {
629 statusbar_push_temporary_msg("You didn't choose a valid character set.");
630 return;
632 string = convert_string_case(filter_text, case_type);
633 } else {
635 * Display filter search - try to compile the filter.
637 if (!dfilter_compile(filter_text, &sfcode)) {
638 /* The attempt failed; report an error. */
639 bad_dfilter_alert_box(GTK_WIDGET(parent_w), filter_text);
640 return;
643 /* Was it empty? */
644 if (sfcode == NULL) {
645 /* Yes - complain. */
646 statusbar_push_temporary_msg("That filter doesn't test anything.");
647 return;
652 * Remember the search parameters.
654 g_free(cfile.sfilter);
655 cfile.sfilter = g_strdup(filter_text);
656 cfile.dir = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (up_rb)) ? SD_BACKWARD : SD_FORWARD;
657 cfile.hex = hex_search;
658 cfile.string = string_search;
659 cfile.scs_type = scs_type;
660 cfile.case_type = case_type;
661 cfile.packet_data = packet_data;
662 cfile.decode_data = decode_data;
663 cfile.summary_data = summary_data;
665 if (cfile.hex) {
666 /* Hex value in packet data */
667 found_packet = cf_find_packet_data(&cfile, bytes, nbytes, cfile.dir);
668 g_free(bytes);
669 if (!found_packet) {
670 /* We didn't find a packet */
671 statusbar_push_temporary_msg("No packet contained those bytes.");
672 return;
674 } else if (cfile.string) {
675 if (cfile.summary_data) {
676 /* String in the Info column of the summary line */
677 found_packet = cf_find_packet_summary_line(&cfile, string, cfile.dir);
678 g_free(string);
679 if (!found_packet) {
680 statusbar_push_temporary_msg("No packet contained that string in its Info column.");
681 return;
683 } else if (cfile.decode_data) {
684 /* String in the protocol tree headings */
685 found_packet = cf_find_packet_protocol_tree(&cfile, string, cfile.dir);
686 g_free(string);
687 if (!found_packet) {
688 statusbar_push_temporary_msg("No packet contained that string in its dissected display.");
689 return;
691 } else if (cfile.packet_data && string) {
692 /* String in the ASCII-converted packet data */
693 found_packet = cf_find_packet_data(&cfile, string, strlen(string), cfile.dir);
694 g_free(string);
695 if (!found_packet) {
696 statusbar_push_temporary_msg("No packet contained that string in its ASCII-converted data.");
697 return;
700 } else {
701 /* Search via display filter */
702 found_packet = cf_find_packet_dfilter(&cfile, sfcode, cfile.dir);
703 dfilter_free(sfcode);
704 if (!found_packet) {
705 statusbar_push_temporary_msg("No packet matched that filter.");
706 g_free(bytes);
707 return;
710 window_destroy(GTK_WIDGET(parent_w));
713 static void
714 find_frame_close_cb(GtkWidget *close_bt _U_, gpointer parent_w)
716 gtk_grab_remove(GTK_WIDGET(parent_w));
717 window_destroy(GTK_WIDGET(parent_w));
720 static void
721 find_frame_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
723 /* Note that we no longer have a "Find Packet" dialog box. */
724 find_frame_w = NULL;
727 static void
728 find_previous_next(GtkWidget *w, gpointer d, search_direction dir)
730 guint8 *bytes;
731 size_t nbytes;
732 char *string;
733 dfilter_t *sfcode;
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) {
741 * XXX - this shouldn't happen, as we've already successfully
742 * translated the string once.
744 return;
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);
761 g_free(string);
762 } else {
763 if (!dfilter_compile(cfile.sfilter, &sfcode)) {
765 * XXX - this shouldn't happen, as we've already successfully
766 * translated the string once.
768 return;
770 if (sfcode == NULL) {
772 * XXX - this shouldn't happen, as we've already found that the
773 * string wasn't null.
775 return;
777 cf_find_packet_dfilter(&cfile, sfcode, dir);
778 dfilter_free(sfcode);
780 } else
781 find_frame_cb(w, d);
784 void
785 find_next_cb(GtkWidget *w , gpointer d)
787 find_previous_next(w, d, SD_FORWARD);
790 void
791 find_previous_cb(GtkWidget *w , gpointer d)
793 find_previous_next(w, d, SD_BACKWARD);