eejames@cybaswan.UUCP (jw.powrie) (10/09/90)
Hello, Are there any X-Gurus out there who can assist me with my problem? I am writing an X-windows program (xgraph) which (amongst other things) reads data from stdin and uses this data to update a graph. The data is produced by another program, (data_feed) and takes the form of one integer per line e.g. 4 5 4 6 3 etc. The two programs are executed as a pipe as follows: prompt% data_feed | xgraph Previously, I had written the xgraph program using Xlib. The main loop was something like this: while (1) { /* poll for X events (say) 20 times */ for (i=0; i<20; i++ ) if ( XCheckMaskEvent(dpy,event_mask,%pe) { /* process X events */ } /* read in the next line of data */ scanf("%d",&time); } Because the Xevents anticipated were few and far between, the above (rather crude) approach worked fine. However, I am now trying to improve my program by using a widget based approach. According to the "X Toolkit Intrinsics - C Language Interface", I can register an (arbirary?) file as an input (event) source using the XtAppAddInput() function. I re-coded the xgraph program (to use widgets) and the program works fine on its own (ie with stdin connected to the keyboard). However, if I run a program as part of a UNIX pipe (e.g. cat | program ), I get the following error message: X Toolkit Error: Select failed. My questions are: 1) Why does the program work fine with the keyboard attached to stdin, but not with a pipe attched? 2) Is there a simple fix? 3) If not, is there another/better way in which I can turn piped input into an X event source? The relevant extracts of my code are included below: /************************************************************************ main(argc,argv) unsigned int argc; char **argv; { Widget toplevel; XtAppContext theAppContext; XtInputId input_id; toplevel = XtInitialize(argv[0], "Demo", NULL,0, &argc,argv); ................................................................ /* open various widgets etc */ ................................................................ theAppContext = XtWidgetToApplicationContext(toplevel); input_id = XtAppAddInput(theAppContext,0,XtInputReadMask,input_fn,NULL); XtMainLoop(); } void input_fn(w,client_data,call_data) Widget w; caddr_t client_data; caddr_t call_data; { int time; scanf("%d",&time); printf("time is %d\n",time); /* other processing etc */ } **************************************************************************** Many thanks for any help. James. - - - - - - - - - - - - - - - - - - - - James Powrie, | UUCP : ...!ukc!pyr.swan.ac.uk!eejames | Image Processing Laboratory, | JANET : eejames@pyr.swan.ac.uk | Electrical Engineering Dept., | : | University of Wales, | voice : +44 792 205678 Ext 4698 | Swansea, SA2 8PP, U.K. | Fax : +44 792 295532 | | Telex : 48358 | - - - - - - - - - - - - - - - - - - - -
pete@iris49.UUCP (Pete Ware) (10/13/90)
eejames> My questions are: eejames> 1) Why does the program work fine with the keyboard attached eejames> to stdin, but not with a pipe attched? The program providing input is probably exiting which closes the pipe. eejames> 2) Is there a simple fix? Yes, change your function, input_fn() to something like: void input_fn(client_data, source, id) caddr_t client_data; int *source; XtInputId *id; { int time; if (scanf("%d",&time) == EOF) { XtRemoveInput (*id); return; } printf("time is %d\n",time); /* other processing etc */ } - You might also consider using using gets() so you don't block if the user just enters a return (scanf keeps looking for input). - You might want to use the client_data to pass in the actual file pointer so it can work for any source of input. - You might want to close the file pointer when EOF is reached. --pete Pete Ware / Biosym / San Diego CA / (619) 546-5532 uucp: scripps.edu!bioc1!pete Internet: bioc1!pete@scripps.edu