2 * Routines for packet display windows
4 * $Id: display_opts.c,v 1.25 2002/01/21 07:37:41 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
45 #ifdef HAVE_SYS_SOCKIO_H
46 # include <sys/sockio.h>
49 #ifdef NEED_SNPRINTF_H
50 # include "snprintf.h"
54 #include <epan/resolv.h>
55 #include <epan/timestamp.h>
56 #include <epan/packet.h>
58 #include "display_opts.h"
60 #include "dlg_utils.h"
62 extern capture_file cfile;
64 /* Display callback data keys */
65 #define E_DISPLAY_TIME_ABS_KEY "display_time_abs"
66 #define E_DISPLAY_DATE_TIME_ABS_KEY "display_date_time_abs"
67 #define E_DISPLAY_TIME_REL_KEY "display_time_rel"
68 #define E_DISPLAY_TIME_DELTA_KEY "display_time_delta"
70 #define E_DISPLAY_AUTO_SCROLL_KEY "display_auto_scroll"
72 #define E_DISPLAY_M_NAME_RESOLUTION_KEY "display_mac_name_resolution"
73 #define E_DISPLAY_N_NAME_RESOLUTION_KEY "display_network_name_resolution"
74 #define E_DISPLAY_T_NAME_RESOLUTION_KEY "display_transport_name_resolution"
76 static void display_opt_ok_cb(GtkWidget *, gpointer);
77 static void display_opt_apply_cb(GtkWidget *, gpointer);
78 static void get_display_options(GtkWidget *);
79 static void update_display(void);
80 static void display_opt_close_cb(GtkWidget *, gpointer);
81 static void display_opt_destroy_cb(GtkWidget *, gpointer);
84 * Keep a static pointer to the current "Display Options" window, if any,
85 * so that if somebody tries to do "Display:Options" while there's already
86 * a "Display Options" window up, we just pop up the existing one, rather
87 * than creating a new one.
89 static GtkWidget *display_opt_w;
91 static ts_type initial_timestamp_type;
92 static ts_type current_timestamp_type;
95 display_opt_cb(GtkWidget *w, gpointer d) {
96 GtkWidget *button, *main_vb, *bbox, *ok_bt, *apply_bt, *cancel_bt;
97 GtkAccelGroup *accel_group;
99 if (display_opt_w != NULL) {
100 /* There's already a "Display Options" dialog box; reactivate it. */
101 reactivate_window(display_opt_w);
105 /* Save the timestamp type value as of when the dialog box was first popped
106 up, so that "Cancel" can put it back if we've changed it with "Apply". */
107 initial_timestamp_type = timestamp_type;
109 /* Save the current timestamp type so that we know whether it has changed;
110 we don't want to redisplay the time fields unless we've changed the way
111 they should be displayed (as redisplaying the time fields could be
112 expensive - we have to scan through all the packets and rebuild the
114 current_timestamp_type = timestamp_type;
116 display_opt_w = dlg_window_new("Ethereal: Display Options");
117 gtk_signal_connect(GTK_OBJECT(display_opt_w), "destroy",
118 GTK_SIGNAL_FUNC(display_opt_destroy_cb), NULL);
120 /* Accelerator group for the accelerators (or, as they're called in
121 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
122 Ctrl+<key> is an accelerator). */
123 accel_group = gtk_accel_group_new();
124 gtk_window_add_accel_group(GTK_WINDOW(display_opt_w), accel_group);
126 /* Container for each row of widgets */
127 main_vb = gtk_vbox_new(FALSE, 3);
128 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
129 gtk_container_add(GTK_CONTAINER(display_opt_w), main_vb);
130 gtk_widget_show(main_vb);
132 button = dlg_radio_button_new_with_label_with_mnemonic(NULL, "_Time of day",
134 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button),
135 (timestamp_type == ABSOLUTE));
136 gtk_object_set_data(GTK_OBJECT(display_opt_w), E_DISPLAY_TIME_ABS_KEY,
138 gtk_box_pack_start(GTK_BOX(main_vb), button, TRUE, TRUE, 0);
140 gtk_widget_show(button);
142 button = dlg_radio_button_new_with_label_with_mnemonic(
143 gtk_radio_button_group(GTK_RADIO_BUTTON(button)),
144 "_Date and time of day", accel_group);
145 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button),
146 (timestamp_type == ABSOLUTE_WITH_DATE));
147 gtk_object_set_data(GTK_OBJECT(display_opt_w), E_DISPLAY_DATE_TIME_ABS_KEY,
149 gtk_box_pack_start(GTK_BOX(main_vb), button, TRUE, TRUE, 0);
150 gtk_widget_show(button);
152 button = dlg_radio_button_new_with_label_with_mnemonic(
153 gtk_radio_button_group(GTK_RADIO_BUTTON(button)),
154 "Seconds since _beginning of capture", accel_group);
155 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button),
156 (timestamp_type == RELATIVE));
157 gtk_object_set_data(GTK_OBJECT(display_opt_w), E_DISPLAY_TIME_REL_KEY,
159 gtk_box_pack_start(GTK_BOX(main_vb), button, TRUE, TRUE, 0);
160 gtk_widget_show(button);
162 button = dlg_radio_button_new_with_label_with_mnemonic(
163 gtk_radio_button_group(GTK_RADIO_BUTTON(button)),
164 "Seconds since _previous frame", accel_group);
165 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button),
166 (timestamp_type == DELTA));
167 gtk_object_set_data(GTK_OBJECT(display_opt_w), E_DISPLAY_TIME_DELTA_KEY,
169 gtk_box_pack_start(GTK_BOX(main_vb), button, TRUE, TRUE, 0);
170 gtk_widget_show(button);
173 button = dlg_check_button_new_with_label_with_mnemonic(
174 "_Automatic scrolling in live capture", accel_group);
175 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), auto_scroll_live);
176 gtk_object_set_data(GTK_OBJECT(display_opt_w), E_DISPLAY_AUTO_SCROLL_KEY,
178 gtk_box_pack_start(GTK_BOX(main_vb), button, TRUE, TRUE, 0);
179 gtk_widget_show(button);
182 button = dlg_check_button_new_with_label_with_mnemonic(
183 "Enable _MAC name resolution", accel_group);
184 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button),
185 g_resolv_flags & RESOLV_MAC);
186 gtk_object_set_data(GTK_OBJECT(display_opt_w), E_DISPLAY_M_NAME_RESOLUTION_KEY,
188 gtk_box_pack_start(GTK_BOX(main_vb), button, TRUE, TRUE, 0);
189 gtk_widget_show(button);
191 button = dlg_check_button_new_with_label_with_mnemonic(
192 "Enable _network name resolution", accel_group);
193 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button),
194 g_resolv_flags & RESOLV_NETWORK);
195 gtk_object_set_data(GTK_OBJECT(display_opt_w), E_DISPLAY_N_NAME_RESOLUTION_KEY,
197 gtk_box_pack_start(GTK_BOX(main_vb), button, TRUE, TRUE, 0);
198 gtk_widget_show(button);
200 button = dlg_check_button_new_with_label_with_mnemonic(
201 "Enable _transport name resolution", accel_group);
202 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button),
203 g_resolv_flags & RESOLV_TRANSPORT);
204 gtk_object_set_data(GTK_OBJECT(display_opt_w), E_DISPLAY_T_NAME_RESOLUTION_KEY,
206 gtk_box_pack_start(GTK_BOX(main_vb), button, TRUE, TRUE, 0);
207 gtk_widget_show(button);
209 /* Button row: OK, Apply, and Cancel buttons */
210 bbox = gtk_hbutton_box_new();
211 gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
212 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
213 gtk_container_add(GTK_CONTAINER(main_vb), bbox);
214 gtk_widget_show(bbox);
216 ok_bt = gtk_button_new_with_label ("OK");
217 gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked",
218 GTK_SIGNAL_FUNC(display_opt_ok_cb), GTK_OBJECT(display_opt_w));
219 GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
220 gtk_box_pack_start (GTK_BOX (bbox), ok_bt, TRUE, TRUE, 0);
221 gtk_widget_grab_default(ok_bt);
222 gtk_widget_show(ok_bt);
224 apply_bt = gtk_button_new_with_label ("Apply");
225 gtk_signal_connect(GTK_OBJECT(apply_bt), "clicked",
226 GTK_SIGNAL_FUNC(display_opt_apply_cb), GTK_OBJECT(display_opt_w));
227 GTK_WIDGET_SET_FLAGS(apply_bt, GTK_CAN_DEFAULT);
228 gtk_box_pack_start (GTK_BOX (bbox), apply_bt, TRUE, TRUE, 0);
229 gtk_widget_show(apply_bt);
231 cancel_bt = gtk_button_new_with_label ("Cancel");
232 gtk_signal_connect(GTK_OBJECT(cancel_bt), "clicked",
233 GTK_SIGNAL_FUNC(display_opt_close_cb), GTK_OBJECT(display_opt_w));
234 GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
235 gtk_box_pack_start (GTK_BOX (bbox), cancel_bt, TRUE, TRUE, 0);
236 gtk_widget_show(cancel_bt);
238 /* Catch the "key_press_event" signal in the window, so that we can catch
239 the ESC key being pressed and act as if the "Cancel" button had
241 dlg_set_cancel(display_opt_w, cancel_bt);
243 gtk_widget_show(display_opt_w);
247 display_opt_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
248 get_display_options(GTK_WIDGET(parent_w));
250 gtk_widget_destroy(GTK_WIDGET(parent_w));
256 display_opt_apply_cb(GtkWidget *ok_bt, gpointer parent_w) {
257 get_display_options(GTK_WIDGET(parent_w));
263 get_display_options(GtkWidget *parent_w)
267 button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w),
268 E_DISPLAY_TIME_ABS_KEY);
269 if (GTK_TOGGLE_BUTTON (button)->active)
270 timestamp_type = ABSOLUTE;
272 button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w),
273 E_DISPLAY_DATE_TIME_ABS_KEY);
274 if (GTK_TOGGLE_BUTTON (button)->active)
275 timestamp_type = ABSOLUTE_WITH_DATE;
277 button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w),
278 E_DISPLAY_TIME_REL_KEY);
279 if (GTK_TOGGLE_BUTTON (button)->active)
280 timestamp_type = RELATIVE;
282 button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w),
283 E_DISPLAY_TIME_DELTA_KEY);
284 if (GTK_TOGGLE_BUTTON (button)->active)
285 timestamp_type = DELTA;
288 button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w),
289 E_DISPLAY_AUTO_SCROLL_KEY);
290 auto_scroll_live = (GTK_TOGGLE_BUTTON (button)->active);
293 g_resolv_flags = RESOLV_NONE;
294 button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w),
295 E_DISPLAY_M_NAME_RESOLUTION_KEY);
296 g_resolv_flags |= (GTK_TOGGLE_BUTTON (button)->active ? RESOLV_MAC : RESOLV_NONE);
297 button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w),
298 E_DISPLAY_N_NAME_RESOLUTION_KEY);
299 g_resolv_flags |= (GTK_TOGGLE_BUTTON (button)->active ? RESOLV_NETWORK : RESOLV_NONE);
300 button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w),
301 E_DISPLAY_T_NAME_RESOLUTION_KEY);
302 g_resolv_flags |= (GTK_TOGGLE_BUTTON (button)->active ? RESOLV_TRANSPORT : RESOLV_NONE);
309 if (timestamp_type != current_timestamp_type) {
310 /* Time stamp format changed; update the display.
312 XXX - redissecting the packets could actually be faster;
313 we have to find the row number for each frame, in order to
314 update the time stamp columns, and doing that is linear in
315 the row number, which means the whole process is N^2 in
316 the number of rows, whilst redissecting the packets is only
317 linear in the number of rows (assuming you're using our
318 CList code, or the GTK+ 1.2.8 CList code, or other CList
319 code which doesn't have to scan the entire list to find the
320 last element), even though the latter involves doing more work
322 current_timestamp_type = timestamp_type;
323 change_time_formats(&cfile);
328 display_opt_close_cb(GtkWidget *close_bt, gpointer parent_w)
330 /* Revert the timestamp type to the value it has when we started. */
331 timestamp_type = initial_timestamp_type;
333 /* Update the display if either of those changed. */
336 gtk_grab_remove(GTK_WIDGET(parent_w));
337 gtk_widget_destroy(GTK_WIDGET(parent_w));
341 display_opt_destroy_cb(GtkWidget *win, gpointer user_data)
343 /* Note that we no longer have a "Display Options" dialog box. */
344 display_opt_w = NULL;