diff options
Diffstat (limited to 'libX11/specs/libX11/AppC')
-rw-r--r-- | libX11/specs/libX11/AppC | 2230 |
1 files changed, 2230 insertions, 0 deletions
diff --git a/libX11/specs/libX11/AppC b/libX11/specs/libX11/AppC new file mode 100644 index 000000000..43261ba83 --- /dev/null +++ b/libX11/specs/libX11/AppC @@ -0,0 +1,2230 @@ +.\" Copyright \(co 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1994, 1996 X Consortium +.\" +.\" Permission is hereby granted, free of charge, to any person obtaining +.\" a copy of this software and associated documentation files (the +.\" "Software"), to deal in the Software without restriction, including +.\" without limitation the rights to use, copy, modify, merge, publish, +.\" distribute, sublicense, and/or sell copies of the Software, and to +.\" permit persons to whom the Software is furnished to do so, subject to +.\" the following conditions: +.\" +.\" The above copyright notice and this permission notice shall be included +.\" in all copies or substantial portions of the Software. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +.\" IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR +.\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +.\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +.\" OTHER DEALINGS IN THE SOFTWARE. +.\" +.\" Except as contained in this notice, the name of the X Consortium shall +.\" not be used in advertising or otherwise to promote the sale, use or +.\" other dealings in this Software without prior written authorization +.\" from the X Consortium. +.\" +.\" Copyright \(co 1985, 1986, 1987, 1988, 1989, 1990, 1991 by +.\" Digital Equipment Corporation +.\" +.\" Portions Copyright \(co 1990, 1991 by +.\" Tektronix, Inc. +.\" +.\" Permission to use, copy, modify and distribute this documentation for +.\" any purpose and without fee is hereby granted, provided that the above +.\" copyright notice appears in all copies and that both that copyright notice +.\" and this permission notice appear in all copies, and that the names of +.\" Digital and Tektronix not be used in in advertising or publicity pertaining +.\" to this documentation without specific, written prior permission. +.\" Digital and Tektronix makes no representations about the suitability +.\" of this documentation for any purpose. +.\" It is provided ``as is'' without express or implied warranty. +.\" +\& +.sp 1 +.ce 3 +\s+1\fBAppendix C\fP\s-1 + +\s+1\fBExtensions\fP\s-1 +.sp 2 +.na +.LP +.XS +Appendix C: Extensions +.XE +Because X can evolve by extensions to the core protocol, +it is important that extensions not be perceived 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, +automatically initializing 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 a bad practice. +Rather, they should be packaged into a single extension +and should use minor opcodes to distinguish the requests. +.NE +.LP +The symbols and macros used for writing stubs to Xlib are listed in +.hN X11/Xlibint.h . +.SH +Basic Protocol Support Routines +.LP +The basic protocol requests for extensions are +.PN XQueryExtension +and +.PN XListExtensions . +.IN "XQueryExtension" "" "@DEF@" +.sM +.FD 0 +Bool XQueryExtension(\^\fIdisplay\fP, \fIname\fP, \fImajor_opcode_return\fP, \ +\fIfirst_event_return\fP, \fIfirst_error_return\fP\^) +.br + Display *\fIdisplay\fP\^; +.br + char *\fIname;\fP\^ +.br + int *\fImajor_opcode_return\fP\^; +.br + int *\fIfirst_event_return\fP\^; +.br + int *\fIfirst_error_return\fP\^; +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fIname\fP 1i +Specifies the extension name. +.IP \fImajor_opcode_return\fP 1i +Returns the major opcode. +.IP \fIfirst_event_return\fP 1i +Returns the first event code, if any. +.IP \fIfirst_error_return\fP 1i +Returns the first error code, if any. +.LP +.eM +The +.PN XQueryExtension +function determines if the named extension is present. +If the extension is not present, +.PN XQueryExtension +returns +.PN False ; +otherwise, it returns +.PN True . +If the extension is present, +.PN XQueryExtension +returns the major opcode for the extension to major_opcode_return; +otherwise, +it returns zero. +Any minor opcode and the request formats are specific to the +extension. +If the extension involves additional event types, +.PN XQueryExtension +returns the base event type code to first_event_return; +otherwise, +it returns zero. +The format of the events is specific to the extension. +If the extension involves additional error codes, +.PN XQueryExtension +returns the base error code to first_error_return; +otherwise, +it returns zero. +The format of additional data in the errors is specific to the extension. +.LP +If the extension name is not in the Host Portable Character Encoding +the result is implementation-dependent. +Uppercase and lowercase matter; +the strings ``thing'', ``Thing'', and ``thinG'' +are all considered different names. +.IN "XListExtensions" "" "@DEF@" +.sM +.FD 0 +char **XListExtensions(\^\fIdisplay\fP, \fInextensions_return\fP\^) +.br + Display *\fIdisplay\fP\^; +.br + int *\fInextensions_return\fP\^; +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fInextensions_return\fP 1i +Returns the number of extensions listed. +.LP +.eM +The +.PN XListExtensions +function returns a list of all extensions supported by the server. +If the data returned by the server is in the Latin Portable Character Encoding, +then the returned strings are in the Host Portable Character Encoding. +Otherwise, the result is implementation-dependent. +.IN "XFreeExtensionList" "" "@DEF@" +.sM +.FD 0 +XFreeExtensionList(\^\fIlist\fP\^) +.br + char **\fIlist\fP\^; +.FN +.IP \fIlist\fP 1i +Specifies the list of extension names. +.LP +.eM +The +.PN XFreeExtensionList +function frees the memory allocated by +.PN XListExtensions . +.SH +Hooking into Xlib +.LP +These functions allow you 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 here allow the extension to be +called when these events occur. +.LP +The +.PN XExtCodes +structure returns the information from +.PN XInitExtension +and is defined in +.hN X11/Xlib.h : +.LP +.IN "XExtCodes" "" "@DEF@" +.sM +.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 +.LP +.eM +.IN "XInitExtension" "" "@DEF@" +.sM +.FD 0 +XExtCodes *XInitExtension(\^\fIdisplay\fP, \fIname\fP\^) +.br + Display *\fIdisplay\fP\^; +.br + char *\fIname\fP\^; +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fIname\fP 1i +Specifies the extension name. +.LP +.eM +The +.PN XInitExtension +function determines if the named 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. +If the extension does not exist, +.PN XInitExtension +returns NULL. +.LP +If the extension name is not in the Host Portable Character Encoding, +the result is implementation-dependent. +Uppercase and lowercase matter; +the strings ``thing'', ``Thing'', and ``thinG'' +are all considered different names. +.LP +The extension number in the +.PN XExtCodes +structure is +needed in the other calls that follow. +This extension number is unique only to a single connection. +.LP +.IN "XAddExtension" "" "@DEF@" +.sM +.FD 0 +XExtCodes *XAddExtension\^(\^\fIdisplay\fP\^) +.br + Display *\fIdisplay\fP\^; +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.LP +.eM +For local Xlib extensions, the +.PN XAddExtension +function allocates the +.PN XExtCodes +structure, bumps the extension number count, +and chains the extension onto the extension list. +(This permits extensions to Xlib without requiring server extensions.) +.SH +Hooks into the Library +.LP +These functions allow you to define procedures that 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 of 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 procedure defined for this +extension. +.IN "XESetCloseDisplay" "" "@DEF@" +.sM +.FD 0 +int (*XESetCloseDisplay(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^) +.br + Display *\fIdisplay\fP\^; +.br + int \fIextension\fP\^; +.br + int (\^*\fIproc\fP\^)(\^); +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fIextension\fP 1i +Specifies the extension number. +.IP \fIproc\fP 1i +Specifies the procedure to call when the display is closed. +.LP +.eM +The +.PN XESetCloseDisplay +function defines a procedure to be called whenever +.PN XCloseDisplay +is called. +It returns any previously defined procedure, usually NULL. +.LP +When +.PN XCloseDisplay +is called, +your procedure is called +with these arguments: +.LP +.sM +.Ds 0 +.TA .5i 3i +.ta .5i 3i +.R +(*\fIproc\fP\^)(\^\fIdisplay\fP, \fIcodes\fP\^) + Display *\fIdisplay\fP\^; + XExtCodes *\fIcodes\fP\^; +.De +.LP +.eM +.IN "XESetCreateGC" "" "@DEF@" +.sM +.FD 0 +int (*XESetCreateGC(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^) +.br + Display *\fIdisplay\fP\^; +.br + int \fIextension\fP\^; +.br + int (\^*\fIproc\fP\^)(\^); +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fIextension\fP 1i +Specifies the extension number. +.IP \fIproc\fP 1i +Specifies the procedure to call when a GC is closed. +.LP +.eM +The +.PN XESetCreateGC +function defines a procedure to be called whenever +a new GC is created. +It returns any previously defined procedure, usually NULL. +.LP +When a GC is created, +your procedure is called with these arguments: +.LP +.sM +.Ds 0 +.TA .5i 3i +.ta .5i 3i +.R +(*\fIproc\fP\^)(\^\fIdisplay\fP, \fIgc\fP, \fIcodes\fP\^) + Display *\fIdisplay\fP\^; + GC \fIgc\fP\^; + XExtCodes *\fIcodes\fP\^; +.De +.LP +.eM +.IN "XESetCopyGC" "" "@DEF@" +.sM +.FD 0 +int (*XESetCopyGC(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^) +.br + Display *\fIdisplay\fP\^; +.br + int \fIextension\fP\^; +.br + int (\^*\fIproc\fP\^)(\^); +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fIextension\fP 1i +Specifies the extension number. +.IP \fIproc\fP 1i +Specifies the procedure to call when GC components are copied. +.LP +.eM +The +.PN XESetCopyGC +function defines a procedure to be called whenever +a GC is copied. +It returns any previously defined procedure, usually NULL. +.LP +When a GC is copied, +your procedure is called with these arguments: +.LP +.sM +.Ds 0 +.TA .5i 3i +.ta .5i 3i +.R +(*\fIproc\fP\^)(\^\fIdisplay\fP, \fIgc\fP, \fIcodes\fP\^) + Display *\fIdisplay\fP\^; + GC \fIgc\fP\^; + XExtCodes *\fIcodes\fP\^; +.De +.LP +.eM +.IN "XESetFreeGC" "" "@DEF@" +.sM +.FD 0 +int (*XESetFreeGC(\^\fIdisplay\fP, \fIextension\fP, \fIproc)\fP\^)(\^) +.br + Display *\fIdisplay\fP\^; +.br + int \fIextension\fP\^; +.br + int (\^*\fIproc\fP\^)(\^); +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fIextension\fP 1i +Specifies the extension number. +.IP \fIproc\fP 1i +Specifies the procedure to call when a GC is freed. +.LP +.eM +The +.PN XESetFreeGC +function defines a procedure to be called whenever +a GC is freed. +It returns any previously defined procedure, usually NULL. +.LP +When a GC is freed, +your procedure is called with these arguments: +.LP +.sM +.Ds 0 +.TA .5i 3i +.ta .5i 3i +.R +(*\fIproc\fP\^)(\^\fIdisplay\fP, \fIgc\fP, \fIcodes\fP\^) + Display *\fIdisplay\fP\^; + GC \fIgc\fP\^; + XExtCodes *\fIcodes\fP\^; +.De +.LP +.eM +.IN "XESetCreateFont" "" "@DEF@" +.sM +.FD 0 +int (*XESetCreateFont(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP))(\^) +.br + Display *\fIdisplay\fP\^; +.br + int \fIextension\fP\^; +.br + int (\^*\fIproc\fP\^)(\^); +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fIextension\fP 1i +Specifies the extension number. +.IP \fIproc\fP 1i +Specifies the procedure to call when a font is created. +.LP +.eM +The +.PN XESetCreateFont +function defines a procedure to be called whenever +.PN XLoadQueryFont +and +.PN XQueryFont +are called. +It returns any previously defined procedure, usually NULL. +.LP +When +.PN XLoadQueryFont +or +.PN XQueryFont +is called, +your procedure is called with these arguments: +.LP +.sM +.Ds 0 +.TA .5i 3i +.ta .5i 3i +.R +(*\fIproc\fP\^)(\^\fIdisplay\fP, \fIfs\fP, \fIcodes\fP\^) + Display *\fIdisplay\fP\^; + XFontStruct *\fIfs\fP\^; + XExtCodes *\fIcodes\fP\^; +.De +.LP +.eM +.IN "XESetFreeFont" "" "@DEF@" +.sM +.FD 0 +int (*XESetFreeFont(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^) +.br + Display *\fIdisplay\fP\^; +.br + int \fIextension\fP\^; +.br + int (\^*\fIproc\fP)(\^); +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fIextension\fP 1i +Specifies the extension number. +.IP \fIproc\fP 1i +Specifies the procedure to call when a font is freed. +.LP +.eM +The +.PN XESetFreeFont +function defines a procedure to be called whenever +.PN XFreeFont +is called. +It returns any previously defined procedure, usually NULL. +.LP +When +.PN XFreeFont +is called, your procedure is called with these arguments: +.LP +.sM +.Ds 0 +.TA .5i 3i +.ta .5i 3i +.R +(*\fIproc\fP\^)(\^\fIdisplay\fP, \fIfs\fP, \fIcodes\fP\^) + Display *\fIdisplay\fP\^; + XFontStruct *\fIfs\fP\^; + XExtCodes *\fIcodes\fP\^; +.De +.LP +.eM +The +.PN XESetWireToEvent +and +.PN XESetEventToWire +functions allow you to define new events to the library. +An +.PN XEvent +structure always has a type code (type +.PN int ) +as the first component. +This uniquely identifies what kind of event it is. +The second component is always the serial number (type +.PN unsigned +.PN long ) +of the last request processed by the server. +The third component is always a Boolean (type +.PN Bool ) +indicating whether the event came from a +.PN SendEvent +protocol request. +The fourth component is always a pointer to the display +the event was read from. +The fifth component is always a resource ID of one kind or another, +usually a window, carefully selected to be useful to toolkit dispatchers. +The fifth component should always exist, even if +the event does not have a natural destination; +if there is no value +from the protocol to put in this component, initialize it to zero. +.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@" +.sM +.FD 0 +int (*XESetWireToEvent(\^\fIdisplay\fP, \fIevent_number\fP, \fIproc\fP\^))(\^) +.br + Display *\fIdisplay\fP\^; +.br + int \fIevent_number\fP\^; +.br + Status (\^*\fIproc\fP\^)(\^); +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fIevent_number\fP 1i +Specifies the event code. +.IP \fIproc\fP 1i +Specifies the procedure to call when converting an event. +.LP +.eM +The +.PN XESetWireToEvent +function defines a procedure to be called when an event +needs to be converted from wire format +.Pn ( xEvent ) +to host format +.Pn ( XEvent ). +The event number defines which protocol event number to install a +conversion procedure for. +.PN XESetWireToEvent +returns any previously defined procedure. +.NT +You can replace a core event conversion function with one +of your own, although this is not encouraged. +It would, however, allow you to intercept a core event +and modify it before being placed in the queue or otherwise examined. +.NE +When Xlib needs to convert an event from wire format to host +format, your procedure is called with these arguments: +.LP +.sM +.Ds 0 +.TA .5i 3i +.ta .5i 3i +.R +Status (*\fIproc\fP\^)(\^\fIdisplay\fP, \fIre\fP, \fIevent\fP\^) + Display *\fIdisplay\fP\^; + XEvent *\fIre\fP\^; + xEvent *\fIevent\fP\^; +.De +.LP +.eM +Your procedure must return status to indicate if the conversion succeeded. +The re argument is a pointer to where the host format event should be stored, +and the event argument is the 32-byte wire event structure. +In the +.PN XEvent +structure you are creating, +you must fill in the five required members of the event structure. +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 procedure should return +.PN True +if the event should be placed in the queue or +.PN False +if it should not be placed in the queue. +.LP +To initialize the serial number component of the event, call +.PN _XSetLastRequestRead +with the event and use the return value. +.LP +.IN "_XSetLastRequestRead" "" "@DEF@" +.sM +.FD 0 +unsigned long _XSetLastRequestRead(\^\fIdisplay\fP, \fIrep\fP\^) +.br + Display *\fIdisplay\fP\^; +.br + xGenericReply *\fIrep\fP\^; +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fIrep\fP 1i +Specifies the wire event structure. +.LP +.eM +The +.PN _XSetLastRequestRead +function computes and returns a complete serial number from the partial +serial number in the event. +.sp +.LP +.IN "XESetEventToWire" "" "@DEF@" +.sM +.FD 0 +Status (*XESetEventToWire(\^\fIdisplay\fP, \fIevent_number\fP, \fIproc\fP\^))(\^) +.br + Display *\fIdisplay\fP\^; +.br + int \fIevent_number\fP\^; +.br + int (\^*\fIproc\fP\^)(\^); +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fIevent_number\fP 1i +Specifies the event code. +.IP \fIproc\fP 1i +Specifies the procedure to call when converting an event. +.LP +.eM +The +.PN XESetEventToWire +function defines 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 procedure for. +.PN XESetEventToWire +returns any previously defined procedure. +It returns zero if the conversion fails or nonzero otherwise. +.NT +You can replace a core event conversion function with one +of your own, although 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 host format to wire format, +your procedure is called with these arguments: +.LP +.sM +.Ds 0 +.TA .5i 3i +.ta .5i 3i +.R +(*\fIproc\fP\^)(\^\fIdisplay\fP, \fIre\fP, \fIevent\fP\^) + Display *\fIdisplay\fP\^; + XEvent *\fIre\fP\^; + xEvent *\fIevent\fP\^; +.De +.LP +.eM +The re argument is a pointer to the host format event, +and the event argument is a pointer to where the 32-byte wire event +structure should be stored. +You should fill in the type with the type from the +.PN XEvent +structure. +All other members then should be copied from the host format to the +.PN xEvent +structure. +.IN "XESetWireToError" "" "@DEF@" +.sM +.FD 0 +Bool (*XESetWireToError(\^\fIdisplay\fP, \fIerror_number\fP, \fIproc\fP\^)(\^) +.br + Display *\fIdisplay\fP\^; +.br + int \fIerror_number\fP\^; +.br + Bool (\^*\fIproc\fP\^)(\^); +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fIerror_number\fP 1i +Specifies the error code. +.IP \fIproc\fP 1i +Specifies the procedure to call when an error is received. +.LP +.eM +The +.PN XESetWireToError +function defines a procedure to be called when an extension +error needs to be converted from wire format to host format. +The error number defines which protocol error code to install +the conversion procedure for. +.PN XESetWireToError +returns any previously defined procedure. +.LP +Use this function for extension errors that contain additional error values +beyond those in a core X error, when multiple wire errors must be combined +into a single Xlib error, or when it is necessary to intercept an +X error before it is otherwise examined. +.LP +When Xlib needs to convert an error from wire format to host format, +the procedure is called with these arguments: +.LP +.sM +.Ds 0 +.TA .5i 3i +.ta .5i 3i +.R +Bool (*\fIproc\fP\^)(\^\fIdisplay\fP, \fIhe\fP, \fIwe\fP\^) + Display *\fIdisplay\fP\^; + XErrorEvent *\fIhe\fP\^; + xError *\fIwe\fP\^; +.De +.LP +.eM +The he argument is a pointer to where the host format error should be stored. +The structure pointed at by he is guaranteed to be as large as an +.PN XEvent +structure and so can be cast to a type larger than an +.PN XErrorEvent +to store additional values. +If the error is to be completely ignored by Xlib +(for example, several protocol error structures will be combined into +one Xlib error), +then the function should return +.PN False ; +otherwise, it should return +.PN True . +.IN "XESetError" "" "@DEF@" +.sM +.FD 0 +int (*XESetError(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^) +.br + Display *\fIdisplay\fP\^; +.br + int \fIextension\fP\^; +.br + int (\^*\fIproc\fP\^)(\^); +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fIextension\fP 1i +Specifies the extension number. +.IP \fIproc\fP 1i +Specifies the procedure to call when an error is received. +.LP +.eM +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 functions are query operations, in any +case, and are typically programmed to be synchronous). +.LP +When Xlib detects a protocol error in +.PN _XReply , +it calls your procedure with these arguments: +.LP +.sM +.Ds 0 +.TA .5i 3i +.ta .5i 3i +.R +int (*\fIproc\fP\^)(\fIdisplay\fP, \fIerr\fP, \fIcodes\fP, \fIret_code\fP\^) + Display *\fIdisplay\fP\^; + xError *\fIerr\fP\^; + XExtCodes *\fIcodes\fP\^; + int *\fIret_code\fP\^; +.De +.LP +.eM +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 +.PN _XReply +returned to. +.LP +If your procedure returns a zero value, +the error is not suppressed, and +the client's error handler is called. +(For further information, see section 11.8.2.) +If your procedure returns nonzero, +the error is suppressed, and +.PN _XReply +returns the value of ret_code. +.IN "XESetErrorString" "" "@DEF@" +.sM +.FD 0 +char *(*XESetErrorString(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^) +.br + Display *\fIdisplay\fP\^; +.br + int \fIextension\fP\^; +.br + char *(\^*\fIproc\fP\^)(\^); +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fIextension\fP 1i +Specifies the extension number. +.IP \fIproc\fP 1i +Specifies the procedure to call to obtain an error string. +.LP +.eM +The +.PN XGetErrorText +function returns a string to the user for an error. +.PN XESetErrorString +allows you to define a procedure to be called that +should return a pointer to the error message. +The following is an example. +.LP +.sM +.Ds 0 +.TA .5i 3i +.ta .5i 3i +.R +(*\fIproc\fP\^)(\^\fIdisplay\fP, \fIcode\fP, \fIcodes\fP, \fIbuffer\fP, \fInbytes\fP\^) + Display *\fIdisplay\fP\^; + int \fIcode\fP\^; + XExtCodes *\fIcodes\fP\^; + char *\fIbuffer\fP\^; + int \fInbytes\fP\^; +.De +.LP +.eM +Your procedure is called with the error code for every error detected. +You should copy nbytes of a null-terminated string containing the +error message into buffer. +.IN "XESetPrintErrorValues" "" "@DEF@" +.sM +.FD 0 +void (*XESetPrintErrorValues(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^) +.br + Display *\fIdisplay\fP\^; +.br + int \fIextension\fP\^; +.br + void (\^*\fIproc\fP\^)(\^); +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fIextension\fP 1i +Specifies the extension number. +.IP \fIproc\fP 1i +Specifies the procedure to call when an error is printed. +.LP +.eM +The +.PN XESetPrintErrorValues +function defines a procedure to be called when an extension +error is printed, to print the error values. +Use this function for extension errors that contain additional error values +beyond those in a core X error. +It returns any previously defined procedure. +.LP +When Xlib needs to print an error, +the procedure is called with these arguments: +.LP +.sM +.Ds 0 +.TA .5i 3i +.ta .5i 3i +.R +void (*\fIproc\fP\^)(\^\fIdisplay\fP, \fIev\fP, \fIfp\fP\^) + Display *\fIdisplay\fP\^; + XErrorEvent *\fIev\fP\^; + void *\fIfp\fP\^; +.De +.LP +.eM +The structure pointed at by ev is guaranteed to be as large as an +.PN XEvent +structure and so can be cast to a type larger than an +.PN XErrorEvent +to obtain additional values set by using +.PN XESetWireToError . +The underlying type of the fp argument is system dependent; +on a POSIX-compliant system, fp should be cast to type FILE*. +.IN "XESetFlushGC" "" "@DEF@" +.sM +.FD 0 +int (*XESetFlushGC(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^) +.br + Display *\fIdisplay\fP\^; +.br + int \fIextension\fP\^; +.br + int *(\^*\fIproc\fP\^)(\^); +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fIextension\fP 1i +Specifies the extension number. +.IP \fIproc\fP 1i +Specifies the procedure to call when a GC is flushed. +.LP +.eM +The procedure set by the +.PN XESetFlushGC +function has the same interface as the procedure set by the +.PN XESetCopyGC +function, but is called when a GC cache needs to be updated in the server. +.IN "XESetBeforeFlush" "" "@DEF@" +.sM +.FD 0 +int (*XESetBeforeFlush(\^\fIdisplay\fP, \fIextension\fP, \fIproc\fP\^))(\^) +.br + Display *\fIdisplay\fP\^; +.br + int \fIextension\fP\^; +.br + int *(\^*\fIproc\fP\^)(\^); +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.IP \fIextension\fP 1i +Specifies the extension number. +.IP \fIproc\fP 1i +Specifies the procedure to call when a buffer is flushed. +.LP +.eM +The +.PN XESetBeforeFlush +function defines a procedure to be called when data is about to be +sent to the server. When data is about to be sent, your procedure is +called one or more times with these arguments: +.LP +.sM +.Ds 0 +.TA .5i 3i +.ta .5i 3i +.R +void (*\fIproc\fP\^)(\^\fIdisplay\fP, \fIcodes\fP, \fIdata\fP, \fIlen\fP\^) + Display *\fIdisplay\fP\^; + XExtCodes *\fIcodes\fP\^; + char *\fIdata\fP\^; + long \fIlen\fP\^; +.De +.LP +.eM +The data argument specifies a portion of the outgoing data buffer, +and its length in bytes is specified by the len argument. +Your procedure must not alter the contents of the data and must not +do additional protocol requests to the same display. +.SH +Hooks onto Xlib Data Structures +.LP +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. +.LP +The following structure is used in the functions in this section +and is defined in +.hN X11/Xlib.h : +.LP +.IN "XExtData" "" "@DEF@" +.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 +.LP +.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. +.LP +.sM +.Ds 0 +.TA .5i +.ta .5i +union { Display *display; + GC gc; + Visual *visual; + Screen *screen; + ScreenFormat *pixmap_format; + XFontStruct *font } XEDataObject; +.De +.LP +.eM +.IN "XEHeadOfExtensionList" "" "@DEF@" +.sM +.FD 0 +XExtData **XEHeadOfExtensionList(\^\fIobject\fP\^) + XEDataObject \fIobject\fP\^; +.FN +.IP \fIobject\fP 1i +Specifies the object. +.LP +.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 . +.LP +.IN "XAddToExtensionList" "" "@DEF@" +.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. +.LP +.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. +.IN "XFindOnExtensionList" "" "@DEF@" +.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 . +.LP +.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. +.LP +The +.PN XAllocID +macro, which allocates and returns a resource ID, is defined in +.hN X11/Xlib.h . +.IN "XAllocID" "" "@DEF@" +.sM +.FD 0 +XAllocID\^(\fIdisplay\fP\^) +.br + Display *\fIdisplay\fP\^; +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.LP +.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. +.LP +The +.PN XAllocIDs +macro allocates and returns an array of resource ID. +.IN "XAllocIDs" "" "@DEF@" +.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. +.LP +.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 +.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 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. +.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 +macro is defined as follows: +.IN "FlushGC" "" "@DEF@" +.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. +.LP +.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: +.IN "_XFlushGCCache" "" "@DEF@" +.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. +.LP +.eM +.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. +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 <X11/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 +.eM +To keep clients from generating very long requests that may monopolize the +server, +there is a symbol defined in +.hN 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 +.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 ``X Window System Protocol.'' +.SH +Requests, Replies, and Xproto.h +.LP +The +.hN X11/Xproto.h +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 +.hN X11/Xproto.h +for your extension and need to include it in your stub procedure. +Each stub procedure also must include +.hN X11/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 +.hN X11/Xlibint.h , +takes advantage of this naming scheme. +.LP +For each X request, +there is a definition in +.hN X11/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 opcode, +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 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). +.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 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. +.LP +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. +.LP +Most protocol requests have a corresponding structure typedef in +.hN X11/Xproto.h , +which looks like: +.LP +.IN "xDoSomethingReq" "" "@DEF@" +.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 +.LP +.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 +.hN 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 . +.LP +.IN "xResourceReq" "" "@DEF@" +.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 +.LP +.eM +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 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. +.LP +A few protocol requests take no arguments at all. +Instead, they use the +.PN xReq +structure in +.hN X11/Xproto.h , +which contains only a reqType and a length (and a pad byte). +.LP +If the protocol request requires a reply, +then +.hN X11/Xproto.h +also contains a reply structure typedef: +.LP +.IN "xDoSomethingReply" "" "@DEF@" +.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 +.LP +.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. +.LP +Only +.PN GetWindowAttributes , +.PN QueryFont , +.PN QueryKeymap , +and +.PN GetKeyboardControl +have reply structures longer than 32 bytes in the core protocol. +.LP +A few protocol requests return replies that contain no data. +.hN 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 +.LP +An Xlib stub procedure should start like this: +.LP +.Ds +.R +#include "<X11/Xlibint.h> + +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: +.LP +.Ds +.R +xDoSomethingReply rep; +.De +.SH +Locking Data Structures +.LP +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. +.IN "LockDisplay" "" "@DEF@" +.sM +.FD 0 +LockDisplay(\^\fIdisplay\fP\^) +.br + Display *\fIdisplay\fP\^; +.FN +.LP +.IN "UnlockDisplay" "" "@DEF@" +.FD 0 +UnlockDisplay(\^\fIdisplay\fP\^) +.br + Display *\fIdisplay\fP\^; +.FN +.IP \fIdisplay\fP 1i +Specifies the connection to the X server. +.LP +.eM +.SH +Sending the Protocol Request and Arguments +.LP +After the variable declarations, +a stub procedure should call one of four macros defined in +.hN 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 +.hN 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. +.LP +If the protocol request has no arguments (for instance, X_GrabServer), +then use +.PN GetEmptyReq . +.LP +.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. +.LP +.Ds +.R +GetResReq (DoSomething, rid, req); +.De +The rid argument is the +.PN Pixmap , +.PN 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 procedure. +.LP +.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. +.LP +.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 +.LP +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. +.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 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 +.LP +.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. +.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-length 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. +.IN "_XReply" "" "@DEF@" +.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. +.LP +.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 +.LP +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. +.LP +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. +.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, 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. +.LP +.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. +.LP +.eM +The +.PN _XRead +function reads the specified number of bytes into data_return. +.LP +.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. +.LP +.eM +The +.PN _XRead16 +function reads the specified number of bytes, +unpacking them as 16-bit quantities, +into the specified array as shorts. +.LP +.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. +.LP +.eM +The +.PN _XRead32 +function reads the specified number of bytes, +unpacking them as 32-bit quantities, +into the specified array as longs. +.LP +.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. +.LP +.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. +.LP +.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. +.LP +.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. +.LP +Each protocol request is a little different. +For further information, +see the Xlib sources for examples. +.SH +Synchronous Calling +.LP +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 +.LP +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 +.LP +These should be used in place of any calls you would make to the normal +C library functions. +.LP +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: +.IN "_XAllocScratch" "" "@DEF@" +.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. +.LP +.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. +.LP +.sp +The following function returns a scratch buffer for use across +critical sections: +.IN "_XAllocTemp" "" "@DEF@" +.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. +.LP +.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: +.IN "_XFreeTemp" "" "@DEF@" +.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. +.LP +.eM +You must pass back the same pointer and size that were returned by +.PN _XAllocTemp . +.SH +Portability Considerations +.LP +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. +.LP +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.) +.LP +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 . +.LP +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 +.LP +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 +.hN 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 |