From 566df6918473da40008c3871420ba9c44d454110 Mon Sep 17 00:00:00 2001 From: mdw Date: Wed, 24 Mar 1999 22:23:57 +0000 Subject: [PATCH] Improve display for large files. Keep newly added material in view if scrolled to bottom of window. --- xcatch.c | 181 ++++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 115 insertions(+), 66 deletions(-) diff --git a/xcatch.c b/xcatch.c index 9a69aa1..43d3b02 100644 --- a/xcatch.c +++ b/xcatch.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: xcatch.c,v 1.3 1998/12/20 17:19:16 mdw Exp $ + * $Id: xcatch.c,v 1.4 1999/03/24 22:23:57 mdw Exp $ * * Catch input and trap it in an X window * @@ -29,6 +29,10 @@ /*----- Revision history --------------------------------------------------* * * $Log: xcatch.c,v $ + * Revision 1.4 1999/03/24 22:23:57 mdw + * Improve display for large files. Keep newly added material in view if + * scrolled to bottom of window. + * * Revision 1.3 1998/12/20 17:19:16 mdw * Return exit status of child process, rather than always returning * success. @@ -97,82 +101,122 @@ static void killwin(GtkWidget *w, gpointer p) static void ready(gpointer data, gint fd, GdkInputCondition c) { char buf[1024]; - int count; + int doscroll = 1; + GtkText *t; + GtkAdjustment *va; - /* --- Read the next buffer of data --- */ + /* --- If not ready to read then go away --- */ if (!(c & GDK_INPUT_READ)) return; - count = read(fd, buf, sizeof(buf)); - /* --- Decide what to do --- */ + /* --- Decide whether to scroll the window --- */ - if (count < 0) { - msg(":~OK", "error reading data: %s", strerror(errno)); - exit(EXIT_FAILURE); + if (textbox) { + t = GTK_TEXT(textbox); + va = t->vadj; + if (va->value + va->page_size < va->upper) + doscroll = 0; + gtk_text_freeze(t); } - if (count == 0) { - close(fd); - if (textbox) - flags |= f_closed; - else - gtk_main_quit(); - return; - } + /* --- Read data into the buffer --- * + * + * This is a bit of a mess. + */ - /* --- If there's no output window, create one --- */ - - if (!textbox) { - GtkWidget *win; - GtkWidget *t; - GtkWidget *w; - - win = gtk_dialog_new(); - gtk_signal_connect(GTK_OBJECT(win), "destroy", - GTK_SIGNAL_FUNC(killwin), 0); - - t = gtk_table_new(2, 2, 0); - gtk_container_border_width(GTK_CONTAINER(t), 8); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(win)->vbox), t, 1, 1, 0); - gtk_widget_show(t); - - textbox = gtk_text_new(0, 0); - gtk_table_attach(GTK_TABLE(t), textbox, 0, 1, 0, 1, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, - 0, 0); - gtk_text_set_editable(GTK_TEXT(textbox), 0); - gtk_widget_set_usize(textbox, 500, 100); - gtk_widget_show(textbox); - - w = gtk_vscrollbar_new(GTK_TEXT(textbox)->vadj); - gtk_table_attach(GTK_TABLE(t), w, 1, 2, 0, 1, - 0, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); - gtk_widget_show(w); - - w = gtk_hscrollbar_new(GTK_TEXT(textbox)->hadj); - gtk_table_attach(GTK_TABLE(t), w, 0, 1, 1, 2, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0, 0); - gtk_widget_show(w); - - gtk_box_set_homogeneous(GTK_BOX(GTK_DIALOG(win)->action_area), 0); - w = gtk_button_new_with_label("Dismiss"); - gtk_signal_connect_object(GTK_OBJECT(w), "clicked", - GTK_SIGNAL_FUNC(gtk_object_destroy), - GTK_OBJECT(win)); - gtk_box_pack_end(GTK_BOX(GTK_DIALOG(win)->action_area), w, 0, 0, 0); - GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT); - gtk_widget_grab_default(w); - cancel(GTK_WINDOW(win), w); - gtk_widget_show(w); - - gtk_widget_show(win); - } + for (;;) { + int r = read(fd, buf, sizeof(buf)); + + /* --- The read failed --- * + * + * Maybe there's no more data to read. In this case, we get + * @EWOULDBLOCK@, indicating it's time to stop and do something else. + * Otherwise something serious has happened. + */ + + if (r < 0) { + if (errno == EWOULDBLOCK) + break; + msg(":~OK", "error reading data: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + /* --- End of file --- * + * + * If the box is closed, then exit quiety; otherwise wait for it to + * go away. + */ - /* --- Append the new text --- */ + if (r == 0) { + close(fd); + if (textbox) + flags |= f_closed; + else + gtk_main_quit(); + break; + } + + /* --- If there's no output window, create one --- */ + + if (!textbox) { + GtkWidget *win; + GtkWidget *tbl; + GtkWidget *w; + + win = gtk_dialog_new(); + gtk_signal_connect(GTK_OBJECT(win), "destroy", + GTK_SIGNAL_FUNC(killwin), 0); + + tbl = gtk_table_new(2, 2, 0); + gtk_container_border_width(GTK_CONTAINER(tbl), 8); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(win)->vbox), tbl, 1, 1, 0); + gtk_widget_show(tbl); + + textbox = gtk_text_new(0, 0); + t = GTK_TEXT(textbox); + va = t->vadj; + gtk_table_attach(GTK_TABLE(tbl), textbox, 0, 1, 0, 1, + GTK_EXPAND | GTK_SHRINK | GTK_FILL, + GTK_EXPAND | GTK_SHRINK | GTK_FILL, + 0, 0); + gtk_text_set_editable(t, 0); + gtk_widget_set_usize(textbox, 500, 300); + gtk_text_freeze(t); + gtk_widget_show(textbox); + + w = gtk_vscrollbar_new(va); + gtk_table_attach(GTK_TABLE(tbl), w, 1, 2, 0, 1, + 0, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show(w); + + w = gtk_hscrollbar_new(t->hadj); + gtk_table_attach(GTK_TABLE(tbl), w, 0, 1, 1, 2, + GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0, 0); + gtk_widget_show(w); + + gtk_box_set_homogeneous(GTK_BOX(GTK_DIALOG(win)->action_area), 0); + w = gtk_button_new_with_label("Dismiss"); + gtk_signal_connect_object(GTK_OBJECT(w), "clicked", + GTK_SIGNAL_FUNC(gtk_object_destroy), + GTK_OBJECT(win)); + gtk_box_pack_end(GTK_BOX(GTK_DIALOG(win)->action_area), w, 0, 0, 0); + GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT); + gtk_widget_grab_default(w); + cancel(GTK_WINDOW(win), w); + gtk_widget_show(w); + + gtk_widget_show(win); + } - gtk_text_insert(GTK_TEXT(textbox), font, 0, 0, buf, count); + gtk_text_insert(t, font, 0, 0, buf, r); + } + + if (textbox) { + gtk_text_thaw(t); + if (doscroll) + gtk_adjustment_set_value(va, va->upper - va->page_size); + } } /* --- Signal handler --- */ @@ -321,6 +365,11 @@ int main(int argc, char *argv[]) } } + { + int f = fcntl(fd, F_GETFL); + fcntl(fd, F_SETFL, f | O_NONBLOCK); + } + gdk_input_add(fd, GDK_INPUT_READ, ready, 0); gtk_main(); return (status); -- 2.11.0