Fix tabbing in help text.
[xtoys] / xcatch.c
CommitLineData
63351ac6 1/* -*-c-*-
2 *
4e6aae28 3 * $Id: xcatch.c,v 1.2 1998/12/16 00:10:58 mdw Exp $
63351ac6 4 *
5 * Catch input and trap it in an X window
6 *
7 * (c) 1998 Straylight/Edgeware
8 */
9
10/*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of the Edgeware X tools collection.
13 *
14 * X tools is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * X tools is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with X tools; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29/*----- Revision history --------------------------------------------------*
30 *
31 * $Log: xcatch.c,v $
4e6aae28 32 * Revision 1.2 1998/12/16 00:10:58 mdw
33 * Fix tabbing in help text.
34 *
63351ac6 35 * Revision 1.1 1998/12/15 23:46:50 mdw
36 * New program: captures input and puts it in a window.
37 *
38 */
39
40/*----- Header files ------------------------------------------------------*/
41
42#include <errno.h>
43#include <signal.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47
48#include <sys/types.h>
49#include <sys/wait.h>
50
51#include <fcntl.h>
52#include <unistd.h>
53
54#include <gtk/gtk.h>
55
56#include <mLib/dstr.h>
57#include <mLib/mdwopt.h>
58#include <mLib/report.h>
59#include <mLib/quis.h>
60
61#include <mgLib/cancel.h>
62#include <mgLib/msg.h>
63
64/*----- Inportant state ---------------------------------------------------*/
65
66static unsigned int flags;
67
68enum {
69 f_closed = 1,
70 f_bogus = 2
71};
72
73GtkWidget *textbox = 0;
74GdkFont *font;
75
76/*----- Main code ---------------------------------------------------------*/
77
78/* --- The window's closed --- */
79
80static void killwin(GtkWidget *w, gpointer p)
81{
82 if (flags & f_closed)
83 gtk_main_quit();
84 else
85 textbox = 0;
86}
87
88/* --- Some input has arrived --- */
89
90static void ready(gpointer data, gint fd, GdkInputCondition c)
91{
92 char buf[1024];
93 int count;
94
95 /* --- Read the next buffer of data --- */
96
97 if (!(c & GDK_INPUT_READ))
98 return;
99 count = read(fd, buf, sizeof(buf));
100
101 /* --- Decide what to do --- */
102
103 if (count < 0) {
104 msg(":~OK", "error reading data: %s", strerror(errno));
105 exit(EXIT_FAILURE);
106 }
107
108 if (count == 0) {
109 close(fd);
110 if (textbox)
111 flags |= f_closed;
112 else
113 gtk_main_quit();
114 return;
115 }
116
117 /* --- If there's no output window, create one --- */
118
119 if (!textbox) {
120 GtkWidget *win;
121 GtkWidget *t;
122 GtkWidget *w;
123
124 win = gtk_dialog_new();
125 gtk_signal_connect(GTK_OBJECT(win), "destroy",
126 GTK_SIGNAL_FUNC(killwin), 0);
127
128 t = gtk_table_new(2, 2, 0);
129 gtk_container_border_width(GTK_CONTAINER(t), 8);
130 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(win)->vbox), t, 1, 1, 0);
131 gtk_widget_show(t);
132
133 textbox = gtk_text_new(0, 0);
134 gtk_table_attach(GTK_TABLE(t), textbox, 0, 1, 0, 1,
135 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
136 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
137 0, 0);
138 gtk_text_set_editable(GTK_TEXT(textbox), 0);
139 gtk_widget_set_usize(textbox, 500, 100);
140 gtk_widget_show(textbox);
141
142 w = gtk_vscrollbar_new(GTK_TEXT(textbox)->vadj);
143 gtk_table_attach(GTK_TABLE(t), w, 1, 2, 0, 1,
144 0, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
145 gtk_widget_show(w);
146
147 w = gtk_hscrollbar_new(GTK_TEXT(textbox)->hadj);
148 gtk_table_attach(GTK_TABLE(t), w, 0, 1, 1, 2,
149 GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0, 0);
150 gtk_widget_show(w);
151
152 gtk_box_set_homogeneous(GTK_BOX(GTK_DIALOG(win)->action_area), 0);
153 w = gtk_button_new_with_label("Dismiss");
154 gtk_signal_connect_object(GTK_OBJECT(w), "clicked",
155 GTK_SIGNAL_FUNC(gtk_object_destroy),
156 GTK_OBJECT(win));
157 gtk_box_pack_end(GTK_BOX(GTK_DIALOG(win)->action_area), w, 0, 0, 0);
158 GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
159 gtk_widget_grab_default(w);
160 cancel(GTK_WINDOW(win), w);
161 gtk_widget_show(w);
162
163 gtk_widget_show(win);
164 }
165
166 /* --- Append the new text --- */
167
168 gtk_text_insert(GTK_TEXT(textbox), font, 0, 0, buf, count);
169}
170
171/* --- Signal handler --- */
172
173static void reap(int sig)
174{
175 while (waitpid(-1, 0, WNOHANG) > 0)
176 ;
177}
178
179/* --- Main program --- */
180
181static void version(FILE *fp)
182{
183 fprintf(fp, "%s (xtoys version " VERSION ")\n", QUIS);
184}
185
186static void usage(FILE *fp)
187{
188 fprintf(fp, "Usage: %s [-f file] [-F font] [command [args...]]\n", QUIS);
189}
190
191int main(int argc, char *argv[])
192{
193 int fd = -1;
194
195 ego(argv[0]);
196
197 gtk_init(&argc, &argv);
198
199 for (;;) {
200 static struct option opt[] = {
201 { "help", 0, 0, 'h' },
202 { "usage", 0, 0, 'u' },
203 { "version", 0, 0, 'v' },
204 { "file", gFlag_argReq, 0, 'f' },
205 { "font", gFlag_argReq, 0, 'F' },
206 { 0, 0, 0, 0 }
207 };
208 int i = mdwopt(argc, argv, "huvf:F:", opt, 0, 0, 0);
209
210 if (i < 0)
211 break;
212
213 switch (i) {
214 case 'h':
215 version(stdout);
216 fputc('\n', stdout);
217 usage(stdout);
218 fputs(
219"\n"
220"Catches input from a pipe or other source, and captures it in a window.\n"
221"Nothing is displayed if there's no input.\n"
222"\n"
223"Options provided:\n"
224"\n"
225"-h, --help Display this help text\n"
226"-u, --usage Display a quick usage summary\n"
227"-v, --version Display the version number\n"
4e6aae28 228"-f, --file=FILE\t Read input from the named file\n"
229"-F, --font=FONT\t Display output in the named font\n",
63351ac6 230 stdout);
231 exit(0);
232 break;
233 case 'u':
234 usage(stdout);
235 exit(0);
236 break;
237 case 'v':
238 version(stdout);
239 exit(0);
240 break;
241 case 'f':
242 if ((fd = open(optarg, O_RDONLY)) < 0) {
243 die(1, "couldn't open file: %s", strerror(errno));
244 exit(1);
245 }
246 break;
247 case 'F':
248 font = gdk_font_load(optarg);
249 break;
250 default:
251 flags |= f_bogus;
252 break;
253 }
254 }
255
256 if (flags & f_bogus) {
257 usage(stderr);
258 exit(1);
259 }
260
261 if (fd == -1) {
262 if (optind == argc)
263 fd = STDIN_FILENO;
264 else {
265 int pfd[2];
266 pid_t kid;
267 struct sigaction sa;
268
269 /* --- Set up a signal handler --- */
270
271 sa.sa_handler = reap;
272 sigemptyset(&sa.sa_mask);
273 sa.sa_flags = 0;
274 sigaction(SIGCHLD, &sa, 0);
275
276 /* --- Start a child program --- */
277
278 if (pipe(pfd))
279 die(1, "couldn't open pipe: %s", strerror(errno));
280 kid = fork();
281 if (kid < 0)
282 die(1, "couldn't fork: %s", strerror(errno));
283 if (kid == 0) {
284 dstr d;
285
286 close(pfd[0]);
287 if (pfd[1] != STDOUT_FILENO)
288 dup2(pfd[1], STDOUT_FILENO);
289 if (pfd[1] != STDERR_FILENO)
290 dup2(pfd[1], STDERR_FILENO);
291 if (pfd[1] != STDOUT_FILENO && pfd[1] != STDERR_FILENO)
292 close(pfd[1]);
293 execvp(argv[optind], argv + optind);
294
295 dstr_create(&d);
296 dstr_putf(&d, "%s: couldn't run `%s': %s\n",
297 QUIS, argv[optind], strerror(errno));
298 write(STDERR_FILENO, d.buf, d.len);
299 _exit(127);
300 }
301 fd = pfd[0];
302 close(pfd[1]);
303 }
304 }
305
306 gdk_input_add(fd, GDK_INPUT_READ, ready, 0);
307 gtk_main();
308 return (0);
309}
310
311/*----- That's all, folks -------------------------------------------------*/