Remove the progress bar from the status line, and, instead, for any

potentially long-running operation that has a progress indicator, pop up
a modal dialog box with

	an indication of what is being done;

	a progress bar;

	a "Cancel" button to stop the operation.

This:

	leaves more room on the status line for a filter expression;

	provides a mechanism to allow the user to cancel long-running
	operations (although the way we do so may not back out of them
	as nicely as the user might like, if it's not obvious what the
	"right" way is or if the "right" way is difficult to implement
	or involves doing as much work as letting the operation
	continue);

	means that, because the dialog box is modal, we don't have to
	worry about the user performing arbitrary UI operations out from
	under the operation and changing arbitrary bits of state being
	used by that operation.

svn path=/trunk/; revision=2103
This commit is contained in:
Guy Harris 2000-07-03 08:36:52 +00:00
parent 6f4d2c0cb8
commit 9e42b3a4ed
9 changed files with 317 additions and 77 deletions

View File

@ -327,8 +327,7 @@ the I<File:Print Packet> menu item.
The main window is split into three panes. You can resize each pane using
a "thumb" at the right end of each divider line. Below the panes is a
strip that shows the file load progress, current filter, and informational
text.
strip that shows the current filter and informational text.
=over 6

151
file.c
View File

@ -1,7 +1,7 @@
/* file.c
* File I/O routines
*
* $Id: file.c,v 1.192 2000/06/27 09:26:10 guy Exp $
* $Id: file.c,v 1.193 2000/07/03 08:35:39 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -85,7 +85,7 @@
#include "plugins.h"
extern GtkWidget *packet_list, *prog_bar, *info_bar, *byte_view, *tree_view;
extern GtkWidget *packet_list, *info_bar, *byte_view, *tree_view;
extern guint file_ctx;
gboolean auto_scroll_live = FALSE;
@ -166,7 +166,6 @@ open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
cf->esec = 0;
cf->eusec = 0;
cf->snap = wtap_snapshot_length(cf->wth);
cf->update_progbar = FALSE;
cf->progbar_quantum = 0;
cf->progbar_nextstep = 0;
firstsec = 0, firstusec = 0;
@ -288,12 +287,16 @@ set_display_filename(capture_file *cf)
read_status_t
read_cap_file(capture_file *cf, int *err)
{
gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
size_t msg_len;
char *errmsg;
char errmsg_errno[1024+1];
gchar err_str[2048+1];
int data_offset;
gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
size_t msg_len;
char *errmsg;
char errmsg_errno[1024+1];
gchar err_str[2048+1];
int data_offset;
void *progbar;
gboolean stop_flag;
int file_pos;
float prog_val;
name_ptr = get_basename(cf->filename);
@ -301,9 +304,7 @@ read_cap_file(capture_file *cf, int *err)
load_msg = g_malloc(msg_len);
snprintf(load_msg, msg_len, load_fmt, name_ptr);
gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
g_free(load_msg);
cf->update_progbar = TRUE;
/* Update the progress bar when it gets to this value. */
cf->progbar_nextstep = 0;
/* When we reach the value that triggers a progress bar update,
@ -316,17 +317,37 @@ read_cap_file(capture_file *cf, int *err)
freeze_clist(cf);
stop_flag = FALSE;
progbar = create_progress_dlg(load_msg, &stop_flag);
g_free(load_msg);
while ((data_offset = wtap_read(cf->wth, err)) > 0) {
if (cf->state == FILE_READ_ABORTED) {
/* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
when we update it, we have to run the GTK+ main loop to get it
to repaint what's pending, and doing so may involve an "ioctl()"
to see if there's any pending input from an X server, and doing
that for every packet can be costly, especially on a big file. */
if (data_offset >= cf->progbar_nextstep) {
file_pos = lseek(cf->filed, 0, SEEK_CUR);
prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
update_progress_dlg(progbar, prog_val);
cf->progbar_nextstep += cf->progbar_quantum;
}
if (stop_flag) {
/* Well, the user decided to abort the read. Close the capture
file, and return READ_ABORTED so our caller can do whatever is
appropriate when that happens. */
cf->state = FILE_READ_ABORTED; /* so that we're allowed to close it */
close_cap_file(cf, info_bar);
return (READ_ABORTED);
}
read_packet(cf, data_offset);
}
/* We're done reading the file; destroy the progress bar. */
destroy_progress_dlg(progbar);
/* We're done reading sequentially through the file. */
cf->state = FILE_READ_DONE;
@ -342,9 +363,6 @@ read_cap_file(capture_file *cf, int *err)
cf->current_frame = cf->first_displayed;
thaw_clist(cf);
gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
gtk_progress_set_value(GTK_PROGRESS(prog_bar), 0);
gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
set_display_filename(cf);
@ -711,28 +729,6 @@ read_packet(capture_file *cf, int offset)
int passed;
proto_tree *protocol_tree;
frame_data *plist_end;
int file_pos;
float prog_val;
/* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
when we update it, we have to run the GTK+ main loop to get it
to repaint what's pending, and doing so may involve an "ioctl()"
to see if there's any pending input from an X server, and doing
that for every packet can be costly, especially on a big file.
Do so only if we were told to do so; when reading a capture file
being updated by a live capture, we don't do so (as we're not
"done" until the capture stops, so we don't know how close to
"done" we are. */
if (cf->update_progbar && offset >= cf->progbar_nextstep) {
file_pos = lseek(cf->filed, 0, SEEK_CUR);
prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), prog_val);
cf->progbar_nextstep += cf->progbar_quantum;
while (gtk_events_pending())
gtk_main_iteration();
}
/* Allocate the next list entry, and add it to the list. */
fdata = g_mem_chunk_alloc(cf->plist_chunk);
@ -829,6 +825,8 @@ void
colorize_packets(capture_file *cf)
{
frame_data *fdata;
void *progbar;
gboolean stop_flag;
guint32 progbar_quantum;
guint32 progbar_nextstep;
int count;
@ -855,8 +853,6 @@ colorize_packets(capture_file *cf)
/* Initialize protocol-specific variables */
init_all_protocols();
gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
/* Freeze the packet list while we redo it, so we don't get any
screen updates while it happens. */
gtk_clist_freeze(GTK_CLIST(packet_list));
@ -884,7 +880,8 @@ colorize_packets(capture_file *cf)
/* Count of packets at which we've looked. */
count = 0;
gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
stop_flag = FALSE;
progbar = create_progress_dlg("Filtering", &stop_flag);
for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
/* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
@ -898,12 +895,25 @@ colorize_packets(capture_file *cf)
*/
g_assert(cf->count > 0);
gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
(gfloat) count / cf->count);
update_progress_dlg(progbar, (gfloat) count / cf->count);
progbar_nextstep += progbar_quantum;
while (gtk_events_pending())
gtk_main_iteration();
}
if (stop_flag) {
/* Well, the user decided to abort the filtering. Just stop.
XXX - go back to the previous filter? Users probably just
want not to wait for a filtering operation to finish;
unless we cancel by having no filter, reverting to the
previous filter will probably be even more expensive than
continuing the filtering, as it involves going back to the
beginning and filtering, and even with no filter we currently
have to re-generate the entire clist, which is also expensive.
I'm not sure what Network Monitor does, but it doesn't appear
to give you an unfiltered display if you cancel. */
break;
}
count++;
@ -916,7 +926,8 @@ colorize_packets(capture_file *cf)
selected_row = row;
}
gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
/* We're done filtering the packets; destroy the progress bar. */
destroy_progress_dlg(progbar);
/* Unfreeze the packet list. */
gtk_clist_thaw(GTK_CLIST(packet_list));
@ -939,6 +950,8 @@ print_packets(capture_file *cf, print_args_t *print_args)
{
int i;
frame_data *fdata;
void *progbar;
gboolean stop_flag;
guint32 progbar_quantum;
guint32 progbar_nextstep;
guint32 count;
@ -1022,7 +1035,8 @@ print_packets(capture_file *cf, print_args_t *print_args)
/* Count of packets at which we've looked. */
count = 0;
gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
stop_flag = FALSE;
progbar = create_progress_dlg("Printing", &stop_flag);
/* Iterate through the list of packets, printing the packets that
were selected by the current display filter. */
@ -1038,12 +1052,21 @@ print_packets(capture_file *cf, print_args_t *print_args)
*/
g_assert(cf->count > 0);
gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
(gfloat) count / cf->count);
update_progress_dlg(progbar, (gfloat) count / cf->count);
progbar_nextstep += progbar_quantum;
while (gtk_events_pending())
gtk_main_iteration();
}
if (stop_flag) {
/* Well, the user decided to abort the printing. Just stop.
XXX - note that what got generated before they did that
will get printed, as we're piping to a print program; we'd
have to write to a file and then hand that to the print
program to make it actually not print anything. */
break;
}
count++;
if (fdata->flags.passed_dfilter) {
@ -1113,6 +1136,9 @@ print_packets(capture_file *cf, print_args_t *print_args)
}
}
/* We're done printing the packets; destroy the progress bar. */
destroy_progress_dlg(progbar);
if (col_widths != NULL)
g_free(col_widths);
if (line_buf != NULL)
@ -1122,8 +1148,6 @@ print_packets(capture_file *cf, print_args_t *print_args)
close_print_dest(print_args->to_file, cf->print_fh);
gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
cf->print_fh = NULL;
proto_tree_is_visible = FALSE;
@ -1214,6 +1238,8 @@ find_packet(capture_file *cf, dfilter *sfcode)
frame_data *start_fd;
frame_data *fdata;
frame_data *new_fd = NULL;
void *progbar;
gboolean stop_flag;
guint32 progbar_quantum;
guint32 progbar_nextstep;
int count;
@ -1223,8 +1249,6 @@ find_packet(capture_file *cf, dfilter *sfcode)
start_fd = cf->current_frame;
if (start_fd != NULL) {
gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
/* Iterate through the list of packets, starting at the packet we've
picked, calling a routine to run the filter on the packet, see if
it matches, and stop if so. */
@ -1236,7 +1260,9 @@ find_packet(capture_file *cf, dfilter *sfcode)
/* When we reach the value that triggers a progress bar update,
bump that value by this amount. */
progbar_quantum = cf->count/N_PROGBAR_UPDATES;
gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
stop_flag = FALSE;
progbar = create_progress_dlg("Searching", &stop_flag);
fdata = start_fd;
for (;;) {
@ -1251,12 +1277,16 @@ find_packet(capture_file *cf, dfilter *sfcode)
*/
g_assert(cf->count > 0);
gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
(gfloat) count / cf->count);
update_progress_dlg(progbar, (gfloat) count / cf->count);
progbar_nextstep += progbar_quantum;
while (gtk_events_pending())
gtk_main_iteration();
}
if (stop_flag) {
/* Well, the user decided to abort the search. Go back to the
frame where we started. */
new_fd = start_fd;
break;
}
/* Go past the current frame. */
@ -1296,7 +1326,8 @@ find_packet(capture_file *cf, dfilter *sfcode)
}
}
gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
/* We're done scanning the packets; destroy the progress bar. */
destroy_progress_dlg(progbar);
}
if (new_fd != NULL) {

3
file.h
View File

@ -1,7 +1,7 @@
/* file.h
* Definitions for file structures and routines
*
* $Id: file.h,v 1.69 2000/06/27 07:13:14 guy Exp $
* $Id: file.h,v 1.70 2000/07/03 08:35:41 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -92,7 +92,6 @@ typedef struct _capture_file {
guint32 esec; /* Elapsed seconds */
guint32 eusec; /* Elapsed microseconds */
guint32 snap; /* Captured packet length */
gboolean update_progbar; /* TRUE if we should update the progress bar */
long progbar_quantum; /* Number of bytes read per progress bar update */
long progbar_nextstep; /* Next point at which to update progress bar */
gchar *iface; /* Interface */

View File

@ -1,7 +1,7 @@
# Makefile.am
# Automake file for the GTK interface routines for Ethereal
#
# $Id: Makefile.am,v 1.26 2000/05/02 08:04:28 guy Exp $
# $Id: Makefile.am,v 1.27 2000/07/03 08:36:02 guy Exp $
#
# Ethereal - Network traffic analyzer
# By Gerald Combs <gerald@zing.org>
@ -67,6 +67,7 @@ libui_a_SOURCES = \
print_dlg.c \
print_prefs.c \
print_prefs.h \
progress_dlg.c \
proto_draw.c \
proto_draw.h \
simple_dialog.c \

View File

@ -1,7 +1,7 @@
/* gtkglobals.h
* GTK-related Global defines, etc.
*
* $Id: gtkglobals.h,v 1.8 2000/04/01 12:03:39 guy Exp $
* $Id: gtkglobals.h,v 1.9 2000/07/03 08:36:02 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -31,7 +31,7 @@
#endif
extern GtkWidget *top_level, *packet_list, *tree_view,
*byte_view, *prog_bar, *info_bar;
*byte_view, *info_bar;
extern GdkFont *m_r_font, *m_b_font;
extern GtkStyle *item_style;

View File

@ -1,6 +1,6 @@
/* main.c
*
* $Id: main.c,v 1.125 2000/06/27 07:13:25 guy Exp $
* $Id: main.c,v 1.126 2000/07/03 08:36:02 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -121,7 +121,7 @@ FILE *data_out_file = NULL;
packet_info pi;
capture_file cfile;
GtkWidget *top_level, *packet_list, *tree_view, *byte_view,
*prog_bar, *info_bar, *tv_scrollw, *pkt_scrollw;
*info_bar, *tv_scrollw, *pkt_scrollw;
static GtkWidget *bv_scrollw;
GdkFont *m_r_font, *m_b_font;
guint main_ctx, file_ctx;
@ -1785,16 +1785,12 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
create_byte_view(bv_size, l_pane, &byte_view, &bv_scrollw,
prefs->gui_scrollbar_on_right);
/* Progress/filter/info box */
/* Filter/info box */
stat_hbox = gtk_hbox_new(FALSE, 1);
gtk_container_border_width(GTK_CONTAINER(stat_hbox), 0);
gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0);
gtk_widget_show(stat_hbox);
prog_bar = gtk_progress_bar_new();
gtk_box_pack_start(GTK_BOX(stat_hbox), prog_bar, FALSE, TRUE, 3);
gtk_widget_show(prog_bar);
filter_bt = gtk_button_new_with_label("Filter:");
gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked",
GTK_SIGNAL_FUNC(filter_browse_cb), NULL);

190
gtk/progress_dlg.c Normal file
View File

@ -0,0 +1,190 @@
/* progress_dlg.c
* Routines for progress-bar (modal) dialog
*
* $Id: progress_dlg.c,v 1.1 2000/07/03 08:36:52 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
* Copyright 1998 Gerald Combs
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "gtkglobals.h"
#include "ui_util.h"
#define PROG_BAR_KEY "progress_bar"
static void delete_cb(GtkWidget *w, GdkEvent *event, gpointer data);
static void cancel_cb(GtkWidget *w, gpointer data);
/*
* Create and pop up the progress dialog; return a pointer to it, as
* a "void *", so that our caller doesn't have to know the GUI
* implementation.
*
* The first argument is the title to give the dialog box; the second
* argument is a pointer to a Boolean variable that will be set to
* TRUE if the user hits the "Cancel" button.
*
* XXX - should the button say "Cancel", or "Stop"?
*
* XXX - provide a way to specify the progress in units, with the total
* number of units specified as an argument when the progress dialog
* is created; updates would be given in units, with the progress dialog
* code computing the percentage, and the progress bar would have a
* label "0" on the left and <total number of units> on the right, with
* a label in the middle giving the number of units we've processed
* so far. This could be used when filtering packets, for example; we
* wouldn't always use it, as we have no idea how many packets are to
* be read.
*/
void *
create_progress_dlg(gchar *title, gboolean *stop_flag)
{
GtkWidget *dlg_w, *main_vb, *title_al, *title_lb, *prog_bar,
*cancel_al, *cancel_bt;
dlg_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(dlg_w), title);
/*
* Container for dialog widgets.
*/
main_vb = gtk_vbox_new(FALSE, 1);
gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
gtk_container_add(GTK_CONTAINER(dlg_w), main_vb);
gtk_widget_show(main_vb);
/*
* Put the title here as a label indicating what we're
* doing; stick it on the left, by putting it inside a
* GtkAlignment.
*/
title_al = gtk_alignment_new(0.0, 0.0, 0.0, 0.0);
title_lb = gtk_label_new(title);
gtk_container_add(GTK_CONTAINER(title_al), title_lb);
gtk_box_pack_start(GTK_BOX(main_vb), title_al, FALSE, TRUE, 3);
gtk_widget_show(title_lb);
gtk_widget_show(title_al);
/*
* The progress bar.
*/
prog_bar = gtk_progress_bar_new();
gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
gtk_box_pack_start(GTK_BOX(main_vb), prog_bar, FALSE, TRUE, 3);
gtk_widget_show(prog_bar);
/*
* Attach a pointer to the progress bar widget to the top-level
* widget.
*/
gtk_object_set_data(GTK_OBJECT(dlg_w), PROG_BAR_KEY, prog_bar);
/*
* Allow user to either click a "Cancel" button, or the close button
* on the window, to stop an operation in progress.
*
* Put the button in an alignment so it doesn't get any wider than
* it needs to to say "Cancel".
*/
cancel_al = gtk_alignment_new(0.5, 0.0, 0.0, 0.0);
cancel_bt = gtk_button_new_with_label("Cancel");
gtk_container_add(GTK_CONTAINER(cancel_al), cancel_bt);
gtk_signal_connect(GTK_OBJECT(cancel_bt), "clicked",
GTK_SIGNAL_FUNC(cancel_cb), (gpointer) stop_flag);
gtk_signal_connect(GTK_OBJECT(dlg_w), "delete_event",
GTK_SIGNAL_FUNC(delete_cb), (gpointer) stop_flag);
gtk_box_pack_end(GTK_BOX(main_vb), cancel_al, FALSE, FALSE, 3);
GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
gtk_widget_grab_default(cancel_bt);
GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
gtk_widget_grab_default(cancel_bt);
gtk_widget_show(cancel_bt);
gtk_widget_show(cancel_al);
gtk_widget_show(dlg_w);
gtk_grab_add(dlg_w); /* make it modal */
return dlg_w; /* return as opaque pointer */
}
/*
* Called when the dialog box is to be deleted.
* We just treat this the same way we treat clicking the "Cancel" button.
*/
static void
delete_cb(GtkWidget *w, GdkEvent *event, gpointer data)
{
cancel_cb(NULL, data);
}
/*
* Called when the "Cancel" button is clicked.
* Set the Boolean to TRUE.
*/
static void
cancel_cb(GtkWidget *w, gpointer data)
{
gboolean *stop_flag = (gboolean *) data;
GtkWidget *toplevel;
*stop_flag = TRUE;
if (w != NULL) {
/*
* The cancel button was clicked, so we have to destroy
* the dialog box ourselves.
*/
toplevel = gtk_widget_get_toplevel(w);
destroy_progress_dlg(toplevel);
}
}
/*
* Set the percentage value of the progress bar.
*/
void
update_progress_dlg(void *dlg, gfloat percentage)
{
GtkWidget *dlg_w = dlg;
GtkWidget *prog_bar;
prog_bar = gtk_object_get_data(GTK_OBJECT(dlg_w), PROG_BAR_KEY);
gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), percentage);
/*
* Flush out the update and process any input events.
*/
while (gtk_events_pending())
gtk_main_iteration();
}
/*
* Destroy the progress bar.
*/
void
destroy_progress_dlg(void *dlg)
{
GtkWidget *dlg_w = dlg;
gtk_grab_remove(GTK_WIDGET(dlg_w));
gtk_widget_destroy(GTK_WIDGET(dlg_w));
}

View File

@ -1,6 +1,6 @@
/* tethereal.c
*
* $Id: tethereal.c,v 1.31 2000/06/27 04:35:46 guy Exp $
* $Id: tethereal.c,v 1.32 2000/07/03 08:35:42 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -1045,7 +1045,6 @@ open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
cf->esec = 0;
cf->eusec = 0;
cf->snap = wtap_snapshot_length(cf->wth);
cf->update_progbar = FALSE;
cf->progbar_quantum = 0;
cf->progbar_nextstep = 0;
firstsec = 0, firstusec = 0;

View File

@ -1,7 +1,7 @@
/* ui_util.h
* Definitions for UI utility routines
*
* $Id: ui_util.h,v 1.4 2000/02/29 06:24:16 guy Exp $
* $Id: ui_util.h,v 1.5 2000/07/03 08:35:42 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -43,6 +43,31 @@ void reactivate_window(GtkWidget *);
/* Destroy all popup packet windows. */
void destroy_packet_wins(void);
/*
* Progress (modal) dialog box routines.
*/
/*
* Create and pop up the progress dialog; return a pointer to it, as
* a "void *", so that our caller doesn't have to know the GUI
* implementation.
*
* The first argument is the title to give the dialog box; the second
* argument is a pointer to a Boolean variable that will be set to
* TRUE if the user hits the "Cancel" button.
*/
void *create_progress_dlg(gchar *title, gboolean *stop_flag);
/*
* Set the percentage value of the progress bar.
*/
void update_progress_dlg(void *dlg, gfloat percentage);
/*
* Destroy the progress bar.
*/
void destroy_progress_dlg(void *dlg);
#ifdef __cplusplus
}
#endif /* __cplusplus */