.SH Hooks onto Xlib Data Structures

Various Xlib data structures have provisions for extension procedures 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 member in the structure, a single set of procedures can be used to manipulate the data on these lists.

The following structure is used in the functions in this section and is defined in X11/Xlib.h :

.sM .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_private)(); /* if defined, called to free private */ XPointer private_data; /* data private to this extension. */ } XExtData; .De

.eM When any of the data structures listed above are freed, the list is walked, and the structure's free procedure (if any) is called. If free is NULL, then the library frees both the data pointed to by the private_data member and the structure itself.

.sM .Ds 0 .TA .5i .ta .5i union { Display *display; GC gc; Visual *visual; Screen *screen; ScreenFormat *pixmap_format; XFontStruct *font } XEDataObject; .De

.eM .sM .FD 0 XExtData **XEHeadOfExtensionList(\fIobject\fP) XEDataObject \fIobject\fP; .FN .IP \fIobject\fP 1i Specifies the object.

.eM The .PN XEHeadOfExtensionList function returns a pointer to the list of extension structures attached to the specified object. In concert with .PN XAddToExtensionList , .PN XEHeadOfExtensionList allows an extension to attach arbitrary data to any of the structures of types contained in .PN XEDataObject .

.sM .FD 0 XAddToExtensionList(\fIstructure\fP, \fIext_data\fP) .br XExtData **\fIstructure\fP; .br XExtData *\fIext_data\fP; .FN .IP \fIstructure\fP 1i Specifies the extension list. .IP \fIext_data\fP 1i Specifies the extension data structure to add.

.eM 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 function. .sM .FD 0 XExtData *XFindOnExtensionList(\fIstructure\fP, \fInumber\fP) .br struct _XExtData **\fIstructure\fP; .br int \fInumber\fP; .FN .IP \fIstructure\fP 1i Specifies the extension list. .IP \fInumber\fP 1i Specifies the extension number from .PN XInitExtension .

.eM The .PN XFindOnExtensionList function returns the first extension data structure for the extension numbered number. It is expected that an extension will add at most one extension data structure to any single data structure's extension data list. There is no way to find additional structures.

The .PN XAllocID macro, which allocates and returns a resource ID, is defined in X11/Xlib.h . .sM .FD 0 XAllocID(\fIdisplay\fP) .br Display *\fIdisplay\fP; .FN .IP \fIdisplay\fP 1i Specifies the connection to the X server.

.eM This macro is a call through the .PN Display structure to an internal resource ID allocator. It returns a resource ID that you can use when creating new resources.

The .PN XAllocIDs macro allocates and returns an array of resource ID. .sM .FD 0 XAllocIDs(\fIdisplay\fP, \fIids_return\fP, \fIcount\fP) .br Display *\fIdisplay\fP; .br XID *\fIids_return\fP; .br int \fIcount\fP; .FN .IP \fIdisplay\fP 1i Specifies the connection to the X server. .IP \fIids_return\fP 1i Returns the resource IDs. .IP \fIrep\fP 1i Specifies the number of resource IDs requested.

.eM This macro is a call through the .PN Display structure to an internal resource ID allocator. It returns resource IDs to the array supplied by the caller. To correctly handle automatic reuse of resource IDs, you must call .PN XAllocIDs when requesting multiple resource IDs. This call might generate protocol requests. .SH GC Caching

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 procedure 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.

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 macro is defined as follows: .sM .FD 0 FlushGC(\fIdisplay\fP, \fIgc\fP) .br Display *\fIdisplay\fP; .br GC \fIgc\fP; .FN .IP \fIdisplay\fP 1i Specifies the connection to the X server. .IP \fIgc\fP 1i Specifies the GC.

.eM Note that if you extend the GC to add additional resource ID components, you should ensure that the library stub sends the change request immediately. 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: .sM .FD 0 _XFlushGCCache(\fIdisplay\fP, \fIgc\fP) .br Display *\fIdisplay\fP; .br GC \fIgc\fP; .FN .IP \fIdisplay\fP 1i Specifies the connection to the X server. .IP \fIgc\fP 1i Specifies the GC.

.eM .SH Graphics Batching

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. A pointer to an .PN xReq , called last_req in the display structure, 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 improve performance by five times or more in naive programs. For example, here is the source for the .PN XDrawPoint stub. (Writing extension stubs is discussed in the next section.) .IP .sM .nf #include /* 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

.eM To keep clients from generating very long requests that may monopolize the server, there is a symbol defined in X11/Xlibint.h of EPERBATCH on the number of requests batched. Most of the performance benefit occurs in the first few merged requests. Note that .PN FlushGC is called \fIbefore\fP picking up the value of last_req, because it may modify this field. .SH Writing Extension Stubs

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 ``X Window System Protocol.'' .SH Requests, Replies, and Xproto.h

The X11/Xproto.h file contains three sets of definitions that are of interest to the stub implementor: request names, request structures, and reply structures.

You need to generate a file equivalent to X11/Xproto.h for your extension and need to include it in your stub procedure. Each stub procedure also must include X11/Xlibint.h .

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 X11/Xlibint.h , takes advantage of this naming scheme.

For each X request, there is a definition in X11/Xproto.h that looks similar to this:

.Ds .R #define X_DoSomething 42 .De In your extension header file, this will be a minor opcode, instead of a major opcode. .SH Request Format

Every request contains an 8-bit major opcode and a 16-bit length field expressed in units of four bytes. Every request consists of four 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 server should generate a .PN BadLength error. Unused bytes in a request are not required to be zero. Extensions should be designed in such a way that long protocol requests can be split up into smaller requests, if it is possible to exceed the maximum request size of the server. The protocol guarantees the maximum request size to be no smaller than 4096 units (16384 bytes).

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 second 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.

To help but not cure portability problems to certain machines, the .PN B16 and .PN B32 macros have been defined so that they can become bitfield specifications on some machines. For example, on a Cray, these should be used for all 16-bit and 32-bit quantities, as discussed below.

Most protocol requests have a corresponding structure typedef in X11/Xproto.h , which looks like:

.sM .Ds 0 .TA .5i 3i .ta .5i 3i typedef struct _DoSomethingReq { CARD8 reqType; /* X_DoSomething */ CARD8 someDatum; /* used differently in different requests */ CARD16 length B16; /* total # of bytes in request, divided by 4 */ ... /* request-specific data */ ... } xDoSomethingReq; .De

.eM 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 the .PN xResourceReq structure in X11/Xproto.h . This structure is used for any request whose single argument is a .PN Window , .PN Pixmap , .PN Drawable , .PN GContext , .PN Font , .PN Cursor , .PN Colormap , .PN Atom , or .PN VisualID .

.sM .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 B16; /* 2 (= total # of bytes in request, divided by 4) */ CARD32 id B32; /* the Window, Drawable, Font, GContext, etc. */ } xResourceReq; .De

.eM If convenient, you can do something similar in your extension header file.

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 the request is in units of 4-byte longwords. 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 multiples of four bytes long.

A few protocol requests take no arguments at all. Instead, they use the .PN xReq structure in X11/Xproto.h , which contains only a reqType and a length (and a pad byte).

If the protocol request requires a reply, then X11/Xproto.h also contains a reply structure typedef:

.sM .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 B16; /* # of requests sent so far */ CARD32 length B32; /* # of additional bytes, divided by 4 */ ... /* request-specific data */ ... } xDoSomethingReply; .De

.eM 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.

Only .PN GetWindowAttributes , .PN QueryFont , .PN QueryKeymap , and .PN GetKeyboardControl have reply structures longer than 32 bytes in the core protocol.

A few protocol requests return replies that contain no data. X11/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 Procedure

An Xlib stub procedure should start like this:

.Ds .R #include " XDoSomething (arguments, ... ) /* argument declarations */ { register XDoSomethingReq *req; ... .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:

.Ds .R xDoSomethingReply rep; .De .SH Locking Data Structures

To lock the display structure for systems that 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 until all arguments to the call have been stored into the buffer. The precise instructions needed for this locking depend upon the machine architecture. Two calls, which are generally implemented as macros, have been provided. .sM .FD 0 LockDisplay(\fIdisplay\fP) .br Display *\fIdisplay\fP; .FN

.FD 0 UnlockDisplay(\fIdisplay\fP) .br Display *\fIdisplay\fP; .FN .IP \fIdisplay\fP 1i Specifies the connection to the X server.

.eM .SH Sending the Protocol Request and Arguments

After the variable declarations, a stub procedure should call one of four macros defined in X11/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 X11/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.

If the protocol request has no arguments (for instance, X_GrabServer), then use .PN GetEmptyReq .

.Ds .R GetEmptyReq (DoSomething, req); .De If the protocol request has a single 32-bit argument (such as a .PN Pixmap , .PN Window , .PN Drawable , .PN 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.

.Ds .R GetResReq (DoSomething, rid, req); .De The rid argument is the .PN Pixmap , .PN Window , or other resource ID.

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 procedure.

.Ds .R GetReq (DoSomething, req); /* fill in arguments here */ req->arg1 = arg1; req->arg2 = arg2; ... .De A few stub procedures (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 procedures 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.

.Ds .R rid = req->rid = XAllocID(); ... return (rid); .De Finally, some stub procedures transmit a fixed amount of variable length data after the request. Typically, these procedures (such as .PN XMoveWindow and .PN XSetBackground ) are special cases of more general functions like .PN XMoveResizeWindow and .PN XChangeGC . These procedures 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 four. .SH Variable Length Arguments

Some protocol requests take additional variable length data that follow the .PN xDoSomethingReq structure. The format of this data varies from request to request. Some requests require a sequence of 8-bit bytes, others a sequence of 16-bit or 32-bit entities, and still others a sequence of structures.

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:

.Ds .R req->length += (nbytes+3)>>2; .De To transmit variable length data, use the .PN Data macros. 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 macros take three arguments: the display, a pointer to the beginning of the data, and the number of bytes to be sent. .sM .FD 0 Data(\fIdisplay\fP, (char *) \fIdata\fP, \fInbytes\fP); .sp Data16(\fIdisplay\fP, (short *) \fIdata\fP, \fInbytes\fP); .sp Data32(\fIdisplay\fP, (long *) \fIdata\fP, \fInbytes\fP); .FN

.eM .PN Data , .PN Data16 , and .PN Data32 are macros that 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 them. Use the appropriate macro when sending byte, short, or long data.

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

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 places them in the queue for later use. .sM .FD 0 Status _XReply(\fIdisplay\fP, \fIrep\fP, \fIextra\fP, \fIdiscard\fP) .br Display *\fIdisplay\fP; .br xReply *\fIrep\fP; .br int \fIextra\fP; .br Bool \fIdiscard\fP; .FN .IP \fIdisplay\fP 1i Specifies the connection to the X server. .IP \fIrep\fP 1i Specifies the reply structure. .IP \fIextra\fP 1i Specifies the number of 32-bit words expected after the replay. .IP \fIdiscard\fP 1i Specifies if any data beyond that specified in the extra argument should be discarded.

.eM The .PN _XReply function 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 32-bit words (beyond .Pn sizeof( xReply ) = 32 bytes) in the reply structure .IP \(bu 5 A Boolean that indicates whether .PN _XReply is to discard any additional bytes beyond those it was told to read

Because most reply structures are 32 bytes long, the third argument is usually 0. The only core protocol exceptions are the replies to .PN GetWindowAttributes , .PN QueryFont , .PN QueryKeymap , and .PN GetKeyboardControl , which have longer replies.

The last argument should be .PN False if the reply structure is followed by additional variable length data (such as a list or string). It should be .PN True 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 that sends more data than the client expected. For example, some later version of .PN GetWindowAttributes might use a larger, but compatible, .PN xGetWindowAttributesReply that contains additional attribute data at the end. .NE .PN _XReply returns .PN True if it received a reply successfully or .PN False if it received any sort of error.

For a request with a reply that is not followed by variable length data, you write something like:

.Ds .R _XReply(display, (xReply *)&rep, 0, True); *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 .PN True to .PN False , and use the appropriate .PN _XRead function to read the variable length data.

.sM .FD 0 _XRead(\fIdisplay\fP, \fIdata_return\fP, \fInbytes\fP) Display *\fIdisplay\fP; char *\fIdata_return\fP; long \fInbytes\fP; .FN .IP \fIdisplay\fP 1i Specifies the connection to the X server. .IP \fIdata_return\fP 1i Specifies the buffer. .IP \fInbytes\fP 1i Specifies the number of bytes required.

.eM The .PN _XRead function reads the specified number of bytes into data_return.

.sM .FD 0 _XRead16(\fIdisplay\fP, \fIdata_return\fP, \fInbytes\fP) Display *\fIdisplay\fP; short *\fIdata_return\fP; long \fInbytes\fP; .FN .IP \fIdisplay\fP 1i Specifies the connection to the X server. .IP \fIdata_return\fP 1i Specifies the buffer. .IP \fInbytes\fP 1i Specifies the number of bytes required.

.eM The .PN _XRead16 function reads the specified number of bytes, unpacking them as 16-bit quantities, into the specified array as shorts.

.sM .FD 0 _XRead32(\fIdisplay\fP, \fIdata_return\fP, \fInbytes\fP) Display *\fIdisplay\fP; long *\fIdata_return\fP; long \fInbytes\fP; .FN .IP \fIdisplay\fP 1i Specifies the connection to the X server. .IP \fIdata_return\fP 1i Specifies the buffer. .IP \fInbytes\fP 1i Specifies the number of bytes required.

.eM The .PN _XRead32 function reads the specified number of bytes, unpacking them as 32-bit quantities, into the specified array as longs.

.sM .FD 0 _XRead16Pad(\fIdisplay\fP, \fIdata_return\fP, \fInbytes\fP) Display *\fIdisplay\fP; short *\fIdata_return\fP; long \fInbytes\fP; .FN .IP \fIdisplay\fP 1i Specifies the connection to the X server. .IP \fIdata_return\fP 1i Specifies the buffer. .IP \fInbytes\fP 1i Specifies the number of bytes required.

.eM The .PN _XRead16Pad function reads the specified number of bytes, unpacking them as 16-bit quantities, into the specified array as shorts. If the number of bytes is not a multiple of four, .PN _XRead16Pad reads and discards up to two additional pad bytes.

.sM .FD 0 _XReadPad(\fIdisplay\fP, \fIdata_return\fP, \fInbytes\fP) Display *\fIdisplay\fP; char *\fIdata_return\fP; long \fInbytes\fP; .FN .IP \fIdisplay\fP 1i Specifies the connection to the X server. .IP \fIdata_return\fP 1i Specifies the buffer. .IP \fInbytes\fP 1i Specifies the number of bytes required.

.eM The .PN _XReadPad function reads the specified number of bytes into data_return. If the number of bytes is not a multiple of four, .PN _XReadPad reads and discards up to three additional pad bytes.

Each protocol request is a little different. For further information, see the Xlib sources for examples. .SH Synchronous Calling

Each procedure should have a call, just before returning to the user, to a macro called .PN SyncHandle . If synchronous mode is enabled (see .PN XSynchronize ), the request is sent immediately. The library, however, waits until any error the procedure could generate at the server has been handled. .SH Allocating and Deallocating Memory

To support the possible reentry of these procedures, you must observe several conventions when allocating and deallocating memory, 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). The standard C library functions on many systems are not protected against signals or other multithreaded uses. The following analogies to standard I/O library functions have been defined: .TS l l. T{ .PN Xmalloc () T} T{ Replaces .PN malloc () T} T{ .PN XFree () T} T{ Replaces .PN free () T} T{ .PN Xcalloc () T} T{ Replaces .PN calloc () T} .TE

These should be used in place of any calls you would make to the normal C library functions.

If you need a single scratch buffer inside a critical section (for example, to pack and unpack data to and from the wire protocol), the general memory allocators may be too expensive to use (particularly in output functions, which are performance critical). The following function returns a scratch buffer for use within a critical section: .sM .FD 0 char *_XAllocScratch(\fIdisplay\fP, \fInbytes\fP) .br Display *\fIdisplay\fP; .br unsigned long \fInbytes\fP; .FN .IP \fIdisplay\fP 1i Specifies the connection to the X server. .IP \fInbytes\fP 1i Specifies the number of bytes required.

.eM This storage must only be used inside of a critical section of your stub. The returned pointer cannot be assumed valid after any call that might permit another thread to execute inside Xlib. For example, the pointer cannot be assumed valid after any use of the .PN GetReq or .PN Data families of macros, after any use of .PN _XReply , or after any use of the .PN _XSend or .PN _XRead families of functions.

.sp The following function returns a scratch buffer for use across critical sections: .sM .FD 0 char *_XAllocTemp(\fIdisplay\fP, \fInbytes\fP) .br Display *\fIdisplay\fP; .br unsigned long \fInbytes\fP; .FN .IP \fIdisplay\fP 1i Specifies the connection to the X server. .IP \fInbytes\fP 1i Specifies the number of bytes required.

.eM This storage can be used across calls that might permit another thread to execute inside Xlib. The storage must be explicitly returned to Xlib. The following function returns the storage: .sM .FD 0 void _XFreeTemp(\fIdisplay\fP, \fIbuf\fP, \fInbytes\fP) .br Display *\fIdisplay\fP; .br char *\fIbuf\fP; .br unsigned long \fInbytes\fP; .FN .IP \fIdisplay\fP 1i Specifies the connection to the X server. .IP \fIbuf\fP 1i Specifies the buffer to return. .IP \fInbytes\fP 1i Specifies the size of the buffer.

.eM You must pass back the same pointer and size that were returned by .PN _XAllocTemp . .SH Portability Considerations

Many machine architectures, including many of the more recent RISC architectures, do not correctly access data at unaligned locations; their compilers pad out structures to preserve this characteristic. Many other machines capable of unaligned references pad inside of structures as well to preserve alignment, because accessing aligned data is usually much faster. Because the library and the server use structures to access data at arbitrary points in a byte stream, all data in request and reply packets \fImust\fP be naturally aligned; that is, 16-bit data starts on 16-bit boundaries in the request and 32-bit data on 32-bit boundaries. All requests \fImust\fP be a multiple of 32 bits in length to preserve the natural alignment in the data stream. You must pad structures out to 32-bit boundaries. Pad information does not have to be zeroed unless you want 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.

This code may run on machines with 16-bit ints. So, if any integer argument, variable, or return value either can take only nonnegative values or is declared as a .PN CARD16 in the protocol, be sure to declare it as .PN unsigned .PN int and not as .PN int . (This, of course, does not apply to Booleans or enumerations.)

Similarly, if any integer argument or return value is declared .PN CARD32 in the protocol, declare it as an .PN unsigned .PN long and not as .PN int or .PN long . This also goes for any internal variables that may take on values larger than the maximum 16-bit .PN unsigned .PN int .

The library currently assumes that a .PN char is 8 bits, a .PN short is 16 bits, an .PN int is 16 or 32 bits, and a .PN long is 32 bits. The .PN 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 work properly. .SH Deriving the Correct Extension Opcode

The remaining problem a writer of an extension stub procedure 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 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 procedure for this display. Call your initialization procedure and pass to it the display pointer. .IP 3. 5 Once in your initialization procedure, call .PN XInitExtension ; 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 procedure 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 procedure, the stub can now continue normally, because it has its major opcode safely in its hand in the .PN XExtCodes structure. .bp