quasar@ctt.bellcore.com (Laurence R. Brothers) (11/30/89)
After some struggle, I've finally managed to do it reliably. The obvious way to do this is to use "implicit dispatching", a mechanism more or less the same in sunview and xview that allows you to replace xv_main_loop() with your own code, on the understanding that event dispatching will only occur when you are hung in a blocking read. Another obvious possibility is using "explicit dispatching", a similar mechanism under which event dispatching will only occur when you call notify_dispatch() -- obviously for this you should use nonblocking reads or the program will hang when there is no input. Unfortunately, neither of these currently works the way I needed. Implicit dispatching does in fact function, but unfortunately, due to what is SOP in X, things you display or render in response to input do not necessarily get shown immediately -- instead they are buffered, a natural consequence of the distributed X client and server. The result of this is that what you think has been displayed has not been. With more and more input and no user events (input events flush the buffer), eventually the buffer overflows, or some other internal error dumps core. Explicit dispatching (at least a la sunview) fails entirely and hangs the interface. A search of the xview manual revealed the existence of the following calls (of course, not properly indexed): xv_set(xv_default_server,SERVER_SYNC,1,0); xv_set(xv_default_server,SERVER_SYNC_AND_PROCESS_EVENTS,1,0); XSync((Display*)xv_default_server,0); XFlush((Display*)xv_default_server,0); Apparently, any one of the above should at least have the effect of flushing the X buffer, and thus fixing the above problem with implicit dispatching. Actually, the first two completely wedge the program. The last two, which are Xlib calls, have the effect of a programmatic call to exit() -- ie, the program immediately terminates with no error message. So no joy with either special dispatching mechanism. Finally, after much travail, I discovered another mechanism in the sunview (not xview) manual: notify_set_input_func(base_frame,input_read_proc,input_fd); What this does is tells the notifier that whenever input is available for immediate read on the file descriptor input_fd, post an input event that calls input_read_proc (your i/o routine). This first of all lets you go back to using xv_main_loop(), and secondly fixes the X buffering problem, as input events immediately automagically stimulate flushing the X protocol buffer. Your read function is also guaranteed not to block since an event is only posted when there is data present on the input fd already. If the input_fd is some kind of stream, like a pipe for example (my case), then the data coming in is reliable and buffered correctly, so you don't have to fiddle about writing complicated i/o routines, but can simply read whatever is there to be read. notify_set_input_func() is of course undocumented in the xview manual, but supported by the xview include files and library archives. Laurence R. Brothers (quasar@ctt.bellcore.com)