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:
(def-toolkit-request <C name> <Lisp name> <:confirm|:no-confirm> "Documentation string" (<arguments>) (<return-values>) <optional forms>)
Entries in the argument list should be of the form (<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 RESULT
(if there was only one) or
FIRST
, SECOND
, …, 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 (:CONFIRM
or :NO-CONFIRM
). If
you expect return values, you must specify :CONFIRM
in order
to receive them. Otherwise, you may specify :NO-CONFIRM
.
Use of :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:
(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))
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:
int R<name>(message_t message) { int arg; ... toolkit_read_value(message,&arg,XtRInt); ... }
Where <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:
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); }
Certain standard functions for returning arguments are provided in the file
requests.c
; reply_with_widget()
is an example of these.