From d2401425e6934d9649416cd9523f20776b40d7e6 Mon Sep 17 00:00:00 2001
From: dtc <dtc>
Date: Sun, 28 Dec 1997 18:03:24 +0000
Subject: [PATCH] Documentation of implementation of CMU CL Motif server. Based
 on internals.doc 1.1, with LaTeX formatting by Marco Antoniotti.

---
 docs/interface/internals.tex | 477 +++++++++++++++++++++++++++++++++++
 1 file changed, 477 insertions(+)
 create mode 100644 docs/interface/internals.tex

diff --git a/docs/interface/internals.tex b/docs/interface/internals.tex
new file mode 100644
index 000000000..a4f254ff7
--- /dev/null
+++ b/docs/interface/internals.tex
@@ -0,0 +1,477 @@
+%% -*- Mode: LaTeX -*-
+%% internals.tex
+
+%% LaTeX formatting by Marco Antoniotti based on internals.doc.
+
+\documentclass{article}
+\usepackage{a4wide}
+
+\title{General Design Notes on the Motif Toolkit Interface}
+
+\begin{document}
+
+\maketitle
+
+\section{Data Transport}
+
+\subsection{Packet format}
+
+\begin{itemize}
+\item	\textbf{Header:}\\[2mm]
+	\begin{center}
+\begin{tabular}{|l|l|l|}
+	\hline
+	32 bits & serial number & \\\cline{1-2}
+	16 bits & sequence position &  This header\\\cline{1-2}
+	16 bits & sequence length   &  takes 12 bytes\\\cline{1-2}
+	32 bits & packet length (including header) & \\\hline
+	\end{tabular}
+\end{center}
+\item	\textbf{Data:}\\[2mm]
+	(packet\_length - 12) bytes of information
+\end{itemize}
+
+\begin{itemize}
+\item	Packets have a fixed maximum size (4k).
+
+\item	Packets a grouped together to form random length messages.  The
+	sequence length refers to how many packets comprise the
+	message, and each packet is tagged with its position in that sequence.
+
+\item	All packets in the same message have the same serial number.
+\item	Messages are built up as their constituent packets arrive.  It should
+	be possible to interleave the packets of different messages
+	and still have the individual messages be constructed
+	properly.
+\item	It is tacitly assumed that packets arrive in their proper
+	sequence order. 
+\item	A packet with a sequence position/length field denoting [0 of 0] is a
+	cancellation packet.  The message having that serial number should be
+	discarded.
+\end{itemize}
+
+\subsubsection{Data format}
+
+Each data entry in a message is represented as:\\[2mm]
+\begin{center}
+\begin{tabular}{|rl|l|}
+\hline
+ 8 & bits & type tag\\\hline
+24 & bits & immediate data\\\hline
+   & rest & other data (if necessary)\\\hline
+\end{tabular}
+\end{center}
+
+
+\section{Greeting Protocol}
+
+When a Lisp process first establishes a connection to the server, it
+sends a 16 bit quantity which represents "1" to it.  The server using this
+to decide whether to byte swap words when sending them to Lisp.  The
+general policy is that all data is presented to the Lisp process in the
+order that Lisp uses.
+
+Following the byte swapping information, the Lisp process sends an
+initial message which contains:
+\begin{itemize}
+\item A string giving the target X display name
+\item A string for the application name
+\item A string for the application class
+\end{itemize}
+
+\section{Request Protocol}
+
+\paragraph{Request format:}{\ }\\[2mm]
+\begin{center}
+\begin{tabular}{|rl|l|}
+\hline
+	16 & bits & request opcode\\\hline
+	 8 & bits & request flags (0=nothing, 1=require confirm)\\\hline
+	 8 & bits & argument count (unused)\\\hline
+\end{tabular}
+\end{center}
+
+At the moment, the request flags field is used only to indicate whether
+the Lisp client desires a confirmation message when the request is finished
+processing.  If the request returns any values, this counts as the
+confirmation.  Otherwise, an empty confirmation message will be sent.
+
+\paragraph{Server reply format:}{\ }\\[2mm]
+\begin{center}
+\begin{tabular}{|rl|l|}
+\hline
+	32 & bits & response tag\\\hline
+	   & rest & return data (if any)\\\hline
+\end{tabular}
+\end{center}
+
+\noindent
+The response tag can have the following values:\\[2mm]
+\begin{center}
+\begin{tabular}{|l|l|}
+\hline
+\textsc{Tag} & \textsc{Meaning}\\\hline\hline
+	\texttt{CONFIRM\_REPLY}  & confirmation (for synchronization)\\\hline
+	\texttt{VALUES\_REPLY}   & return values from a request\\\hline
+	\texttt{CALLBACK\_REPLY} & a widget callback has been invoked\\\hline
+	\texttt{EVENT\_REPLY}    & an X event handler has been invoked\\\hline
+	\texttt{ERROR\_REPLY}    & an error has occurred\\\hline
+	\texttt{WARNING\_REPLY}  & a non-fatal problem has occurred\\\hline
+	\texttt{PROTOCOL\_REPLY} & a protocol callback has been invoked\\\hline
+\end{tabular}
+\end{center}
+
+
+\section{Object Representations}
+
+\subsection{Data format in message}
+
+\begin{center}
+\begin{tabular}{|l|rl|p{.6\textwidth}|}
+\hline
+Accelerators	& 32 & bit & integer ID\\
+Atom		& 32 & bit & Atom ID\\
+Boolean		& 24 & bit & immediate data\\
+Color		& 24 & bit & immediate data (Red value) followed by
+			     2 16 bit words for Green and Blue\\
+Colormap	& 32 & bit & Colormap XID\\
+Compound Strings	& 32 & bit & address\\
+Cursor		& 32 & bit & Cursor XID\\
+Enumeration	& 24 & bit & immediate integer\\
+Font		& 32 & bit & Font XID\\
+Font List	& 32 & bit & integer ID\\
+Function	& 24 & bit & immediate token\\
+Int		& 32 & bit & integer\\
+List		& 24 & bit & immediate data (length) followed by each element
+			     recorded in order\\
+Pixmap		& 32 & bit & Pixmap XID\\
+Short		& 24 & bit & immediate integer\\
+(1) Strings	& 24 & bit & immediate data (length of string
+                             including \verb+'\0'+)
+			     followed by string data padded to end on
+			     a word boundary \ldots\emph{or}\ldots\\
+(2) Strings	& 24 & bit & immediate token (for common strings)\\
+Translations	& 32 & bit & integer ID\\
+Widgets		& 32 & bit & integer ID\\
+Window		& 32 & bit & Window XID\\\hline
+\end{tabular}
+\end{center}
+
+\vspace{2mm}
+
+For objects such as translations, widgets, accelerators, font lists,
+and compound strings, the 32 bit ID is just the address of the object in
+the C server process.  They are represented in Lisp by structures which
+encapsulate their ID's and provide them with Lisp data types (other than
+simply INTEGER).
+
+\section{Information in widget structure}
+
+\begin{itemize}
+\item integer ID for identifying the widget to the C server
+\item widget class keyword (e.g. \texttt{:FORM},
+      \texttt{:PUSH-BUTTON-GADGET}, \texttt{:UNKNOWN})
+\item parent widget
+\item list of (known) children
+\item \texttt{USER-DATA} slot for programmer use
+\item list of active callback lists
+\item list of active protocol lists
+\item list of active event handlers
+\end{itemize}
+The last three are for internal use in cleaning up Lisp state on
+widget destruction
+
+
+\section{Callback handlers}
+
+A callback handler is defined as:
+
+\begin{verbatim}
+
+(defun handler (widget call-data &rest client-data) ....)
+
+\end{verbatim}
+
+\noindent
+The \texttt{WIDGET} argument is the widget for which the callback is
+being invoked.\\
+The \texttt{CLIENT-DATA} \texttt{\&rest} argument allows the
+programmer to pass an 
+arbitrary number of Lisp objects to the callback
+procedure\footnote{\textbf{Note:} this deviates from CLM and Motif in C.}.\\
+The \texttt{CALL-DATA} argument provides the information passed by Motif
+regarding the reason for the callback and any other relevant
+information.\\
+The \texttt{XEvent} which generated the event may be accessed by:
+
+\begin{verbatim}
+
+(with-callback-event (event call-data)
+   ....)
+
+\end{verbatim}
+
+\noindent
+Action procedures are used in translation tables as:
+
+\begin{verbatim}
+
+<Key> q: Lisp(SOME-PACKAGE:MY-FUNCTION)\n
+
+\end{verbatim}
+
+\noindent
+Action procedures may access their event information by:
+
+\begin{verbatim}
+
+(with-action-event (event call-data)
+   ....)
+
+\end{verbatim}
+
+\noindent
+Where callback data is passed in structures, \texttt{XEvent}s are represented
+as aliens.  This is because \texttt{XEvent}s are rather large.  This saves the
+consing of large structures for each event processed.
+
+Actions to be taken after the callback handler terminates the server's
+callback loop can be registered by:
+
+\begin{verbatim}
+
+(with-callback-deferred-actions <forms>)
+
+\end{verbatim}
+
+
+\section{Structure of the Server}
+
+
+When the server process is started, it establishes standard sockets
+for clients to connect to it and waits for incoming connections.  When
+a client connects to the server, the server will fork a new process
+(unless \texttt{-nofork} was specified on the command line) to deal
+with incoming requests from the client.  The result of this is that
+each logical application has its own dedicated request server.  This
+prevents event handling in one application from blocking event
+dispatching in another.
+
+Each request server is essentially an event loop.  It waits for an
+event to occur, and dispatches that event to the appropriate handlers.
+If the event represents input available on the client connection, it
+reads the message off the stream and executes the corresponding
+request.  If the event is an X event or a Motif callback, relevant
+information about that event is packed into a message and sent to the
+Lisp client.  After sending the event notification, the server will
+enter a callback event loop to allow processing of requests from the
+client's callback procedure.  However, during the callback event loop,
+only input events from the client will be processed; all other events
+will be deferred until the callback is terminated.
+
+The server supports a standard means for reading and writing data
+objects into messages for communication with the Lisp client.  For
+every available type of data which may be transported there are reader
+and writer functions.  For instance, \texttt{WIDGET} is a valid type
+for argument data.  Two functions are defined in the server:
+\texttt{message\_read\_widget()} and
+\texttt{message\_write\_widget()}. To allow for a more generalized
+interface to argument passing, the server defines the functions
+\texttt{toolkit\_write\_value()} and \texttt{toolkit\_read\_value()}.
+These functions are passed data and a type identifier; it is their job
+to look up the correct reader/writer function.  Clearly, if the type
+of an argument is known at compile time then it is best to use the
+specific reader/writer functions.  However, if such type information
+is not known at compile time, as is the case with arbitrary resource
+lists, the higher level \texttt{toolkit\_xxx\_value()} functions are
+the only available options.
+
+
+\section{Structure of the Client}
+
+\ldots
+
+
+
+
+
+\section{Adding New Requests to the System}
+
+In order to add a new function to the toolkit interface, this new
+function must be declared in both C and Lisp.
+
+Lisp provides a convenient macro interface for writing the necessary RPC
+stub.  The form of this definition is:
+
+\begin{verbatim}
+(def-toolkit-request <C name> <Lisp name> <:confirm|:no-confirm>
+  "Documentation string"
+  (<arguments>)
+  (<return-values>)
+  <optional forms>)
+\end{verbatim}
+
+Entries in the argument list should be of the form \texttt{(<name>
+<type>)}.  The return value list is simply a list of types of the
+return value(s).  Any forms supplied at the end will be executed in a
+context where the arguments are bound to the given names and the
+return value is bound to \texttt{RESULT} (if there was only one) or
+\texttt{FIRST}, \texttt{SECOND}, \ldots, \texttt{FOURTH} (for up to 4
+return values).  At the moment, the interface does not support any
+more than 4 return values.  You must also specify a value for the
+confirmation option (\texttt{:CONFIRM} or \texttt{:NO-CONFIRM}).  If
+you expect return values, you must specify \texttt{:CONFIRM} in order
+to receive them.  Otherwise, you may specify \texttt{:NO-CONFIRM}.
+Use of \texttt{:NO-CONFIRM} allows for increased efficiency since the
+client will issue a request but not wait for any response.  All
+function prototypes should be placed in the prototypes.lisp file.  A
+few examples of request prototypes:
+
+\begin{verbatim}
+
+(def-toolkit-request "XtSetSensitive" set-sensitive :no-confirm
+  "Sets the event sensitivity of the given widget."
+  ;;
+  ;; Takes two arguments:  widget and sensitivep
+  ((widget widget) (sensitivep (member t nil)))
+  ;;
+  ;; No return values expected
+  ())
+
+(def-toolkit-request "XtIsManaged" is-managed :confirm
+  "Returns a value indicating whether the specified widget is managed."
+  ;;
+  ;; Takes one argument: widget
+  ((widget widget))
+  ;;
+  ;; Expects one return value (which is a boolean)
+  ((member t nil)))
+
+(def-toolkit-request "XmSelectionBoxGetChild" selection-box-get-child
+                     :confirm
+  "Accesses a child component of a SelectionBox widget."
+  ;;
+  ;; Takes two arguments: w and child
+  ((w widget) (child keyword))
+  ;;
+  ;; Expects a return value which is a widget
+  (widget)
+  ;;
+  ;; Now we execute some code to maintain the state of the world.
+  ;; Given that this widget may be one we don't know about, we must
+  ;; register it as the child of one we do know about.
+  (widget-add-child w result)
+  (setf (widget-type result) :unknown))
+\end{verbatim}
+
+After adding a request prototype in Lisp, you must add the actual code
+to process the request to the C server code.  The general form of the
+request function should be:
+
+\begin{verbatim}
+
+int R<name>(message_t message)
+{
+  int arg;
+  ...
+  toolkit_read_value(message,&arg,XtRInt);
+  ...
+}
+\end{verbatim}
+
+Where \texttt{<name>} is the C name given in the request prototype
+above.  You must also add an entry for this function in the
+functions.h file.  An example of a standard request function is:
+
+\begin{verbatim}
+
+int RXtCreateWidget(message_t message)
+{
+  String name;
+  WidgetClass class;
+  Widget w,parent;
+  ResourceList resources;
+
+  toolkit_read_value(message,&name,XtRString);
+  toolkit_read_value(message,&class,XtRWidgetClass);
+  toolkit_read_value(message,&parent,XtRWidget);
+
+  resources.class = class;
+  resources.parent = parent;
+  toolkit_read_value(message,&resources,ExtRResourceList);
+
+  w = XtCreateWidget(name,class,parent,
+		     resources.args,resources.length);
+  reply_with_widget(message,w);
+}
+\end{verbatim}
+
+Certain standard functions for returning arguments are provided in the file
+\texttt{requests.c}; \texttt{reply\_with\_widget()} is an example of these.
+
+
+\section{Summary of differences with CLM}
+
+X objects (e.g. windows, fonts, pixmaps) are represented as CLX objects
+rather than the home-brewed representations of CLM.  As a consequence,
+this requires that CLX be present in the core.  If this were to cause
+unacceptable core bloat, a skeletal CLX could be built which only
+supported the required functionality.
+
+Stricter naming conventions are used, in particular for enumerated
+types.  A value named \texttt{XmFOO\_BAR} in C will be called
+\texttt{:foo-bar} in Lisp, consistently.  Abbreviations such as
+\texttt{:form} (for \texttt{:attach-form}) are not allowed since they
+are often ambiguous.  Where CLM abbreviates callback names
+(e.g. \texttt{XmNactivateCallback} becomes \texttt{:activate}), we do
+not (e.g.  \texttt{:activate-callback}).
+
+Some differently named functions which can be resolved without undo
+hassle.
+
+Passing of information to callbacks and event handlers.  In CLM,
+callback handlers are defined as:
+
+\begin{verbatim}
+
+(defun handler (widget client-data &rest call-data) .... )
+
+\end{verbatim}
+
+The \texttt{CLIENT-DATA} argument is some arbitrary data which was
+stashed with the callback when it was registered by the application.
+The call-data represents the call-data information provided by Motif
+to the callback handler.  Each data item of the callback information
+is passed as a separate argument.  In our world, callback handlers are
+defined as:
+
+\begin{verbatim}
+
+(defun handler (widget call-data &rest client-data) .... )
+
+\end{verbatim}
+
+The call-data is packaged into a structure and passed as a single
+argument and the user is allowed to register any number of items to be
+passed to the callback as client-data.  Being able to pass several
+items of client-data is more convenient for the programmer and the
+packaging of the call-data information is more appealing than
+splitting it apart into separate arguments.  Also, CLM only transports
+a limited subset of the available callback information.  We transport
+all information.  Event handlers differ in the same way.  The
+client-data is the \texttt{\&rest} arg and the event info is packaged
+as a single object.  Accessing the generating event in a callback
+handler is done in the following manner:
+
+\begin{verbatim}
+
+(defun handler (widget call-data &rest client-data)
+  (with-callback-event (event call-data)
+    ;; Access slots of event such as:
+    ;;  (event-window event) or
+    ;;  (button-event-x event)
+  ))
+
+\end{verbatim}
+
+\end{document}
-- 
GitLab