2 * Routines for "find frame" window
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.
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
;
72 find_filter_te_syntax_check_cb(GtkWidget
*w
, gpointer parent_w
);
75 find_frame_ok_cb(GtkWidget
*ok_bt
, gpointer parent_w
);
78 find_frame_close_cb(GtkWidget
*close_bt
, gpointer parent_w
);
81 find_frame_destroy_cb(GtkWidget
*win
, gpointer user_data
);
84 hex_selected_cb(GtkWidget
*button_rb _U_
, gpointer parent_w
);
87 string_selected_cb(GtkWidget
*button_rb _U_
, gpointer parent_w
);
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
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
;
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
,
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",
138 if (find_frame_w
!= NULL
) {
139 /* There's already a "Find Packet" dialog box; reactivate it. */
140 reactivate_window(find_frame_w
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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 */
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.
395 find_filter_te_syntax_check_cb(GtkWidget
*w
, gpointer parent_w
)
398 GtkWidget
*hex_rb
, *string_rb
;
399 guint8
*bytes
= NULL
;
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
);
414 bytes
= convert_string_to_hex(strval
, &nbytes
);
416 colorize_filter_te_as_invalid(w
);
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
);
431 if (strcmp(strval
, "") == 0)
432 colorize_filter_te_as_invalid(w
);
434 colorize_filter_te_as_valid(w
);
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.
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
);
470 * This function will disable the string options until
471 * the string search is selected.
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
);
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
);
520 * This function will disable the filter button until
521 * the filter search is selected.
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
);
546 gtk_widget_set_sensitive(GTK_WIDGET(filter_bt
), FALSE
);
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
;
561 dfilter_t
*sfcode
= NULL
;
562 gboolean found_packet
=FALSE
;
564 gboolean string_search
;
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.
582 * SCS_NARROW_AND_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.
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
);
606 statusbar_push_temporary_msg("That's not a valid hex string.");
609 } else if (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.");
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
)
629 statusbar_push_temporary_msg("You didn't choose a valid character set.");
632 string
= convert_string_case(filter_text
, case_type
);
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
);
644 if (sfcode
== NULL
) {
645 /* Yes - complain. */
646 statusbar_push_temporary_msg("That filter doesn't test anything.");
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
;
666 /* Hex value in packet data */
667 found_packet
= cf_find_packet_data(&cfile
, bytes
, nbytes
, cfile
.dir
);
670 /* We didn't find a packet */
671 statusbar_push_temporary_msg("No packet contained those bytes.");
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
);
680 statusbar_push_temporary_msg("No packet contained that string in its Info column.");
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
);
688 statusbar_push_temporary_msg("No packet contained that string in its dissected display.");
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
);
696 statusbar_push_temporary_msg("No packet contained that string in its ASCII-converted data.");
701 /* Search via display filter */
702 found_packet
= cf_find_packet_dfilter(&cfile
, sfcode
, cfile
.dir
);
703 dfilter_free(sfcode
);
705 statusbar_push_temporary_msg("No packet matched that filter.");
710 window_destroy(GTK_WIDGET(parent_w
));
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
));
721 find_frame_destroy_cb(GtkWidget
*win _U_
, gpointer user_data _U_
)
723 /* Note that we no longer have a "Find Packet" dialog box. */
728 find_previous_next(GtkWidget
*w
, gpointer d
, search_direction dir
)
738 bytes
= convert_string_to_hex(cfile
.sfilter
, &nbytes
);
741 * XXX - this shouldn't happen, as we've already successfully
742 * translated the string once.
746 cf_find_packet_data(&cfile
, bytes
, nbytes
, dir
);
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
);
758 /* The raw packet data */
759 cf_find_packet_data(&cfile
, string
, strlen(string
), dir
);
763 if (!dfilter_compile(cfile
.sfilter
, &sfcode
)) {
765 * XXX - this shouldn't happen, as we've already successfully
766 * translated the string once.
770 if (sfcode
== NULL
) {
772 * XXX - this shouldn't happen, as we've already found that the
773 * string wasn't null.
777 cf_find_packet_dfilter(&cfile
, sfcode
, dir
);
778 dfilter_free(sfcode
);
785 find_next_cb(GtkWidget
*w
, gpointer d
)
787 find_previous_next(w
, d
, SD_FORWARD
);
791 find_previous_cb(GtkWidget
*w
, gpointer d
)
793 find_previous_next(w
, d
, SD_BACKWARD
);