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