\section{Handling event-callbacks} \label{sec:event} When PCE is active and has open windows it must process events it receives from the X-server. It is desirable that the user can interact with the host-language while PCE is active. The PCE/Host process can therefore be seen as a two-thread process: \begin{enumerate} \tick{Read and process the host toplevel} Most interactive symbolic languages have a {\em toplevel} that reads requests and executes them. \tick{Read and process X-events} PCE has to read events from its connection to the X-server and execute them. \end{enumerate} Especially if PCE is connected to a closed% \footnote{With {\em closed} we refer to a programming environment that comes as a completely linked Unix process with an external interface that does not allow for certain modifications.} programming environment, realising this functionality is generally the hardest problem of writing the PCE/Host interface. Currently this problem has been solved by: \begin{itemize} \tick{Patch the read function of the host-language} In the SWI-Prolog; SICStus Prolog and Lucid CommonLisp interface we have patched the function of the host-language that reads characters from the user for the interactive toplevel. For both Prolog systems this has been realised by adding a hook to the read function of the Prolog environment. For SWI-Prolog the low-level read function is defined as: \begin{code} int (*PL_dispatch_events)() = NULL; char pl_get_char() { if ( PL_dispatch_events != NULL ) { for(;;) { char c; if ( (*PL_dispatch_events)() == PL_DISPATCH_INPUT ) { if ( read(0, &c, 1) == 0 ) c = EOF; return c; } } } return getchar(); } \end{code} The PCE/SWI-Prolog interface assigns \var{PL_dispatch_events} with a function that processes X-events and looks for input on file-descriptor 0. This function returns with PL_DISPATCH_INPUT if there is input on file-descriptor 0 and with another value on a timeout or after processing an X-event. This function is defines as: \begin{code} static int pce_dispatch() { if ( pceDispatch(0, 0) == PCE_DISPATCH_INPUT ) return PL_DISPATCH_INPUT; return PL_DISPATCH_TIMEOUT; } \end{code} \tick{Use a threat in a multi-thread environment} If the host-language is a multi-thread system it is possible to have one or more threats that execute the interactive toplevel and one thread that handles the X-window events for PCE. This approach has been takes in the LispWorks interface. \end{itemize} The C-functions applicable to event-dispatching are: \begin{description} \cfunction{int}{pceDispatch}{int fd, int msec} Look for X-events and input on file-descriptor \arg{fd}. Return \const{PCE_DISPATCH_INPUT} if there is input on the specified file-descriptor and \const{PCE_DISPATCH_TIMEOUT} if the timer has expired before there is input. If \arg{fd} equals -1 no file-descriptor is watched. The argument \arg{msec} is the time-out time in milliseconds. If \arg{msec} equals 0 this call blocks until there is input. See also `window_manager ->dispatch'. \end{description} When using a separate thread to handle X-events for PCE, the following interface functions may be applicable. \begin{description} \cfunction{void}{pceRedraw}{void} Update the display for any changed graphical object and flush all output for the X-server (calling \cfunc{Xflush()}). \cfunction{XtAppContext}{pceXtAppContext}{XtAppContext context} If there is already an Xt application context, return this context. Else if \arg{context} is not \const{NULL}, make the \arg{context} the Xt application context for PCE. Finally, if there is no context and the argument is \const{NULL}, create a context and return it. This function is only necessary if the host-environment defines an interface for X-windows that requires the application context of PCE. Whenever PCE itself needs the application context (normally when it invokes `display ->open'), it will call this function with \arg{context} equal to \const{NULL}. There is no entry for this function in the header file \file{xpce/src/itf-interface.h} as this would require including the X11 include files. The necessary declarations should be made in the interface. \end{description}