.\".U7
.\".UT "Extensions" D
\&
.sp 1
.ce 3
\s+1\fBAppendix D\fP\s-1

\s+1\fBExtensions\fP\s-1
.sp 2
.na
.LP
.XS
Appendix D: Extensions
.XE
Because X can only evolve by extension to the core protocol, 
it is important that extensions not be perceivable as second class citizens.
At some point, 
your favorite extensions may be adopted as additional parts of the 
``X Standard''.
.LP
Therefore, there should be little to distinguish the use of an extension from 
that of the core protocol.
To avoid having to initialize extensions explicitly in application programs, 
it is also important that extensions perform ``lazy evaluations'' 
and automatically initialize themselves when called for the first time.  
.LP
This appendix describes techniques for writing extensions to Xlib that will
run at essentially the same performance as the core protocol requests.
.NT
It is expected that a given extension to X consists of multiple
requests.
Defining 10 new features as 10 separate extensions is very bad practice.
Rather, they should be packaged into a single extension
and should use minor opcodes to distinguish the features.
.NE
.SH
Basic Protocol Support Routines
.LP
The basic protocol requests for extensions are 
.PN XQueryExtension
and
.PN XListExtensions .
.IN "XQueryExtension" "" "@DEF@"
.FD 0
Bool XQueryExtension(\^\fIdisplay\fP, \fIname\fP, \fImajor_opcode\fP, \fIfirst_event\fP, \fIfirst_error\fP\^)
.br
      Display *\fIdisplay\fP\^;
.br
      char *\fIname;\fP\^
.br
      int *\fImajor_opcode\fP\^; 	/* RETURN */
.br
      int *\fIfirst_event\fP\^;	/* RETURN */
.br
      int *\fIfirst_error\fP\^;	/* RETURN */
.FN
.PN XQueryExtension
determines if the named extension is present.  
If so, the major opcode for the extension is returned (if it has one).
Otherwise, zero is returned.  
Any minor opcode and the request formats are specific to the
extension.  
If the extension involves additional event types, 
the base event type code is returned.
Otherwise, zero is returned.  
The format of the events is specific to the extension.  
If the extension involves additional error codes, 
the base error code is returned. 
Otherwise, zero is returned.  
The format of additional data in the errors is specific to the extension.
.LP
The extension name should be in the ISO LATIN-1 encoding, and upper/lower
case does matter.
.IN "XListExtensions" "" "@DEF@"
.FD 0
char **XListExtensions(\^\fIdisplay\fP, \fInextensions\fP\^)
.br
      Display *\fIdisplay\fP\^;
.br
      int *\fInextensions\fP\^;
.FN
.PN XListExtensions   
returns a list of all extensions supported by the server.
.IN "XFreeExtensionList" "" "@DEF@"
.FD 0
XFreeExtensionList(\^\fIlist\fP\^)
.br
      char **\fIlist\fP\^;
.FN
.PN XFreeExtensionList
frees the memory allocated by 
.PN XListExtensions .
.SH
Hooking into Xlib 
.LP
These functions allow one to hook into the library.  
They are not normally used by application programmers but are used 
by people who need to extend the core X protocol and
the X library interface.
The functions, which generate protocol requests for X, are typically
called ``stubs''.
.LP
In extensions, stubs first should check to see if they have initialized 
themselves on a connection.
If they have not, they then should call 
.PN XInitExtension 
to attempt to initialize themselves on the connection.
.LP
If the extension needs to be informed of GC/font allocation or
deallocation, or if the extension defines new event types, 
the functions described in the following sections allow an extension to be 
called when these events occur.
.LP
In 
.Pn < X11/Xlib.h >, 
the following structure is defined to return the information from 
.PN XQueryExtension .
.LP
.Ds 0
.TA .5i 3i
.ta .5i 3i
typedef struct _XExtCodes {	/* public to extension, cannot be changed */
	int extension;	/* extension number */
	int major_opcode;	/* major op-code assigned by server */
	int first_event;	/* first event number for the extension */
	int first_error;	/* first error number for the extension */
} XExtCodes;
.De
.IN "XExtCodes" "" "@DEF@"
.LP
.IN "XInitExtension" "" "@DEF@"
.FD 0
XExtCodes *XInitExtension(\^\fIdisplay\fP, \fIname\fP\^)
.br
      Display *\fIdisplay\fP\^;
.br
      char *\fIname\fP\^;
.FN
.PN XInitExtension
first calls 
.PN XQueryExtension 
to see if the extension exists. 
Then, it allocates storage for maintaining the 
information about the extension on the connection, 
chains this onto the extension list for the connection,
and returns the information the stub implementor will need to access
the extension.
.LP
In particular, 
the extension number in the 
.PN XExtCodes 
structure is
needed in other calls below.  
This extension number is unique only to a single connection.
.SH
Hooks into the Library
.LP
These functions allow you to define procedures which are to be
called when various circumstances occur.
The procedures include the creation of a new GC for a connection,
the copying of a GC, the freeing a GC, the creating and freeing of fonts,
the conversion of events defined by extensions to and from wire
format, and the handling of errors.
.LP
All of these functions return the previous routine defined for this
extension.
.IN "XESetCloseDisplay" "" "@DEF@"
.FD 0
int (*XESetCloseDisplay(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
.br
      Display *\fIdisplay\fP\^;	/* display */
.br
      int \fIextension\fP\^;	/* extension number */
.br
      int (\^*\fIproc\fP\^)(\^);	/* routine to call when display closed */
.FN
You use this procedure to define a procedure to be called whenever
.PN XCloseDisplay 
is called.  
This procedure returns any previously defined procedure, usually NULL.
.LP
When 
.PN XCloseDisplay 
is called, 
your routine is called 
with these arguments:
.LP
.Ds 0
.TA .5i 3i
.ta .5i 3i
.R
(*proc)(display, codes)
	Display *display;
	XExtCodes *codes;
.De
.LP
.IN "XESetCreateGC" "" "@DEF@"
.FD 0
int (*XESetCreateGC(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
.br
      Display *\fIdisplay\fP\^;	/* display */
.br
      int \fIextension\fP\^;	/* extension number */
.br
      int (\^*\fIproc\fP\^)(\^);	/* routine to call when GC created */
.FN
You use this procedure to define a procedure to be called whenever
a new GC is created.  
This procedure returns any previously defined procedure, usually NULL.
.LP
When a GC is created, 
your routine will be called with these arguments:
.LP
.Ds 0
.TA .5i 3i
.ta .5i 3i
.R
(*proc)(display, gc, codes)
	Display *display;
	GC gc;
	XExtCodes *codes;
.De
.LP
.IN "XESetCopyGC" "" "@DEF@"
.FD 0
int (*XESetCopyGC(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
.br
      Display *\fIdisplay\fP\^;	/* display */
.br
      int \fIextension\fP\^;	/* extension number */
.br
      int (\^*\fIproc\fP\^)(\^);	/* routine to call when GC copied */
.FN
You use this procedure to define a procedure to be called whenever
a GC is copied.  
This procedure returns any previously defined procedure, usually NULL.
.LP
When a GC is copied, 
your routine will be called with these arguments:
.LP
.Ds 0
.TA .5i 3i
.ta .5i 3i
.R
(*proc)(display, gc, codes)
	Display *display;
	GC gc;
	XExtCodes *codes;
.De
.LP
.IN "XESetFreeGC" "" "@DEF@"
.FD 0
int (*XESetFreeGC(\^\fIdisplay\fP, \fIextension\fP, \fIproc)\fP\^)(\^)
.br
      Display *\fIdisplay\fP\^;	/* display */
.br
      int \fIextension\fP\^;	/* extension number */
.br
      int (\^*\fIproc\fP\^)(\^);	/* routine to call when GC freed */
.FN
You use this procedure to define a procedure to be called whenever
a GC is freed.  
This procedure returns any previously defined procedure, usually NULL.
.LP
When a GC is freed, 
your routine will be called with these arguments:
.LP
.Ds 0
.TA .5i 3i
.ta .5i 3i
.R
(*proc)(display, gc, codes)
	Display *display;
	GC gc;
	XExtCodes *codes;
.De
.LP
.IN "XESetCreateFont" "" "@DEF@"
.FD 0
int (*XESetCreateFont(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP))(\^)
.br
      Display *\fIdisplay\fP\^;	/* display */
.br
      int \fIextension\fP\^;	/* extension number */
.br
      int (\^*\fIproc\fP\^)(\^);	/* routine to call when font created */
.FN
You use this procedure to define a procedure to be called whenever
.PN XLoadQueryFont 
is called.  
This procedure returns any previously defined procedure, usually NULL.
.LP
When 
.PN XLoadQueryFont 
is called, 
your routine will be called with these arguments:
.LP
.Ds 0
.TA .5i 3i
.ta .5i 3i
.R
(*proc)(display, fs, codes)
	Display *display;
	XFontStruct *fs;
	XExtCodes *codes;
.De
.LP
.IN "XESetFreeFont" "" "@DEF@"
.FD 0
int (*XESetFreeFont(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
.br
      Display *\fIdisplay\fP\^;	/* display */
.br
      int \fIextension\fP\^;	/* extension number */
.br
      int (\^*\fIproc\fP)(\^);	/* routine to call when font freed */
.FN
You use this procedure to define a procedure to be called whenever
.PN XFreeFont 
is called.  
This procedure returns any previously defined procedure, usually NULL.
.LP
When 
.PN XFreeFont 
is called, your routine will be called with these arguments:
.LP
.Ds 0
.TA .5i 3i
.ta .5i 3i
.R
(*proc)(display, fs, codes)
	Display *display;
	XFontStruct *fs;
	XExtCodes *codes;
.De
The next two functions allow you to define new events to the library.
.NT
There is an implementation limit such that your host event
structure size cannot be bigger than the size of the
.PN XEvent 
union of structures.
There also is no way to guarantee that more than 24 elements or 96 characters
in the structure will be fully portable between machines.
.NE
.IN "XESetWireToEvent" "" "@DEF@"
.FD 0
int (*XESetWireToEvent(\^\fIdisplay\fP, \fIevent_number\fP, \fIproc\fP\^))(\^)
.br
      Display *\fIdisplay\fP\^;	/* display */
.br
      int \fIevent_number\fP\^;	/* event routine to replace */
.br
      Bool (\^*\fIproc\fP\^)(\^);	/* routine to call when converting event */
.FN
You use this procedure to define a procedure to be called when an event
needs to be converted from wire format (
.PN xEvent )
to host format (
.PN XEvent )
form.  
The event number defines which protocol event number to install a
conversion routine for.
This procedure returns any previously defined procedure.
.NT
You can replace a core event conversion routine with one
of your own, though this is not encouraged.  It would, however,
allow you to intercept a core event and modify it before being enqueued
or otherwise examined.
.NE
When Xlib needs to convert an event from wire format to natural host
format, your routine will be called with these arguments:
.LP
.Ds 0
.TA .5i 3i
.ta .5i 3i
.R
Status (*proc)(display, re, event)
	Display *display;
	XEvent *re;
	xEvent event;
.De
Your routine must return status to indicate if the conversion suceeded.
The re argument is a pointer to where the host format event should be stored,
while the event argument is the 32-byte wire event structure.
In the 
.PN XEvent 
structure you are creating, type must be the first member and window
must be the second member.
You should fill in the type member with the type specified for the 
.PN xEvent 
structure.
You should copy all other members from the 
.PN xEvent 
structure (wire format) to the
.PN XEvent 
structure (host format).
Your conversion routine should return 
.PN True
if the event should be enqueued or
.PN False
if it should not be enqueued.
.IN "XESetEventToWire" "" "@DEF@"
.FD 0
Status (*XESetEventToWire(\^\fIdisplay\fP, \fIevent_number\fP, \fIproc\fP\^))(\^)
.br
      Display *\fIdisplay\fP\^;	/* display */
.br
      int \fIevent_number\fP\^;	/* event routine to replace */
.br
      int (\^*\fIproc\fP\^)(\^);	/* routine to call when converting event */
.FN
You use this procedure to define a procedure to be called when an event
needs to be converted from host format (
.PN XEvent ) 
to wire format (
.PN xEvent )
form.  
The event number defines which protocol event number to install a
conversion routine for.
This procedure returns any previously defined procedure.
It returns zero if the conversion fails or nonzero otherwise.
.NT
You can replace a core event conversion routine with one
of your own, though this is not encouraged.  
It would, however, allow you to intercept a core event and modify it before being 
sent to another client.
.NE
When Xlib needs to convert an event from wire format to natural host
format, your routine will be called with these arguments:
.LP
.Ds 0
.TA .5i 3i
.ta .5i 3i
.R
(*proc)(display, re, event)
	Display *display;
	XEvent *re;
	xEvent event;
.De
The re argument is a pointer to the host format event,
while the event argument is a pointer to where the 32-byte wire event 
structure should be stored.
In the XEvent structure that you are forming,
you must have ``type'' the first element and ``window'' the second.
You then should fill in the type with the type from the 
.PN xEvent 
structure.
All other elements then should be copied from the wire format to
the 
.PN XEvent 
structure.
.IN "XESetError" "" "@DEF@"
.FD 0
int (*XESetError(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
.br
      Display *\fIdisplay\fP\^;	/* display */
.br
      int \fIextension\fP\^;	/* extension number */
.br
      int (\^*\fIproc\fP\^)(\^);	/* routine to call when X error happens */
.FN
Inside Xlib, there are times that you may want to suppress the
calling of the external error handling when an error occurs.
This allows status to be returned on a call at the cost of the call
being synchronous (though most such routines are query operations, in any
case, and are typically programmed to be synchronous).
.LP
When Xlib detects an protocol error in _XReply, 
it will call your procedure with these arguments:
.LP
.Ds 0
.TA .5i 3i
.ta .5i 3i
.R
int (*proc)(display, err, codes, ret_code)
	Display *display;
	xError *err;
	XExtCodes *codes;
	int *ret_code;
.De
The err argument is a pointer to the 32 byte wire format error.
The codes argument is a pointer to the extension codes structure.
The ret_code argument is the return code you may want _XReply to return.
.LP
If your routine returns a value 0, 
the error is not suppressed, and 
.PN XError 
is called.
If your routine returns nonzero, 
the error is suppressed, and 
.PN _XReply 
returns the value of ret_code.
.IN "XESetErrorString" "" "@DEF@"
.FD 0
char  *(*XESetErrorString(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
.br
      Display *\fIdisplay\fP\^;	/* display */
.br
      int \fIextension\fP\^;	/* extension number */
.br
      char *(\^*\fIproc\fP\^)(\^);	/* routine to call when I/O error happens */
.FN
.IN "XESetFlushGC" "" "@DEF@"
.FD 0
int (*XESetFlushGC(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^)
.br
      Display *\fIdisplay\fP\^;	/* display */
.br
      int \fIextension\fP\^;	/* extension number */
.br
      char *(\^*\fIproc\fP\^)(\^);	/* routine to call when I/O error happens */
.FN
The
.PN XESetFlushGC
procedure is identical to
.PN XSetCopyGC ,
except that
.PN XESetFlushGC
is called when a GC cache needs to be updated in the server.
.LP
The 
.PN XGetErrorText 
function returns a string to the user for an error.  
This procedure allows you to define a routine to be called which
should return a pointer to the error message.
The following is an example.
.LP
.Ds 0
.TA .5i 3i
.ta .5i 3i
.R
char *(*proc)(display, code, codes)
	Display *display;
	int code;
	XExtCodes *codes;
.De
Your procedure is called with the error code detected.
You should return a pointer to a null terminated string containing the
error message.
.SH
Hooks onto Xlib Data Structures
.LP
Various Xlib data structures have provisions for extension routines
to chain extension supplied data onto a list.
These structures are:
.PN GC , 
.PN Visual , 
.PN Screen , 
.PN ScreenFormat , 
.PN Display , 
and 
.PN XFontStruct .
Because the list pointer is always the first element in the structure, 
a single set of routines can be used to manipulate the data
on these lists.
.LP
The following structure is used in the routines in this section
and is defined in 
.Pn < X11/Xlib.h >.
.LP
.Ds 0
.TA .5i 3i
.ta .5i 3i
typedef struct _XExtData {
	int number;	/* number returned by XInitExtension */
	struct _XExtData *next;	/* next item on list of data for structure */
	int (*free)();	/* if defined,  called to free private */
	char *private;	/* data private to this extension. */
} XExtData;
.De
.IN "XExtData" "" "@DEF@"
When any of the data structures listed above are freed, 
the list is walked, and the free routine (if any) is called. 
If free is NULL, 
then the library will free the data pointed to by private 
and the structure, itself. 
.IN "XAddToExtensionList" "" "@DEF@"
.FD 0
XAddToExtensionList(\^\fIstructure\fP, \fIext_data\fP\^)
.br
      struct _XExtData **\fIstructure\fP\^;	/* pointer to structure to add */
.br
      XExtData *\fIext_data\fP\^;	/* extension data structure to add */
.FN
The structure argument is a pointer to one of the data structures enumerated above.
You must initialize ext_data->number with the extension number
before calling this routine.
.LP
It is expected that an extension will add at most one extension
data structure to any single data structure's extension data list.
.IN "XFindOnExtensionList" "" "@DEF@"
.FD 0
XExtData *XFindOnExtensionList(\^\fIstructure\fP, \fInumber\fP\^)
.br
      struct _XExtData **\fIstructure\fP\^;
.br
      int \fInumber\fP\^;	/* extension number from XInitExtension*/
.FN
.PN XFindOnExtensionList
returns the first extension data structure for the extension numbered
number.
.LP
The 
.PN XAllocID 
macro, which allocates and returns a resource ID, is defined in 
.Pn < X11/Xlib.h >.
.FD 0
XAllocID\^\fIdisplay\fP\^)
.br
     Display *\fIdisplay\fP\^;
.FN
This macro is a call through the 
.IN "Display"
.PN Display
structure to the internal resource ID allocator.
It returns a resource ID that you can use when creating new resources.
.SH
GC Caching
.LP
GCs are cached by the library, to allow merging of independent change
requests to the same GC into single protocol requests.
This is typically called a "write back" cache.
Any extension routine whose behavior depends on the contents of a GC must flush
the GC cache, to make sure the server has up to date contents in its GC.
.LP
The 
.PN FlushGC
macro checks the dirty bits in the library's GC structure and calls
.PN _XFlushGCCache 
if any elements have changed.
The
.PN FlushGC
macros is defined as follows:
.FD 0
FlushGC (\^\fIdisplay\fP\^, \fIgc\fP\^)
.br
      Display *\^\fIdisplay\fP\^;
.br
      GC \fIgc\fP\^;
.FN
.LP
Note that if you extend the GC to add additional resource ID components,
you should ensure that the library stub immediately sends the change
request.
This is because a client can free a resource immediately after
using it, so if you only stored the value in the cache without
forcing a protocol request, the resource might be destroyed before being
set into the GC.
You can use the
.PN _XFlushGCCache 
procedure 
to force the cache to be flushed.
The
.PN _XFlushGCCache 
procedure
is defined as follows:
.FD 0
_XFlushGCCache (\^\fIdisplay\fP\^, \fIgc\fP\^)
.br
      Display *\^\fIdisplay\fP\^;
.br
      GC \fIgc\fP\^;
.FN
.SH
Graphics Batching
.LP
If you extend X to add more poly graphics primitives, you may be able to
take advantage of facilities in the library to allow back-to-back 
single calls to be transformed into poly requests.
This may dramatically improve performance of programs that are not
written using poly requests. 
In the display
structure is a pointer to an 
.PN xReq 
called last_req which is the last
request being processed.  
By checking that the last request
type, drawable, gc, and other options are the same as the new one,
and that there is enough space left in the buffer, you may be able
to just extend the previous graphics request by extending the length
field of the request and appending the data to the buffer.  
This can cause a 5 times or more improvement in stupid programs.  
For example, here is the source for the 
.PN XDrawPoint 
stub.
(Writing extension stubs is discussed in the next section.)
.IP
.nf
#include "copyright.h"

#include "Xlibint.h"

/* precompute the maximum size of batching request allowed */

static int size = sizeof(xPolyPointReq) + EPERBATCH * sizeof(xPoint);

XDrawPoint(dpy, d, gc, x, y)
    register Display *dpy;
    Drawable d;
    GC gc;
    int x, y; /* INT16 */
{
    xPoint *point;
    LockDisplay(dpy);
    FlushGC(dpy, gc);
    {
    register xPolyPointReq *req = (xPolyPointReq *) dpy->last_req;
    /* if same as previous request, with same drawable, batch requests */
    if (
          (req->reqType == X_PolyPoint)
       && (req->drawable == d)
       && (req->gc == gc->gid)
       && (req->coordMode == CoordModeOrigin)
       && ((dpy->bufptr + sizeof (xPoint)) <= dpy->bufmax)
       && (((char *)dpy->bufptr - (char *)req) < size) ) {
         point = (xPoint *) dpy->bufptr;
         req->length += sizeof (xPoint) >> 2;
         dpy->bufptr += sizeof (xPoint);
         }

    else {
        GetReqExtra(PolyPoint, 4, req); /* 1 point = 4 bytes */
        req->drawable = d;
        req->gc = gc->gid;
        req->coordMode = CoordModeOrigin;
        point = (xPoint *) (req + 1);
        }
    point->x = x;
    point->y = y;
    }
    UnlockDisplay(dpy);
    SyncHandle();
}
.fi
.LP
There is a limit of EPERBATCH on the number of requests batched, to keep
clients from generating very long requests that may monopolize the server.
Most of the performance benefit occurs in the first few merged requests.
Note that 
.PN FlushGC 
is called BEFORE picking up the value of last_req,
since it may modify this field.
.SH
Writing Extension Stubs
.LP
All X requests always contain the length of the request,
expressed as a 16-bit quantity of 32-bits.
This means that a single request can be no more than 256k Bytes in
length.
Some servers may not support single requests of such a length.
The value of dpy->max_request_size contains the maximum length as
defined by the server implementation.
For further information,
see the X Protocol documentation.
.SH
Requests, Replies, and Xproto.h
.LP
It may make it easier to understand if you look at 
the 
.PN Xproto.h 
header file. 
The file contains three sets of definitions that
are of interest to the stub implementor:  
request names, request structures, and reply structures.
.LP
You need to generate a file equivalent to 
.PN Xproto.h 
for your
extension and need to include it in your stub routine.
Each stub routine also must include 
.PN Xlibint.h .
.LP
The identifiers are deliberately chosen in such a way that, if the
request is called X_DoSomething, then its request structure is
xDoSomethingReq, and its reply is xDoSomethingReply.  
The ``GetReq'' family of macros, defined in 
.PN Xlibint.h , 
takes advantage of this naming scheme.
.LP
For each X Request, 
there is a definition in 
.PN Xproto.h 
that looks similar to this:
.LP
.Ds 
.R
#define X_DoSomething   42
.De
In your extension header file, 
this will be a minor op-code, 
instead of a major opcode.
.SH
Request Format
.LP
Every request contains an 8-bit ``major'' opcode and a 16-bit length field
expressed in units of 4 bytes.  
Every request consists of 4 bytes of header
(containing the major opcode, the length field, and a data byte) followed by
zero or more additional bytes of data. 
The length field defines the total length of the request, including the header.  
The length field in a request must equal the minimum length required to contain 
the request. 
If the specified length is smaller or larger than the required length, 
the extension should generate a 
.PN BadLength 
error.
Unused bytes in a request are not required to be zero.  
.LP
Major opcodes 128 through 255 are reserved for extensions.
Extensions are intended to contain multiple requests, 
so extension requests typically have an additional minor opcode encoded 
in the ``spare'' data byte in the request header, 
but the placement and interpretation of this minor opcode as well as all
other fields in extension requests are not defined by the core protocol.
Every request is implicitly assigned a sequence number (starting with one)
used in replies, errors, and events.
.LP
Most protocol requests have a corresponding structure typedef in
.PN Xproto.h , 
which looks like:
.LP
.Ds 0
.TA .5i 3i
.ta .5i 3i
typedef struct _DoSomethingReq {
	CARD8 reqType;	/* X_DoSomething */
	CARD8 someDatum;	/* used differently in different requests */
	CARD16 length;	/* total # of bytes in request, divided by 4 */
	...
	/* request-specific data */
	...
} xDoSomethingReq;
.De
.IN "xDoSomethingReq" "" "@DEF@"
If a core protocol request has a single 32-bit argument, 
you need not declare a request structure in your extension header file.
Instead, such requests use 
.PN Xproto.h 's 
.PN xResourceReq
structure.  
This structure is used for any request whose single argument is a Window, Pixmap,
Drawable, GContext, Font, Cursor, Colormap, Device, Atom, VisualID, or Time.
.LP
.Ds 0
.TA .5i 3i
.ta .5i 3i
typedef struct _ResourceReq {
	CARD8 reqType;	/* the request type, e.g. X_DoSomething */
	BYTE pad;	/* not used */
	CARD16 length;	/* 2 (= total # of bytes in request, divided by 4) */
	CARD32 id;	/* the Window, Drawable, Font, GContext, etc. */
} xResourceReq;
.De
.IN "xResourceReq" "" "@DEF@"
If convenient,
you can do something similar in your extension header file. 
.LP
In both of these structures, 
the reqType field identifies the type of the request (for example, 
X_MapWindow or X_CreatePixmap).  
The length field tells how long,
in units of 4-byte ``longwords'', the request is. 
This length includes both the request structure itself and any
variable length data, such as strings or lists, that follow the
request structure.  
Request structures come in different sizes, 
but all requests are padded to be a multiple of 4 bytes long.
.LP
A few protocol requests take no arguments at all. 
Instead, they use 
.PN Xproto.h 's 
.PN xReq 
structure, which contains only a reqType and a length (and a pad byte).
.LP 
If the protocol request requires a reply, 
then
.PN Xproto.h 
also contains a reply structure typedef:
.LP
.Ds 0
.TA .5i 3i
.ta .5i 3i
typedef struct _DoSomethingReply {
	BYTE type;	/* always X_Reply */
	BYTE someDatum;	/* used differently in different requests */
	CARD16 sequenceNumber;	/* # of requests sent so far */
	CARD32 length;	/* # of additional bytes, divided by 4 */
	...
	/* request-specific data */
	...
} xDoSomethingReply;
.De
.IN "xDoSomethingReply" "" "@DEF@"
Most of these reply structures are 32 bytes long. 
If there are not that many reply values, 
then they contain a sufficient number of pad fields
to bring them up to 32 bytes.  
The length field is the total number of bytes in the request minus 32, divided by 4.  
This length will be nonzero only if:
.IP \(bu 5
The reply structure is followed by variable length
data such as a list or string
.IP \(bu 5
The reply structure is longer than 32 bytes  
.LP
Only GetWindowAttributes, QueryFont, QueryKeymap, and
GetKeyboardControl have reply structures longer than 32 bytes.
.LP
A few protocol requests return replies that contain no data.  
.PN Xproto.h
does not define reply structures for these.
Instead, they use the 
.PN xGenericReply
structure, which contains only a type, length,
and sequence number (and sufficient padding to make it 32 bytes long).
.SH
Starting to Write a Stub Routine
.LP
An Xlib stub routine should always start like this:
.LP
.Ds 
.R
#include "Xlibint.h"

XDoSomething (arguments, ... )
/* argument declarations */
{

/* variable declarations, if any */
...
.De
If the protocol request has a reply, 
then the variable declarations should include the reply structure for the request.
The following is an example.
.LP
.Ds 
.R
xDoSomethingReply rep;
.De 
.SH
Locking Data Structures
.NT
Locking has not yet been tested as of February 20, 1988!
.NE
.LP
In order to lock the display structure, for systems which
want to support multithreaded access to a single display connection,
each stub will need to lock its critical section.
Generally, this section is the point from just before the appropriate GetReq
call documented below and when all arguments to the call have been
stored into the request.
The precise instructions needed for this locking depend upon the machine
architecture. 
Two calls, which are generally implemented as macros, have been provided.
.IN "LockDisplay"
.FD 0
LockDisplay(\^\fIdisplay\fP\^)
.br
      Display *\fIdisplay\fP\^;
.FN
.IN "UnlockDisplay"
.FD 0
UnlockDisplay(\^\fIdisplay\fP\^)
.br
      Display *\fIdisplay\fP\^;
.FN
.SH
Sending the Protocol Request and Arguments
.LP
After the variable declarations, 
a stub routine should call one of four macros defined in 
.PN Xlibint.h : 
.PN GetReq , 
.PN GetReqExtra , 
.PN GetResReq , 
or 
.PN GetEmptyReq .  
All of these macros take as their first argument
the name of the protocol request as declared in 
.PN Xproto.h , 
except with "X_" removed.   
Each one declares a 
.PN Display 
structure pointer,
called ``dpy'', and a pointer to a request structure, called ``req'',
which is of the appropriate type.  
The macro then appends the request structure to the output buffer, 
fills in its type and length field, and sets "req" to point to it.
.LP
If the protocol request has no arguments (for instance, X_GrabServer),
then use 
.PN GetEmptyReq :
.LP
.Ds
.R 
GetEmptyReq (DoSomething);
.De
If the protocol request has a single 32-bit argument (such as, a
Pixmap, Window, Drawable, Atom, and so on),
then use 
.PN GetResReq .  
The second argument to the macro is the 32-bit object.  
.PN X_MapWindow 
is a good example.
.LP
.Ds
.R
GetResReq (DoSomething, rid);
.De
The rid argument is the Pixmap, Window, or other resource ID.
.LP
If the protocol request takes any other argument list, 
then call 
.PN GetReq .  
After the 
.PN GetReq , 
you need to set all the other fields in the request structure,
usually from arguments to the stub routine.
.LP
.Ds 
.R
GetReq (DoSomething);
/* fill in arguments here */
req->arg1 = arg1;
req->arg2 = arg2;
...
.De
A few stub routines (such as, 
.PN XCreateGC 
and 
.PN XCreatePixmap ) 
return a resource ID to the caller but pass a resource ID as an argument
to the protocol request.   
Such routines use the macro 
.PN XAllocID 
to allocate a resource ID from the range of IDs 
that were assigned to this client when it opened the connection.
.LP
.Ds 
.R
rid = req->rid = XAllocID();
...
return (rid);
.De
Finally, some stub routines transmit a fixed amount of variable-length
data after the request.  
Typically, these are routines (such as, 
.PN XMoveWindow 
and 
.PN XSetBackgroundPixel ) 
are special cases of more general functions like 
.PN XMoveResizeWindow 
and 
.PN XChangeGC .   
These special case routines use 
.PN GetReqExtra , 
which is the same as 
.PN GetReq ,
except that it takes an additional argument (the number of
extra bytes to allocate in the output buffer after the request structure).  
This number should always be a multiple of 4.
.SH
Variable Length Arguments
.LP
Some protocol requests take additional variable length data that
follow the 
.PN xDoSomethingReq 
structure.    
The format of these data varies from request to request. 
Some require a sequence of 8-bit bytes, others a sequence of 16- or 32-bit entities, 
and still others a sequence of structures.
.LP
It is necessary to add the length of any variable length data to the
length field of the request structure.  
That length field is in units of 32-bit longwords.  
If the data is a string or other sequence of 8-bit bytes, 
then you must round the length up and shift it before adding:
.LP
.Ds
.R
req->length += (nbytes+3)>>2;
.De
To transmit the variable length data, use the 
.PN Data 
macro.  
If the data fits into the output buffer, 
then this macro copies it to the buffer.  
If it does not fit, however,
the 
.PN Data 
macro calls 
.PN _XSend , 
which transmits first the contents of the buffer and then your data.
The 
.PN Data 
macro takes three arguments:  
the Display, a pointer to the beginning of the data, and the number of bytes to be sent.
.Ds 0
.R
Data(dpy, (char *) data, nbytes);
.De
If the data are 16-bit entities, 
then use the 
.PN PackData 
macro instead.
It takes the same arguments and does the same things, 
but it does the right thing on machines where a short is 32-bits instead
of the usual 16.   
.LP
Both 
.PN Data 
and 
.PN PackData 
are macros which may use their last argument
more than once, so that argument should be a variable rather than
an expression such as ``nitems*sizeof(item)''.  
You should do that kind of computation in a separate statement before calling 
.PN Data .
.LP
If the protocol request requires a reply, 
then call the procedure 
.PN _XSend 
instead of the 
.PN Data 
macro.  
.PN _XSend 
takes the same arguments, but, because it sends your data immediately instead of 
copying it into the output buffer (which would later be flushed
anyway by the following call on 
.PN _XReply ), 
it is faster.
.SH
Replies
.LP
If the protocol request has a reply, 
then call 
.PN _XReply 
after you have finished dealing with 
all the fixed and variable length arguments.  
.PN _XReply 
flushes the output buffer and waits for an 
.PN xReply 
packet to arrive.  
If any events arrive in the meantime,
.PN _XReply 
enqueues them for later use.
.IN "_XReply" "" "@DEF@"
.FD 0
Status _XReply(\^\fIdisplay\fP, \fIrep\fP, \fIextra\fP, \fIdiscard\fP\^)
.br
      Display *\fIdisplay\fP\^;
.br
      xReply *\fIrep\fP\^;
.br
      int \fIextra\fP\^;	/* number of 32-bit words expected after the reply */
.br
      Bool \fIdiscard\fP\^;	/* should I discard data following "extra" words? */
.FN
.PN _XReply 
waits for a reply packet and copies its contents into the
specified rep.  
.PN _XReply 
handles error and event packets that occur before the reply is received.
.PN _XReply 
takes four arguments:
.IP \(bu 5
A 
.PN Display 
* structure
.IP \(bu 5
A pointer to a reply structure (which must be cast to an 
.PN xReply 
*)
.IP \(bu 5
The number of additional bytes (beyond sizeof(xReply) = 32 bytes)
in the reply structure
.IP \(bu 5
A boolean which tells 
.PN _XReply 
to discard any additional bytes
beyond those it was told to read
.LP
Because most reply structures are 32 bytes long, 
the third argument is usually 0.  
The only exceptions are the replies to 
.PN GetWindowAttributes , 
.PN QueryFont , 
.PN QueryKeymap , 
and 
.PN GetKeyboardControl 
in the core protocol, which have longer replies.
.LP
The last argument should be 
.PN xFalse , 
if the reply structure is followed
by additional variable length data (such as, a list or string).  
It should be 
.PN xTrue 
if there is not any variable length data.
.NT
This last argument is provided for upward-compatibility reasons--to
allow a client to communicate properly with a hypothetical later
version of the server which sends more data than the client expected.
For example, some later version of 
.PN GetWindowAttributes 
might use a
larger, but compatible, 
.PN xGetWindowAttributesReply 
which contains
additional attribute data at the end.
.NE
.PN _XReply 
returns true, if it received a reply successfully, or false, if it
received an 
.PN XError 
instead (or some other error condition occurred).
.LP
For a request with a reply that is not followed by variable length
data, you write something like:
.LP
.Ds 
.R
_XReply (display, (xReply *)&rep, 0, xTrue);
*ret1 = rep.ret1;
*ret2 = rep.ret2;
*ret3 = rep.ret3;
...
UnlockDisplay(dpy);
SyncHandle();
return (rep.ret4);
}
.De
If there is variable length data after the reply, 
change the ``xTrue'' to ``xFalse'', and use 
.PN _XRead 
to read the variable-length data.
.LP
Each protocol request is a little different. 
For further information,
see the Xlib sources for examples.
.SH
Synchronous Calling
.LP
To ease debugging, 
each routine should have a call to a routine, just before returning to the user, 
called 
.PN SyncHandle .
This routine generally is implemented as a macro.
If synchronous mode is enabled (see 
.PN XSynchronize ), 
the request is sent immediately.
The library, however, waits until any error the routine could generate
at the server has been handled.
.SH
Allocating and Deallocating Memory
.LP
To support the possible reentrancy of these routines, 
you must observe several conventions when allocating and deallocating memory.
This is most often done when returning data to the user from the window
system of a size the caller could not know in advance
(for example, a list of fonts or a list of extensions).
This occurs because the standard C library routines on many systems
are not protected against signals or other multithreaded use.
The following analogies to standard I/O library routines
have been defined:
.LP
.Ds 0
.TA .5i 1.5i
.ta .5i 1.5i
.R
Xmalloc()	Replaces malloc()
Xfree()		Replaces free()
Xcalloc()	Replaces calloc()
.De
These should be used in place of any calls you would make to the normal
C library routines.
.LP
If you need a single scratch buffer inside a critical section (for example, to pack
and unpack data to and from wire protocol), the general memory allocators
may be too expensive for use (particularly in output routines, which
are performance critical).  
The routine below returns a scratch buffer for your use:
.IN "_XAllocScratch" "" "@DEF@"
.FD 0
char *_XAllocScratch(\^\fIdisplay\fP, \fInbytes\fP\^)
.br
      Display *\fIdisplay\fP\^;
.br
      unsigned long \fInbytes\fP\^;
.FN
This storage must only be used inside of the critical section of your
stub.
.SH
Portability Considerations
.LP
Many machine architectures, including many of the more
recent RISC architectures, will not correctly access data
at unaligned locations; their compilers will pad out structures
to preserve this characteristic.
Many other machines capable of unaligned references pad inside of structures
as well to preserve alignment, since accessing aligned data is
usually much faster.
Since the library and the server is using structures to access data at
arbitrary points in a byte stream,
all data in request and reply packets MUST be naturally aligned;
that is 16 bit data start on 16 bit boundaries in the request,
32 bit data on 32 bit boundaries.
All requests MUST be a multiple of 32 bits in length, to preserve
the natural alignment in the data stream.
Pad structures out to 32 bit boundaries.
Pad information does not have to be zeroed, unless you wish to
preserve such fields for future use in your protocol requests.
Floating point varies radically between machines, and should be
avoided completely if at all possible.
.LP
This code may run on machines with 16-bit ``int''s.  
So, if any integer argument, variable, or return value either can take 
only non-negative values or is declared as a CARD16 in the protocol, 
be sure to declare it as ``unsigned int'' and not as ``int''.
(This of course does not apply to booleans or enumerations.)
.LP
Similarly, if any integer argument or return value is declared CARD32
in the protocol, 
declare it as an ``unsigned long'' and not as ``int'' or ``long''.
This also goes for any internal variables that may
take on values larger than the maximum 16-bit unsigned int.
.LP
The library currently assumes that a ``char'' is 8 bits, a ``short'' is
16 bits, an ``int'' is 16 or 32 bits, and a ``long'' is 32 bits.  
The PackData macro is a half-hearted attempt to deal with the possibility of 
32-bit ``shorts''. 
However, much more work is needed to make this really work properly.
.SH
Deriving the Correct Extension Opcode
.LP
The remaining problem a writer of an extension stub routine faces that
the core protocol does not face is to map from the call to the proper
major and minor opcodes.  
While there are a number of strategies, 
the simplest and fastest is outlined below.
.IP 1. 5
Declare an array of pointers, _NFILE long (this is normally found
in 
.Pn < stdio.h > 
and is the number of file descriptors supported on the system,
of type 
.PN XExtCodes .
Make sure these are all initialized to NULL.
.IP 2. 5
When your stub is entered, your initialization test is just to use
the display pointer passed in to access the file descriptor, and an index
into the array.  
If the entry is NULL, then this is the first time you
are entering the routine for this display.  
Call your initialization routine and pass it the display pointer.
.IP 3. 5
Once in your initialization routine, call 
.PN XInitExtension , 
and if it succeeds, store the pointer returned into this array.  
Make sure to establish a close display handler to allow you to zero the entry.
Do whatever other initialization your extension requires.
(For example, install event handlers, and so on).
Your initialization routine would normally return a pointer to the
.PN XExtCodes 
structure for this extension, which is what would normally
be found in your array of pointers.
.IP 4. 5
After returning from your initialization routine, 
the stub can now continue normally, since it has its major opcode safely in its
had in the 
.PN XExtCodes 
structure.
.bp
