Separated internal data from the preferences data

This commit is contained in:
Pierre Pronchery 2007-09-15 10:47:11 +00:00
parent 2298a2d670
commit e6a0c782db

View File

@ -15,8 +15,7 @@
* Place, Suite 330, Boston, MA 02111-1307 USA */ * Place, Suite 330, Boston, MA 02111-1307 USA */
/* TODO: /* TODO:
* - speed estimation * - speed estimation
* - implement -z * - implement -z */
* - separate preferences from internal data */
@ -36,19 +35,27 @@ typedef struct _Prefs
int flags; int flags;
char * filename; char * filename;
size_t length; size_t length;
/* XXX internal data */
int fd;
int fds[2];
pid_t pid;
GtkWidget * progress;
} Prefs; } Prefs;
#define PREFS_z 0x1 #define PREFS_z 0x1
/* progress */ /* progress */
/* types */
typedef struct _Progress
{
Prefs * prefs; /* preferences */
int fd; /* read descriptor */
int fds[2]; /* for the pipe */
pid_t pid; /* child's pid */
/* widgets */
GtkWidget * progress;
} Progress;
/* functions */ /* functions */
static int _progress_error(char const * message, int ret); static int _progress_error(char const * message, int ret);
static int _progress_exec(Prefs * prefs, char * argv[]); static int _progress_exec(Progress * progress, char * argv[]);
/* callbacks */ /* callbacks */
static gboolean _progress_out(GIOChannel * source, GIOCondition condition, static gboolean _progress_out(GIOChannel * source, GIOCondition condition,
@ -56,48 +63,50 @@ static gboolean _progress_out(GIOChannel * source, GIOCondition condition,
static int _progress(Prefs * prefs, char * argv[]) static int _progress(Prefs * prefs, char * argv[])
{ {
Progress p;
struct stat st; struct stat st;
GIOChannel * channel; GIOChannel * channel;
GtkWidget * window = NULL; GtkWidget * window = NULL;
GtkWidget * vbox; GtkWidget * vbox;
GtkWidget * widget; GtkWidget * widget;
p.prefs = prefs;
if(prefs->filename == NULL) if(prefs->filename == NULL)
prefs->filename = "Standard input"; prefs->filename = "Standard input";
else if((prefs->fd = open(prefs->filename, O_RDONLY)) < 0) else if((p.fd = open(prefs->filename, O_RDONLY)) < 0)
return _progress_error(prefs->filename, 1); return _progress_error(prefs->filename, 1);
else if(fstat(prefs->fd, &st) == 0) else if(fstat(p.fd, &st) == 0)
prefs->length = st.st_size; prefs->length = st.st_size;
if(pipe(prefs->fds) != 0) if(pipe(p.fds) != 0)
{ {
close(prefs->fd); close(p.fd);
return _progress_error("pipe", 1); return _progress_error("pipe", 1);
} }
channel = g_io_channel_unix_new(prefs->fds[1]); channel = g_io_channel_unix_new(p.fds[1]);
g_io_add_watch(channel, G_IO_OUT, _progress_out, prefs); g_io_add_watch(channel, G_IO_OUT, _progress_out, &p);
if((prefs->pid = fork()) == -1) if((p.pid = fork()) == -1)
{ {
close(prefs->fd); close(p.fd);
close(prefs->fds[0]); close(p.fds[0]);
close(prefs->fds[1]); close(p.fds[1]);
return _progress_error("fork", 1); return _progress_error("fork", 1);
} }
if(prefs->pid != 0) if(p.pid != 0)
return _progress_exec(prefs, argv); return _progress_exec(&p, argv);
close(prefs->fds[0]); close(p.fds[0]);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL); window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Progress"); gtk_window_set_title(GTK_WINDOW(window), "Progress");
vbox = gtk_vbox_new(FALSE, 0); vbox = gtk_vbox_new(FALSE, 0);
widget = gtk_label_new(prefs->filename); widget = gtk_label_new(prefs->filename);
gtk_box_pack_start(GTK_BOX(vbox), widget, TRUE, TRUE, 4); gtk_box_pack_start(GTK_BOX(vbox), widget, TRUE, TRUE, 4);
prefs->progress = gtk_progress_bar_new(); p.progress = gtk_progress_bar_new();
gtk_box_pack_start(GTK_BOX(vbox), prefs->progress, TRUE, TRUE, 4); gtk_box_pack_start(GTK_BOX(vbox), p.progress, TRUE, TRUE, 4);
gtk_container_add(GTK_CONTAINER(window), vbox); gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_container_set_border_width(GTK_CONTAINER(window), 4); gtk_container_set_border_width(GTK_CONTAINER(window), 4);
gtk_widget_show_all(window); gtk_widget_show_all(window);
gtk_main(); gtk_main();
close(prefs->fd); close(p.fd);
close(prefs->fds[1]); close(p.fds[1]);
return 0; return 0;
} }
@ -114,10 +123,10 @@ static int _progress_error(char const * message, int ret)
} }
static int _progress_exec(Prefs * prefs, char * argv[]) static int _progress_exec(Progress * progress, char * argv[])
{ {
close(prefs->fds[1]); close(progress->fds[1]);
if(dup2(prefs->fds[0], 0) == -1) if(dup2(progress->fds[0], 0) == -1)
exit(1); /* FIXME warn user */ exit(1); /* FIXME warn user */
execvp(argv[0], argv); execvp(argv[0], argv);
/* FIXME warn user */ /* FIXME warn user */
@ -130,7 +139,7 @@ static gboolean _progress_out(GIOChannel * source, GIOCondition condition,
gpointer data) gpointer data)
{ {
static size_t cnt = 0; static size_t cnt = 0;
Prefs * prefs = data; Progress * p = data;
char buf[BUFSIZ]; char buf[BUFSIZ];
ssize_t len; ssize_t len;
gsize written; gsize written;
@ -138,10 +147,10 @@ static gboolean _progress_out(GIOChannel * source, GIOCondition condition,
/* FIXME use g_io_channel_read too? */ /* FIXME use g_io_channel_read too? */
if(condition != G_IO_OUT if(condition != G_IO_OUT
|| (len = read(prefs->fd, buf, sizeof(buf))) < 0) || (len = read(p->fd, buf, sizeof(buf))) < 0)
{ {
gtk_main_quit(); gtk_main_quit();
_progress_error(prefs->filename, 0); _progress_error(p->prefs->filename, 0);
return FALSE; return FALSE;
} }
if(g_io_channel_write(source, buf, len, &written) != G_IO_ERROR_NONE if(g_io_channel_write(source, buf, len, &written) != G_IO_ERROR_NONE
@ -150,21 +159,20 @@ static gboolean _progress_out(GIOChannel * source, GIOCondition condition,
/* FIXME it may just be that everything was not written /* FIXME it may just be that everything was not written
* => put buffer and position in Prefs/Progress */ * => put buffer and position in Prefs/Progress */
gtk_main_quit(); gtk_main_quit();
_progress_error(prefs->filename, 0); _progress_error(p->prefs->filename, 0);
return FALSE; return FALSE;
} }
cnt += len; cnt += len;
if(prefs->length == 0 || cnt == 0) if(p->prefs->length == 0 || cnt == 0)
gtk_progress_bar_pulse(GTK_PROGRESS_BAR(prefs->progress)); gtk_progress_bar_pulse(GTK_PROGRESS_BAR(p->progress));
else else
{ {
fraction = cnt; fraction = cnt;
fraction /= prefs->length; fraction /= p->prefs->length;
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(prefs->progress), gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(p->progress),
fraction); fraction);
snprintf(buf, sizeof(buf), "%.1f%%", fraction * 100); snprintf(buf, sizeof(buf), "%.1f%%", fraction * 100);
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(prefs->progress), gtk_progress_bar_set_text(GTK_PROGRESS_BAR(p->progress), buf);
buf);
} }
if(len == 0) if(len == 0)
{ {