[comp.windows.x] ANSWER: How to use XtAddInput

bjaspan@athena.mit.edu (Barr3y Jaspan) (01/20/91)

There seems to be a great deal of confusion about how to use XtAddInput to
read data from a source (regardless of what kind of source it is).  Enclosed
below is a newer version of the example I've posted several times before that
works for pipes (specifically, stdin) and files.  You can think of it as a
horribly inefficient and limited form of the 'cat' program. :-)

The confusing point seems to be that the registered input procedure gets
called continuously after a certain point.  As I explained in my previous
message, this occurs when end-of-file is reached but the file is not closed
and the input procedure is not removed with XtRemoveInput.  Notice that in the
example below, the file is actually closed and the procedure unregistered when
EOF occurs.  Uncommenting those two lines causes the previously described
(losing) behavior.

Next week's lesson will cover why XtAddInput for output sinks (using
XtInputWriteMask) does not do what you expected.  :-)

(Disclaimer: This program was tested on an IBM RT running a 4.3BSD-based
system.  Your mileage may vary, particularly if your system does not have the
open(), read(), and close() syscalls.)

-- 
Barr3y Jaspan, bjaspan@mit.edu
Watchmaker Computing

---- snip snip ----

#include <stdio.h>

#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Label.h>

void input();

main(argc, argv)
   int argc;
   char **argv;
{
     Widget	top;
     int	fd;

     top = XtInitialize("Hello", "World", NULL, 0, &argc, argv);

     if (argc == 2) {
	  fprintf(stderr, "Reading input from file \"%s\".\n", argv[1]);
	  fd = open(argv[1], "r", 0);
	  if (fd == -1) {
	       perror("opening file");
	       exit(1);
	  }
     } else {
	  fprintf(stderr, "Reading input from stdin.\n");
	  fd = 0;
     }

     (void) XtCreateManagedWidget("label", labelWidgetClass, top,
				  NULL, 0);
     
     XtAddInput(fd, XtInputReadMask, input, NULL);
     XtRealizeWidget(top);
     XtMainLoop();
}

void input(client_data, source, input_id)
   caddr_t	client_data;
   int		*source;
   XtInputId	*input_id;
{
     char	buf[BUFSIZ];
     int    	c;
     
     c = read(*source, buf, BUFSIZ);
     fprintf(stderr, "%d bytes read on fd %d.\n", c, *source);
     if (c == 0) {
	  fprintf(stderr, "closing file.\n");
	  close(*source);
	  XtRemoveInput(*input_id);
     } else if (c == -1) {
	  perror("reading from file");
	  exit(1);
     } else {
	  buf[c] = 0;
	  printf("\"%s\"\n", buf);
	  bzero(buf, c);
     }
}