add parameter dcerpc_info to PIDL_dissect_ipv?address()
[wireshark-wip.git] / ui / gtk / dlg_utils.c
blobbce3c9e9923f78e31a41661f0cc0165730c6e508
1 /* dlg_utils.c
2 * Utilities to use when constructing dialogs
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"
26 #include <string.h>
27 #include <stdarg.h>
29 #include <gtk/gtk.h>
31 #include "ui/gtk/gtkglobals.h"
32 #include "ui/gtk/gui_utils.h"
33 #include "ui/gtk/dlg_utils.h"
34 #include "ui/gtk/stock_icons.h"
35 #include "ui/gtk/old-gtk-compat.h"
37 #include "epan/filesystem.h"
40 static void
41 dlg_activate (GtkWidget *widget, gpointer ok_button);
43 /* create a button for the button row (helper for dlg_button_row_new) */
44 static GtkWidget *
45 dlg_button_new(GtkWidget *hbox, GtkWidget *button_hbox, const gchar *stock_id)
47 GtkWidget *button;
49 button = gtk_button_new_from_stock(stock_id);
50 gtk_widget_set_can_default(button, TRUE);
51 g_object_set_data(G_OBJECT(hbox), stock_id, button);
52 gtk_box_pack_end(GTK_BOX(button_hbox), button, FALSE, FALSE, 0);
53 gtk_widget_show(button);
54 return button;
58 * Set the focus and default for the nth item in a button row, with
59 * 0 being the first item.
61 #define BUTTON_HBOX_KEY "button_hbox"
62 void
63 dlg_button_focus_nth(GtkWidget *hbox, gint focus_item) {
64 GtkWidget *button_hbox, *button;
65 GList *children;
66 gint cur_item = 0;
68 if (!hbox)
69 return;
71 button_hbox = (GtkWidget *)g_object_get_data(G_OBJECT(hbox), BUTTON_HBOX_KEY);
72 children = gtk_container_get_children(GTK_CONTAINER(button_hbox));
74 while (children) {
75 if (cur_item == focus_item) {
76 button = (GtkWidget *)children->data;
77 gtk_widget_grab_focus(button);
78 gtk_widget_grab_default(button);
79 break;
81 children = g_list_next(children);
82 cur_item++;
85 g_list_free(children);
88 /* create a button row for a dialog */
90 /* The purpose of this is, to have one place available, where all button rows
91 * from all dialogs are laid out. This will:
93 * a.) keep the button layout more consistent over the different dialogs
94 * b.) being able to switch between different button layouts, e.g.:
95 * e.g. Win32: "OK" "Apply" "Cancel"
96 * e.g. GNOME: "Apply" "Cancel" "OK"
98 GtkWidget *
99 dlg_button_row_new(const gchar *stock_id_first, ...)
101 gint buttons = 0;
102 va_list stock_id_list;
103 const gchar *stock_id = stock_id_first;
104 GtkWidget *hbox;
105 GtkWidget *button_hbox;
106 GtkWidget *help_hbox;
107 GtkWidget *button;
109 const gchar *apply = NULL;
110 const gchar *cancel = NULL;
111 const gchar *cap_start = NULL;
112 const gchar *cap_stop = NULL;
113 const gchar *cap_options = NULL;
114 #ifdef _WIN32
115 const gchar *cap_details = NULL;
116 #endif
117 const gchar *clear = NULL;
118 const gchar *closex = NULL;
119 const gchar *copy = NULL;
120 const gchar *create_stat = NULL;
121 const gchar *delete_id = NULL;
122 const gchar *dont_save = NULL;
123 const gchar *filter_stream = NULL;
124 const gchar *find = NULL;
125 const gchar *help = NULL;
126 const gchar *jump = NULL;
127 const gchar *no = NULL;
128 const gchar *ok = NULL;
129 const gchar *print = NULL;
130 const gchar *save = NULL;
131 const gchar *save_as = NULL;
132 const gchar *save_all = NULL;
133 const gchar *stop = NULL;
134 const gchar *yes = NULL;
135 const gchar *refresh = NULL;
136 const gchar *add = NULL;
137 #ifdef HAVE_GEOIP
138 const gchar *map = NULL;
139 #endif /* HAVE_GEOIP */
140 const gchar *follow_stream = NULL;
141 const gchar *graph_a_b = NULL;
142 const gchar *graph_b_a = NULL;
145 va_start(stock_id_list, stock_id_first);
147 /* get all buttons needed */
148 while(stock_id != NULL) {
149 if (strcmp(stock_id, GTK_STOCK_OK) == 0) {
150 ok = stock_id;
151 } else if (strcmp(stock_id, WIRESHARK_STOCK_CREATE_STAT) == 0) {
152 create_stat = stock_id;
153 } else if (strcmp(stock_id, GTK_STOCK_APPLY) == 0) {
154 apply = stock_id;
155 } else if (strcmp(stock_id, GTK_STOCK_SAVE) == 0) {
156 save = stock_id;
157 } else if (strcmp(stock_id, GTK_STOCK_SAVE_AS) == 0) {
158 save_as = stock_id;
159 } else if (strcmp(stock_id, WIRESHARK_STOCK_SAVE_ALL) == 0) {
160 save_all = stock_id;
161 } else if (strcmp(stock_id, WIRESHARK_STOCK_DONT_SAVE) == 0) {
162 dont_save = stock_id;
163 } else if (strcmp(stock_id, WIRESHARK_STOCK_QUIT_DONT_SAVE) == 0) {
164 dont_save = stock_id;
165 } else if (strcmp(stock_id, GTK_STOCK_CANCEL) == 0) {
166 cancel = stock_id;
167 } else if (strcmp(stock_id, GTK_STOCK_CLOSE) == 0) {
168 closex = stock_id;
169 } else if (strcmp(stock_id, GTK_STOCK_CLEAR) == 0) {
170 clear = stock_id;
171 } else if (strcmp(stock_id, GTK_STOCK_REFRESH) == 0) {
172 refresh = stock_id;
173 } else if (strcmp(stock_id, GTK_STOCK_ADD) == 0) {
174 add = stock_id;
175 #ifdef HAVE_LIBPCAP
176 } else if (strcmp(stock_id, WIRESHARK_STOCK_CAPTURE_START) == 0) {
177 cap_start = stock_id;
178 } else if (strcmp(stock_id, WIRESHARK_STOCK_CAPTURE_STOP) == 0) {
179 cap_stop = stock_id;
180 } else if (strcmp(stock_id, WIRESHARK_STOCK_CAPTURE_OPTIONS) == 0) {
181 cap_options = stock_id;
182 #ifdef _WIN32
183 } else if (strcmp(stock_id, WIRESHARK_STOCK_CAPTURE_DETAILS) == 0) {
184 cap_details = stock_id;
185 #endif
186 #endif /* HAVE_LIBPCAP */
187 #ifdef HAVE_GEOIP
188 } else if (strcmp(stock_id, WIRESHARK_STOCK_MAP) == 0) {
189 map = stock_id;
190 #endif /* HAVE_GEOIP */
191 } else if (strcmp(stock_id, WIRESHARK_STOCK_FOLLOW_STREAM) == 0) {
192 follow_stream = stock_id;
193 } else if (strcmp(stock_id, GTK_STOCK_STOP) == 0) {
194 stop = stock_id;
195 } else if (strcmp(stock_id, GTK_STOCK_HELP) == 0) {
196 help = stock_id;
197 } else if (strcmp(stock_id, GTK_STOCK_PRINT) == 0) {
198 print = stock_id;
199 } else if (strcmp(stock_id, GTK_STOCK_FIND) == 0) {
200 find = stock_id;
201 } else if (strcmp(stock_id, GTK_STOCK_JUMP_TO) == 0) {
202 jump = stock_id;
203 } else if (strcmp(stock_id, GTK_STOCK_YES) == 0) {
204 yes = stock_id;
205 } else if (strcmp(stock_id, GTK_STOCK_NO) == 0) {
206 no = stock_id;
207 } else if (strcmp(stock_id, WIRESHARK_STOCK_FILTER_OUT_STREAM) == 0) {
208 filter_stream = stock_id;
209 } else if (strcmp(stock_id, GTK_STOCK_DELETE) == 0) {
210 delete_id = stock_id;
211 } else if (strcmp(stock_id, GTK_STOCK_COPY) == 0) {
212 copy = stock_id;
213 } else if (strcmp(stock_id, WIRESHARK_STOCK_GRAPH_A_B) == 0) {
214 graph_a_b = stock_id;
215 } else if (strcmp(stock_id, WIRESHARK_STOCK_GRAPH_B_A) == 0) {
216 graph_b_a = stock_id;
217 } else {
218 /* we don't know that button! */
219 g_assert_not_reached();
221 buttons++;
222 stock_id = va_arg(stock_id_list, gchar *);
224 va_end(stock_id_list);
226 hbox = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, DLG_BUTTON_SPACING, FALSE);
227 gtk_widget_show(hbox);
229 button_hbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
230 gtk_box_pack_end(GTK_BOX(hbox), button_hbox, TRUE, TRUE, 0);
231 g_object_set_data(G_OBJECT(hbox), BUTTON_HBOX_KEY, button_hbox);
232 gtk_widget_show(button_hbox);
233 gtk_box_set_spacing(GTK_BOX(button_hbox), DLG_BUTTON_SPACING);
235 help_hbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
236 gtk_box_pack_end(GTK_BOX(hbox), help_hbox, FALSE, FALSE, 0);
237 gtk_widget_show(help_hbox);
238 gtk_box_set_spacing(GTK_BOX(help_hbox), DLG_BUTTON_SPACING);
240 if (buttons == 0) {
241 /* if no buttons wanted, simply do nothing */
242 return hbox;
245 if (buttons == 1) {
246 /* if only one button, simply put it in the middle (default) */
247 dlg_button_new(hbox, button_hbox, stock_id_first);
248 return hbox;
251 /* do we have a help button? -> special handling for it */
252 if (help) {
253 button = gtk_button_new_from_stock(help);
254 gtk_widget_set_can_default(button, TRUE);
255 g_object_set_data(G_OBJECT(hbox), help, button);
256 gtk_box_pack_start(GTK_BOX(help_hbox), button, FALSE, FALSE, 0);
257 gtk_widget_show(button);
258 buttons--;
261 /* do we have a copy button? -> special handling for it */
262 if (copy) {
263 button = gtk_button_new_from_stock(copy);
264 gtk_widget_set_can_default(button, TRUE);
265 g_object_set_data(G_OBJECT(hbox), copy, button);
266 gtk_box_pack_start(GTK_BOX(help_hbox), button, FALSE, FALSE, 0);
267 gtk_widget_show(button);
268 buttons--;
271 /* do we have a refresh button? -> special handling for it */
272 if (refresh) {
273 button = gtk_button_new_from_stock(refresh);
274 g_object_set_data(G_OBJECT(hbox), refresh, button);
275 gtk_box_pack_start(GTK_BOX(help_hbox), button, FALSE, FALSE, 0);
276 gtk_widget_show(button);
277 buttons--;
280 /* do we have an add button? -> special handling for it */
281 if (add) {
282 button = gtk_button_new_from_stock(add);
283 g_object_set_data(G_OBJECT(hbox), add, button);
284 gtk_box_pack_start(GTK_BOX(help_hbox), button, FALSE, FALSE, 0);
285 gtk_widget_show(button);
286 buttons--;
289 #ifdef HAVE_GEOIP
290 /* do we have a map button? -> special handling for it */
291 if (map) {
292 button = gtk_button_new_from_stock(map);
293 gtk_widget_set_can_default(button, TRUE);
294 g_object_set_data(G_OBJECT(hbox), map, button);
295 gtk_box_pack_start(GTK_BOX(help_hbox), button, FALSE, FALSE, 0);
296 gtk_widget_show(button);
297 buttons--;
299 #endif /* HAVE_GEOIP */
301 /* if more than one button, sort buttons from left to right */
302 /* (the whole button cluster will then be right aligned) */
303 gtk_button_box_set_layout (GTK_BUTTON_BOX(button_hbox), GTK_BUTTONBOX_END);
305 #if !defined(_WIN32)
306 /* beware: sequence of buttons are important! */
308 /* XXX: this can be implemented more elegant of course, but it works as it should */
309 if (buttons == 2) {
310 if (ok && cancel) {
311 dlg_button_new(hbox, button_hbox, cancel);
312 dlg_button_new(hbox, button_hbox, ok);
313 return hbox;
315 if (print && cancel) {
316 dlg_button_new(hbox, button_hbox, cancel);
317 dlg_button_new(hbox, button_hbox, print);
318 return hbox;
320 if (find && cancel) {
321 dlg_button_new(hbox, button_hbox, cancel);
322 dlg_button_new(hbox, button_hbox, find);
323 return hbox;
325 if (jump && cancel) {
326 dlg_button_new(hbox, button_hbox, cancel);
327 dlg_button_new(hbox, button_hbox, jump);
328 return hbox;
330 if (save && cancel) {
331 dlg_button_new(hbox, button_hbox, cancel);
332 dlg_button_new(hbox, button_hbox, save);
333 return hbox;
335 if (ok && clear) {
336 dlg_button_new(hbox, button_hbox, clear);
337 dlg_button_new(hbox, button_hbox, ok);
338 return hbox;
340 if (save && closex) {
341 dlg_button_new(hbox, button_hbox, closex);
342 dlg_button_new(hbox, button_hbox, save);
343 return hbox;
345 if (create_stat && cancel) {
346 dlg_button_new(hbox, button_hbox, cancel);
347 dlg_button_new(hbox, button_hbox, create_stat);
348 return hbox;
350 if (cap_start && cancel) {
351 dlg_button_new(hbox, button_hbox, cancel);
352 dlg_button_new(hbox, button_hbox, cap_start);
353 return hbox;
355 if (cap_stop && cancel) {
356 dlg_button_new(hbox, button_hbox, cancel);
357 dlg_button_new(hbox, button_hbox, cap_stop);
358 return hbox;
360 if (delete_id && cancel) {
361 dlg_button_new(hbox, button_hbox, cancel);
362 dlg_button_new(hbox, button_hbox, delete_id);
363 return hbox;
366 if (buttons == 3) {
367 if (ok && save && closex) {
368 dlg_button_new(hbox, button_hbox, save);
369 dlg_button_new(hbox, button_hbox, closex);
370 dlg_button_new(hbox, button_hbox, ok);
371 return hbox;
373 if (ok && apply && cancel) {
374 dlg_button_new(hbox, button_hbox, apply);
375 dlg_button_new(hbox, button_hbox, cancel);
376 dlg_button_new(hbox, button_hbox, ok);
377 return hbox;
379 if (apply && save && closex) {
380 dlg_button_new(hbox, button_hbox, save);
381 dlg_button_new(hbox, button_hbox, closex);
382 dlg_button_new(hbox, button_hbox, apply);
383 return hbox;
385 if (yes && no && cancel) {
386 dlg_button_new(hbox, button_hbox, no);
387 dlg_button_new(hbox, button_hbox, cancel);
388 dlg_button_new(hbox, button_hbox, yes);
389 return hbox;
391 if (save && dont_save && cancel) {
392 dlg_button_new(hbox, button_hbox, dont_save);
393 dlg_button_new(hbox, button_hbox, cancel);
394 dlg_button_new(hbox, button_hbox, save);
395 return hbox;
398 if (buttons == 4) {
399 if (ok && apply && save && cancel) {
400 dlg_button_new(hbox, button_hbox, save);
401 dlg_button_new(hbox, button_hbox, apply);
402 dlg_button_new(hbox, button_hbox, cancel);
403 dlg_button_new(hbox, button_hbox, ok);
404 return hbox;
406 if (ok && apply && save && closex) {
407 dlg_button_new(hbox, button_hbox, save);
408 dlg_button_new(hbox, button_hbox, apply);
409 dlg_button_new(hbox, button_hbox, closex);
410 dlg_button_new(hbox, button_hbox, ok);
411 return hbox;
414 #endif
416 /* beware: sequence of buttons is important! */
417 if (ok != NULL) dlg_button_new(hbox, button_hbox, ok);
418 if (delete_id != NULL) dlg_button_new(hbox, button_hbox, delete_id);
419 if (jump != NULL) dlg_button_new(hbox, button_hbox, jump);
420 if (find != NULL) dlg_button_new(hbox, button_hbox, find);
421 if (print != NULL) dlg_button_new(hbox, button_hbox, print);
422 if (create_stat != NULL) dlg_button_new(hbox, button_hbox, create_stat);
423 if (apply != NULL) dlg_button_new(hbox, button_hbox, apply);
424 if (yes != NULL) dlg_button_new(hbox, button_hbox, yes);
425 if (no != NULL) dlg_button_new(hbox, button_hbox, no);
426 if (save != NULL) dlg_button_new(hbox, button_hbox, save);
427 if (save_as != NULL) dlg_button_new(hbox, button_hbox, save_as);
428 if (save_all != NULL) dlg_button_new(hbox, button_hbox, save_all);
429 if (dont_save != NULL) dlg_button_new(hbox, button_hbox, dont_save);
430 if (cap_start != NULL) dlg_button_new(hbox, button_hbox, cap_start);
431 if (cap_stop != NULL) dlg_button_new(hbox, button_hbox, cap_stop);
432 if (cap_options != NULL) dlg_button_new(hbox, button_hbox, cap_options);
433 #ifdef _WIN32
434 if (cap_details != NULL) dlg_button_new(hbox, button_hbox, cap_details);
435 #endif
436 if (stop != NULL) dlg_button_new(hbox, button_hbox, stop);
437 if (clear != NULL) dlg_button_new(hbox, button_hbox, clear);
438 if (filter_stream != NULL) dlg_button_new(hbox, button_hbox, filter_stream);
439 if (follow_stream != NULL) dlg_button_new(hbox, button_hbox, follow_stream);
440 if (graph_a_b != NULL) dlg_button_new(hbox, button_hbox, graph_a_b);
441 if (graph_b_a != NULL) dlg_button_new(hbox, button_hbox, graph_b_a);
442 if (closex != NULL) dlg_button_new(hbox, button_hbox, closex);
443 if (cancel != NULL) dlg_button_new(hbox, button_hbox, cancel);
445 return hbox;
449 /* Create a dialog box window that belongs to Wireshark's main window. */
450 GtkWidget *
451 dlg_window_new(const gchar *title)
453 GtkWidget *win;
455 win = window_new(GTK_WINDOW_TOPLEVEL, title);
458 * On Windows, making the dialogs transient to top_level behaves strangely.
459 * It is not possible any more to bring the top level window to front easily.
460 * So we don't do this on Windows.
462 * XXX: Note well: This means that *on Windows* any code which creates a
463 * window using dlg_window_new() and then calls
464 * gtk_widget_destroy_with_parent() will *not* get the desired effect
465 * since the dialog window actually has has no parent.
467 #ifndef _WIN32
468 if (top_level) {
469 gtk_window_set_transient_for(GTK_WINDOW(win), GTK_WINDOW(top_level));
471 #endif /*_WIN32*/
473 return win;
476 /* Create a configuration dialog box window that belongs to Wireshark's
477 * main window and add the name of the current profile name to its title bar
479 GtkWidget *
480 dlg_conf_window_new(const gchar *title)
482 const char *profile_name;
483 gchar *win_name;
484 GtkWidget *win;
487 * Set window title to reflect which preferences profile we are
488 * working with.
490 profile_name = get_profile_name();
492 win_name = g_strdup_printf("%s - Profile: %s", title, profile_name);
493 win = dlg_window_new(win_name);
495 g_free(win_name);
497 return win;
500 /* Set the "activate" signal for a widget to call a routine to
501 activate the "OK" button for a dialog box.
503 XXX - there should be a way to specify that a GtkEntry widget
504 shouldn't itself handle the Return key, but should let it be
505 passed on to the parent, so that you don't have to do this
506 by hand for every GtkEntry widget in a dialog box, but, alas,
507 there isn't. (Does this problem exist for other widgets?
508 I.e., are there any others that seize the Return key? */
509 void
510 dlg_set_activate(GtkWidget *widget, GtkWidget *ok_button)
512 g_signal_connect(widget, "activate", G_CALLBACK(dlg_activate), ok_button);
515 static void
516 dlg_activate (GtkWidget *widget _U_, gpointer ok_button)
518 gtk_widget_activate(GTK_WIDGET(ok_button));