Remove xcl and CVSROOT.
authorJosh Triplett <josh@freedesktop.org>
Sun, 19 Feb 2006 00:49:41 +0000 (16:49 -0800)
committerJosh Triplett <josh@josh-mobile.localdomain>
Sun, 19 Feb 2006 00:49:41 +0000 (16:49 -0800)
41 files changed:
.cvsignore [new file with mode: 0644]
COPYING [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
autogen.sh [new file with mode: 0755]
configure.ac [new file with mode: 0644]
debian/.cvsignore [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright.debian [new file with mode: 0644]
debian/libxcb0-dev.dirs [new file with mode: 0644]
debian/libxcb0-dev.install [new file with mode: 0644]
debian/libxcb0.dirs [new file with mode: 0644]
debian/libxcb0.install [new file with mode: 0644]
debian/rules [new file with mode: 0755]
doc/tutorial/index.html [new file with mode: 0755]
doc/tutorial/xcb.css [new file with mode: 0755]
src/.cvsignore [new file with mode: 0644]
src/Makefile.am [new file with mode: 0644]
src/c-client.xsl [new file with mode: 0644]
src/xcb.h [new file with mode: 0644]
src/xcb_auth.c [new file with mode: 0644]
src/xcb_conn.c [new file with mode: 0644]
src/xcb_ext.c [new file with mode: 0644]
src/xcb_in.c [new file with mode: 0644]
src/xcb_list.c [new file with mode: 0644]
src/xcb_out.c [new file with mode: 0644]
src/xcb_util.c [new file with mode: 0644]
src/xcb_xid.c [new file with mode: 0644]
src/xcb_xlib.c [new file with mode: 0644]
src/xcbext.h [new file with mode: 0644]
src/xcbint.h [new file with mode: 0644]
src/xcbxlib.h [new file with mode: 0644]
tests/.cvsignore [new file with mode: 0644]
tests/CheckLog.xsl [new file with mode: 0644]
tests/Makefile.am [new file with mode: 0644]
tests/check_all.c [new file with mode: 0644]
tests/check_public.c [new file with mode: 0644]
tests/check_suites.h [new file with mode: 0644]
xcb.pc.in [new file with mode: 0644]

diff --git a/.cvsignore b/.cvsignore
new file mode 100644 (file)
index 0000000..3d5e104
--- /dev/null
@@ -0,0 +1,17 @@
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+compile
+config.guess
+config.log
+config.status
+config.sub
+configure
+depcomp
+install-sh
+libtool
+ltmain.sh
+missing
+mkinstalldirs
+*.pc
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..8c328d3
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,30 @@
+Copyright (C) 2001-2004 Bart Massey, Jamey Sharp, and Josh Triplett.
+All Rights Reserved.
+
+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 AUTHORS
+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 names of the authors
+or their institutions 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
+authors.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..7ba7263
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,610 @@
+2005-12-28  Jamey Sharp  <jamey@minilop.net>
+
+       * configure.ac:
+       Replace obsolete AC_OUTPUT(...) call with AC_CONFIG_FILES(...)
+       and the no-argument AC_OUTPUT macro.
+
+2005-12-24  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_xlib.c, src/xcbxlib.h, src/Makefile.am:
+       New header and two functions specifically for Xlib's use, so
+       we can quit installing xcbint.h.
+
+       * src/xcb_out.c, src/xcbint.h:
+       Now that Xlib uses entirely public API, force_sequence_wrap is
+       purely internal to xcb_out.
+
+2005-12-20  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_util.c:
+       Use AF_UNIX instead of PF_UNIX, because they're interchangeable
+       on Linux (and 4.x BSD?) but on MacOS X the latter is not
+       available. Thanks to Ian Osgood for testing.
+
+2005-12-12  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_util.c:
+       Rewrite XCBParseDisplay to handle all error cases correctly.
+       Thanks to Travis Spencer for pointing out a problem with
+       the previous sscanf call; turns out that sscanf won't do what
+       I want anyway, so this version just uses strtoul.
+
+2005-12-12  Jamey Sharp  <jamey@minilop.net>
+
+       * tests/check_public.c:
+       Fix segfault in fail_unless calls and provide more useful error
+       messages. Also remove DISPLAY from the environment and test
+       ParseDisplay on a null pointer.
+
+2005-12-07  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb.h, src/xcb_in.c:
+       Use GCC attribute extension, if available, to mark some
+       functions deprecated; and rename XCBWaitEvent to
+       XCBWaitForEvent, with a deprecated backwards compatibility
+       function.
+
+2005-12-07  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb.h, src/xcb_conn.c, src/xcb_util.c:
+       Rename XCBConnect to XCBConnectToFD, and implement XCBConnect
+       and XCBConnectToDisplayWithAuthInfo, as specified by the XcbApi
+       documentation. Provide a trivial implementation of deprecated
+       XCBConnectBasic for backwards compatibility. Fix XCBParseDisplay
+       to accept a null screen pointer.
+
+2005-09-30  Trevor Woerner <twoerner.x@gmail.com>
+
+       reviewer: Jamey Sharp <jamey@minilop.net>
+
+       * Makefile.am, configure.ac, src/Makefile.am, tests/Makefile.am,
+         src/check_all.c, src/check_public.c, src/check_suites.h:
+       Created a new directory called "tests" where the unit tests
+       will reside, separate from other files. Moved the unit
+       test files from the "src" directory into the new "tests"
+       directory.
+
+       * configure.ac, tests/CheckLog.xsl, tests/.cvsignore,
+         tests/Makefile.am, tests/check_all.c:
+       Added an XSLT transform to post-process the XML log file which
+       is generated by the unit test suite into an HTML page. Added
+       the necessary hooks into the build system to have this
+       translation occur when necessary as part of the build process.
+
+2005-08-15  Trevor Woerner <twoerner.x@gmail.com>
+
+       reviewer: Jamey Sharp <jamey@minilop.net>
+
+       * src/Makefile.am:
+       Make builds work when the source and build directories
+       are different.
+
+2005-08-03  Trevor Woerner <twoerner.x@gmail.com>
+
+       reviewer: Jamey Sharp <jamey@minilop.net>
+
+       * configure.ac:
+       Allow people to not have check as long as they have at
+       least automake version 1.9. Older versions of automake
+       still work as long as check is installed or the NoCheck
+       instructions are followed.
+
+2005-07-21  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_conn.c:
+       Fix one uninitialized memory warning from Valgrind.
+       More will have to wait.
+
+2005-07-21  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_ext.c:
+       Fix memory leak reported by Carl Worth (thanks Carl!).
+
+2005-05-22  Josh Triplett  <josh@freedesktop.org>
+
+       * src/c-client.xsl:
+       Permit unions to have fixed-length list fields.
+
+2005-05-21  Josh Triplett  <josh@freedesktop.org>
+
+       * src/c-client.xsl:
+       In function parameters and structure fields, line up field names in
+       the same starting column.
+
+2005-05-17  Josh Triplett  <josh@freedesktop.org>
+
+       * src/c-client.xsl:
+       Make header files self-sufficient, by including xcb.h in the
+       generated headers rather than the generated sources.
+
+       * src/xcbext.h:
+       Make xcbext.h self-sufficient, by including xcb.h.
+
+2005-05-17  Josh Triplett  <josh@freedesktop.org>
+
+       * src/c-client.xsl:
+       Line up function parameters with opening parenthesis.
+
+2005-05-17  Jamey Sharp  <jamey@minilop.net>
+
+       * src/c-client.xsl:
+       Improve whitespace output on function declarations.
+
+2005-04-23  Jeremy Kolb  <jkolb@brandeis.edu>
+       * src/c-client.xsl:
+       Added list support for typedefs.
+       GLX now compiles.
+
+2005-04-23  Josh Triplett  <josh@freedesktop.org>
+
+       * src/c-client.xsl:
+       Allow protocol descriptions to explicitly qualify types with a
+       namespace, which should be the value of the header attribute from
+       the protocol description containing the desired type.
+
+2005-04-10  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb.h, src/xcb_in.c:
+       New public function XCBGetRequestRead: returns the last sequence
+       number that the server is known to have processed. This function
+       enables apps to determine whether forcing a cookie is going to
+       block.
+
+2005-04-09  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_ext.c:
+       Implement XCBPrefetchExtensionData. An extension can now be in
+       one of three states in a particular connection's cache: not
+       queried; query cookie available; and query reply available.
+
+2005-04-09  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_ext.c, src/xcbint.h:
+       Assign a display-independent unique integer to each XCBExtension
+       structure. Use a map instead of a list for the extension cache.
+       Key the map on the assigned integer.
+
+2005-04-06  Jeremy Kolb  <jkolb@brandeis.edu>
+
+       * src/c-client.xsl:
+       Added support for c types float and double.
+       Needed for GLX extension.
+
+2005-04-02  Jamey Sharp  <jamey@minilop.net>
+
+       * src/c-client.xsl:
+       Workaround for XSLT processors that can't understand attribute
+       values of the form '{{ "{...}" }}'. (What? That looks completely
+       clear to me. *grin*)
+
+2005-04-01  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_list.c:
+       Make the _destroy operations no-op on null pointers.
+
+2005-03-31  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb.h, src/xcb_conn.c, src/xcb_out.c, src/xcbint.h:
+       Lazily check for BIG-REQUESTS support. The first call to
+       XCBGetMaximumRequestLength takes the two-round-trip penalty for
+       discovering BIG-REQUESTS support, and caches the result for
+       subsequent calls. Also XCBSendRequest is now careful to only ask
+       for the true maximum request length if the length from the
+       connection setup data isn't sufficient for the current request.
+
+2005-03-31  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_in.c:
+       Fix X error handling to, uh, not hang.
+
+2005-03-30  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_in.c, src/xcbint.h:
+       Accept zero or more replies to any request. Eliminates, for the
+       moment, nearly all run-time error checking regarding the number
+       of replies expected for a particular request. Also breaks the
+       unexpected reply callback, which is OK because I was going to
+       remove it anyway, and now I've done so.
+
+2005-03-30  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_list.c, src/xcbint.h:
+       Add a map ADT implemented using the list ADT.
+
+2005-03-28  Vincent Torri  <torri@iecn.u-nancy.fr>
+
+       * doc/tutorial/index.html, doc/tutorial/xcb.css:
+       Add a tutorial
+
+2005-03-27  Jeremy Kolb  <jkolb@brandeis.edu>
+
+       * src/Makefile.am:
+       Added xf86dri (xcb-proto/src/extensions/xf86dri.h).
+       Removed compilation of record as it's broken.
+
+2005-03-25  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_in.c:
+       Instead of storing a pending flag per reply record, look in the
+       readers list to find out whether there's a reader waiting for
+       the reply we've just been asked to wait for.
+
+2005-03-25  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_list.c, src/xcbint.h:
+       Add _xcb_queue_is_empty.
+
+2005-03-25  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_in.c, src/xcb_list.c, src/xcbint.h:
+       Add a queue ADT. Currently implemented using the list ADT, but
+       analysis will probably suggest a better data structure. The
+       split is intended to help that analysis.
+
+2005-03-25  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_in.c, src/xcb_list.c, src/xcbint.h:
+       Remove _xcb_list_length. (Two callers in xcb_in didn't actually
+       care about the returned value beyond "empty" or "non-empty",
+       which they can get other ways.) _xcb_in_events_length became
+       obsolete in the process, and I took _xcb_list_clear out of
+       xcbint.h while I was at it because only _xcb_list_delete calls
+       it these days.
+
+2005-03-25  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb.h, src/xcb_in.c:
+       Remove XCBEventQueueLength and XCBEventQueueClear: they're not
+       part of the new API, and they interfere with analysis of the
+       _xcb_list implementation.
+
+2005-03-24  Josh Triplett  <josh@freedesktop.org>
+
+       * configure.ac:
+       Change pdx.freedesktop.org to lists.freedesktop.org in package
+       email address.
+
+2005-03-23  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_conn.c, src/xcb_in.c:
+       avn@daemon.hole.ru pointed out two memory leaks in XCB, which
+       this update fixes. I also introduced a third a couple of days
+       ago, which this fixes as well.
+
+2005-03-23  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_in.c:
+       Quit storing an "error" flag: it's redundant with the contents
+       of the packet that it was stored with.
+
+2005-03-22  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_in.c, src/xcbint.h:
+       My recent Xlib patch stressed XCB's pending reply queue in ways
+       it has never been stressed before, with thousands of entries.
+       Profiling revealed that wake_up_next_reader was taking most of
+       the cycles of my test app with its linear search of the reply
+       queue. So I gave it its own 'readers' queue, which can have at
+       most one entry per thread, and which can be no more than the
+       number of pending replies. In the current implementation the
+       readers queue uses only constant-time operations, too.
+
+2005-03-20  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_in.c:
+       Wait for the last known read sequence number to pass the request
+       we're waiting for, instead of checking whether data has arrived
+       for the current request. Causes null to be returned if somebody
+       screwed up by expecting a reply when none can come; relied on by
+       new Xlib/XCB bits that intentionally and routinely screw up this
+       way because the API doesn't give them enough information.
+
+       * src/xcb_list.c, src/xcbint.h:
+       Add _xcb_list_peek_head so Xlib doesn't have to repeatedly
+       remove and re-insert the item at the head of its new
+       pending_requests queue. Profiling showed that was a significant
+       performance hit for the above-mentioned patch and with this
+       three-line function apps are actually usable again.
+
+2004-11-26  Josh Triplett  <josh@freedesktop.org>
+
+       * src/c-client.xsl:
+       In do-request processing, use the existing num-parts variable
+       rather than recalculating the same expression.
+
+2004-11-26  Josh Triplett  <josh@freedesktop.org>
+
+       * src/c-client.xsl:
+         * Add a list of known core types, and don't search all the
+           protocol descriptions for types in that list.  This
+           significantly shortens the processing time.
+         * Search for all definitions of a non-core type, not just the
+           first, in order to check for duplicate definitions.
+         * Add an error message for non-core types with no definitions
+           found.
+
+2004-11-10  Josh Triplett  <josh@freedesktop.org>
+
+       * src/c-client.xsl:
+       Don't create a separate local variable for exprfields, and change
+       an explicit xsl:for-each to an xsl:apply-templates.
+
+2004-11-10  Josh Triplett  <josh@freedesktop.org>
+
+       * src/c-client.xsl:
+       Prefix variables in request functions with "xcb_" to avoid
+       collisions with field names.
+
+2004-11-09  Josh Triplett  <josh@freedesktop.org>
+
+       * src/c-client.xsl:
+       * src/xcb_out.c:
+       * src/xcbext.h:
+       More API changes: Put constant request-specific data into a static
+       const structure in each request function.
+
+2004-11-09  Josh Triplett  <josh@freedesktop.org>
+
+       * src/c-client.xsl:
+       Add support for an <indent> tag in a function body, which indents
+       the <l>s it contains.
+
+       * debian/.cvsignore:
+       debian/copyright is a generated file, so add it to
+       debian/.cvsignore
+       
+2004-11-08  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_conn.c:
+       Make the __thread-based assertion a compile-time
+       option, defaulting to off. It breaks on many systems
+       and isn't critical to XCB's functionality.
+
+2004-11-07  Josh Triplett  <josh@freedesktop.org>
+
+       * c-client.xsl:
+       Update XSLT to deal with change from extension element to
+       extension-name and extension-xname attributes on xcb element.
+
+2004-11-06  Josh Triplett  <josh@freedesktop.org>
+
+       * xcb.h:
+       * xcb_auth.c:
+       * xcb_conn.c:
+       * xcb_ext.c:
+       * xcb_in.c:
+       * xcb_list.c:
+       * xcb_out.c:
+       * xcb_util.c:
+       * xcb_xid.c:
+       * xcbext.h:
+       * xcbint.h:
+       Include license in every file rather than referencing COPYING.
+       Update copyright notices to 2004.
+
+       * COPYING:
+       Remove non-applicable licenses from COPYING file.
+
+2004-11-06  Josh Triplett  <josh@freedesktop.org>
+
+       * configure.ac:
+       * src/.cvsignore:
+       * src/Makefile.am:
+       * src/xcb.h:
+       Merged changes for XML-XCB project.
+
+       * src/c-client.xsl:
+       * src/xcb.h:
+       Add XSLT binding generator and non-M4 version of xcb.h.
+       
+       * src/client-c.xcb:
+       * src/xcb.h.m4:
+       Remove M4 binding generator and M4 version of xcb.h.
+
+       * debian/changelog:
+       * debian/control:
+       * debian/copyright.debian:
+       * debian/rules:
+       Updated Debian packaging.
+
+2004-09-30  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcbext.h:
+       * src/xcb_in.c:
+       * src/client-c.xcb:
+       Renamed XCBWaitReply to XCBWaitForReply for new API.
+
+2004-09-30  Jamey Sharp  <jamey@minilop.net>
+
+       * src/Makefile.am:
+       Fix build failure when compiling tests.
+
+2004-09-29  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb.h.m4:
+       * src/xcb_in.c:
+       Added XCBPollForEvent function from new API.
+
+2004-09-29  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb.h.m4:
+       * src/xcbext.h:
+       * src/client-c.xcb:
+       * src/xcb_ext.c:
+       Update the extension cache for its new API. The
+       optimizations that this API enables are not yet
+       implemented, but the current implementation should
+       at least function correctly.
+
+2004-09-29  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_util.c:
+       * src/xcbext.h:
+       Oops, XCBPopcount was supposed to change argument
+       types too.
+
+2004-09-29  Jamey Sharp  <jamey@minilop.net>
+
+       * src/client-c.xcb:
+       * src/xcb_util.c:
+       * src/xcbext.h:
+       Renamed XCBOnes to XCBPopcount as per new API spec.
+
+2004-09-29  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcbext.h:
+       * src/xcb.h.m4:
+       * src/Makefile.am:
+       * src/client-c.xcb:
+       * src/xcb_in.c:
+       * src/xcb_out.c:
+       * src/xcb_util.c:
+       * src/xcb_xid.c:
+       Moved declarations that are only useful to protocol
+       implementations into a separate header file,
+       xcbext.h.
+
+2004-09-28  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcbint.h:
+       * src/xcb_conn.c:
+       Add internal sanity check macros for sequence
+       numbers, and invoke them every time _xcb_conn_wait
+       is entered.
+
+2004-09-28  Jamey Sharp  <jamey@minilop.net>
+
+       * src/client-c.xcb:
+       Allow LISTPARAMs to omit the length argument. When
+       generating C code, a LOCALPARAM is automatically
+       generated for the length if the length argument is
+       omitted.
+
+2004-08-13  Jamey Sharp  <jamey@minilop.net>
+
+       * configure.ac:
+       * src/Makefile.am:
+       * src/.cvsignore:
+       * src/check_all.c:
+       * src/check_suites.h:
+       * src/check_public.c:
+       Add the first unit tests for XCB. This adds a build
+       dependency on 'check'; I hope somebody will make it
+       more of a build recommendation.
+
+2004-08-13  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_conn.c:
+       Add a sanity check: assert() that _xcb_conn_wait
+       will not be re-entered within the same thread. This
+       turns out not to be true in some current buggy code.
+       Xlib re-enters from _XAsyncReplyHandler in
+       src/xcl/display.c; and the X Test Suite seems to
+       catch SIGABRT and continue running.
+
+2004-08-10  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_out.c:
+       I misread the BIG-REQUESTS specification. The long
+       length field needs to count itself too.
+
+2004-07-24  Jamey Sharp  <jamey@minilop.net>
+
+       * src/client-c.xcb:
+       Renamed functions that return new iterators to
+       *Iter, to avoid conflict with similar functions that
+       return arrays.
+
+       Deprecating ARRAYFIELD in favor of LISTFIELD, which
+       now generates both array and iterator accessors. You
+       get an array accessor as long as the element type is
+       fixed length; you get an interator accessor as long
+       as the base type has an iterator. You always get a
+       'Length' function.
+
+2004-07-24  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_auth.c:
+       Bart cleaned up some code that I made ugly, and
+       I'm fixing a warning that resulted from a static
+       function being created but not necessarily used.
+
+2004-07-07  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_xid.c:
+       OK, it might be a good idea to commit something
+       that compiles. I thought I'd tested this change...
+
+2004-07-06  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcbint.h:
+       * src/xcb_xid.c:
+       Added support for the XC-Misc extension's ability
+       to request more XIDs from the server when the
+       client runs out of them.
+
+2004-07-06  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb.h.m4:
+       * src/xcb_auth.c:
+       * src/xcb_util.c:
+       Removed XCBNextNonce, and the nonce parameter of
+       XCBGetAuthInfo, from the API. XCB can compute
+       that just fine without help from the application.
+
+2004-07-06  Jamey Sharp  <jamey@minilop.net>
+
+       * src/Makefile.am:
+       Importing part of patches, adding SYNC, by
+       Mikko Markus Torni <mikko.markus.torni@iki.fi>.
+       This needed better padding computation in XCB
+       before it could be implemented cleanly.
+
+2004-07-02  Jamey Sharp  <jamey@minilop.net>
+
+       * src/Makefile.am:
+       Importing part of patches, adding XC-MISC, by
+       Mikko Markus Torni <mikko.markus.torni@iki.fi>.
+
+2004-07-02  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb.h.m4:
+       * src/xcb_in.c:
+       Remove XCBEventQueueRemove and XCBEventQueueFind.
+       Their existence in the API constrains the
+       implementation, and they're not useful for real
+       code, like toolkits, anyway.
+
+2004-07-02  Jamey Sharp  <jamey@minilop.net>
+
+       * src/client-c.xcb:
+       * src/xcb.h.m4:
+       XCB headers are now compatible with C++ source.
+
+2004-07-02  Jamey Sharp  <jamey@minilop.net>
+
+       * src/client-c.xcb:
+       * src/xcb.h.m4:
+       Keith's fix for padding didn't quite work, despite
+       looking quite sensible at the time. Replaced
+       XCB_TYPE_CEIL with XCB_TYPE_PAD and made all the
+       iterators, lists, and arrays count the number of
+       bytes from the beginning of the current request.
+
+2004-07-02  Jamey Sharp  <jamey@minilop.net>
+
+       * src/xcb_out.c:
+       * src/xcbint.h:
+       Force a response from the server if we haven't seen
+       one in 65530 requests. If you don't do this, XCB
+       gets confused the next time it waits for a reply.
+
+2004-06-16  Keith Packard  <keithp@keithp.com>
+
+       * src/client-c.xcb:
+       * src/xcb.h.m4:
+       Must round datatype lengths to 4-byte boundary for
+       NEXTFIELD and End macros.  Created new XCB_TYPE_CEIL
+       macro for this purpose and used it in a couple of
+       places.  It is to be hoped that this represents all
+       of the locations that need changing...
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..54caf7c
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,229 @@
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
+Foundation, Inc.
+
+   This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory.  After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on.  Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+   Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+     Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..df93163
--- /dev/null
@@ -0,0 +1,6 @@
+SUBDIRS=src tests
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = xcb.pc
+
+EXTRA_DIST=xcb.pc.in
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..d68a142
--- /dev/null
@@ -0,0 +1,3 @@
+#! /bin/sh
+autoreconf -v --install || exit 1
+./configure "$@"
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..903eeed
--- /dev/null
@@ -0,0 +1,84 @@
+#                                               -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.57)
+AC_INIT([libXCB],
+        0.9,
+        [xcb@lists.freedesktop.org])
+AC_CONFIG_SRCDIR([xcb.pc.in])
+AM_INIT_AUTOMAKE([foreign dist-bzip2])
+
+dnl This ifdef has no useful effect prior to automake 1.9, but in 1.9
+dnl it allows the user to not have check.m4 installed.
+m4_ifdef([AM_PATH_CHECK],[
+AM_PATH_CHECK(0.8.2, [HAVE_CHECK=true], [HAVE_CHECK=false])
+])
+AM_CONDITIONAL(HAVE_CHECK, test x$HAVE_CHECK = xtrue)
+
+AC_CONFIG_HEADERS([src/config.h])
+
+AC_PROG_LIBTOOL
+AC_PROG_CC
+
+AC_PATH_PROG(XSLTPROC, xsltproc, no)
+if test "$XSLTPROC" = "no"; then
+   AC_MSG_ERROR([XCB requires xsltproc.])
+fi
+
+HTML_CHECK_RESULT=false
+if test x"$HAVE_CHECK" = xtrue; then
+       if test x"$XSLTPROC" != xno; then
+               HTML_CHECK_RESULT=true
+       fi
+fi
+AC_SUBST(HTML_CHECK_RESULT)
+
+# Checks for pkg-config packages
+PKG_CHECK_MODULES(XCBPROTO, xcb-proto >= 0.9)
+PKG_CHECK_MODULES(XPROTO, xproto)
+PKG_CHECK_MODULES(XAU, xau)
+
+# Find the xcb-proto protocol descriptions
+AC_MSG_CHECKING(XCBPROTO_XCBINCLUDEDIR)
+XCBPROTO_XCBINCLUDEDIR=`$PKG_CONFIG --variable=xcbincludedir xcb-proto`
+AC_MSG_RESULT($XCBPROTO_XCBINCLUDEDIR)
+AC_SUBST(XCBPROTO_XCBINCLUDEDIR)
+
+AC_HEADER_STDC
+AC_SEARCH_LIBS(gethostbyname, nsl)
+AC_SEARCH_LIBS(connect, socket)
+
+xcbincludedir='${includedir}/X11/XCB'
+AC_SUBST(xcbincludedir)
+
+AC_ARG_WITH(opt,
+AC_HELP_STRING([--with-opt],       [compile with reasonable optimizations])
+AC_HELP_STRING([--with-opt=FLAGS], [compile with specified FLAGS])
+AC_HELP_STRING([--with-opt=small], [compile for smallest code])
+AC_HELP_STRING([--with-opt=debug], [compile for debugging (default)]),
+[
+       case "$withval" in
+       yes)
+               optflags="-O3"
+               ;;
+       small)
+               optflags="-Os -fomit-frame-pointer -DNDEBUG"
+               ;;
+       no|debug)
+               optflags="-g"
+               ;;
+       *)
+               optflags="$withval"
+               ;;
+       esac
+])
+AC_CACHE_CHECK([what compiler optimizations to apply], [optflags], [optflags="-g"])
+AC_DEFINE(_XOPEN_SOURCE, 500, [Conform to Single Unix Specification.])
+CDEBUGFLAGS="$optflags -Wall -pedantic -Wpointer-arith \
+       -Wstrict-prototypes -Wmissing-declarations -Wnested-externs"
+AC_SUBST(CDEBUGFLAGS)
+
+AC_CONFIG_FILES([Makefile src/Makefile tests/Makefile])
+AC_CONFIG_FILES([xcb.pc])
+
+AC_OUTPUT
diff --git a/debian/.cvsignore b/debian/.cvsignore
new file mode 100644 (file)
index 0000000..cad8b05
--- /dev/null
@@ -0,0 +1,6 @@
+compat
+copyright
+fd.o-*
+stamp-*
+tmp
+files
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..148dd94
--- /dev/null
@@ -0,0 +1,41 @@
+libxcb0 (0.9-1pre2v4) unstable; urgency=low
+
+  pre2v1:
+    * Split into libxcb0 and libxcb0-dev.
+      * Change control file for new packages.
+      * Add install and dirs files for new packages.
+    * Update Build-Depends for renaming of fd.o-xau, fd.o-xproto, and
+      fd.o-xcb-proto.
+    * Remove fd.o prefix from package name.
+    * Change Maintainer to xcb@lists.freedesktop.org, move myself to
+      Uploaders, and add Jamey Sharp to Uploaders.  Update copyright.debian
+      accordingly.
+    * Add Bugs field pointing to xcb@lists.freedesktop.org.
+    * Update homepage URL in description and copyright.debian to
+      http://xcb.freedesktop.org, and put it in a Homepage: field in the
+      description.
+
+  pre2v2:
+    * Add libxcb0-dbg package.
+  
+  pre2v3:
+    * New upstream snapshot.
+
+  pre2v4:
+    * New upstream snapshot.
+
+ -- Josh Triplett <josh@freedesktop.org>  Tue, 17 May 2005 12:53:53 -0700
+
+fd.o-xcb (0.9-1) unstable; urgency=low
+
+  * New version using XSLT; works with XML descriptions in xcb-proto 0.9.
+  * Updated Debian packaging.
+
+ -- Josh Triplett <josh@freedesktop.org>  Fri, 29 Oct 2004 15:11:09 -0700
+
+fd.o-xcb (0.8-1) unstable; urgency=low
+
+  * Initial Release.
+
+ -- Jamey Sharp <sharpone@debian.org>  Thu, 18 Mar 2004 00:09:03 -0800
+
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..33c61c0
--- /dev/null
@@ -0,0 +1,56 @@
+Source: libxcb0
+Priority: optional
+Maintainer: XCB Developers <xcb@lists.freedesktop.org>
+Uploaders: Jamey Sharp <sharpone@debian.org>, Josh Triplett <josh@freedesktop.org>
+Build-Depends: x-dev, libxau-dev, xcb-proto, cdbs, debhelper (>= 4.1.76), pkg-config, autoconf, automake1.9 | automaken, libtool, xsltproc, check, binutils (>= 2.12.90.0.9)
+Build-Conflicts: automake1.4, automake1.5, automake1.6
+Standards-Version: 3.6.1
+Bugs: mailto:xcb@lists.freedesktop.org
+
+Package: libxcb0
+Section: libs
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: X C Binding
+ Xlib has been the standard C binding for the X Window System protocol for
+ many years now. It is an excellent piece of work, but there are applications
+ for which it is not ideal. XCB builds on nearly two decades of experience
+ with X specifically and software engineering in general in an effort to
+ replace the aging Xlib code base.
+ .
+ This package contains the library files needed to run software using
+ XCB.
+ .
+ Homepage: http://xcb.freedesktop.org
+
+Package: libxcb0-dev
+Section: libdevel
+Architecture: any
+Depends: libxcb0 (= ${Source-Version}), x-dev
+Description: X C Binding, development files
+ Xlib has been the standard C binding for the X Window System protocol for
+ many years now. It is an excellent piece of work, but there are applications
+ for which it is not ideal. XCB builds on nearly two decades of experience
+ with X specifically and software engineering in general in an effort to
+ replace the aging Xlib code base.
+ .
+ This package contains the header and library files needed to build software
+ using XCB.
+ .
+ Homepage: http://xcb.freedesktop.org
+
+Package: libxcb0-dbg
+Section: libdevel
+Architecture: any
+Depends: libxcb0 (= ${Source-Version})
+Description: X C Binding, debugging symbols
+ Xlib has been the standard C binding for the X Window System protocol for
+ many years now. It is an excellent piece of work, but there are applications
+ for which it is not ideal. XCB builds on nearly two decades of experience
+ with X specifically and software engineering in general in an effort to
+ replace the aging Xlib code base.
+ .
+ This package contains the debugging symbols associated with libxcb0. gdb will
+ automatically use these symbols when debugging libxcb0.
+ .
+ Homepage: http://xcb.freedesktop.org
diff --git a/debian/copyright.debian b/debian/copyright.debian
new file mode 100644 (file)
index 0000000..7cd330a
--- /dev/null
@@ -0,0 +1,12 @@
+This package was debianized by Jamey Sharp <sharpone@debian.org> on
+Thu, 18 Mar 2004 00:48:42 -0800, and later updated by Josh Triplett
+<josh@freedesktop.org>.  The package is co-maintained by the XCB developers
+via the XCB mailing list <xcb@lists.freedesktop.org>.
+
+It was downloaded from http://xcb.freedesktop.org.
+
+Upstream Authors: Jamey Sharp <sharpone@debian.org>
+                  Josh Triplett <josh@freedesktop.org>
+
+Copyright:
+
diff --git a/debian/libxcb0-dev.dirs b/debian/libxcb0-dev.dirs
new file mode 100644 (file)
index 0000000..4418816
--- /dev/null
@@ -0,0 +1,2 @@
+usr/lib
+usr/include
diff --git a/debian/libxcb0-dev.install b/debian/libxcb0-dev.install
new file mode 100644 (file)
index 0000000..5ab44bc
--- /dev/null
@@ -0,0 +1,5 @@
+usr/X11R6/include/X11/*
+usr/lib/lib*.a
+usr/lib/lib*.so
+usr/lib/pkgconfig/*
+usr/lib/*.la
diff --git a/debian/libxcb0.dirs b/debian/libxcb0.dirs
new file mode 100644 (file)
index 0000000..6845771
--- /dev/null
@@ -0,0 +1 @@
+usr/lib
diff --git a/debian/libxcb0.install b/debian/libxcb0.install
new file mode 100644 (file)
index 0000000..d0dbfd1
--- /dev/null
@@ -0,0 +1 @@
+usr/lib/lib*.so.*
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..e81cbea
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/make -f
+
+DEB_DH_INSTALL_SOURCEDIR=debian/tmp
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/class/autotools.mk
+
+DEB_CONFIGURE_EXTRA_FLAGS = --with-opt
+DEB_CONFIGURE_INCLUDEDIR = "\$${prefix}/X11R6/include"
+DEB_DH_STRIP_ARGS=--dbg-package=libxcb0
+
+debian/stamp-autotools-files:
+       autoreconf -v --install
+       touch debian/stamp-autotools-files
+
+debian/copyright: debian/copyright.debian COPYING
+       cat $+ > $@
+
+clean::
+       -rm -f debian/copyright
+
+common-install-prehook-arch common-install-prehook-indep:: debian/copyright
diff --git a/doc/tutorial/index.html b/doc/tutorial/index.html
new file mode 100755 (executable)
index 0000000..ac6e502
--- /dev/null
@@ -0,0 +1,3772 @@
+<!DOCTYPE html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+
+<head>
+  <title>Basic Graphics Programming With The XCB Library</title>
+  <link href="xcb.css" rel="stylesheet" type="text/css" />
+</head>
+
+<body>
+  <div class="title">
+    Basic Graphics Programming With The XCB Library
+  </div>
+  <div class="toc">
+  <ol>
+    <li><a class="section" href="#intro">Introduction</a></li>
+    <li><a class="section" href="#Xmodel">The client and server model of the X window system</a></li>
+    <li><a class="section" href="#asynch">GUI programming: the asynchronous model</a></li>
+    <li><a class="section" href="#notions">Basic XCB notions</a></li>
+      <ol>
+        <li><a class="subsection" href="#conn">The X Connection</a></li>
+       <li><a class="subsection" href="#requestsreplies">Requests and replies: the Xlib killers</a></li>
+       <li><a class="subsection" href="#gc">The Graphics Context</a></li>
+       <li>Object handles</li>
+       <li>Memory allocation for XCB structures</li>
+       <li><a class="subsection" href="#events">Events</a></li>
+      </ol>
+    <li><a class="section" href="#use">Using XCB-based programs</a></li>
+      <ol>
+        <li><a class="subsection" href="#inst">Installation of XCB</a></li>
+       <li><a class="subsection" href="#comp">Compiling XCB-based programs</a></li>
+      </ol>
+    <li><a class="section" href="#openconn">Opening and closing the connection to an X server</a></li>
+    <li><a class="section" href="#screen">Checking basic information about a connection</a></li>
+    <li><a class="section" href="#helloworld">Creating a basic window - the "hello world" program</a></li>
+    <li><a class="section" href="#drawing">Drawing in a window</a></li>
+      <ol>
+        <li><a class="subsection" href="#allocgc">Allocating a Graphics Context</a></li>
+        <li><a class="subsection" href="#changegc">Changing the attributes of a Graphics Context</a></li>
+       <li><a class="subsection" href="#drawingprim">Drawing primitives: point, line, box, circle,...</a></li>
+      </ol>
+    <li><a class="section" href="#xevents">X Events</a></li>
+      <ol>
+        <li><a class="subsection" href="#register">Registering for event types using event masks</a></li>
+       <li><a class="subsection" href="#loop">Receiving events: writing the events loop</a></li>
+       <li><a class="subsection" href="#expose">Expose events</a></li>
+       <li><a class="subsection" href="#userinput">Getting user input</a></li>
+         <ol>
+           <li><a class="subsubsection" href="#mousepressrelease">Mouse button press and release events</a></li>
+           <li><a class="subsubsection" href="#mousemvnt">Mouse movement events</a></li>
+           <li><a class="subsubsection" href="#mouseenter">Mouse pointer enter and leave events</a></li>
+           <li><a class="subsubsection" href="#focus">The keyboard focus</a></li>
+           <li><a class="subsubsection" href="#keypress">Keyboard press and release events</a></li>
+         </ol>
+       <li><a class="subsection" href="#eventex">X events: a complete example</a></li>
+      </ol>
+    <li><a class="section" href="#font">Handling text and fonts</a></li>
+      <ol>
+        <li><a class="subsection" href="#fontstruct">The Font structure</a></li>
+       <li>Loading a Font</li>
+       <li>Assigning a Font to a Graphic Context</li>
+       <li>Drawing text in a window</li>
+      </ol>
+    <li>Windows hierarchy</li>
+      <ol>
+       <li>Root, parent and child windows</li>
+       <li>Events propagation</li>
+      </ol>
+    <li><a class="section" href="#wm">Interacting with the window manager</a></li>
+      <ol>
+       <li><a class="subsection" href="#wmprop">Window properties</a></li>
+       <li><a class="subsection" href="#wmname">Setting the window name and icon name</a></li>
+       <li>Setting preferred window size(s)</li>
+       <li>Setting miscellaneous window manager hints</li>
+       <li>Setting an application's icon</li>
+      </ol>
+    <li><a class="section" href="#winop">Simple window operations</a></li>
+      <ol>
+       <li><a class="subsection" href="#winmap">Mapping and un-mapping a window</a></li>
+       <li><a class="subsection" href="#winconf">Configuring a window</a></li>
+       <li><a class="subsection" href="#winmove">Moving a window around the screen</a></li>
+       <li><a class="subsection" href="#winsize">Resizing a window</a></li>
+       <li><a class="subsection" href="#winstack">Changing windows stacking order: raise and lower</a></li>
+       <li>Iconifying and de-iconifying a window</li>
+       <li><a class="subsection" href="#wingetinfo">Getting informations about a window</a></li>
+      </ol>
+    <li><a class="section" href="#usecolor">Using colors to paint the rainbow</a></li>
+      <ol>
+       <li><a class="subsection" href="#colormap">Color maps</a></li>
+       <li><a class="subsection" href="#colormapalloc">Allocating and freeing Color Maps</a></li>
+       <li><a class="subsection" href="#alloccolor">Allocating and freeing a color entry</a></li>
+       <li>Drawing with a color</li>
+      </ol>
+    <li><a class="section" href="#pixmaps">X Bitmaps and Pixmaps</a></li>
+      <ol>
+       <li><a class="subsection" href="#pixmapswhat">What is a X Bitmap ? An X Pixmap ?</a></li>
+       <li>Loading a bitmap from a file</li>
+       <li>Drawing a bitmap in a window</li>
+       <li><a class="subsection" href="#pixmapscreate">Creating a pixmap</a></li>
+       <li><a class="subsection" href="#pixmapsdraw">Drawing a pixmap in a window</a></li>
+       <li><a class="subsection" href="#pixmapsfree">Freeing a pixmap</a></li>
+      </ol>
+    <li>Messing with the mouse cursor</li>
+      <ol>
+       <li>Creating and destroying a mouse cursor</li>
+       <li>Setting a window's mouse cursor</li>
+      </ol>
+    <li><a class="subsection" href="#translation">Translation of basic Xlib functions and macros</a></li>
+      <ol>
+        <li><a class="subsection" href="#displaystructure">Members of the Display structure</a></li>
+          <ol>
+            <li><a class="subsection" href="#ConnectionNumber">ConnectionNumber</a></li>
+            <li><a class="subsection" href="#DefaultScreen">DefaultScreen</a></li>
+            <li><a class="subsection" href="#QLength">QLength</a></li>
+            <li><a class="subsection" href="#ScreenCount">ScreenCount</a></li>
+            <li><a class="subsection" href="#ServerVendor">ServerVendor</a></li>
+            <li><a class="subsection" href="#ProtocolVersion">ProtocolVersion</a></li>
+            <li><a class="subsection" href="#ProtocolRevision">ProtocolRevision</a></li>
+            <li><a class="subsection" href="#VendorRelease">VendorRelease</a></li>
+            <li><a class="subsection" href="#DisplayString">DisplayString</a></li>
+            <li><a class="subsection" href="#BitmapUnit">BitmapUnit</a></li>
+            <li><a class="subsection" href="#BitmapBitOrder">BitmapBitOrder</a></li>
+            <li><a class="subsection" href="#BitmapPad">BitmapPad</a></li>
+            <li><a class="subsection" href="#ImageByteOrder">ImageByteOrder</a></li>
+          </ol>
+        <li><a class="subsection" href="#screenofdisplay">ScreenOfDisplay related functions</a></li>
+          <ol>
+            <li><a class="subsection" href="#ScreenOfDisplay">ScreenOfDisplay</a></li>
+            <li><a class="subsection" href="#DefaultScreenOfDisplay">DefaultScreenOfDisplay</a></li>
+            <li><a class="subsection" href="#RootWindow">RootWindow / RootWindowOfScreen</a></li>
+            <li><a class="subsection" href="#DefaultRootWindow">DefaultRootWindow</a></li>
+            <li><a class="subsection" href="#DefaultVisual">DefaultVisual / DefaultVisualOfScreen</a></li>
+            <li><a class="subsection" href="#DefaultGC">DefaultGC / DefaultGCOfScreen</a></li>
+            <li><a class="subsection" href="#BlackPixel">BlackPixel / BlackPixelOfScreen</a></li>
+            <li><a class="subsection" href="#WhitePixel">WhitePixel / WhitePixelOfScreen</a></li>
+            <li><a class="subsection" href="#DisplayWidth">DisplayWidth / WidthOfScreen</a></li>
+            <li><a class="subsection" href="#DisplayHeight">DisplayHeight / HeightOfScreen</a></li>
+            <li><a class="subsection" href="#DisplayWidthMM">DisplayWidthMM / WidthMMOfScreen</a></li>
+            <li><a class="subsection" href="#DisplayHeightMM">DisplayHeightMM / HeightMMOfScreen</a></li>
+            <li><a class="subsection" href="#DisplayPlanes">DisplayPlanes / DefaultDepth / DefaultDepthOfScreen / PlanesOfScreen</a></li>
+            <li><a class="subsection" href="#DefaultColormap">DefaultColormap / DefaultColormapOfScreen</a></li>
+            <li><a class="subsection" href="#MinCmapsOfScreen">MinCmapsOfScreen</a></li>
+            <li><a class="subsection" href="#MaxCmapsOfScreen">MaxCmapsOfScreen</a></li>
+            <li><a class="subsection" href="#DoesSaveUnders">DoesSaveUnders</a></li>
+            <li><a class="subsection" href="#DoesBackingStore">DoesBackingStore</a></li>
+            <li><a class="subsection" href="#EventMaskOfScreen">EventMaskOfScreen</a></li>
+          </ol>
+        <li><a class="subsection" href="#misc">Miscellaneaous macros</a></li>
+          <ol>
+            <li><a class="subsection" href="#DisplayOfScreen">DisplayOfScreen</a></li>
+            <li><a class="subsection" href="#DisplayCells">DisplayCells / CellsOfScreen</a></li>
+          </ol>
+      </ol>
+  </ol>
+  </div>
+  <div class="section">
+    <ol>
+      <li class="title"><a name="intro">Introduction</a></li>
+      <p>
+      This tutorial is based on the
+      <a href="http://users.actcom.co.il/~choo/lupg/tutorials/xlib-programming/xlib-programming.html">Xlib Tutorial</a>
+      written by <a href="mailto:choor@atcom.co.il">Guy Keren</a>. The
+      author allowed me to take some parts of his text, mainly the text which
+      deals with the X Windows generality.
+      </p>
+      <p>
+      This tutorial is intended to people who want to start to program
+      with the <a href="http://xcb.freedesktop.org">XCB</a>
+      library. As for the <a href="http://tronche.com/gui/x/xlib/introduction">Xlib</a>
+      library, it is useless and a real X 
+      programmer should use a much higher level of abstraction, such
+      as using Motif,
+      <a href="http://www.lesstif.org">LessTiff</a>,
+      <a href="http://www.gtk.org">GTK</a>,
+      <a href="http://www.trolltech.com">QT</a> or
+      <a href="http://www.enlightenment.org">EWL</a>. However,
+      we need to start somewhere. More than this, knowing how things
+      work down below is never a bad idea.
+      </p>
+      <p>
+      After reading this tutorial, one should be able to write very
+      simple graphical programs, but not programs with a descent user
+      interface. For such programs, one of the previously mentioned
+      library should be used.
+      </p>
+      <p>
+      But what is XCB ? Xlib has been
+      the standard C binding for the <a href="http://www.xfree86.org">X
+      Window System</a> protocol for many years now. It is an
+      excellent piece of work, but there are applications for which it
+      is not ideal, for example
+      <ul>
+        <li><b>Small platforms</b>: Xlib is a large piece of code, and
+       it's difficult to make it smaller</li>
+        <li><b>Latency hiding</b>: Xlib requests requiring a reply are
+       effectively synchronous: they block until the reply appears,
+       whether the result is needed immediately or not.</li>
+       <li><b>Direct access to the protocol</b>: Xlib does quite a
+       bit of caching, layering, and similar optimizations. While this
+       is normally a feature, it makes it difficult to simply emit
+       specified X protocol requests and process specific
+       responses.</li>
+       <li><b>Threaded applications</b>: While Xlib does attempt to
+       support multithreading, the API makes this difficult and
+       error-prone.</li>
+       <li><b>New extensions</b>: The Xlib infrastructure provides
+       limited support for the new creation of X extension client side
+       code.</li>
+      </ul>
+      </p>
+      <p>
+      For these reasons, among others, XCB, an X C binding, has been
+      designed to solve the above problems and thus provide a base for
+      <ul>
+        <li>Toolkit implementation.</li>
+       <li>Direct protocol-level programming.</li>
+       <li>Lightweight emulation of commonly used portions of the
+       Xlib API (in progress)</li>
+      </ul>
+      </p>
+      <p></p>
+      <li class="title"><a name="Xmodel">The client and server model of the X window system</a></li>
+      <p>
+      The X Window System was developed with one major goal:
+      flexibility. The idea was that the way things look is one thing,
+      but the way things work is another matter. Thus, the lower
+      levels provide the tools required to draw windows, handle user
+      input, allow drawing graphics using colors (or black and white
+      screens), etc. To this point, a decision was made to separate
+      the system into two parts. A client that decides what to do, and
+      a server that actually draws on the screen and reads user input
+      in order to send it to the client for processing.
+      </p>
+      <p>
+      This model is the complete opposite of what is used to when
+      dealing with clients and servers. In our case, the user seats
+      near the machine controlled by the server, while the client
+      might be running on a remote machine. The server controls the
+      screens, mouse and keyboard. A client may connect to the server,
+      request that it draws a window (or several windows), and ask the
+      server to send it any input the user sends to these
+      windows. Thus, several clients may connect to a single X server
+      (one might be running an mail software, one running a WWW
+      browser, etc). When input is sent by the user to some window,
+      the server sends a message to the client controlling this window
+      for processing. The client decides what to do with this input,
+      and sends the server requests for drawing in the window.
+      </p>
+      <p>
+      The whole session is carried out using the X message
+      protocol. This protocol was originally carried over the TCP/IP
+      protocol suite, allowing the client to run on any machine
+      connected to the same network that the server is. Later on, the
+      X servers were extended to allow clients running on the local
+      machine with more optimized access to the server (note that an X
+      protocol message may be several hundreds of KB in size), such as
+      using shred memory, or using Unix domain sockets (a method for
+      creating a logical channel on a Unix system between two processors).
+      </p>
+      <li class="title"><a name="asynch">GUI programming: the asynchronous model</a></li>
+      <p>
+      Unlike conventional computer programs, that carry some serial
+      nature, a GUI program usually uses an asynchronous programming
+      model, also known as "event-driven programming". This means that
+      that program mostly sits idle, waiting for events sent by the X
+      server, and then acts upon these events. An event may say "The
+      user pressed the 1st button mouse in spot (x,y)", or "The window
+      you control needs to be redrawn". In order for the program to e
+      responsive to the user input, as well as to refresh requests, it
+      needs to handle each event in a rather short period of time
+      (e.g. less that 200 milliseconds, as a rule of thumb).
+      </p>
+      <p>
+      This also implies that the program may not perform operations
+      that might take a long time while handling an event (such as
+      opening a network connection to some remote server, or
+      connecting to a database server, or even performing a long file
+      copy operation). Instead, it needs to perform all these
+      operations in an asynchronous manner. This may be done by using
+      various asynchronous models to perform the longish operations,
+      or by performing them in a different process or thread.
+      </p>
+      <p>
+      So the way a GUI program looks is something like that:
+      <ol>
+        <li>Perform initialization routines.</li>
+       <li>Connect to the X server.</li>
+       <li>Perform X-related initialization.</li>
+       <li>While not finished:</li>
+         <ol>
+           <li>Receive the next event from the X server.</li>
+           <li>Handle the event, possibly sending various drawing
+           requests to the X server.</li>
+           <li>If the event was a quit message, exit the loop.</li>
+         </ol>
+       <li>Close down the connection to the X server. </li>
+       <li>Perform cleanup operations.</li>
+      </ol>
+      </p>
+      <p></p>
+      <li class="title"><a name="notions">Basic XCB notions</a></li>
+      <p>
+      XCB has been created to eliminate the needs of
+      programs to actually implement the X protocol layer. This
+      library gives a program a very low-level access to any X
+      server. Since the protocol is standardized, a client using any
+      implementation of XCB may talk with any X server (the same
+      occurs for Xlib, of course). We now give a brief description of
+      the basic XCB notions. They will be detailed later.
+      </p>
+      <ol>
+        <li class="subtitle"><a name="conn">The X Connection</a></li>
+       <p>
+       The major notion of using XCB is the X Connection. This is a
+       structure representing the connection we have open with a
+       given X server. It hides a queue of messages coming from the
+       server, and a queue of pending requests that our client
+       intends to send to the server. In XCB, this structure is named
+       'XCBConnection'. When we open a connection to an X server, the
+       library returns a pointer to such a structure. Later, we
+       supply this pointer to any XCB function that should send
+       messages to the X server or receive messages from this server.
+       </p>
+        <li class="subtitle"><a name="requestsreplies">Requests and
+        replies: the Xlib killers</a></li>
+       <p>
+        To ask informations to the X server, we have to make a request
+        and ask for a reply. With Xlib, these two tasks are
+        automatically done: Xlib locks the system, sends a request,
+        waits for a reply from the X server and unlocks. This is
+        annoying, especially if one makes a lot of requests to the X
+        server. Indeed, Xlib has to wait for the end of a reply
+        before asking for the next request (because of the locks that
+        Xlib sends). For example, here is a time-line of N=4
+        requests/replies with Xlib, with a round-trip latency
+        <b>T_round_trip</b> that is 5 times long as the time required
+        to write or read a request/reply (<b>T_write/T_read</b>):
+       </p>
+       <pre class="text">
+  W-----RW-----RW-----RW-----R
+</pre>
+        <ul>
+          <li>W: Writing request</li>
+          <li>-: Stalled, waiting for data</li>
+          <li>R: Reading reply</li>
+        </ul>
+        <p>
+        The total time is N * (T_write + T_round_trip + T_read).
+        </p>
+        <p>
+        With XCB, we can suppress most of the round-trips as the
+        requests and the replies are not locked. We usually send a
+        request, then XCB returns to us a <b>cookie</b>, which is an
+        identifier. Then, later, we ask for a reply using this
+        <b>cookie</b> and XCB returns a
+        pointer to that reply. Hence, with XCB, we can send a lot of
+        requests, and later in the program, ask for all the replies
+        when we need them. Here is the time-line for 4
+        requests/replies when we use this property of XCB:
+        </p>
+       <pre class="text">
+  WWWW--RRRR
+</pre>
+        <p>
+        The total time is N * T_write + max (0, T_round_trip - (N-1) *
+        T_write) + N * T_read. Which can be considerably faster than
+        all those Xlib round-trips.
+        </p>
+        <p>
+        Here is a program that computes the time to create 500 atoms
+        with Xlib and XCB. It shows the Xlib way, the bad XCB way
+        (which is similar to Xlib) and the good XCB way. On my
+        computer, XCB is 25 times faster than Xlib.
+        </p>
+      <pre class="code">
+#include &lt;stdlib.h&gt;
+#include &lt;stdio.h&gt;
+#include &lt;string.h&gt;
+#include &lt;sys/time.h&gt;
+
+#include &lt;X11/XCB/xcb.h&gt;
+
+#include &lt;X11/Xlib.h&gt;
+
+double
+get_time(void)
+{
+  struct timeval timev;
+  
+  gettimeofday(&timev, NULL);
+
+  return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
+}
+
+int
+main ()
+{
+  XCBConnection       *c;
+  XCBATOM             *atoms;
+  XCBInternAtomCookie *cs;
+  char               **names;
+  int                  count;
+  int                  i;
+  double               start;
+  double               end;
+  double               diff;
+
+  /* Xlib */
+  Display *disp;
+  Atom    *atoms_x;
+  double   diff_x;
+
+  c = XCBConnectBasic ();
+
+  count = 500;
+  atoms = (XCBATOM *)malloc (count * sizeof (atoms));
+  names = (char **)malloc (count * sizeof (char *));
+
+  /* init names */
+  for (i = 0; i &lt; count; ++i)
+    {
+      char buf[100];
+
+      sprintf (buf, "NAME%d", i);
+      names[i] = strdup (buf);
+    }
+
+  /* bad use */
+  start = get_time ();
+
+  for (i = 0; i &lt; count; ++i)
+    atoms[i] = XCBInternAtomReply (c, 
+                                   XCBInternAtom (c,
+                                                  0,
+                                                  strlen(names[i]),
+                                                  names[i]),
+                                   NULL)->atom;
+
+  end = get_time ();
+  diff = end - start;
+  printf ("bad use time  : %f\n", diff);
+
+  /* good use */
+  start = get_time ();
+
+  cs = (XCBInternAtomCookie *) malloc (count * sizeof(XCBInternAtomCookie));
+  for(i = 0; i &lt; count; ++i)
+    cs[i] = XCBInternAtom (c, 0, strlen(names[i]), names[i]);
+
+  for(i = 0; i &lt; count; ++i)
+    {
+      XCBInternAtomRep *r;
+
+      r = XCBInternAtomReply(c, cs[i], 0);
+      if(r)
+        atoms[i] = r->atom;
+      free(r);
+    }
+
+  end = get_time ();
+  printf ("good use time : %f\n", end - start);
+  printf ("ratio         : %f\n", diff / (end - start));
+  diff = end - start;
+
+  /* free var */
+  for (i = 0; i &lt; count; ++i)
+    {
+      free (names[i]);
+    }
+  free (atoms);
+  free (cs);
+
+  XCBDisconnect (c);
+
+  /* Xlib */
+  disp = XOpenDisplay (getenv("DISPLAY"));
+
+  atoms_x = (Atom *)malloc (count * sizeof (atoms_x));
+
+  start = get_time ();
+
+  for (i = 0; i &lt; count; ++i)
+    atoms_x[i] = XInternAtom(disp, names[i], 0);
+
+  end = get_time ();
+  diff_x = end - start;
+  printf ("Xlib use time : %f\n", diff_x);
+  printf ("ratio         : %f\n", diff_x / diff);
+
+  free (atoms_x);
+  free (names);
+
+  XCloseDisplay (disp);
+  
+  return 1;
+}
+</pre>
+        <li class="subtitle"><a name="gc">The Graphic Context</a></li>
+       <p>
+       When we perform various drawing operations (graphics, text,
+       etc), we may specify various options for controlling how the
+       data will be drawn (what foreground and background colors to
+       use, how line edges will be connected, what font to use when
+       drawing some text, etc). In order to avoid the need to supply
+       hundreds of parameters to each drawing function, a graphical
+       context structure is used. We set the various drawing options
+       in this structure, and then, we pass a pointer to this
+       structure to any drawing routines. This is rather handy, as we
+       often need to perform several drawing requests with the same
+       options. Thus, we would initialize a graphical context, set
+       the desired options, and pass this structure to all drawing
+       functions.
+       </p>
+        <p>
+        Note that graphic contexts have no client-side structure in
+        XCB, they're just XIDs. Xlib has a client-side structure
+        because it caches the GC contents so it can avoid making
+        redundant requests, but of course XCB doesn't do that.
+        </p>
+        <li class="subtitle"><a name="events">Events</a></li>
+       <p>
+       A structure is used to pass events received from the X
+       server. XCB supports exactly the events specified in the
+       protocol (33 events). This structure contains the type
+       of event received, as well as the data associated with the
+       event (e.g. position on the screen where the event was
+       generated, mouse button associated with the event, region of
+       the screen associated with a "redraw" event, etc). The way to
+       read the event's data epends on the event type.
+       </p>
+      </ol>
+      <p></p>
+      <li class="title"><a name="use">Using XCB-based programs</a></li>
+      <p></p>
+      <ol>
+        <li class="subtitle"><a name="inst">Installation of XCB</a></li>
+       <p>
+       To build XCB from source, you need to have installed at
+       least:
+       </p>
+       <ul>
+         <li>pkgconfig 0.15.0</li>
+         <li>automake 1.7</li>
+         <li>autoconf 2.50</li>
+         <li><a href="http://www.check.org">check</a></li>
+         <li><a href="http://xmlsoft.org/XSLT/">xsltproc</a></li>
+       </ul>
+       <p>
+       You have to checkout in CVS the following modules:
+       </p>
+       <ul>
+          <li>Xproto from xlibs</li>
+         <li>Xau from xlibs</li>
+         <li>xcb-proto</li>
+         <li>xcb</li>
+       </ul>
+       <p>
+       Note that Xproto and xcb-proto exist only to install header
+       files, so typing 'make' or 'make all' will produce the message
+       "Nothing to be done for 'all'". That's normal.
+       </p>
+       <li class="subtitle"><a name="comp">Compiling XCB-based programs</a></li>
+       <p>
+       Compiling XCB-based programs requires linking them with the XCB
+       library. This is easily done thanks to pkgconfig:
+       </p>
+       <pre class="text">
+gcc -Wall prog.c -o prog `pkg-config --cflags --libs xcb`
+</pre>
+      </ol>
+      <li class="title"><a name="openconn">Opening and closing the connection to an X server</a></li>
+      <p>
+      An X program first needs to open the connection to the X
+      server. There is a function that opens a connection. It requires
+      the display name, or NULL. In the latter case, the display name
+      will be the one in the environment variable DISPLAY.
+      </p>
+      <pre class="code">
+XCBConnection *XCBConnect (const char *displayname,
+                           int        *screenp);
+</pre>
+      <p>
+      The second parameter returns the screen number used for the
+      connection. The returned structure describes an XCB connection
+      and is opaque. Here is how the connection can be opened:
+      </p>
+      <pre class="code">
+#include &lt;X11/XCB/xcb.h&gt;
+
+int
+main (int argc, char *argv[])
+{
+  XCBConnection *c;
+  
+  /* Open the connection to the X server. use the DISPLAY environment variable as the default display name */
+  c = XCBConnect (NULL, NULL);
+
+  return 1;
+}
+</pre>
+      <p>
+      To close a connection, it suffices to use:
+      </p>
+      <pre class="code">
+void XCBDisconnect (XCBConnection *c);
+</pre>
+      <div class="comp">
+        <div class="title">
+       Comparison Xlib/XCB
+       </div>
+       <div class="xlib">
+       <ul>
+         <li>XOpenDisplay ()</li>
+       </ul>
+       </div>
+       <div class="xcb">
+       <ul>
+         <li>XCBConnect ()</li>
+       </ul>
+       </div>
+       <div class="xlib">
+       <ul>
+         <li>XCloseDisplay ()</li>
+       </ul>
+       </div>
+       <div class="xcb">
+       <ul>
+         <li>XCBDisconnect ()</li>
+       </ul>
+       </div>
+      </div>
+      <p>
+      </p>
+      <li class="title"><a name="screen">Checking basic information about a connection</a></li>
+      <p>
+      Once we opened a connection to an X server, we should check some
+      basic informations about it: what screens it has, what is the
+      size (width and height) of the screen, how many colors it
+      supports (black and white ? grey scale ?, 256 colors ? more ?),
+      and so on. We get such informations from the XCBSCREEN
+      structure:
+      </p>
+      <pre class="code">
+typedef struct {
+    XCBWINDOW root;
+    XCBCOLORMAP default_colormap;
+    CARD32 white_pixel;
+    CARD32 black_pixel;
+    CARD32 current_input_masks;
+    CARD16 width_in_pixels;
+    CARD16 height_in_pixels;
+    CARD16 width_in_millimeters;
+    CARD16 height_in_millimeters;
+    CARD16 min_installed_maps;
+    CARD16 max_installed_maps;
+    XCBVISUALID root_visual;
+    BYTE backing_stores;
+    BOOL save_unders;
+    CARD8 root_depth;
+    CARD8 allowed_depths_len;
+} XCBSCREEN;
+</pre>
+      <p>
+      We could retrieve the first screen of the connection by using the
+      following function:
+      </p>
+      <pre class="code">
+XCBSCREENIter XCBConnSetupSuccessRepRootsIter (XCBConnSetupSuccessRep *R);
+</pre>
+      <p>
+      Here is a small program that shows how to use this function:
+      </p>
+      <pre class="code">
+#include &lt;stdio.h&gt;
+
+#include &lt;X11/XCB/xcb.h&gt;
+
+int
+main (int argc, char *argv[])
+{
+  XCBConnection *c;
+  XCBSCREEN     *screen;
+  int            screen_nbr;
+  XCBSCREENIter  iter;
+  
+  /* Open the connection to the X server. Use the DISPLAY environment variable */
+  c = XCBConnect (NULL, &screen_nbr);
+  
+  /* Get the screen #screen_nbr */
+  iter = XCBConnSetupSuccessRepRootsIter (XCBGetSetup (c));
+  for (; iter.rem; --screen_nbr, XCBSCREENNext (&iter))
+    if (screen_nbr == 0)
+      {
+        screen = iter.data;
+        break;
+      }
+
+  printf ("\n");
+  printf ("Informations of screen %ld:\n", screen-&gt;root.xid);
+  printf ("  width.........: %d\n", screen-&gt;width_in_pixels);
+  printf ("  height........: %d\n", screen-&gt;height_in_pixels);
+  printf ("  white pixel...: %ld\n", screen-&gt;white_pixel);
+  printf ("  black pixel...: %ld\n", screen-&gt;black_pixel);
+  printf ("\n");
+
+  return 1;
+}
+</pre>
+      <li class="title"><a name="helloworld">Creating a basic window - the "hello world" program</a></li>
+      <p>
+      After we got some basic informations about our screen, we can
+      create our first window. In the X Window System, a window is
+      characterized by an Id. So, in XCB, a window is of type:
+      </p>
+      <pre class="code">
+typedef struct {
+    CARD32 xid;
+} XCBWINDOW;
+</pre>
+      <p>
+      We first ask for a new Id for our window, with this function:
+      </p>
+      <pre class="code">
+XCBWINDOW XCBWINDOWNew(XCBConnection *c);
+</pre>
+      <p>
+      Then, XCB supplies the following function to create new windows:
+      </p>
+      <pre class="code">
+XCBVoidCookie XCBCreateWindow (XCBConnection *c,             /* Pointer to the XCBConnection structure */
+                               CARD8          depth,         /* Depth of the screen */
+                               XCBWINDOW      wid,           /* Id of the window */
+                              XCBWINDOW      parent,        /* Id of an existing window that should be the parent of the new window */
+                              INT16          x,             /* X position of the top-left corner of the window (in pixels) */
+                              INT16          y,             /* Y position of the top-left corner of the window (in pixels) */
+                              CARD16         width,         /* Width of the window (in pixels) */
+                              CARD16         height,        /* Height of the window (in pixels) */
+                              CARD16         border_width,  /* Width of the window's border (in pixels) */
+                              CARD16         _class,
+                              XCBVISUALID    visual,
+                              CARD32         value_mask,
+                              const CARD32  *value_list);
+</pre>
+      <p>
+      The fact that we created the window does not mean that it will
+      be drawn on screen. By default, newly created windows are not
+      mapped on the screen (they are invisible). In order to make our
+      window visible, we use the function <span class="code">XCBMapWindow()</span>, whose
+      prototype is
+      </p>
+      <pre class="code">
+XCBVoidCookie XCBMapWindow (XCBConnection *c, XCBWINDOW window);
+</pre>
+      <p>
+      Finally, here is a small program to create a window of size
+      150x150 pixels, positioned at the top-left corner of the screen:
+      </p>
+      <pre class="code">
+#include &lt;unistd.h&gt;
+
+#include &lt;X11/XCB/xcb.h&gt;
+
+int
+main (int argc, char *argv[])
+{
+  XCBConnection *c;
+  XCBSCREEN     *screen;
+  XCBDRAWABLE    win;
+  
+  /* Open the connection to the X server */
+  c = XCBConnect (NULL, NULL);
+  
+  /* Get the first screen */
+  screen = XCBConnSetupSuccessRepRootsIter (XCBGetSetup (c)).data;
+
+  /* Ask for our window's Id */
+  win.window = XCBWINDOWNew(c);
+
+  /* Create the window */
+  XCBCreateWindow (c,                        /* Connection          */
+                  0,                        /* depth               */
+                  win.window,               /* window Id           */
+                  screen-&gt;root,             /* parent window       */
+                  0, 0,                     /* x, y                */
+                  150, 150,                 /* width, height       */
+                  10,                       /* border_width        */
+                  InputOutput,              /* class               */
+                  screen-&gt;root_visual,      /* visual              */
+                  0, NULL);                 /* masks, not used yet */
+
+  /* Map the window on the screen */
+  XCBMapWindow (c, win.window);
+
+  XCBSync (c, 0);
+  
+  pause ();
+
+  return 1;
+}
+</pre>
+      <p>
+      In this code, you see one more function - <span class="code">XCBSync()</span>, not explained
+      yet. It is used to flush all the pending requests. More
+      precisely, there are 2 functions that do such things. The first
+      one is <span class="code">XCBFlush()</span>:
+      </p>
+      <pre class="code">
+int XCBFlush (XCBConnection *c);
+</pre>
+      <p>
+      This function flushes all pending requests to the X server (much
+      like the <span class="code">fflush()</span> function is used to
+      flush standard output). The second function is 
+      <span class="code">XCBSync()</span>:
+      </p>
+      <pre class="code">
+int XCBSync(XCBConnection *c, XCBGenericError **e);
+</pre>
+      <p>
+      This functions also flushes all pending requests to the X
+      server, and then waits until the X server finishing processing
+      these requests. In a normal program, this will not be necessary
+      (we'll see why when we get to write a normal X program), but for
+      now, we put it there. 
+      </p>
+      <p>
+      The window that is created by the above code has a default
+      background (gray). This one can be set to a specific color,
+      thanks to the two last parameters of
+      <span class="code">XCBCreateWindow()</span>, which are not
+      described yet. See the subsections
+      <a href="#winconf">Configuring a window</a> or
+      <a href="#winconf">Registering for event types using event masks</a>
+      for exemples on how to use these parameters. In addition, as no
+      events are handled, you have to make a Ctrl-C to interrupt the
+      program.
+      </p>
+      <p>
+      <b>TODO</b>: one should tell what these functions return and
+      about the generic error
+      </p>
+      <div class="comp">
+        <div class="title">
+       Comparison Xlib/XCB
+       </div>
+       <div class="xlib">
+       <ul>
+         <li>XCreateWindow ()</li>
+       </ul>
+       </div>
+       <div class="xcb">
+       <ul>
+         <li>XCBWINDOWNew ()</li>
+         <li>XCBCreateWindow ()</li>
+       </ul>
+       </div>
+      </div>
+      <p></p>
+      <li class="title"><a name="drawing">Drawing in a window</a></li>
+      <p>
+      Drawing in a window can be done using various graphical
+      functions (drawing pixels, lines, rectangles, etc). In order to
+      draw in a window, we first need to define various general
+      drawing parameters (what line width to use, which color to draw
+      with, etc). This is done using a graphical context.
+      </p>
+      <ol>
+        <li class="subtitle"><a name="allocgc">Allocating a Graphics Context</a></li>
+        <p>
+       As we said, a graphical context defines several attributes to
+       be used with the various drawing functions. For this, we
+       define a graphical context. We can use more than one graphical
+       context with a single window, in order to draw in multiple
+       styles (different colors, different line widths, etc). In XCB,
+       a Graphics Context is, as a window, characterized by an Id:
+        </p>
+       <pre class="code">
+typedef struct {
+    CARD32 xid;
+} XCBGCONTEXT;
+</pre>
+        <p>
+        We first ask the X server to attribute an Id to our graphic
+       context with this function:
+        </p>
+       <pre class="code">
+XCBGCONTEXT XCBGCONTEXTNew (XCBConnection *c);
+</pre>
+        <p>
+        Then, we set the attributes of the graphic context with this function:
+        </p>
+       <pre class="code">
+XCBVoidCookie XCBCreateGC (XCBConnection *c,
+                           XCBGCONTEXT    cid,
+                          XCBDRAWABLE    drawable,
+                          CARD32         value_mask,
+                          const CARD32  *value_list);
+</pre>
+        <p>
+       We give now an example on how to allocate a graphic context
+       that specifies that each drawing functions that use it will
+       draw in foreground with a black color.
+        </p>              
+        <pre class="code">
+#include &lt;X11/XCB/xcb.h&gt;
+
+int
+main (int argc, char *argv[])
+{
+  XCBConnection *c;
+  XCBSCREEN     *screen;
+  XCBDRAWABLE    win;
+  XCBGCONTEXT    black;
+  CARD32         mask;
+  CARD32         value[1];
+  
+  /* Open the connection to the X server and get the first screen */
+  c = XCBConnect (NULL, NULL);
+  screen = XCBConnSetupSuccessRepRootsIter (XCBGetSetup (c)).data;
+
+  /* Create a black graphic context for drawing in the foreground */
+  win.window = screen-&gt;root;
+  black = XCBGCONTEXTNew (c);
+  mask = GCForeground;
+  value[0] = screen-&gt;black_pixel;
+  XCBCreateGC (c, black, win, mask, value);
+
+  return 1;
+}
+</pre>
+        <p>
+        Note should be taken regarding the role of "value_mask" and
+       "value_list" in the prototype of <span class="code">XCBCreateGC()</span>. Since a 
+       graphic context has many attributes, and since we often just
+       want to define a few of them, we need to be able to tell the
+       <span class="code">XCBCreateGC()</span> which attributes we
+       want to set. This is what the "value_mask" parameter is
+       for. We then use the "value_list" parameter to specify actual
+       values for the attribute we defined in "value_mask". Thus, for
+       each constant used in "value_list", we will use the matching
+       constant in "value_mask". In this case, we define a graphic
+       context with one attribute: when drawing (a point, a line,
+       etc), the foreground color will be black. The rest of the
+       attributes of this graphic context will be set to their
+       default values.
+        </p>
+       <p>
+       See the next Subsection for more details.
+       </p>
+        <div class="comp">
+          <div class="title">
+         Comparison Xlib/XCB
+         </div>
+         <div class="xlib">
+         <ul>
+           <li>XCreateGC ()</li>
+         </ul>
+         </div>
+         <div class="xcb">
+         <ul>
+           <li>XCBGCONTEXTNew ()</li>
+           <li>XCBCreateGC ()</li>
+         </ul>
+         </div>
+        </div>
+        <p></p>
+        <li class="subtitle"><a name="changegc">Changing the attributes of a Graphics Context</a></li>
+        <p>
+       Once we have allocated a Graphic Context, we may need to
+       change its attributes (for example, changing the foreground
+       color we use to draw a line, or changing the attributes of the
+       font we use to display strings. See Subsections Drawing with a
+       color and Assigning a Font to a Graphic Context). This is done
+       by using this function:
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBChangeGC (XCBConnection *c,           /* The XCB Connection */
+                           XCBGCONTEXT    gc,          /* The Graphic Context */
+                          CARD32         value_mask,  /* Components of the Graphic Context that have to be set */
+                          const CARD32  *value_list); /* Value as specified by value_mask */
+</pre>
+        <p>
+       The <span class="code">value_mask</span> parameter could take
+       these values:
+       </p>
+       <ul>
+         <li>GCFunction</li>
+         <li>GCPlaneMask</li>
+         <li>GCForeground</li>
+         <li>GCBackground</li>
+         <li>GCLineWidth</li>
+         <li>GCLineStyle</li>
+         <li>GCCapStyle</li>
+         <li>GCJoinStyle</li>
+         <li>GCFillStyle</li>
+         <li>GCFillRule</li>
+         <li>GCTile</li>
+         <li>GCStipple</li>
+         <li>GCTileStipXOrigin</li>
+         <li>GCTileStipYOrigin</li>
+         <li>GCFont</li>
+         <li>GCSubwindowMode</li>
+         <li>GCGraphicsExposures</li>
+         <li>GCClipXOrigin</li>
+         <li>GCClipYOrigin</li>
+         <li>GCClipMask</li>
+         <li>GCDashOffset</li>
+         <li>GCDashList</li>
+         <li>GCArcMode</li>
+       </ul>
+       <p>
+       It is possible to set several attributes at the same
+       time (for example setting the attributes of a font and the
+       color which will be used to display a string), by OR'ing these
+       values in <span class="code">value_mask</span>. Then
+       <span class="code">value_list</span> has to be an array which
+       lists the value for the respective attributes. See Subsection
+       Drawing with a color to have an example.
+       </p>
+       <p>
+       <b>TODO</b>: set the links of the 3 subsections, once they will
+       be written :)
+       </p>
+       <p>
+       <b>TODO</b>: give an example which sets several attributes.
+       </p>
+        <li class="subtitle"><a name="drawingprim">Drawing primitives: point, line, box, circle,...</a></li>
+        <p>
+       After we have created a Graphic Context, we can draw on a
+       window using this Graphic Context, with a set of XCB
+       functions, collectively called "drawing primitive". Let see
+       how they are used.
+       </p>
+       <p>
+       To draw a point, or several points, we use
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBPolyPoint (XCBConnection  *c,               /* The connection to the X server */
+                            BYTE            coordinate_mode, /* Coordinate mode, usually set to CoordModeOrigin */
+                           XCBDRAWABLE     drawable,        /* The drawable on which we want to draw the point(s) */
+                           XCBGCONTEXT     gc,              /* The Graphic Context we use to draw the point(s) */
+                           CARD32          points_len,      /* The number of points */
+                           const XCBPOINT *points);         /* An array of points */
+</pre>
+       <p>
+       The <span class="code">coordinate_mode</span> parameter
+       specifies the coordinate mode.  Available values are
+       </p>
+       <ul>
+         <li><span class="code">CoordModeOrigin</span></li>
+         <li><span class="code">CoordModePrevious</span></li>
+       </ul>
+       <p>
+       The <span class="code">XCBPOINT</span> type is just a
+       structure with two fields (the coordinates of the point):
+       </p>
+       <pre class="code">
+typedef struct {
+    INT16 x;
+    INT16 y;
+} XCBPOINT;
+</pre>
+        <p>
+       You could see an example in xpoints.c. <b>TODO</b> Set the link.
+       </p>
+       <p>
+       To draw a line, or a polygonal line, we use
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBPolyLine (XCBConnection  *c,               /* The connection to the X server */
+                           BYTE            coordinate_mode, /* Coordinate mode, usually set to CoordModeOrigin */
+                          XCBDRAWABLE     drawable,        /* The drawable on which we want to draw the line(s) */
+                          XCBGCONTEXT     gc,              /* The Graphic Context we use to draw the line(s) */
+                          CARD32          points_len,      /* The number of points in the polygonal line */
+                          const XCBPOINT *points);         /* An array of points */
+</pre>
+       <p>
+       This function will draw the line between the first and the
+       second points, then the line between the second and the third
+       points, and so on.
+       </p>
+       <p>
+       To draw a segment, or several segments, we use
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBPolySegment (XCBConnection    *c,              /* The connection to the X server */
+                              XCBDRAWABLE       drawable,       /* The drawable on which we want to draw the segment(s) */
+                             XCBGCONTEXT       gc,             /* The Graphic Context we use to draw the segment(s) */
+                             CARD32            segments_len,   /* The number of segments */
+                             const XCBSEGMENT *segments);      /* An array of segments */
+</pre>
+       <p>
+       The <span class="code">XCBSEGMENT</span> type is just a
+       structure with four fields (the coordinates of the two points
+       that define the segment):
+       </p>
+       <pre class="code">
+typedef struct {
+    INT16 x1;
+    INT16 y1;
+    INT16 x2;
+    INT16 y2;
+} XCBSEGMENT;
+</pre>
+       <p>
+       To draw a rectangle, or several rectangles, we use
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBPolyRectangle (XCBConnection      *c,              /* The connection to the X server */
+                               XCBDRAWABLE         drawable,       /* The drawable on which we want to draw the rectangle(s) */
+                               XCBGCONTEXT         gc,             /* The Graphic Context we use to draw the rectangle(s) */
+                               CARD32              rectangles_len, /* The number of rectangles */
+                               const XCBRECTANGLE *rectangles);    /* An array of rectangles */
+</pre>
+       <p>
+       The <span class="code">XCBRECTANGLE</span> type is just a
+       structure with four fields (the coordinates of the top-left
+       corner of the rectangle, and its width and height):
+       </p>
+       <pre class="code">
+typedef struct {
+    INT16 x;
+    INT16 y;
+    CARD16 width;
+    CARD16 height;
+} XCBRECTANGLE;
+</pre>
+       <p>
+       <b>TODO</b>: there's no coordinate_mode. Is it normal ?
+       </p>
+       <p>
+       To draw an elliptical arc, or several elliptical arcs, we use
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBPolyArc (XCBConnection *c,          /* The connection to the X server */
+                          XCBDRAWABLE    drawable,   /* The drawable on which we want to draw the arc(s) */
+                         XCBGCONTEXT    gc,         /* The Graphic Context we use to draw the arc(s) */
+                         CARD32         arcs_len,   /* The number of arcs */
+                         const XCBARC  *arcs);      /* An array of arcs */
+</pre>
+       <p>
+       The <span class="code">XCBARC</span> type is a structure with
+       six fields:
+       </p>
+       <pre class="code">
+typedef struct {
+    INT16 x;        /* Top left x coordinate of the rectangle surrounding the ellipse */
+    INT16 y;        /* Top left y coordinate of the rectangle surrounding the ellipse */
+    CARD16 width;   /* Width of the rectangle surrounding the ellipse */
+    CARD16 height;  /* Height of the rectangle surrounding the ellipse */
+    INT16 angle1;   /* Angle at which the arc begins */
+    INT16 angle2;   /* Angle at which the arc ends */
+} XCBARC;
+</pre>
+       <div class="emph">
+       <p>
+       Note: the angles are expressed in units of 1/64 of a degree,
+       so to have an angle of 90 degrees, starting at 0,
+       <span class="code">angle1 = 0</span> and
+       <span class="code">angle2 = 90 &lt;&lt; 6</span>. Positive angles
+       indicate counterclockwise motion, while  negative angles
+       indicate clockwise motion.
+       </p>
+       </div>
+       <p>
+       <b>TODO</b>: there's no coordinate_mode. Is it normal ?
+       </p>
+       <p>
+       <b>TODO</b>: I think that (x,y) should be the center of the
+       ellipse, and (width, height) the radius. It's more logical.
+       </p>
+       <p>
+       The corresponding function which fill inside the geometrical
+       object are listed below, without  further explanation, as they
+       are used as the above functions.
+       </p>
+       <p>
+       To Fill a polygon defined by the points given as arguments ,
+       we use
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBFillPoly (XCBConnection  *c,
+                           XCBDRAWABLE     drawable,
+                          XCBGCONTEXT     gc,
+                          CARD8           shape,
+                          CARD8           coordinate_mode,
+                          CARD32          points_len,
+                          const XCBPOINT *points);
+</pre>
+       <p>
+       The <span class="code">shape</span> parameter specifies a
+       shape that helps the server to improve performance. Available
+       values are
+       </p>
+       <ul>
+         <li><span class="code">Complex</span></li>
+         <li><span class="code">Convex</span></li>
+         <li><span class="code">Nonconvex</span></li>
+       </ul>
+       <p>
+       To fill one or several rectangles, we use
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBPolyFillRectangle (XCBConnection      *c,
+                                    XCBDRAWABLE         drawable,
+                                   XCBGCONTEXT         gc,
+                                   CARD32              rectangles_len,
+                                   const XCBRECTANGLE *rectangles);
+</pre>
+       <p>
+       To fill one or several arcs, we use
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBPolyFillArc (XCBConnection *c,
+                              XCBDRAWABLE    drawable,
+                             XCBGCONTEXT    gc,
+                             CARD32         arcs_len,
+                             const XCBARC  *arcs);
+</pre>
+        <p></p>
+       <p>
+       To illustrate these functions, here is an example that draws
+       four points, a polygonal line, two segments, two rectangles
+       and two arcs. Remark that we use events for the first time, as
+       an introduction to the next section.
+       </p>
+       <pre class="code">
+#include &lt;stdlib.h&gt;
+#include &lt;stdio.h&gt;
+
+#include &lt;X11/XCB/xcb.h&gt;
+
+/* Get the depth of the screen. Needed in order to draw something */
+int
+get_depth(XCBConnection *c,
+         XCBSCREEN     *root)
+{
+  XCBDRAWABLE        drawable;
+  XCBGetGeometryRep *geom;
+  int                depth;
+
+  drawable.window = root-&gt;root;
+  geom = XCBGetGeometryReply (c, XCBGetGeometry(c, drawable), 0);
+
+  if(!geom)
+    {
+      perror ("GetGeometry(root) failed");
+      exit (0);
+    }
+  
+  depth = geom-&gt;depth;
+  free (geom);
+
+  return depth;
+}
+
+int
+main (int argc, char *argv[])
+{
+  XCBConnection   *c;
+  XCBSCREEN       *screen;
+  XCBDRAWABLE      win;
+  XCBGCONTEXT      foreground;
+  XCBGenericEvent *e;
+  CARD32           mask = 0;
+  CARD32           values[2];
+
+  /* geometric objects */
+  XCBPOINT         points[] = {
+    {10, 10},
+    {10, 20},
+    {20, 10},
+    {20, 20}};
+
+  XCBPOINT         polyline[] = {
+    {50, 10},
+    {55, 30},
+    {80, 10},
+    {90, 20}};
+
+  XCBSEGMENT       segments[] = {
+    {100, 10, 140, 30},
+    {110, 25, 130, 60}};
+
+  XCBRECTANGLE     rectangles[] = {
+    { 10, 50, 40, 20},
+    { 80, 50, 10, 40}};
+
+  XCBARC           arcs[] = {
+    {10, 100, 60, 40, 0, 90 << 6},
+    {90, 100, 55, 40, 0, 270 << 6}};
+  
+  /* Open the connection to the X server */
+  c = XCBConnect (NULL, NULL);
+  
+  /* Get the first screen */
+  screen = XCBConnSetupSuccessRepRootsIter (XCBGetSetup (c)).data;
+
+  /* Create black (foregroung) graphic context */
+  win.window = screen-&gt;root;
+
+  foreground = XCBGCONTEXTNew (c);
+  mask = GCForeground | GCGraphicsExposures;
+  values[0] = screen-&gt;black_pixel;
+  values[1] = 0;
+  XCBCreateGC (c, foreground, win, mask, values);
+
+  /* Ask for our window's Id */
+  win.window = XCBWINDOWNew(c);
+
+  /* Create the window */
+  mask = XCBCWBackPixel | XCBCWEventMask;
+  values[0] = screen-&gt;white_pixel;
+  values[1] = ExposureMask;
+  XCBCreateWindow (c,                        /* Connection          */
+                  0,                        /* depth               */
+                  win.window,               /* window Id           */
+                  screen-&gt;root,             /* parent window       */
+                  0, 0,                     /* x, y                */
+                  150, 150,                 /* width, height       */
+                  10,                       /* border_width        */
+                  InputOutput,              /* class               */
+                  screen-&gt;root_visual,      /* visual              */
+                  mask, values);            /* masks */
+
+  /* Map the window on the screen */
+  XCBMapWindow (c, win.window);
+
+
+  /* We flush the request */
+  XCBSync (c, 0);
+
+  while ((e = XCBWaitEvent (c)))
+    {
+      switch (e-&gt;response_type)
+       {
+       case XCBExpose:
+         {
+           /* We draw the points */
+           XCBPolyPoint (c, CoordModeOrigin, win, foreground, 4, points);
+           
+           /* We draw the polygonal line */
+           XCBPolyLine (c, CoordModeOrigin, win, foreground, 4, polyline);
+           
+           /* We draw the segements */
+           XCBPolySegment (c, win, foreground, 2, segments);
+           
+           /* We draw the rectangles */
+           XCBPolyRectangle (c, win, foreground, 2, rectangles);
+           
+           /* We draw the arcs */
+           XCBPolyArc (c, win, foreground, 2, arcs);
+
+           /* We flush the request */
+           XCBSync (c, 0);
+           
+           break;
+         }
+       default:
+         {
+           /* Unknown event type, ignore it */
+           break;
+         }
+       }
+      /* Free the Generic Event */
+      free (e);
+    }
+
+  return 1;
+}
+</pre>
+      </ol>
+      <li class="title"><a name="xevents">X Events</a></li>
+      <p>
+      In an X program, everything is driven by events. Event painting
+      on the screen is sometimes done as a response to an event (an
+      <span class="code">Expose</span> event). If part of a program's
+      window that was hidden, gets exposed (e.g. the window was raised
+      above other widows), the X server will send an "expose" event to
+      let the program know it should repaint that part of the
+      window. User input (key presses, mouse movement, etc) is also
+      received as a set of events.
+      </p>
+      <ol>
+        <li class="subtitle"><a name="register">Registering for event types using event masks</a></li>
+       <p>
+       During the creation of a window, you should give it what kind
+       of events it wishes to receive. Thus, you may register for
+       various mouse (also called pointer) events, keyboard events,
+       expose events, and so on. This is done for optimizing the
+       server-to-client connection (i.e. why send a program (that
+       might even be running at the other side of the globe) an event
+       it is not interested in ?)
+       </p>
+       <p>
+       In XCB, you use the "value_mask" and "value_list" data in the
+       <span class="code">XCBCreateWindow()</span> function to
+       register for events. Here is how we register for
+       <span class="code">Expose</span> event when creating a window:
+       </p>
+       <pre class="code">
+  mask = XCBCWEventMask;
+  valwin[0] = ExposureMask;
+  win.window = XCBWINDOWNew (c);
+  XCBCreateWindow (c, depth, win.window, root-&gt;root,
+                  0, 0, 150, 150, 10,
+                  InputOutput, root-&gt;root_visual,
+                  mask, valwin);
+</pre>
+        <p>
+       <span class="code">ExposureMask</span> is a constant defined
+       in the "X.h" header file. If we wanted to register to several
+       event types, we can logically "or" them, as follows:
+       </p>
+       <pre class="code">
+  mask = XCBCWEventMask;
+  valwin[0] = ExposureMask | ButtonPressMask;
+  win.window = XCBWINDOWNew (c);
+  XCBCreateWindow (c, depth, win.window, root-&gt;root,
+                  0, 0, 150, 150, 10,
+                  InputOutput, root-&gt;root_visual,
+                  mask, valwin);
+</pre>
+       <p>
+       This registers for <span class="code">Expose</span> events as
+       well as for mouse button presses insode the created
+       window. You should note that a mask may represent several
+       event sub-types.
+       </p>
+       <p>
+       The values that a mask could take are given
+       by the <span class="code">XCBCW</span> enumeration:
+       </p>
+       <pre class="code">
+typedef enum {
+    XCBCWBackPixmap       = 1L<<0,
+    XCBCWBackPixel        = 1L<<1,
+    XCBCWBorderPixmap     = 1L<<2,
+    XCBCWBorderPixel      = 1L<<3,
+    XCBCWBitGravity       = 1L<<4,
+    XCBCWWinGravity       = 1L<<5,
+    XCBCWBackingStore     = 1L<<6,
+    XCBCWBackingPlanes    = 1L<<7,
+    XCBCWBackingPixel     = 1L<<8,
+    XCBCWOverrideRedirect = 1L<<9,
+    XCBCWSaveUnder        = 1L<<10,
+    XCBCWEventMask        = 1L<<11,
+    XCBCWDontPropagate    = 1L<<12,
+    XCBCWColormap         = 1L<<13,
+    XCBCWCursor           = 1L<<14
+} XCBCW;
+</pre>
+       <div class="emph">
+        <p>Note: we must be careful when setting the values of the valwin
+        parameter, as they have to follow the order the
+       <span class="code">XCBCW</span> enumeration. Here is an
+        example:
+       </p>
+       </div>
+       <pre class="code">
+  mask = XCBCWEventMask | XCBCWBackPixmap;
+  valwin[0] = None;                           /* for XCBCWBackPixmap (whose value is 1)    */
+  valwin[1] = ExposureMask | ButtonPressMask; /* for XCBCWEventMask, whose value (2048)    */
+                                              /* is superior to the one of XCBCWBackPixmap */
+</pre>
+       <p>
+       If the window has already been created, we can use the
+       <span class="code">XCBConfigureWindow()</span> function to set
+       the events that the window will receive. The subsection
+       <a href="#winconf">Configuring a window</a> shows its
+       prototype. As an example, here is a piece of code that
+       configures the window to receive the
+       <span class="code">Expose</span> and
+       <span class="code">ButtonPressMask</span> events:
+       </p>
+       <pre class="code">
+const static CARD32 values[] = { ExposureMask | ButtonPressMask };
+
+/* The connection c and the window win are supposed to be defined */
+
+XCBConfigureWindow (c, win, XCBCWEventMask, values);
+</pre>
+       <div class="emph">
+       <p>
+       Note: A common bug programmers do is adding code to handle new
+       event types in their program, while forgetting to add the
+       masks for these events in the creation of the window. Such a
+       programmer then should sit down for hours debugging his
+       program, wondering "Why doesn't my program notice that I
+       released the button?", only to find that they registered for
+       button press events but not for button release events.
+       </p>
+       </div>
+        <li class="subtitle"><a name="loop">Receiving events: writing the events loop</a></li>
+       <p>
+       After we have registered for the event types we are interested
+       in, we need to enter a loop of receiving events and handling
+       them. There are two ways to receive events: a blocking way and
+       a non blocking way:
+       </p>
+       <ul>
+         <li>
+         <span class="code">XCBWaitEvent (XCBConnection *c)</span>
+         is the blocking way. It waits (so blocks...) until an event is
+         queued in the X server. Then it retrieves it into a newly
+         allocated structure (it dequeues it from the queue) and returns
+         it. This structure has to be freed. The function returns
+         <span class="code">NULL</span> if an error occurs.
+         </li>
+         <br />
+         <li>
+         <span class="code">XCBPollForEvent (XCBConnection *c, int
+         *error)</span> is the non blocking way. It looks at the event
+         queue and returns (and dequeues too) an existing event into
+         a newly allocated structure. This structure has to be
+         freed. It returns <span class="code">NULL</span> if there is
+         no event. If an error occurs, the parameter <span
+         class="code">error</span> will be filled with the error
+         status.
+         </li> 
+       </ul>
+       <p>
+       There are various ways to write such a loop. We present two
+       ways to write such a loop, with the two functions above. The
+       first one uses <span class="code">XCBWaitEvent</span>, which
+       is similar to an event Xlib loop using only <span
+       class="code">XNextEvent</span>:
+       </p>
+       <pre class="code">
+  XCBGenericEvent *e;
+
+  while ((e = XCBWaitEvent (c)))
+    {
+      switch (e-&gt;response_type)
+       {
+       case XCBExpose:
+         {
+           /* Handle the Expose event type */
+           XCBExposeEvent *ev = (XCBExposeEvent *)e;
+
+           /* ... */
+
+           break;
+         }
+       case XCBButtonPress: 
+         {
+           /* Handle the ButtonPress event type */
+           XCBButtonPressEvent *ev = (XCBButtonPressEvent *)e;
+
+           /* ... */
+
+           break;
+         }
+       default:
+         {
+           /* Unknown event type, ignore it */
+           break;
+         }
+       }
+      /* Free the Generic Event */
+      free (e);
+    }
+</pre>
+       <p>
+       You will certainly want to use <span
+       class="code">XCBPollForEvent(XCBConnection *c, int
+       *error)</span> if, in Xlib, you use <span
+       class="code">XPending</span>:
+       </p>
+       <pre class="code">
+  while (XPending (display))
+    {
+      XEvent ev;
+
+      XNextEvent(d, &ev);
+      
+      /* Manage your event */
+    }
+</pre>
+        <p>
+       Such a loop in XCB looks like:
+       </p>
+       <pre class="code">
+  XCBGenericEvent *ev;
+
+  while ((ev = XCBPollForEvent (conn, 0)))
+    {
+      /* Manage your event */
+    }
+</pre>
+       <p>
+       The events are managed in the same way as with <span
+       class="code">XCBWaitEvent</span>.
+       Obviously, we will need to give the user some way of
+       terminating the program. This is usually done by handling a
+       special "quit" event, as we will soon see.
+       </p>
+       <div class="comp">
+         <div class="title">
+           Comparison Xlib/XCB
+         </div>
+         <div class="xlib">
+           <ul>
+             <li>XNextEvent ()</li>
+             </ul>
+         </div>
+         <div class="xcb">
+           <ul>
+             <li>XCBWaitEvent ()</li>
+           </ul>
+         </div>
+         <div class="xlib">
+           <ul>
+             <li>XPending ()</li>
+             <li>XNextEvent ()</li>
+           </ul>
+         </div>
+         <div class="xcb">
+           <ul>
+             <li>XCBPollForEvent ()</li>
+             <br />
+           </ul>
+         </div>
+       </div>
+       <p />
+        <li class="subtitle"><a name="expose">Expose events</a></li>
+       <p>
+       The <span class="code">Expose</span> event is one of the most
+       basic (and most used) events an application may receive. It
+       will be sent to us in one of several cases:
+         <ul>
+           <li>A window that covered part of our window has moved
+           away, exposing part (or all) of our window.</li>
+           <li>Our window was raised above other windows.</li>
+           <li>Our window mapped for the first time.</li>
+           <li>Our window was de-iconified.</li>
+         </ul>
+       </p>
+       <p>
+       You should note the implicit assumption hidden here: the
+       contents of our window is lost when it is being obscured
+       (covered) by either windows. One may wonder why the X server
+       does not save this contents. The answer is: to save
+       memory. After all, the number of windows on a display at a
+       given time may be very large, and storing the contents of all
+       of them might require a lot of memory. Actually, there is a
+       way to tell the X server to store  the contents of a window in
+       special cases, as we will see later.
+       </p>
+       <p>
+       When we get an <span class="code">Expose</span> event, we
+       should take the event's data from the members of the following
+       structure:
+       </p>
+       <pre class="code">
+typedef struct {
+    BYTE response_type;  /* The type of the event, here it is XCBExpose */
+    CARD8 pad0;
+    CARD16 sequence;
+    XCBWINDOW window;    /* The Id of the window that receives the event (in case */
+                         /* our application registered for events on several windows */
+    CARD16 x;            /* The x coordinate of the top-left part of the window that needs to be redrawn */
+    CARD16 y;            /* The y coordinate of the top-left part of the window that needs to be redrawn */
+    CARD16 width;        /* The width of the part of the window that needs to be redrawn */
+    CARD16 height;       /* The height of the part of the window that needs to be redrawn */
+    CARD16 count;
+} XCBExposeEvent;
+</pre>
+        <li class="subtitle"><a name="userinput">Getting user input</a></li>
+       <p>
+       User input traditionally comes from two sources: the mouse
+       and the keyboard. Various event types exist to notify us of
+       user input (a key being presses on the keyboard, a key being
+       released on the keyboard, the mouse moving over our window,
+       the mouse entering (or leaving) our window, and so on.
+       </p>
+       <ol>
+         <li class="subsubtitle"><a name="mousepressrelease">Mouse button press and release events</a></li>
+         <p>
+         The first event type we will deal with is a mouse
+         button-press (or button-release) event in our window. In
+         order to register to such an event type, we should add one
+         (or more) of the following masks when we create our window:
+         </p>
+         <ul>
+           <li><span class="code">ButtonPressMask</span>: notify us
+           of any button that was pressed in one of our windows.</li>
+           <li><span class="code">ButtonReleaseMask</span>: notify us
+           of any button that was released in one of our windows.</li>
+         </ul>
+         <p>
+         The structure to be checked for in our events loop is the
+         same for these two events, and is the following:
+         </p>
+         <pre class="code">
+typedef struct {
+    BYTE response_type;  /* The type of the event, here it is XCBButtonPressEvent or XCBButtonReleaseEvent */
+    XCBBUTTON detail;
+    CARD16 sequence;
+    XCBTIMESTAMP time;   /* Time, in milliseconds the event took place in */
+    XCBWINDOW root;
+    XCBWINDOW event;
+    XCBWINDOW child;
+    INT16 root_x;
+    INT16 root_y;
+    INT16 event_x;       /* The x coordinate where the mouse has been pressed in the window */
+    INT16 event_y;       /* The y coordinate where the mouse has been pressed in the window */
+    CARD16 state;        /* A mask of the buttons (or keys) during the event */
+    BOOL same_screen;
+} XCBButtonPressEvent;
+
+typedef XCBButtonPressEvent XCBButtonReleaseEvent;
+</pre>
+          <p>
+         The <span class="code">time</span> field may be used to calculate "double-click"
+         situations by an application (e.g. if the mouse button was
+         clicked two times in a duration shorter than a given amount
+         of time, assume this was a double click).
+         </p>
+          <p>
+         The <span class="code">state</span> field is a mask of the buttons held down during
+         the event. It is a bitwise OR of any of the following:
+         </p>
+         <ul>
+           <li><span class="code">Button1Mask</span></li>
+           <li><span class="code">Button2Mask</span></li>
+           <li><span class="code">Button3Mask</span></li>
+           <li><span class="code">Button4Mask</span></li>
+           <li><span class="code">Button5Mask</span></li>
+           <li><span class="code">ShiftMask</span></li>
+           <li><span class="code">LockMask</span></li>
+           <li><span class="code">ControlMask</span></li>
+           <li><span class="code">Mod1Mask</span></li>
+           <li><span class="code">Mod2Mask</span></li>
+           <li><span class="code">Mod3Mask</span></li>
+           <li><span class="code">Mod4Mask</span></li>
+           <li><span class="code">Mod5Mask</span></li>
+         </ul>
+         <p>
+         Their names are self explanatory, where the first 5 refer to
+         the mouse buttons that are being pressed, while the rest
+         refer to various "special keys" that are being pressed (Mod1
+         is usually the 'Alt' key or the 'Meta' key).
+         </p>
+         <p>
+         <b>TODO:</b> Problem: it seems that the state does not
+         change when clicking with various buttons.
+         </p>
+         <li class="subsubtitle"><a name="mousemvnt">Mouse movement events</a></li>
+         <p> 
+         Similar to mouse button press and release events, we also
+         can be notified of various mouse movement events. These can
+         be split into two families. One is of mouse pointer
+         movement while no buttons are pressed, and the second is a
+         mouse pointer motion while one (or more) of the buttons are
+         pressed (this is sometimes called "a mouse drag operation",
+         or just "dragging"). The following event masks may be added
+         during the creation of our window:
+         </p>
+         <ul>
+           <li><span class="code">PointerMotionMask</span>: events of
+           the pointer moving in one of the windows controlled by our
+           application, while no mouse button is held pressed.</li>
+           <li><span class="code">ButtonMotionMask</span>: Events of
+           the pointer moving while one or more of the mouse buttons
+           is held pressed.</li>
+           <li><span class="code">Button1MotionMask</span>: same as
+           <span class="code">ButtonMotionMask</span>, but only when
+           the 1st mouse button is held pressed.</li>
+           <li><span class="code">Button2MotionMask</span>,
+           <span class="code">Button3MotionMask</span>,
+           <span class="code">Button4MotionMask</span>,
+           <span class="code">Button5MotionMask</span>: same as
+           <span class="code">Button1MotionMask</span>, but
+           respectively for 2nd, 3rd, 4th and 5th mouse button.</li>
+         </ul>
+         <p>
+         The structure to be checked for in our events loop is the
+         same for these events, and is the following:
+         </p>
+         <pre class="code">
+typedef struct {
+    BYTE response_type;  /* The type of the event */
+    BYTE detail;
+    CARD16 sequence;
+    XCBTIMESTAMP time;   /* Time, in milliseconds the event took place in */
+    XCBWINDOW root;
+    XCBWINDOW event;
+    XCBWINDOW child;
+    INT16 root_x;
+    INT16 root_y;
+    INT16 event_x;       /* The x coordinate of the mouse when the  event was generated */
+    INT16 event_y;       /* The y coordinate of the mouse when the  event was generated */
+    CARD16 state;        /* A mask of the buttons (or keys) during the event */
+    BOOL same_screen;
+} XCBMotionNotifyEvent;
+</pre>
+         <li class="subsubtitle"><a name="mouseenter">Mouse pointer enter and leave events</a></li>
+         <p>
+         Another type of event that applications might be interested
+         at, is a mouse pointer entering a window the program
+         controls, or leaving such a window. Some programs use these
+         events to show the user tht the applications is now in
+         focus. In order to register for such an event type, we
+         should add one (or more) of the following masks when we
+         create our window:
+         </p>
+         <ul>
+           <li><span class="code">EnterWindowMask</span>: notify us
+           when the mouse pointer enters any of our controlled
+           windows.</li>
+           <li><span class="code">LeaveWindowMask</span>: notify us
+           when the mouse pointer leaves any of our controlled
+           windows.</li>
+         </ul>
+         <p>
+         The structure to be checked for in our events loop is the
+         same for these two events, and is the following:
+         </p>
+         <pre class="code">
+typedef struct {
+    BYTE response_type;  /* The type of the event */
+    BYTE detail;
+    CARD16 sequence;
+    XCBTIMESTAMP time;   /* Time, in milliseconds the event took place in */
+    XCBWINDOW root;
+    XCBWINDOW event;
+    XCBWINDOW child;
+    INT16 root_x;
+    INT16 root_y;
+    INT16 event_x;       /* The x coordinate of the mouse when the  event was generated */
+    INT16 event_y;       /* The y coordinate of the mouse when the  event was generated */
+    CARD16 state;        /* A mask of the buttons (or keys) during the event */
+    BYTE mode;           /* The number of mouse button that was clicked */
+    BYTE same_screen_focus;
+} XCBEnterNotifyEvent;
+
+typedef XCBEnterNotifyEvent XCBLeaveNotifyEvent;
+</pre>
+         <li class="subsubtitle"><a name="focus">The keyboard focus</a></li>
+         <p>
+         There may be many windows on a screen, but only a single
+         keyboard attached to them. How does the X server then know
+         which window should be sent a given keyboard input ? This is
+         done using the keyboard focus. Only a single window on the
+         screen may have the keyboard focus at a given time. There
+         is a XCB function that allow a program to set the keyboard
+         focus to a given window. The user can usually set the
+         keyboard ficus using the window manager (often by clicking
+         on the title bar of the desired window). Once our window
+         has the keyboard focus, every key press or key release will
+         cause an event to be sent to our program (if it regsitered
+         for these event types...).
+         </p>
+         <li class="subsubtitle"><a name="keypress">Keyboard press and release events</a></li>
+         <p>
+         If a window controlled by our program currently holds the
+         keyboard focus, it can receive key press and key release
+         events. So, we should add one (or more) of the following
+         masks when we create our window:
+         </p>
+         <ul>
+           <li><span class="code">KeyPressMask</span>: notify us when
+           a key was pressed while any of our controlled windows had
+           the keyboard focus.</li>
+           <li><span class="code">KeyReleaseMask</span>: notify us
+           when a key was released while any of our controlled
+           windows had the keyboard focus.</li>
+         </ul>
+         <p>
+         The structure to be checked for in our events loop is the
+         same for these two events, and is the following:
+         </p>
+         <pre class="code">
+typedef struct {
+    BYTE response_type;  /* The type of the event */
+    XCBKEYCODE detail;
+    CARD16 sequence;
+    XCBTIMESTAMP time;   /* Time, in milliseconds the event took place in */
+    XCBWINDOW root;
+    XCBWINDOW event;
+    XCBWINDOW child;
+    INT16 root_x;
+    INT16 root_y;
+    INT16 event_x;
+    INT16 event_y;
+    CARD16 state;
+    BOOL same_screen;
+} XCBKeyPressEvent;
+
+typedef XCBKeyPressEvent XCBKeyReleaseEvent;
+</pre>
+        <p>
+       The <span class="code">detail</span> field refer to the
+       physical key on the keyboard.
+       </p>
+       <p>
+        <b>TODO:</b> Talk about getting the ASCII code from the key code.
+       </p>
+       </ol>
+        <li class="subtitle"><a name="eventex">X events: a complete example</a></li>
+       <p>
+       As an example for handling events, we show a program that
+       creates a window, enter an events loop and check for all the
+       events described above, and write on the terminal the relevant
+       characteristics of the event. With this code, it should be
+       easy to add drawing operations, like those which have been
+       described above.
+       </p>
+        <pre class="code">
+#include &lt;malloc.h&gt;
+#include &lt;stdio.h&gt;
+
+#include &lt;X11/XCB/xcb.h&gt;
+
+int
+main (int argc, char *argv[])
+{
+  XCBConnection   *c;
+  XCBSCREEN       *screen;
+  XCBDRAWABLE      win;
+  XCBGenericEvent *e;
+  CARD32           mask = 0;
+  CARD32           values[2];
+  
+  /* Open the connection to the X server */
+  c = XCBConnect (NULL, NULL);
+  
+  /* Get the first screen */
+  screen = XCBConnSetupSuccessRepRootsIter (XCBGetSetup (c)).data;
+
+  /* Ask for our window's Id */
+  win.window = XCBWINDOWNew(c);
+
+  /* Create the window */
+  mask = XCBCWBackPixel | XCBCWEventMask;
+  values[0] = screen-&gt;white_pixel;
+  values[1] = ExposureMask      | ButtonPressMask  | ButtonReleaseMask |
+              PointerMotionMask | EnterWindowMask  | LeaveWindowMask   |
+               KeyPressMask     | KeyReleaseMask;
+  XCBCreateWindow (c,                        /* Connection          */
+                  0,                        /* depth               */
+                  win.window,               /* window Id           */
+                  screen-&gt;root,             /* parent window       */
+                  0, 0,                     /* x, y                */
+                  150, 150,                 /* width, height       */
+                  10,                       /* border_width        */
+                  InputOutput,              /* class               */
+                  screen-&gt;root_visual,      /* visual              */
+                  mask, values);            /* masks */
+
+  /* Map the window on the screen */
+  XCBMapWindow (c, win.window);
+
+  XCBSync (c, 0);
+  while ((e = XCBWaitEvent (c)))
+    {
+      switch (e-&gt;response_type)
+       {
+       case XCBExpose:
+         {
+           XCBExposeEvent *ev = (XCBExposeEvent *)e;
+           
+           printf ("Window %ld exposed. Region to be redrawn at location (%d,%d), with dimension (%d,%d)\n",
+                   ev-&gt;window.xid, ev-&gt;x, ev-&gt;y, ev-&gt;width, ev-&gt;height);
+           break;
+         }
+       case XCBButtonPress: 
+         {
+           XCBButtonPressEvent *ev = (XCBButtonPressEvent *)e;
+           int                  button_num = 0;
+           
+           if ((ev-&gt;state | Button1Mask) == Button1Mask)
+             button_num = 1;
+           if ((ev-&gt;state | Button2Mask) == Button2Mask)
+             button_num = 2;
+           if ((ev-&gt;state | Button3Mask) == Button3Mask)
+             button_num = 3;
+           if ((ev-&gt;state | Button4Mask) == Button4Mask)
+             button_num = 4;
+           if ((ev-&gt;state | Button5Mask) == Button5Mask)
+             button_num = 5;
+             
+           switch (ev-&gt;detail.id)
+             {
+             case 4:
+               {
+               printf ("Wheel Button up in window %ld, at coordinates (%d,%d)\n",
+                        ev-&gt;event.xid, ev-&gt;event_x, ev-&gt;event_y);
+               break;
+               }
+             case 5:
+               {
+               printf ("Wheel Button down in window %ld, at coordinates (%d,%d)\n",
+                        ev-&gt;event.xid, ev-&gt;event_x, ev-&gt;event_y);
+               break;
+               }
+             default:
+               printf ("Button %d pressed in window %ld, at coordinates (%d,%d)\n",
+                        ev-&gt;detail.id, ev-&gt;event.xid, ev-&gt;event_x, ev-&gt;event_y);
+             }
+           break;
+         }
+       case XCBButtonRelease: 
+         {
+           XCBButtonReleaseEvent *ev = (XCBButtonReleaseEvent *)e;
+           int                  button_num = 0;
+           
+           if ((ev-&gt;state | Button1Mask) == Button1Mask)
+             button_num = 1;
+           if ((ev-&gt;state | Button2Mask) == Button2Mask)
+             button_num = 2;
+           if ((ev-&gt;state | Button3Mask) == Button3Mask)
+             button_num = 3;
+           if ((ev-&gt;state | Button4Mask) == Button4Mask)
+             button_num = 4;
+           if ((ev-&gt;state | Button5Mask) == Button5Mask)
+             button_num = 5;
+           
+           printf ("Button %d released in window %ld, at coordinates (%d,%d)\n",
+                    ev-&gt;detail.id, ev-&gt;event.xid, ev-&gt;event_x, ev-&gt;event_y);
+           break;
+         }
+       case XCBMotionNotify:
+         {
+           XCBMotionNotifyEvent *ev = (XCBMotionNotifyEvent *)e;
+           
+           printf ("Mouse moved in window %ld, at coordinates (%d,%d)\n",
+                    ev-&gt;event.xid, ev-&gt;event_x, ev-&gt;event_y);
+           break;
+         }
+       case XCBEnterNotify:
+         {
+           XCBEnterNotifyEvent *ev = (XCBEnterNotifyEvent *)e;
+           
+           printf ("Mouse entered window %ld, at coordinates (%d,%d)\n",
+                    ev-&gt;event.xid, ev-&gt;event_x, ev-&gt;event_y);
+           break;
+         }
+       case XCBLeaveNotify:
+         {
+           XCBLeaveNotifyEvent *ev = (XCBLeaveNotifyEvent *)e;
+           
+           printf ("Mouse leaved window %ld, at coordinates (%d,%d)\n",
+                    ev-&gt;event.xid, ev-&gt;event_x, ev-&gt;event_y);
+           break;
+         }
+       case XCBKeyPress: 
+         {
+           XCBKeyPressEvent *ev = (XCBKeyPressEvent *)e;
+
+           printf ("Key pressed in window %ld\n",
+                    ev-&gt;event.xid);
+           break;
+         }
+       case XCBKeyRelease: 
+         {
+           XCBKeyReleaseEvent *ev = (XCBKeyReleaseEvent *)e;
+
+           printf ("Key releaseed in window %ld\n",
+                    ev-&gt;event.xid);
+           break;
+         }
+       default:
+         {
+           /* Unknown event type, ignore it */
+           break;
+         }
+       }
+      /* Free the Generic Event */
+      free (e);
+    }
+
+  return 1;
+}
+</pre>
+      </ol>
+      <li class="title"><a name="font">Handling text and fonts</a></li>
+      <p>
+      Besides drawing graphics on a window, we often want to draw
+      text. Text strings have two major properties: the characters to
+      be drawn and the font with which they are drawn. In order to
+      draw text, we need to first request the X server to load a
+      font. We the assign a font to a Graphic Context, and finally, we
+      draw the text in a window, using the Graphic Context.
+      </p>
+      <ol>
+        <li class="subtitle"><a name="fontstruct">The Font structure</a></li>
+       <p>
+       In order to support flexible fonts, a font structure is
+       defined. You know what ? Its an Id:
+       </p>
+       <pre class="code">
+typedef struct {
+    CARD32 xid;
+} XCBFONT;
+</pre>
+       <p>
+       It is used to contain information about a font, and is passed
+       to several functions that handle fonts selection and text drawing.
+       </p>
+      </ol>
+      <li class="title"><a name="wm">Interacting with the window manager</a></li>
+      <p>
+      After we have seen how to create windows and draw on them, we
+      take one step back, and look at how our windows are interacting
+      with their environment (the full screen and the other
+      windows). First of all, our application needs to interact with
+      the window manager. The window manager is responsible to
+      decorating drawn windows (i.e. adding a frame, an iconify
+      button, a system menu, a title bar, etc), as well as handling
+      icons shown when windows are being iconified. It also handles
+      ordering of windows on the screen, and other administrative
+      tasks. We need to give it various hints as to how we want it to
+      treat our application's windows.
+      </p>
+      <ol>
+        <li class="subtitle"><a name="wmprop">Window properties</a></li>
+       <p>
+       Many of the parameters communicated to the window manager are
+       passed using data called "properties". These properties are
+       attached by the X server to different windows, and are stores
+       in a format that makes it possible to read them from different
+       machines that may use different architectures (remember that
+       an X client program may run on a remote machine).
+       </p>
+       <p>
+       The property and its type (a string, an integer, etc) are
+       Id. Their type are <span class="code">XCBATOM</span>:
+       </p>
+       <pre class="code">
+typedef struct {
+    CARD32 xid;
+} XCBATOM;
+</pre>
+       <p>
+       To change the property of a window, we use the following
+       function:
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBChangeProperty (XCBConnection *c,  /* Connection to the X server */
+                                 CARD8 mode,        /* Property mode */
+                                XCBWINDOW window,  /* Window */
+                                XCBATOM property,  /* Property to change */
+                                XCBATOM type,      /* Type of the property */
+                                CARD8 format,      /* Format of the property (8, 16, 32) */
+                                CARD32 data_len,   /* Length of the data parameter */
+                                const void *data); /* Data */
+</pre>
+       <p>
+       The <span class="code">mode</span> parameter coud be one of
+       the following value (defined in the X.h header file):
+       </p>
+       <ul>
+         <li>PropModeReplace</li>
+         <li>PropModePrepend</li>
+         <li>PropModeAppend</li>
+       </ul>
+       <p></p>
+        <li class="subtitle"><a name="wmname">Setting the window name and icon name</a></li>
+       <p>
+       The firt thing we want to do would be to set the name for our
+       window. This is done using the
+       <span class="code">XCBChangeProperty()</span> function. This
+       name may be used by the window manager as the title of the
+       window (in the title bar), in a task list, etc. The property
+       atom to use to set the name of a window is
+       <span class="code">WM_NAME</span> (and
+       <span class="code">WM_ICON_NAME</span> for the iconified
+       window) and its type is <span class="code">STRING</span>. Here
+       is an example of utilization:
+       </p>
+       <pre class="code">
+#include &lt;string.h&gt;
+
+#include &lt;X11/XCB/xcb.h&gt;
+#include &lt;X11/XCB/xcb_atom.h&gt;
+
+int
+main (int argc, char *argv[])
+{
+  XCBConnection *c;
+  XCBSCREEN     *screen;
+  XCBDRAWABLE    win;
+  char          *title = "Hello World !";
+  char          *title_icon = "Hello World ! (iconified)";
+
+
+  
+  /* Open the connection to the X server */
+  c = XCBConnect (NULL, NULL);
+  
+  /* Get the first screen */
+  screen = XCBConnSetupSuccessRepRootsIter (XCBGetSetup (c)).data;
+
+  /* Ask for our window's Id */
+  win.window = XCBWINDOWNew(c);
+
+  /* Create the window */
+  XCBCreateWindow (c,                        /* Connection          */
+                  0,                        /* depth               */
+                  win.window,               /* window Id           */
+                  screen-&gt;root,             /* parent window       */
+                  0, 0,                     /* x, y                */
+                  250, 150,                 /* width, height       */
+                  10,                       /* border_width        */
+                  InputOutput,              /* class               */
+                  screen-&gt;root_visual,      /* visual              */
+                  0, NULL);                 /* masks, not used     */
+
+  /* Set the title of the window */
+  XCBChangeProperty(c, PropModeReplace, win.window,
+                   WM_NAME, STRING, 8,
+                   strlen(title), title);
+
+  /* Set the title of the window icon */
+  XCBChangeProperty(c, PropModeReplace, win.window,
+                   WM_ICON_NAME, STRING, 8,
+                   strlen(title_icon), title_icon);
+
+  /* Map the window on the screen */
+  XCBMapWindow (c, win.window);
+
+  XCBSync (c, 0);
+  
+  while (1) {}
+
+  return 1;
+}
+</pre>
+       <div class="emph">
+        <p>Note: the use of the atoms needs our program to be compiled
+        and linked against xcb_atom, so that we have to use
+       </p>
+       </div>
+       <pre class="text">
+gcc prog.c -o prog `pkg-config --cflags --libs xcb_atom`
+</pre>
+       <div class="emph">
+        <p>
+       for the program to compile fine.
+       </p>
+       </div>
+      </ol>
+      <li class="title"><a name="winop">Simple window operations</a></li>
+      <p>
+      One more thing we can do to our window is manipulate them on the
+      screen (resize them, move them, raise or lower them, iconify
+      them, and so on). Some window operations functions are supplied
+      by XCB for this purpose.
+      </p>
+      <ol>
+        <li class="subtitle"><a name="winmap">Mapping and un-mapping a window</a></li>
+       <p>
+       The first pair of operations we can apply on a window is
+       mapping it, or un-mapping it. Mapping a window causes the
+       window to appear on the screen, as we have seen in our simple
+       window program example. Un-mapping it causes it to be removed
+       from the screen (although the window as a logical entity still
+       exists). This gives the effect of making a window hidden
+       (unmapped) and shown again (mapped). For example, if we have a
+       dialog box window in our program, instead of creating it every
+       time the user asks to open it, we can create the window once,
+       in an un-mapped mode, and when the user asks to open it, we
+       simply map the window on the screen. When the user clicked the
+       'OK' or 'Cancel' button, we simply un-map the window. This is
+       much faster than creating and destroying the window, however,
+       the cost is wasted resources, both on the client side, and on
+       the X server side.
+       </p>
+       <p>
+       To map a window, you use the following function:
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBMapWindow(XCBConnection *c, XCBWINDOW window);
+</pre>
+        <p>
+       To have a simple example, see the <a href="#helloworld">example</a>
+       above. The mapping operation will cause an
+       <span class="code">Expose</span> event to be sent to our
+       application, unless the window is completely covered by other
+       windows.
+       </p>
+       <p>
+       Un-mapping a window is also simple. You use the function
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBUnmapWindow(XCBConnection *c, XCBWINDOW window);
+</pre>
+       <p>
+       The utilization of this function is the same as
+       <span class="code">XCBMapWindow()</span>.
+       </p>
+        <li class="subtitle"><a name="winconf">Configuring a window</a></li>
+       <p>
+       As we have seen when we have created our first window, in the
+       X Events subsection, we can set some attributes to the window
+       (that is, the position, the size, the events the window will
+       receive, etc). If we want to modify them, but the window is
+       already created, we can change them by using hte following
+       function:
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBConfigureWindow (XCBConnection *c,            /* The connection to the X server*/
+                                  XCBWINDOW      window,       /* The window to configure */
+                                 CARD16         value_mask,   /* The mask */
+                                 const CARD32  *value_list);  /* The values to set */
+</pre>
+        <p>
+       We set the <span class="code">value_mask</span> to one or
+       several mask values that are in the X.h header:
+       <ul>
+         <li><span class="code">CWX</span>: new x coordinate of the window's top left corner</li>
+         <li><span class="code">CWY</span>: new y coordinate of the window's top left corner</li>
+         <li><span class="code">CWWidth</span>: new width of the window</li>
+         <li><span class="code">CWHeight</span>: new height of the window</li>
+         <li><span class="code">CWBorderWidth</span>: new width of the border of the window</li>
+         <li><span class="code">CWSibling</span></li>
+         <li><span class="code">CWStackMode</span>: the new stacking order</li>
+       </ul>
+       </p>
+       <p>
+       We then give to <span class="code">value_mask</span> the new
+       value. We now describe how to use
+       <span class="code">XCBConfigureWindow</span> in some useful
+       situations.
+       </p>
+        <li class="subtitle"><a name="winmove">Moving a window around the screen</a></li>
+       <p>
+       An operation we might want to do with windows is to move them
+       to a different location. This can be done like this:
+       </p>
+       <pre class="code">
+const static CARD32 values[] = { 10, 20 };
+
+/* The connection c and the window win are supposed to be defined */
+
+/* Move the window to coordinates x = 10 and y = 20 */
+XCBConfigureWindow (c, win, CWX | CWY, values);
+</pre>
+       <p>
+       Note that when the window is moved, it might get partially
+       exposed or partially hidden by other windows, and thus we
+       might get <span class="code">Expose</span> events due to this
+       operation.
+       </p>
+        <li class="subtitle"><a name="winsize">Resizing a window</a></li>
+       <p>
+       Yet another operation we can do is to change the size of a
+       window. This is done using the following code:
+       </p>
+       <pre class="code">
+const static CARD32 values[] = { 200, 300 };
+
+/* The connection c and the window win are supposed to be defined */
+
+/* Resize the window to width = 10 and height = 20 */
+XCBConfigureWindow (c, win, CWWidth | CWHeight, values);
+</pre>
+       <p>
+       We can also combine the move and resize operations using one
+       single call to <span class="code">XCBConfigureWindow</span>:
+       </p>
+       <pre class="code">
+const static CARD32 values[] = { 10, 20, 200, 300 };
+
+/* The connection c and the window win are supposed to be defined */
+
+/* Move the window to coordinates x = 10 and y = 20 */
+/* and resize the window to width = 10 and height = 20 */
+XCBConfigureWindow (c, win, CWX | CWY | CWWidth | CWHeight, values);
+</pre>
+        <li class="subtitle"><a name="winstack">Changing windows stacking order: raise and lower</a></li>
+       <p>
+       Until now, we changed properties of a single window. We'll see
+       that there are properties that relate to the window and other
+       windows. One of hem is the stacking order. That is, the order
+       in which the windows are layered on top of each other. The
+       front-most window is said to be on the top of the stack, while
+       the back-most window is at the bottom of the stack. Here is
+       how to manipulate our windows stack order:
+       </p>
+       <pre class="code">
+const static CARD32 values[] = { Above };
+
+/* The connection c and the window win are supposed to be defined */
+
+/* Move the window on the top of the stack */
+XCBConfigureWindow (c, win, CWStackMode, values);
+</pre>
+       <pre class="code">
+const static CARD32 values[] = { Below };
+
+/* The connection c and the window win are supposed to be defined */
+
+/* Move the window on the bottom of the stack */
+XCBConfigureWindow (c, win, CWStackMode, values);
+</pre>
+        <li class="subtitle"><a name="wingetinfo">Getting information about a window</a></li>
+       <p>
+       Just like we can set various attributes of our windows, we can
+       also ask the X server supply the current values of these
+       attributes. For example, we can chewk where a window is
+       located on the screen, what is its current size, wheter it is
+       mapped or not, etc. The structure that contains some of this
+       information is
+       </p>
+       <pre class="code">
+typedef struct {
+    BYTE response_type;
+    CARD8 depth;            /* depth of the window */
+    CARD16 sequence;
+    CARD32 length;
+    XCBWINDOW root;         /* Id of the root window *>
+    INT16 x;                /* X coordinate of the window's location */
+    INT16 y;                /* Y coordinate of the window's location */
+    CARD16 width;           /* Width of the window */
+    CARD16 height;          /* Height of the window */
+    CARD16 border_width;    /* Width of the window's border */
+} XCBGetGeometryRep;
+</pre>
+        <p>
+       XCB fill this structure with two functions:
+       </p>
+       <pre class="code">
+XCBGetGeometryCookie  XCBGetGeometry      (XCBConnection         *c,
+                                           XCBDRAWABLE            drawable);
+XCBGetGeometryRep    *XCBGetGeometryReply (XCBConnection         *c,
+                                           XCBGetGeometryCookie   cookie,
+                                           XCBGenericError      **e);
+</pre>
+        <p>
+       You use them as follows:
+       </p>
+       <pre class="code">
+  XCBConnection     *c;
+  XCBDRAWABLE        win;
+  XCBGetGeometryRep *geom;
+
+  /* You initialize c and win */
+
+  geom = XCBGetGeometryReply (c, XCBGetGeometry (c, win), 0);
+
+  /* Do something with the fields of geom */
+  
+  free (geom);
+</pre>
+        <p>
+       Remark that you have to free the structure, as
+       <span class="code">XCBGetGeometryReply</span> allocates a
+       newly one.
+       </p>
+        <p>
+       One problem is that the returned location of the window is
+       relative to its parent window. This makes these coordinates
+       rather useless for any window manipulation functions, like
+       moving it on the screen. In order to overcome this problem, we
+       need to take a two-step operation. First, we find out the Id
+       of the parent window of our window. We then translate the
+       above relative coordinates to the screen coordinates.
+       </p>
+       <p>
+       To get the Id of the parent window, we need this structure:
+       </p>
+       <pre class="code">
+typedef struct {
+    BYTE response_type;
+    CARD8 pad0;
+    CARD16 sequence;
+    CARD32 length;
+    XCBWINDOW root;
+    XCBWINDOW parent;    /* Id of the parent window */
+    CARD16 children_len;
+    CARD8 pad1[14];
+} XCBQueryTreeRep;
+</pre>
+        <p>
+       To fill this structure, we use these two functions:
+       </p>
+       <pre class="code">
+XCBQueryTreeCookie XCBQueryTree      (XCBConnection       *c,
+                                      XCBWINDOW            window);
+XCBQueryTreeRep   *XCBQueryTreeReply (XCBConnection       *c,
+                                      XCBQueryTreeCookie   cookie,
+                                     XCBGenericError    **e);
+</pre>
+        <p>
+       The translated coordinates will be found in this structure:
+       </p>
+       <pre class="code">
+typedef struct {
+    BYTE response_type;
+    BOOL same_screen;
+    CARD16 sequence;
+    CARD32 length;
+    XCBWINDOW child;
+    CARD16 dst_x;        /* Translated x coordinate */
+    CARD16 dst_y;        /* Translated y coordinate */
+} XCBTranslateCoordinatesRep;
+</pre>
+        <p>
+       As usual, we need two functions to fill this structure:
+       </p>
+       <pre class="code">
+XCBTranslateCoordinatesCookie XCBTranslateCoordinates      (XCBConnection                  *c,
+                                                            XCBWINDOW                       src_window,
+                                                           XCBWINDOW                       dst_window,
+                                                           INT16                           src_x,
+                                                           INT16                           src_y);
+XCBTranslateCoordinatesRep   *XCBTranslateCoordinatesReply (XCBConnection                 *c,
+                                                           XCBTranslateCoordinatesCookie   cookie,
+                                                           XCBGenericError               **e);
+</pre>
+        <p>
+       We use them as follows:
+       </p>
+       <pre class="code">
+  XCBConnection              *c;
+  XCBDRAWABLE                 win;
+  XCBGetGeometryRep          *geom;
+  XCBQueryTreeRep            *tree;
+  XCBTranslateCoordinatesRep *trans;
+
+  /* You initialize c and win */
+
+  geom  = XCBGetGeometryReply (c, XCBGetGeometry (c, win), 0);
+  if (!geom)
+    return 0;
+
+  tree  = XCBQueryTreeReply (c, XCBQueryTree (c, win), 0);
+  if (!tree)
+    return 0;
+
+  trans = XCBTranslateCoordinatesReply (c,
+                                        XCBTranslateCoordinates (c,
+                                                                 win,
+                                                                tree-&gt;parent,
+                                                                geom-&gt;x, geom-&gt;y),
+                                        0);
+  if (!trans)
+    return 0;
+
+  /* the translated coordinates are in trans-&gt;dst_x and trans-&gt;dst_y */
+
+  free (trans);
+  free (tree);
+  free (geom);
+</pre>
+        <p>
+       Of course, as for <span class="code">geom</span>,
+       <span class="code">tree</span> and
+       <span class="code">trans</span> have to be freed.
+       </p>
+       <p>
+       The work is a bit hard, but XCB is a very low-level library.
+       </p>
+       <p>
+       <b>TODO:</b> the utilization of these functions should be a
+       prog, which displays the coordinates of the window.
+       </p>
+       <p>
+       There is another structure that gives informations about our window:
+       </p>
+       <pre class="code">
+typedef struct {
+    BYTE response_type;
+    CARD8 backing_store;
+    CARD16 sequence;
+    CARD32 length;
+    XCBVISUALID visual;            /* Visual of the window */
+    CARD16 _class;
+    CARD8 bit_gravity;
+    CARD8 win_gravity;
+    CARD32 backing_planes;
+    CARD32 backing_pixel;
+    BOOL save_under;
+    BOOL map_is_installed;
+    CARD8 map_state;               /* Map state of the window */
+    BOOL override_redirect;
+    XCBCOLORMAP colormap;          /* Colormap of the window */
+    CARD32 all_event_masks;
+    CARD32 your_event_mask;
+    CARD16 do_not_propagate_mask;
+} XCBGetWindowAttributesRep;
+</pre>
+        <p>
+       XCB supplies these two functions to fill it:
+       </p>
+       <pre class="code">
+XCBGetWindowAttributesCookie XCBGetWindowAttributes      (XCBConnection                 *c, 
+                                                          XCBWINDOW                      window);
+XCBGetWindowAttributesRep   *XCBGetWindowAttributesReply (XCBConnection                 *c, 
+                                                          XCBGetWindowAttributesCookie   cookie,
+                                                         XCBGenericError              **e);
+</pre>
+        <p>
+       You use them as follows:
+       </p>
+       <pre class="code">
+  XCBConnection             *c;
+  XCBDRAWABLE                win;
+  XCBGetWindowAttributesRep *attr;
+
+  /* You initialize c and win */
+
+  attr = XCBGetWindowAttributesReply (c, XCBGetWindowAttributes (c, win), 0);
+
+  if (!attr)
+    return 0;
+
+  /* Do something with the fields of attr */
+  
+  free (attr);
+</pre>
+        <p>
+       As for <span class="code">geom</span>,
+       <span class="code">attr</span> has to be freed.
+       </p>
+      </ol>
+      <li class="title"><a name="usecolor">Using colors to paint the rainbow</a></li>
+      <p>
+      Up until now, all our painting operation were done using black
+      and white. We will (finally) see now how to draw using colors.
+      </p>
+      <ol>
+        <li class="subtitle"><a name="colormap">Color maps</a></li>
+       <p>
+       In the beginning, there were not enough colors. Screen
+       controllers could only support a limited number of colors
+       simultaneously (initially 2, then 4, 16 and 256). Because of
+       this, an application could not just ask to draw in a "light
+       purple-red" color, and expect that color to be available. Each
+       application allocated the colors it needed, and when all the
+       color entries (4, 16, 256 colors) were in use, the next color
+       allocation would fail.
+       </p>      
+       <p>
+       Thus, the notion of "a color map" was introduced. A color map
+       is a table whose size is the same as the number of
+       simultaneous colors a given screen controller. Each entry
+       contained the RGB (Red, Green and Blue) values of a different
+       color (all colors can be drawn using some combination of red,
+       green and blue). When an application wants to draw on the
+       screen, it does not specify which color to use. Rather, it
+       specifies which color entry of some color map to be used
+       during this drawing. Change the value in this color map entry
+       and the drawing will use a different color.
+       </p>
+       <p>
+       In order to be able to draw using colors that got something to
+       do with what the programmer intended, color map allocation
+       functions are supplied. You could ask to allocate entry for a
+       color with a set of RGB values. If one already existed, you
+       would get its index in the table. If none existed, and the
+       table was not full, a new cell would be allocated to contain
+       the given RGB values, and its index returned. If the table was
+       full, the procedure would fail. You could then ask to get a
+       color map entry with a color that is closest to the one you
+       were asking for. This would mean that the actual drawing on
+       the screen would be done using colors similar to what you
+       wanted, but not the same.
+       </p>
+       <p>
+       On today's more modern screens where one runs an X server with
+       support for 16 million colors, this limitation looks a little
+       silly, but remember that there are still older computers with
+       older graphics cards out there. Using color map, support for
+       these screen becomes transparent to you. On a display
+       supporting 16 million colors, any color entry allocation
+       request would succeed. On a display supporting a limited
+       number of colors, some color allocation requests would return
+       similar colors. It won't look as good, but your application
+       would still work.
+       </p>
+        <li class="subtitle"><a name="colormapalloc">Allocating and freeing Color Maps</a></li>
+       <p>
+       When you draw using XCB, you can choose to use the standard
+       color map of the screen your window is displayed on, or you
+       can allocate a new color map and apply it to a window. In the
+       latter case, each time the mouse moves onto your window, the
+       screen color map will be replaced by your window's color map,
+       and you'll see all the other windows on screen change their
+       colors into something quite bizzare. In fact, this is the
+       effect you get with X applications that use the "-install"
+       command line option.
+       </p>
+       <p>
+       In XCB, a color map is (as often in X) an Id:
+       </p>
+       <pre class="code">
+typedef struct {
+    CARD32 xid;
+} XCBCOLORMAP;
+</pre>
+       <p>
+       In order to access the screen's default color map, you just
+       have to retrieve the <span class="code">default_colormap</span> 
+       field of the <span class="code">XCBSCREEN</span> structure
+       (see Section
+       <a href="#screen">Checking basic information about a connection</a>):
+       </p>
+       <pre class="code">
+#include &lt;stdio.h&gt;
+
+#include &lt;X11/XCB/xcb.h&gt;
+
+int
+main (int argc, char *argv[])
+{
+  XCBConnection *c;
+  XCBSCREEN     *screen;
+  XCBCOLORMAP    colormap;
+  
+  /* Open the connection to the X server and get the first screen */
+  c = XCBConnect (NULL, NULL);
+  screen = XCBConnSetupSuccessRepRootsIter (XCBGetSetup (c)).data;
+
+  colormap = screen-&gt;default_colormap;
+
+  return 1;
+}
+</pre>
+       <p>
+       This will return the color map used by default on the first
+       screen (again, remember that an X server may support several
+       different screens, each of which might have its own resources).
+       </p>
+       <p>
+       The other option, that of allocating a new colormap, works as
+       follows.  We first ask the X server to give an Id to our color
+       map, with this function:
+       </p>
+       <pre class="code">
+XCBCOLORMAP XCBCOLORMAPNew (XCBConnection *c);
+</pre>
+       <p>
+       Then, we create the color map with
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBCreateColormap (XCBConnection *c,       /* Pointer to the XCBConnection structure */
+                                 BYTE           alloc,   /* Colormap entries to be allocated (AllocNone or AllocAll) */
+                                XCBCOLORMAP    mid,     /* Id of the color map */
+                                XCBWINDOW      window,  /* Window on whose screen the colormap will be created */
+                                XCBVISUALID    visual); /* Id of the visual supported by the screen */
+</pre>
+       <p>
+       Here is an example of creation of a new color map:
+       </p>
+       <pre class="code">
+#include &lt;X11/XCB/xcb.h&gt;
+
+int
+main (int argc, char *argv[])
+{
+  XCBConnection *c;
+  XCBSCREEN     *screen;
+  XCBWINDOW      win;
+  XCBCOLORMAP    cmap
+  
+  /* Open the connection to the X server and get the first screen */
+  c = XCBConnect (NULL, NULL);
+  screen = XCBConnSetupSuccessRepRootsIter (XCBGetSetup (c)).data;
+
+  /* We create the window win here*/
+
+  cmap = XCBCOLORMAPNew (c);
+  XCBCreateColormap (c, AllocNone, cmap, win, screen-&gt;root_visual);
+
+  return 1;
+}
+</pre>
+        <p>
+       Note that the window parameter is only used to allow the X
+       server to create the color map for the given screen. We can
+       then use this color map for any window drawn on the same screen.
+       </p>
+       <p>
+       To free  a color map, it suffices to use this function:
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBFreeColormap (XCBConnection *c,   /* The connection */
+                               XCBCOLORMAP cmap);  /* The color map */
+</pre>
+        <div class="comp">
+          <div class="title">
+           Comparison Xlib/XCB
+          </div>
+         <div class="xlib">
+         <ul>
+           <li>XCreateColormap ()</li>
+         </ul>
+         </div>
+         <div class="xcb">
+         <ul>
+            <li>XCBCOLORMAPNew ()</li>
+           <li>XCBCreateColormap ()</li>
+         </ul>
+         </div>
+         <div class="xlib">
+         <ul>
+           <li>XFreeColormap ()</li>
+         </ul>
+         </div>
+         <div class="xcb">
+         <ul>
+           <li>XCBFreeColormap ()</li>
+         </ul>
+         </div>
+        </div>
+       <p></p>
+        <li class="subtitle"><a name="alloccolor">Allocating and freeing a color entry</a></li>
+       <p>
+       Once we got access to some color map, we can strat allocating
+       colors. The informations related to a color are stored in the
+       following structure:
+       </p>
+       <pre class="code">
+typedef struct {
+    BYTE response_type;
+    CARD8 pad0;
+    CARD16 sequence;
+    CARD32 length;
+    CARD16 red;          /* The red component   */
+    CARD16 green;        /* The green component */
+    CARD16 blue;         /* The blue component  */
+    CARD8 pad1[2];
+    CARD32 pixel;        /* The entry in the color map, supplied by the X server */
+} XCBAllocColorRep;
+</pre>
+      <p>
+      XCB supplies these two functions to fill it:
+      </p>
+      <pre class="code">
+XCBAllocColorCookie XCBAllocColor      (XCBConnection *c,
+                                        XCBCOLORMAP    cmap,
+                                       CARD16         red,
+                                       CARD16         green,
+                                       CARD16         blue);
+XCBAllocColorRep   *XCBAllocColorReply (XCBConnection        *c,
+                                        XCBAllocColorCookie   cookie,
+                                       XCBGenericError     **e);
+</pre>
+      <p>
+      The fuction <span class="code">XCBAllocColor()</span> takes the
+      3 RGB components as parameters (red, green and blue). Here is an
+      example of using these functions:
+      </p>
+      <pre class="code">
+#include &lt;malloc.h&gt;
+
+#include &lt;X11/XCB/xcb.h&gt;
+
+int
+main (int argc, char *argv[])
+{
+  XCBConnection    *c;
+  XCBSCREEN        *screen;
+  XCBWINDOW         win;
+  XCBCOLORMAP       cmap;
+  XCBAllocColorRep *rep;
+  
+  /* Open the connection to the X server and get the first screen */
+  c = XCBConnect (NULL, NULL);
+  screen = XCBConnSetupSuccessRepRootsIter (XCBGetSetup (c)).data;
+
+  /* We create the window win here*/
+
+  cmap = XCBCOLORMAPNew (c);
+  XCBCreateColormap (c, AllocNone, cmap, win, screen-&gt;root_visual);
+
+  rep = XCBAllocColorReply (c, XCBAllocColor (c, cmap, 65535, 0, 0), 0);
+  
+  if (!rep)
+    return 0;
+
+  /* Do something with r-&gt;pixel or the components */
+
+  free (rep);
+
+  return 1;
+}
+</pre>
+      <p>
+      As <span class="code">XCBAllocColorReply()</span> allocates
+      memory, you have to free <span class="code">rep</span>.
+      </p>
+      <p>
+      <b>TODO</b>: Talk about freeing colors.
+      </p>
+      </ol>
+      <li class="title"><a name="pixmaps">X Bitmaps and Pixmaps</a></li>
+      <p>
+      One thing many so-called "Multi-Media" applications need to od,
+      is display images. In the X world, this is done using bitmaps
+      and pixmaps. We have already seen some usage of them when
+      setting an icon for our application. Lets study them further,
+      and see how to draw these images inside a window, along side the
+      simple graphics and text we have seen so far.
+      </p>
+      <p>
+      One thing to note before delving further, is that XCB (nor Xlib)
+      supplies no means of manipulating popular image formats, such as
+      gif, png, jpeg or tiff. It is up to the programmer (or to higher
+      level graphics libraries) to translate these image formats into
+      formats that the X server is familiar with (x bitmaps and x
+      pixmaps).
+      </p>
+      <ol>
+        <li class="subtitle"><a name="pixmapswhat">What is a X Bitmap ? An X Pixmap ?</a></li>
+       <p>
+       An X bitmap is a two-color image stored in a format specific
+       to the X window system. When stored in a file, the bitmap data
+       looks like a C source file. It contains variables defining the
+       width and the height of the bitmap, an array containing the
+       bit values of the bitmap (the size of the array is
+       weight*height), and an optional hot-spot location (that will
+       be explained later, when discussing mouse cursors).
+       </p>
+       <p>
+       An X pixmap is a format used to stored images in the memory of
+       an X server. This format can store both black and white images
+       (such as x bitmaps) as well as color images. It is the only
+       image format supported by the X protocol, and any image to be
+       drawn on screen, should be first translated into this format.
+       </p>
+       <p>
+       In actuality, an X pixmap can be thought of as a window that
+       does not appear on the screen. Many graphics operations that
+       work on windows, will also work on pixmaps. Indeed, the type
+       of X pixmap in XCB is an Id like a window:
+       </p>
+       <pre class="code">
+typedef struct {
+    CARD32 xid;
+} XCBPIXMAP;
+</pre>
+       <p>
+       In order to make the difference between a window and a pixmap,
+       XCB introduces a drawable type, which is a <b>union</b>
+       </p>
+       <pre class="code">
+typedef union {
+    XCBWINDOW window;
+    XCBPIXMAP pixmap;
+} XCBDRAWABLE;
+</pre>
+        <p>
+       in order to avoid confusion between a window and a pixmap.The
+       operations that will work indifferently on a window or a pixmap
+       will require a <span class="code">XCBDRAWABLE</span>
+       </p>
+       <div class="emph">
+       <p>
+       Remark: In Xlib, there is no specific difference between a
+       <span class="code">Drawable</span>, a
+       <span class="code">Pixmap</span> or a
+       <span class="code">Window</span>: all are 32 bit long
+       integer.
+       </p>
+       </div>
+        <li class="subtitle"><a name="pixmapscreate">Creating a pixmap</a></li>
+       <p>
+       Sometimes we want to create an un-initialized pixmap, so we
+       can later draw into it. This is useful for image drawing
+       programs (creating a new empty canvas will cause the creation
+       of a new pixmap on which the drawing can be stored). It is
+       also useful when reading various image formats: we load the
+       image data into memory, create a pixmap on the server, and
+       then draw the decoded image data onto that pixmap.
+       </p>
+       <p>
+       To create a new pixmap, we first ask the X server to give an
+       Id to our pixmap, with this function: 
+       </p>
+       <pre class="code">
+XCBPIXMAP XCBPIXMAPNew (XCBConnection *c);
+</pre>
+        <p>
+        Then, XCB supplies the following function to create new pixmaps:
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBCreatePixmap (XCBConnection *c,         /* Pointer to the XCBConnection structure */
+                               CARD8          depth,     /* Depth of the screen */
+                              XCBPIXMAP      pid,       /* Id of the pixmap */
+                              XCBDRAWABLE    drawable,
+                              CARD16         width,     /* Width of the window (in pixels) */
+                              CARD16         height);   /* Height of the window (in pixels) */
+</pre>
+        <p>
+       <b>TODO</b>: Explain the drawable parameter, and give an
+       example (like xpoints.c)
+       </p>
+        <li class="subtitle"><a name="pixmapsdraw"></a>Drawing a pixmap in a window</li>
+       <p>
+       Once we got a handle to a pixmap, we can draw it on some
+       window, using the following function:
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBCopyArea (XCBConnection *c,             /* Pointer to the XCBConnection structure */
+                           XCBDRAWABLE    src_drawable,  /* The Drawable we want to paste */
+                          XCBDRAWABLE    dst_drawable,  /* The Drawable on which we copy the previous Drawable */
+                          XCBGCONTEXT    gc,            /* A Graphic Context */
+                          INT16          src_x,         /* Top left x coordinate of the region we want to copy */
+                          INT16          src_y,         /* Top left y coordinate of the region we want to copy */
+                          INT16          dst_x,         /* Top left x coordinate of the region where we want to copy */
+                          INT16          dst_y,         /* Top left y coordinate of the region where we want to copy */
+                          CARD16         width,         /* Width of the region we want to copy */
+                          CARD16         height);       /* Height of the region we want to copy */
+</pre>
+       <p>
+       As you can see, we could copy the whole pixmap, as well as
+       only a given rectangle of the pixmap. This is useful to
+       optimize the drawing speed: we could copy only what we have
+       modified in the pixmap.
+       </p>
+       <p>
+       <b>One important note should be made</b>: it is possible to
+       create pixmaps with different depths on the same screen. When
+       we perform copy operations (a pixmaap onto a window, etc), we
+       should make sure that both source and target have the same
+       depth. If they have a different depth, the operation would
+       fail. The exception to this is if we copy a specific bit plane
+       of the source pixmap using the
+       <span class="code">XCBCopyPlane</span> function. In such an
+       event, we can copy a specific plain to the target window (in
+       actuality, setting a specific bit in the color of each pixel
+       copied). This can be used to generate strange graphic effects
+       in widow, but beyond the scope of this tutorial.
+       </p>
+        <li class="subtitle"><a name="pixmapsfree"></a>Freeing a pixmap</li>
+       <p>
+       Finally, when we are done using a given pixmap, we should free
+       it, in order to free resources of the X server. This is done
+       using this function:
+       </p>
+       <pre class="code">
+XCBVoidCookie XCBFreePixmap (XCBConnection *c,        /* Pointer to the XCBConnection structure */
+                             XCBPIXMAP      pixmap);  /* A given pixmap */
+</pre>
+       <p>
+       Of course, after having freed it, we must not try accessing
+       the pixmap again.
+       </p>
+       <p>
+       <b>TODO</b>: Give an example, or a link to xpoints.c
+       </p>
+      </ol>
+      <li class="title"><a name="translation">Translation of basic Xlib functions and macros</a></li>
+      <p>
+      The problem when you want to port an Xlib program to XCB is that
+      you don't know if the Xlib function that you want to "translate"
+      is a X Window one or an Xlib macro. In that section, we describe
+      a way to translate the usual functions or macros that Xlib
+      provides. It's usually just a member of a structure.
+      </p>
+      <ol>
+        <li class="subtitle"><a name="displaystructure">Members of the Display structure</a></li>
+        In this section, we look at how to translate the macros that
+        returns some members of the <span class="code">Display</span>
+        structure. They are obtain by using a function that requires a
+        <span class="code">XCBConnection *</span> or a member of the
+        <span class="code">XCBConnSetupSuccessRep</span> structure
+        (via the function <span class="code">XCBGetSetup</span>), or
+        a function that requires that structure.
+        <ol>
+          <li class="subtitle"><a name="ConnectionNumber">ConnectionNumber</a></li>
+          <p>
+          This number is the file descriptor that connects the client
+          to the server. You just have to use that function:
+          </p>
+          <pre class="code">
+int XCBGetFileDescriptor(XCBConnection *c);
+</pre>
+          <li class="subtitle"><a name="DefaultScreen"></a>DefaultScreen</li>
+          <p>
+          That number is not stored by XCB. It is returned in the
+          second parameter of the function <span class="code"><a href="#openconn">XCBConnect</a></span>.
+          Hence, you have to store it yourself if you want to use
+          it. Then, to get the <span class="code">XCBSCREEN</span>
+          structure, you have to iterate on the screens.
+          The equivalent function of the Xlib's
+          <span class="code">ScreenOfDisplay</span> function can be
+          found <a href="#ScreenOfDisplay">below</a>. OK, here is the
+          small piece of code to get that number:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+int            screen_default_nbr;
+
+/* you pass the name of the display you want to XCBConnect */
+
+c = XCBConnect (display_name, &screen_default_nbr);
+
+/* screen_default_nbr contains now the number of the default screen */
+</pre>
+          <li class="subtitle"><a name="QLength"></a>QLength</li>
+          <p>
+          Not documented yet.
+          </p>
+          <li class="subtitle"><a name="ScreenCount"></a>ScreenCount</li>
+          <p>
+          You get the count of screens with the functions
+          <span class="code">XCBGetSetup</span>
+          and
+          <span class="code">XCBConnSetupSuccessRepRootsIter</span>
+          (if you need to iterate):
+          </p>
+          <pre class="code">
+XCBConnection *c;
+int            screen_count;
+
+/* you init the connection */
+
+screen_count = XCBConnSetupSuccessRepRootsIter (XCBGetSetup (c)).rem;
+
+/* screen_count contains now the count of screens */
+</pre>
+          <p>
+          If you don't want to iterate over the screens, a better way
+          to get that number is to use
+          <span class="code">XCBConnSetupSuccessRepRootsLength</span>:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+int            screen_count;
+
+/* you init the connection */
+
+screen_count = XCBConnSetupSuccessRepRootsLength (XCBGetSetup (c));
+
+/* screen_count contains now the count of screens */
+</pre>
+          <li class="subtitle"><a name="ServerVendor"></a>ServerVendor</li>
+          <p>
+          You get the name of the vendor of the server hardware with
+          the functions <span class="code">XCBGetSetup</span>
+          and
+          <span
+          class="code">XCBConnSetupSuccessRepVendor</span>. Beware
+          that, unlike Xlib, the string returned by XCB is not
+          necessarily null-terminaled:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+char          *vendor = NULL;
+int            length;
+
+/* you init the connection */
+length = XCBConnSetupSuccessRepVendorLength (XCBGetSetup (c));
+vendor = (char *)malloc (length + 1);
+if (vendor)
+memcpy (vendor, XCBConnSetupSuccessRepVendor (XCBGetSetup (c)), length);
+vendor[length] = '\0';
+
+/* vendor contains now the name of the vendor. Must be freed when not used anymore */
+</pre>
+          <li class="subtitle"><a name="ProtocolVersion"></a>ProtocolVersion</li>
+          <p>
+          You get the major version of the protocol in the
+          <span class="code">XCBConnSetupSuccessRep</span>
+          structure, with the function <span class="code">XCBGetSetup</span>:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+CARD16         protocol_major_version;
+
+/* you init the connection */
+
+protocol_major_version = XCBGetSetup (c)-&gt;protocol_major_version;
+
+/* protocol_major_version contains now the major version of the protocol */
+</pre>
+          <li class="subtitle"><a name="ProtocolRevision"></a>ProtocolRevision</li>
+          <p>
+          You get the minor version of the protocol in the
+          <span class="code">XCBConnSetupSuccessRep</span>
+          structure, with the function <span class="code">XCBGetSetup</span>:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+CARD16         protocol_minor_version;
+
+/* you init the connection */
+
+protocol_minor_version = XCBGetSetup (c)-&gt;protocol_minor_version;
+
+/* protocol_minor_version contains now the minor version of the protocol */
+</pre>
+          <li class="subtitle"><a name="VendorRelease"></a>VendorRelease</li>
+          <p>
+          You get the number of the release of the server hardware in the
+          <span class="code">XCBConnSetupSuccessRep</span>
+          structure, with the function <span class="code">XCBGetSetup</span>:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+CARD32         release_number;
+
+/* you init the connection */
+
+release_number = XCBGetSetup (c)-&gt;release_number;
+
+/* release_number contains now the number of the release of the server hardware */
+</pre>
+          <li class="subtitle"><a name="DisplayString"></a>DisplayString</li>
+          <p>
+          The name of the display is not stored in XCB. You have to
+          store it by yourself.
+          </p>
+          <li class="subtitle"><a name="BitmapUnit"></a>BitmapUnit</li>
+          <p>
+          You get the bitmap scanline unit in the
+          <span class="code">XCBConnSetupSuccessRep</span>
+          structure, with the function <span class="code">XCBGetSetup</span>:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+CARD8          bitmap_format_scanline_unit;
+
+/* you init the connection */
+
+bitmap_format_scanline_unit = XCBGetSetup (c)-&gt;bitmap_format_scanline_unit;
+
+/* bitmap_format_scanline_unit contains now the bitmap scanline unit */
+</pre>
+          <li class="subtitle"><a name="BitmapBitOrder"></a>BitmapBitOrder</li>
+          <p>
+          You get the bitmap bit order in the
+          <span class="code">XCBConnSetupSuccessRep</span>
+          structure, with the function <span class="code">XCBGetSetup</span>:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+CARD8          bitmap_format_bit_order;
+
+/* you init the connection */
+
+bitmap_format_bit_order = XCBGetSetup (c)-&gt;bitmap_format_bit_order;
+
+/* bitmap_format_bit_order contains now the bitmap bit order */
+</pre>
+          <li class="subtitle"><a name="BitmapPad"></a>BitmapPad</li>
+          <p>
+          You get the bitmap scanline pad in the
+          <span class="code">XCBConnSetupSuccessRep</span>
+          structure, with the function <span class="code">XCBGetSetup</span>:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+CARD8          bitmap_format_scanline_pad;
+
+/* you init the connection */
+
+bitmap_format_scanline_pad = XCBGetSetup (c)-&gt;bitmap_format_scanline_pad;
+
+/* bitmap_format_scanline_pad contains now the bitmap scanline pad */
+</pre>
+          <li class="subtitle"><a name="ImageByteOrder"></a>ImageByteOrder</li>
+          <p>
+          You get the image byte order in the
+          <span class="code">XCBConnSetupSuccessRep</span>
+          structure, with the function <span class="code">XCBGetSetup</span>:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+CARD8          image_byte_order;
+
+/* you init the connection */
+
+image_byte_order = XCBGetSetup (c)-&gt;image_byte_order;
+
+/* image_byte_order contains now the image byte order */
+</pre>
+        </ol>
+      <li class="subtitle"><a name="screenofdisplay">ScreenOfDisplay related functions</a></li>
+      <p>
+      in Xlib, <span class="code">ScreenOfDisplay</span> returns a
+      <span class="code">Screen</span> structure that contains
+      several characteristics of your screen. XCB has a similar
+      structure (<span class="code">XCBSCREEN</span>),
+      but the way to obtain it is a bit different. With
+      Xlib, you just provide the number of the screen and you grab it
+      from an array. With XCB, you iterate over all the screens to
+      obtain the one you want. The complexity of this operation is
+      O(n). So the best is to store this structure if you often use
+      it. See <a href="#ScreenOfDisplay">ScreenOfDisplay</a> just below.
+      </p>
+      <p>
+      Xlib provides generally two functions to obtain the characteristics
+      related to the screen. One with the display and the number of
+      the screen, which calls <span class="code">ScreenOfDisplay</span>,
+      and the other that uses the <span class="code">Screen</span> structure.
+      This might be a bit confusing. As mentioned above, with XCB, it
+      is better to store the <span class="code">XCBSCREEN</span>
+      structure. Then, you have to read the members of this
+      structure. That's why the Xlib functions are put by pairs (or
+      more) as, with XCB, you will use the same code.
+      </p>
+        <ol>
+          <li class="subtitle"><a name="ScreenOfDisplay">ScreenOfDisplay</a></li>
+          <p>
+          This function returns the Xlib <span class="code">Screen</span>
+          structure. With XCB, you iterate over all thee screens and
+          once you get the one you want, you return it:
+          </p>
+          <pre class="code"><a name="ScreenOfDisplay"></a>
+XCBSCREEN *ScreenOfDisplay (XCBConnection *c,
+                            int            screen)
+{
+  XCBSCREENIter iter;
+
+  iter = XCBConnSetupSuccessRepRootsIter (XCBGetSetup (c));
+  for (; iter.rem; --screen, XCBSCREENNext (&iter))
+    if (screen == 0)
+      return iter.data;
+
+  return NULL;
+}
+</pre>
+          <p>
+          As mentioned above, you might want to store the value
+          returned by this function.
+          </p>
+          <p>
+          All the functions below will use the result of that
+          fonction, as they just grab a specific member of the
+          <span class="code">XCBSCREEN</span> structure.
+          </p>
+          <li class="subtitle"><a name="DefaultScreenOfDisplay"></a>DefaultScreenOfDisplay</li>
+          <p>
+          It is the default screen that you obtain when you connect to
+          the X server. It suffices to call the <a href="#ScreenOfDisplay">ScreenOfDisplay</a>
+          function above with the connection and the number of the
+          default screen.
+          </p>
+          <pre class="code">
+XCBConnection *c;
+int            screen_default_nbr;
+XCBSCREEN     *default_screen;  /* the returned default screen */
+
+/* you pass the name of the display you want to XCBConnect */
+
+c = XCBConnect (display_name, &screen_default_nbr);
+default_screen = ScreenOfDisplay (c, screen_default_nbr);
+
+/* default_screen contains now the default root window, or a NULL window if no screen is found */
+</pre>
+          <li class="subtitle"><a name="RootWindow">RootWindow / RootWindowOfScreen</a></li>
+          <p>
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_nbr;
+XCBWINDOW      root_window = { 0 };  /* the returned window */
+
+/* you init the connection and screen_nbr */
+
+screen = ScreenOfDisplay (c, screen_nbr);
+if (screen)
+  root_window = screen-&gt;root;
+
+/* root_window contains now the root window, or a NULL window if no screen is found */
+</pre>
+          <li class="subtitle"><a name="DefaultRootWindow">DefaultRootWindow</a></li>
+          <p>
+          It is the root window of the default screen. So, you call
+          <a name="ScreenOfDisplay">ScreenOfDisplay</a> with the
+          default screen number and you get the
+          <a href="#RootWindow">root window</a> as above:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_default_nbr;
+XCBWINDOW      root_window = { 0 };  /* the returned root window */
+
+/* you pass the name of the display you want to XCBConnect */
+
+c = XCBConnect (display_name, &screen_default_nbr);
+screen = ScreenOfDisplay (c, screen_default_nbr);
+if (screen)
+  root_window = screen-&gt;root;
+
+/* root_window contains now the default root window, or a NULL window if no screen is found */
+</pre>
+          <li class="subtitle"><a name="DefaultVisual">DefaultVisual / DefaultVisualOfScreen</a></li>
+          <p>
+          While a Visual is, in Xlib, a structure, in XCB, there are
+          two types: <span class="code">XCBVISUALID</span>, which is
+          the Id of the visual, and <span class="code">XCBVISUALTYPE</span>,
+          which corresponds to the Xlib Visual. To get the Id of the
+          visual of a screen, just get the
+           <span class="code">root_visual</span>
+           member of a <span class="code">XCBSCREEN</span>:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_nbr;
+XCBVISUALID    root_visual = { 0 };    /* the returned visual Id */
+
+/* you init the connection and screen_nbr */
+
+screen = ScreenOfDisplay (c, screen_nbr);
+if (screen)
+  root_visual = screen-&gt;root_visual;
+
+/* root_visual contains now the value of the Id of the visual, or a NULL visual if no screen is found */
+</pre>
+          <p>
+          To get the <span class="code">XCBVISUALTYPE</span>
+          structure, it's a bit less easier. You have to get the
+          <span class="code">XCBSCREEN</span> structure that you want,
+          get its <span class="code">root_visual</span> member,
+          then iterate on the <span class="code">XCBDEPTH</span>s
+          and the <span class="code">XCBVISUALTYPE</span>s, and compare
+          the <span class="code">XCBVISUALID</span> of these <span class="code">XCBVISUALTYPE</span>s:
+          with <span class="code">root_visual</span>:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_nbr;
+XCBVISUALID    root_visual = { 0 };
+XCBVISUATYPE  *visual_type = NULL;    /* the returned visual type */
+
+/* you init the connection and screen_nbr */
+
+screen = ScreenOfDisplay (c, screen_nbr);
+if (screen)
+  {
+    XCBDEPTHIter depth_iter;
+
+    depth_iter = XCBSCREENAllowedDepthsIter (screen);
+    for (; depth_iter.rem; XCBDEPTHNext (&depth_iter))
+      {
+        XCBVISUALTYPEIter visual_iter;
+
+        visual_iter = XCBDEPTHVisualsIter (depth_iter.data);
+        for (; visual_iter.rem; XCBVISUALTYPENext (&visual_iter))
+          {
+            if (screen-&gt;root_visual.id == visual_iter.data-&gt;visual_id.id)
+              {
+                visual_type = visual_iter.data;
+                break;
+              }
+          }
+      }
+  }
+
+/* visual_type contains now the visual structure, or a NULL visual structure if no screen is found */
+</pre>
+          <li class="subtitle"><a name="DefaultGC">DefaultGC / DefaultGCOfScreen</a></li>
+          <p>
+          This default Graphic Context is just a newly created Graphic
+          Context, associated to the root window of a
+          <span class="code">XCBSCREEN</span>,
+          using the black white pixels of that screen:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_nbr;
+XCBGCONTEXT    gc = { 0 };    /* the returned default graphic context */
+
+/* you init the connection and screen_nbr */
+
+screen = ScreenOfDisplay (c, screen_nbr);
+if (screen)
+  {
+    XCBDRAWABLE draw;
+    CARD32      mask;
+    CARD32      values[2];
+
+    gc = XCBGCONTEXTNew (c);
+    draw.window = screen-&gt;root;
+    mask = GCForeground | GCBackground;
+    values[0] = screen-&gt;black_pixel;
+    values[1] = screen-&gt;white_pixel;
+    XCBCreateGC (c, gc, draw, mask, values);
+  }
+
+/* gc contains now the default graphic context */
+</pre>
+          <li class="subtitle"><a name="BlackPixel">BlackPixel / BlackPixelOfScreen</a></li>
+          <p>
+          It is the Id of the black pixel, which is in the structure
+          of an <span class="code">XCBSCREEN</span>.
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_nbr;
+CARD32         black_pixel = 0;    /* the returned black pixel */
+
+/* you init the connection and screen_nbr */
+
+screen = ScreenOfDisplay (c, screen_nbr);
+if (screen)
+  black_pixel = screen-&gt;black_pixel;
+
+/* black_pixel contains now the value of the black pixel, or 0 if no screen is found */
+</pre>
+          <li class="subtitle"><a name="WhitePixel">WhitePixel / WhitePixelOfScreen</a></li>
+          <p>
+          It is the Id of the white pixel, which is in the structure
+          of an <span class="code">XCBSCREEN</span>.
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_nbr;
+CARD32         white_pixel = 0;    /* the returned white pixel */
+
+/* you init the connection and screen_nbr */
+
+screen = ScreenOfDisplay (c, screen_nbr);
+if (screen)
+  white_pixel = screen-&gt;white_pixel;
+
+/* white_pixel contains now the value of the white pixel, or 0 if no screen is found */
+</pre>
+          <li class="subtitle"><a name="DisplayWidth">DisplayWidth / WidthOfScreen</a></li>
+          <p>
+          It is the width in pixels of the screen that you want, and
+          which is in the structure of the corresponding
+          <span class="code">XCBSCREEN</span>.
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_nbr;
+CARD32         width_in_pixels = 0;    /* the returned width in pixels */
+
+/* you init the connection and screen_nbr */
+
+screen = ScreenOfDisplay (c, screen_nbr);
+if (screen)
+  width_in_pixels = screen-&gt;width_in_pixels;
+
+/* width_in_pixels contains now the width in pixels, or 0 if no screen is found */
+</pre>
+          <li class="subtitle"><a name="DisplayHeight">DisplayHeight / HeightOfScreen</a></li>
+          <p>
+          It is the height in pixels of the screen that you want, and
+          which is in the structure of the corresponding
+          <span class="code">XCBSCREEN</span>.
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_nbr;
+CARD32         height_in_pixels = 0;    /* the returned height in pixels */
+
+/* you init the connection and screen_nbr */
+
+screen = ScreenOfDisplay (c, screen_nbr);
+if (screen)
+  height_in_pixels = screen-&gt;height_in_pixels;
+
+/* height_in_pixels contains now the height in pixels, or 0 if no screen is found */
+</pre>
+          <li class="subtitle"><a name="DisplayWidthMM">DisplayWidthMM / WidthMMOfScreen</a></li>
+          <p>
+          It is the width in millimeters of the screen that you want, and
+          which is in the structure of the corresponding
+          <span class="code">XCBSCREEN</span>.
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_nbr;
+CARD32         width_in_millimeters = 0;    /* the returned width in millimeters */
+
+/* you init the connection and screen_nbr */
+
+screen = ScreenOfDisplay (c, screen_nbr);
+if (screen)
+  width_in_millimeters = screen-&gt;width_in_millimeters;
+
+/* width_in_millimeters contains now the width in millimeters, or 0 if no screen is found */
+</pre>
+          <li class="subtitle"><a name="DisplayHeightMM">DisplayHeightMM / HeightMMOfScreen</a></li>
+          <p>
+          It is the height in millimeters of the screen that you want, and
+          which is in the structure of the corresponding
+          <span class="code">XCBSCREEN</span>.
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_nbr;
+CARD32         height_in_millimeters = 0;    /* the returned height in millimeters */
+
+/* you init the connection and screen_nbr */
+
+screen = ScreenOfDisplay (c, screen_nbr);
+if (screen)
+  height_in_millimeters = screen-&gt;height_in_millimeters;
+
+/* height_in_millimeters contains now the height in millimeters, or 0 if no screen is found */
+</pre>
+          <li class="subtitle"><a name="DisplayPlanes">DisplayPlanes / DefaultDepth / DefaultDepthOfScreen / PlanesOfScreen</a></li>
+          <p>
+          It is the depth (in bits) of the root window of the
+          screen. You get it from the <span class="code">XCBSCREEN</span> structure.
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_nbr;
+CARD8          root_depth = 0;  /* the returned depth of the root window */
+
+/* you init the connection and screen_nbr */
+
+screen = ScreenOfDisplay (c, screen_nbr);
+if (screen)
+  root_depth = screen-&gt;root_depth;
+
+/* root_depth contains now the depth of the root window, or 0 if no screen is found */
+</pre>
+          <li class="subtitle"><a name="DefaultColormap">DefaultColormap / DefaultColormapOfScreen</a></li>
+          <p>
+          This is the default colormap of the screen (and not the
+          (default) colormap of the default screen !). As usual, you
+          get it from the <span class="code">XCBSCREEN</span> structure:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_nbr;
+XCBCOLORMAP    default_colormap = { 0 };  /* the returned default colormap */
+
+/* you init the connection and screen_nbr */
+
+screen = ScreenOfDisplay (c, screen_nbr);
+if (screen)
+  default_colormap = screen-&gt;default_colormap;
+
+/* default_colormap contains now the default colormap, or a NULL colormap if no screen is found */
+</pre>
+          <li class="subtitle"><a name="MinCmapsOfScreen"></a>MinCmapsOfScreen</li>
+          <p>
+          You get the minimum installed colormaps in the <span class="code">XCBSCREEN</span> structure:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_nbr;
+CARD16         min_installed_maps = 0;  /* the returned minimum installed colormaps */
+
+/* you init the connection and screen_nbr */
+
+screen = ScreenOfDisplay (c, screen_nbr);
+if (screen)
+  min_installed_maps = screen-&gt;min_installed_maps;
+
+/* min_installed_maps contains now the minimum installed colormaps, or 0 if no screen is found */
+</pre>
+          <li class="subtitle"><a name="MaxCmapsOfScreen"></a>MaxCmapsOfScreen</li>
+          <p>
+          You get the maximum installed colormaps in the <span class="code">XCBSCREEN</span> structure:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_nbr;
+CARD16         max_installed_maps = 0;  /* the returned maximum installed colormaps */
+
+/* you init the connection and screen_nbr */
+
+screen = ScreenOfDisplay (c, screen_nbr);
+if (screen)
+  max_installed_maps = screen-&gt;max_installed_maps;
+
+/* max_installed_maps contains now the maximum installed colormaps, or 0 if no screen is found */
+</pre>
+          <li class="subtitle"><a name="DoesSaveUnders"></a>DoesSaveUnders</li>
+          <p>
+          You know if <span class="code">save_unders</span> is set,
+          by looking in the <span class="code">XCBSCREEN</span> structure:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_nbr;
+BOOL           save_unders = 0;  /* the returned value of save_unders */
+
+/* you init the connection and screen_nbr */
+
+screen = ScreenOfDisplay (c, screen_nbr);
+if (screen)
+  save_unders = screen-&gt;save_unders;
+
+/* save_unders contains now the value of save_unders, or FALSE if no screen is found */
+</pre>
+          <li class="subtitle"><a name="DoesBackingStore"></a>DoesBackingStore</li>
+          <p>
+          You know the value of <span class="code">backing_stores</span>,
+          by looking in the <span class="code">XCBSCREEN</span> structure:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_nbr;
+BYTE           backing_stores = 0;  /* the returned value of backing_stores */
+
+/* you init the connection and screen_nbr */
+
+screen = ScreenOfDisplay (c, screen_nbr);
+if (screen)
+  backing_stores = screen-&gt;backing_stores;
+
+/* backing_stores contains now the value of backing_stores, or FALSE if no screen is found */
+</pre>
+          <li class="subtitle"><a name="EventMaskOfScreen"></a>EventMaskOfScreen</li>
+          <p>
+          To get the current input masks,
+          you look in the <span class="code">XCBSCREEN</span> structure:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBSCREEN     *screen;
+int            screen_nbr;
+CARD32         current_input_masks = 0;  /* the returned value of current input masks */
+
+/* you init the connection and screen_nbr */
+
+screen = ScreenOfDisplay (c, screen_nbr);
+if (screen)
+  current_input_masks = screen-&gt;current_input_masks;
+
+/* current_input_masks contains now the value of the current input masks, or FALSE if no screen is found */
+</pre>
+        </ol>
+      <li class="subtitle"><a name="misc">Miscellaneous macros</a></li>
+        <ol>
+          <li class="subtitle"><a name="DisplayOfScreen"></a>DisplayOfScreen</li>
+          <p> 
+          in Xlib, the <span class="code">Screen</span> structure
+          stores its associated <span class="code">Display</span>
+          structure. This is not the case in the X Window protocol,
+          hence, it's also not the case in XCB. So you have to store
+          it by yourself.
+          </p>
+          <li class="subtitle"><a name="DisplayCells"></a>DisplayCells / CellsOfScreen</li>
+          <p>
+          To get the colormap entries,
+          you look in the <span class="code">XCBVISUALTYPE</span>
+          structure, that you grab like <a class="subsection" href="#DefaultVisual">here</a>:
+          </p>
+          <pre class="code">
+XCBConnection *c;
+XCBVISUALTYPE *visual_type;
+CARD16         colormap_entries = 0;  /* the returned value of the colormap entries */
+
+/* you init the connection and visual_type */
+
+if (visual_type)
+  colormap_entries = visual_type-&gt;colormap_entries;
+
+/* colormap_entries contains now the value of the colormap entries, or FALSE if no screen is found */
+</pre>
+        </ol>
+      </ol>
+    </ol>
+  </div>
+</body>
+
+</html>
diff --git a/doc/tutorial/xcb.css b/doc/tutorial/xcb.css
new file mode 100755 (executable)
index 0000000..84352c5
--- /dev/null
@@ -0,0 +1,82 @@
+body
+{ 
+  background-color: #dddddd;
+  color: #000000;
+  padding: 8px;
+  margin: 0px;
+}
+div.title
+{
+  text-align: center;
+  font-weight: bold;
+  font-size: 28px;
+}
+div.emph
+{
+  text-align: left;
+  font-weight: bold;
+}
+div.section li.title
+{
+  font-weight: bold;
+  font-size: 22px;
+}
+div.section li.subtitle
+{
+  font-weight: bold;
+  font-size: 18px;
+}
+div.section li.subsubtitle
+{
+  font-weight: bold;
+  font-size: 16px;
+}
+div.comp
+{
+  border: thin solid #000000;
+  background-color: #ffffe0;
+  padding: 14px;
+}
+div.comp div.title
+{
+  font-weight: bold;
+  font-size: 16px;
+  text-align: center;
+}
+div.comp div.xlib
+{
+  font-family: monospace;
+  position: absolute;
+  width: 49%;
+  margin-left: 0px; 
+  margin-top: 10px;
+}
+div.comp div.xcb
+{
+  font-family: monospace;
+  position: relative;
+  margin-left: 51%;
+  margin-top: 10px;
+}
+pre.code
+{
+  border: thin solid #000000;
+  background-color: #efefef;
+  padding: 4px;
+  text-align: left;
+  font-size: 10;
+}
+pre.text
+{
+  border: thin solid #000000;
+  background-color: #efefef;
+  padding: 4px;
+  text-align: left;
+  font-size: 10;
+}
+span.code
+{
+  font-family: monospace;
+  font-size: 10;
+}
+
diff --git a/src/.cvsignore b/src/.cvsignore
new file mode 100644 (file)
index 0000000..adf4164
--- /dev/null
@@ -0,0 +1,17 @@
+.deps
+.libs
+Makefile
+Makefile.in
+config.h
+config.h.in
+stamp-h1
+*.lo
+*.loT
+*.la
+xproto.c
+xproto.h
+xcb_types.c
+xcb_types.h
+extensions
+X11
+check_all
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..8d43475
--- /dev/null
@@ -0,0 +1,83 @@
+lib_LTLIBRARIES = libXCB.la
+
+EXTHEADERS = \
+               extensions/bigreq.h \
+               extensions/composite.h \
+               extensions/damage.h \
+               extensions/glx.h \
+               extensions/shm.h \
+               extensions/shape.h \
+               extensions/randr.h \
+               extensions/record.h \
+               extensions/render.h \
+               extensions/res.h \
+               extensions/dpms.h \
+               extensions/sync.h \
+               extensions/xc_misc.h \
+               extensions/xevie.h \
+               extensions/xf86dri.h \
+               extensions/xfixes.h \
+               extensions/xprint.h \
+               extensions/xv.h \
+               extensions/xvmc.h
+EXTSOURCES = \
+               extensions/bigreq.c \
+               extensions/composite.c \
+               extensions/damage.c \
+               extensions/glx.c \
+               extensions/shm.c \
+               extensions/shape.c \
+               extensions/randr.c \
+               extensions/record.c \
+               extensions/render.c \
+               extensions/res.c \
+               extensions/dpms.c \
+               extensions/sync.c \
+               extensions/xc_misc.c \
+               extensions/xevie.c \
+               extensions/xf86dri.c \
+               extensions/xfixes.c \
+               extensions/xprint.c \
+               extensions/xv.c \
+               extensions/xvmc.c
+EXTENSIONS = $(EXTSOURCES) $(EXTHEADERS)
+
+COREHEADERS = xproto.h xcb_types.h
+CORESOURCES = xproto.c xcb_types.c
+COREPROTO   = $(CORESOURCES) $(COREHEADERS)
+
+xcbinclude_HEADERS = xcb.h xcbext.h xcbxlib.h $(COREHEADERS) $(EXTHEADERS)
+
+CFLAGS =
+AM_CFLAGS = -include config.h $(CDEBUGFLAGS) $(XCBPROTO_CFLAGS) $(XPROTO_CFLAGS) $(XAU_CFLAGS)
+libXCB_la_LIBADD = $(XCBPROTO_LIBS) $(XPROTO_LIBS) $(XAU_LIBS)
+libXCB_la_SOURCES = \
+               xcb_conn.c xcb_out.c xcb_in.c xcb_ext.c xcb_xid.c \
+               xcb_list.c xcb_util.c xcb_xlib.c xcb_auth.c xcb_des.c \
+               $(COREPROTO) $(EXTENSIONS)
+
+xcb_des.c:
+       touch xcb_des.c
+
+BUILT_SOURCES = $(COREPROTO) $(EXTENSIONS)
+CLEANFILES = $(COREPROTO) $(EXTENSIONS)
+clean-local:
+       rmdir extensions || true
+
+vpath %.xml $(XCBPROTO_XCBINCLUDEDIR) $(XCBPROTO_XCBINCLUDEDIR)/extensions
+
+%.h: %.xml c-client.xsl
+       @n=`dirname $*`; test -d $$n || (echo mkdir $$n; mkdir $$n)
+       $(XSLTPROC) --stringparam mode header \
+                   --stringparam base-path $(XCBPROTO_XCBINCLUDEDIR)/ \
+                   --stringparam extension-path \
+                                 $(XCBPROTO_XCBINCLUDEDIR)/extensions/ \
+                   -o $@ $(srcdir)/c-client.xsl $< 
+
+%.c: %.xml c-client.xsl
+       @n=`dirname $*`; test -d $$n || (echo mkdir $$n; mkdir $$n)
+       $(XSLTPROC) --stringparam mode source \
+                   --stringparam base-path $(XCBPROTO_XCBINCLUDEDIR)/ \
+                   --stringparam extension-path \
+                                 $(XCBPROTO_XCBINCLUDEDIR)/extensions/ \
+                   -o $@ $(srcdir)/c-client.xsl $< 
diff --git a/src/c-client.xsl b/src/c-client.xsl
new file mode 100644 (file)
index 0000000..903895d
--- /dev/null
@@ -0,0 +1,1301 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2004 Josh Triplett.  All Rights Reserved.
+
+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
+AUTHORS 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 names of the authors or their
+institutions 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 authors.
+-->
+<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+               version="1.0"
+               xmlns:e="http://exslt.org/common">
+  
+  <xsl:output method="text" />
+
+  <xsl:strip-space elements="*" />
+
+  <!-- "header" or "source" -->
+  <xsl:param name="mode" />
+
+  <!-- Path to the core protocol descriptions. -->
+  <xsl:param name="base-path" />
+
+  <!-- Path to the extension protocol descriptions. -->
+  <xsl:param name="extension-path" select="$base-path" />
+
+  <xsl:variable name="h" select="$mode = 'header'" />
+  <xsl:variable name="c" select="$mode = 'source'" />
+  
+  <!-- String used to indent lines of code. -->
+  <xsl:variable name="indent-string" select="'    '" />
+
+  <xsl:variable name="ucase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
+  <xsl:variable name="lcase" select="'abcdefghijklmnopqrstuvwxyz'" />
+
+  <xsl:variable name="header" select="/xcb/@header" />
+  <xsl:variable name="ucase-header"
+                select="translate($header,$lcase,$ucase)" />
+
+  <xsl:variable name="ext" select="/xcb/@extension-name" />
+
+  <!-- Other protocol descriptions to search for types in, after checking the
+       current protocol description. -->
+  <xsl:variable name="search-path-rtf">
+    <xsl:for-each select="/xcb/import">
+      <path><xsl:value-of select="concat($extension-path, ., '.xml')" /></path>
+    </xsl:for-each>
+    <xsl:choose>
+      <xsl:when test="$header='xproto'">
+        <path><xsl:value-of select="concat($base-path,
+                                           'xcb_types.xml')" /></path>
+      </xsl:when>
+      <xsl:when test="$header='xcb_types'" />
+      <xsl:otherwise>
+        <path><xsl:value-of select="concat($base-path,
+                                           'xproto.xml')" /></path>
+        <path><xsl:value-of select="concat($base-path,
+                                           'xcb_types.xml')" /></path>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:variable>
+  <xsl:variable name="search-path" select="e:node-set($search-path-rtf)/path"/>
+
+  <xsl:variable name="root" select="/" />
+  
+  <!-- First pass: Store everything in a variable. -->
+  <xsl:variable name="pass1-rtf">
+    <xsl:apply-templates select="/" mode="pass1" />
+  </xsl:variable>
+  <xsl:variable name="pass1" select="e:node-set($pass1-rtf)" />
+  
+  <xsl:template match="xcb" mode="pass1">
+    <xcb>
+      <xsl:copy-of select="@*" />
+      <xsl:if test="$ext">
+        <constant type="XCBExtension" name="XCB{$ext}Id">
+          <xsl:attribute name="value">{ "<xsl:value-of select="@extension-xname" />" }</xsl:attribute>
+        </constant>
+        <function type="const XCBQueryExtensionRep *" name="XCB{$ext}Init">
+          <field type="XCBConnection *" name="c" />
+          <l>return XCBGetExtensionData(c, &amp;XCB<!--
+          --><xsl:value-of select="$ext" />Id);</l>
+        </function>
+      </xsl:if>
+      <xsl:apply-templates mode="pass1" />
+    </xcb>
+  </xsl:template>
+
+  <!-- Modify names that conflict with C++ keywords by prefixing them with an
+       underscore.  If the name parameter is not specified, it defaults to the
+       value of the name attribute on the context node. -->
+  <xsl:template name="canonical-var-name">
+    <xsl:param name="name" select="@name" />
+    <xsl:if test="$name='new' or $name='delete'
+                  or $name='class' or $name='operator'">
+      <xsl:text>_</xsl:text>
+    </xsl:if>
+    <xsl:value-of select="$name" />
+  </xsl:template>
+
+  <!-- List of core types, for use in canonical-type-name. -->
+  <xsl:variable name="core-types-rtf">
+    <type name="BOOL" />
+    <type name="BYTE" />
+    <type name="CARD8" />
+    <type name="CARD16" />
+    <type name="CARD32" />
+    <type name="INT8" />
+    <type name="INT16" />
+    <type name="INT32" />
+
+    <type name="char" />
+    <type name="void" />
+    <type name="float" />
+    <type name="double" />
+    <type name="XID" />
+  </xsl:variable>
+  <xsl:variable name="core-types" select="e:node-set($core-types-rtf)" />
+
+  <!--
+    Output the canonical name for a type.  This will be
+    XCB{extension-containing-Type-if-any}Type, wherever the type is found in
+    the search path, or just Type if not found.  If the type parameter is not
+    specified, it defaults to the value of the type attribute on the context
+    node.
+  -->
+  <xsl:template name="canonical-type-name">
+    <xsl:param name="type" select="string(@type)" />
+
+    <xsl:variable name="is-unqualified" select="not(contains($type, ':'))"/>
+    <xsl:variable name="namespace" select="substring-before($type, ':')" />
+    <xsl:variable name="unqualified-type">
+      <xsl:choose>
+        <xsl:when test="$is-unqualified">
+          <xsl:value-of select="$type" />
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:value-of select="substring-after($type, ':')" />
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+
+    <xsl:choose>
+      <xsl:when test="$is-unqualified and $core-types/type[@name=$type]">
+        <xsl:value-of select="$type" />
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:variable name="type-definitions"
+                      select="(/xcb|document($search-path)/xcb
+                              )[$is-unqualified or @header=$namespace]
+                               /*[((self::struct or self::union
+                                    or self::xidtype or self::enum
+                                    or self::event or self::eventcopy
+                                    or self::error or self::errorcopy)
+                                   and @name=$unqualified-type)
+                                  or (self::typedef
+                                      and @newname=$unqualified-type)]" />
+        <xsl:choose>
+          <xsl:when test="count($type-definitions) = 1">
+            <xsl:for-each select="$type-definitions">
+              <xsl:text>XCB</xsl:text>
+              <xsl:value-of select="concat(/xcb/@extension-name,
+                                           $unqualified-type)" />
+            </xsl:for-each>
+          </xsl:when>
+          <xsl:when test="count($type-definitions) > 1">
+            <xsl:message terminate="yes">
+              <xsl:text>Multiple definitions of type "</xsl:text>
+              <xsl:value-of select="$type" />
+              <xsl:text>" found.</xsl:text>
+              <xsl:if test="$is-unqualified">
+                <xsl:for-each select="$type-definitions">
+                  <xsl:text>
+    </xsl:text>
+                  <xsl:value-of select="concat(/xcb/@header, ':', $type)" />
+                </xsl:for-each>
+              </xsl:if>
+            </xsl:message>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:message terminate="yes">
+              <xsl:text>No definitions of type "</xsl:text>
+              <xsl:value-of select="$type" />
+              <xsl:text>" found</xsl:text>
+              <xsl:if test="$is-unqualified">
+                <xsl:text>, and it is not a known core type</xsl:text>
+              </xsl:if>
+              <xsl:text>.</xsl:text>
+            </xsl:message>
+          </xsl:otherwise>
+        </xsl:choose>  
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <!-- Helper template for requests, that outputs the cookie type.  The
+       context node must be the request. -->
+  <xsl:template name="cookie-type">
+    <xsl:text>XCB</xsl:text>
+    <xsl:choose>
+      <xsl:when test="reply">
+        <xsl:value-of select="concat($ext, @name)" />
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:text>Void</xsl:text>
+      </xsl:otherwise>
+    </xsl:choose>
+    <xsl:text>Cookie</xsl:text>
+  </xsl:template>
+
+  <xsl:template match="request" mode="pass1">
+    <xsl:if test="reply">
+      <struct name="XCB{$ext}{@name}Cookie">
+        <field type="unsigned int" name="sequence" />
+      </struct>
+    </xsl:if>
+    <struct name="XCB{$ext}{@name}Req">
+      <field type="CARD8" name="major_opcode" no-assign="true" />
+      <xsl:if test="$ext">
+        <field type="CARD8" name="minor_opcode" no-assign="true" />
+      </xsl:if>
+      <xsl:apply-templates select="*[not(self::reply)]" mode="field" />
+      <middle>
+        <field type="CARD16" name="length" no-assign="true" />
+      </middle>
+    </struct>
+    <function name="XCB{$ext}{@name}">
+      <xsl:attribute name="type">
+        <xsl:call-template name="cookie-type" />
+      </xsl:attribute>
+      <field type="XCBConnection *" name="c" />
+      <xsl:apply-templates select="*[not(self::reply)]" mode="param" />
+      <do-request ref="XCB{$ext}{@name}Req" opcode="{@opcode}">
+        <xsl:if test="reply">
+          <xsl:attribute name="has-reply">true</xsl:attribute>
+        </xsl:if>
+      </do-request>
+    </function>
+    <xsl:if test="reply">
+      <struct name="XCB{$ext}{@name}Rep">
+        <field type="BYTE" name="response_type" />
+        <xsl:apply-templates select="reply/*" mode="field" />
+        <middle>
+          <field type="CARD16" name="sequence" />
+          <field type="CARD32" name="length" />
+        </middle>
+      </struct>
+      <iterator-functions ref="XCB{$ext}{@name}" kind="Rep" />
+      <function type="XCB{$ext}{@name}Rep *" name="XCB{$ext}{@name}Reply">
+        <field type="XCBConnection *" name="c" />
+        <field name="cookie">
+          <xsl:attribute name="type">
+            <xsl:call-template name="cookie-type" />
+          </xsl:attribute>
+        </field>
+        <field type="XCBGenericError **" name="e" />
+        <l>return (XCB<xsl:value-of select="concat($ext, @name)" />Rep *)<!--
+        --> XCBWaitForReply(c, cookie.sequence, e);</l>
+      </function>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template match="xidtype" mode="pass1">
+    <struct name="XCB{$ext}{@name}">
+      <field type="CARD32" name="xid" />
+    </struct>
+    <iterator ref="XCB{$ext}{@name}" />
+    <iterator-functions ref="XCB{$ext}{@name}" />
+    <function type="XCB{$ext}{@name}" name="XCB{$ext}{@name}New">
+      <field type="XCBConnection *" name="c" />
+      <l>XCB<xsl:value-of select="concat($ext, @name)" /> ret;</l>
+      <l>ret.xid = XCBGenerateID(c);</l>
+      <l>return ret;</l>
+    </function>
+  </xsl:template>
+
+  <xsl:template match="struct|union" mode="pass1">
+    <struct name="XCB{$ext}{@name}">
+      <xsl:if test="self::union">
+        <xsl:attribute name="kind">union</xsl:attribute>
+      </xsl:if>
+      <xsl:apply-templates select="*" mode="field" />
+    </struct>
+    <iterator ref="XCB{$ext}{@name}" />
+    <iterator-functions ref="XCB{$ext}{@name}" />
+  </xsl:template>
+
+  <xsl:template match="event|eventcopy|error|errorcopy" mode="pass1">
+    <xsl:variable name="suffix">
+      <xsl:choose>
+        <xsl:when test="self::event|self::eventcopy">
+          <xsl:text>Event</xsl:text>
+        </xsl:when>
+        <xsl:when test="self::error|self::errorcopy">
+          <xsl:text>Error</xsl:text>
+        </xsl:when>
+      </xsl:choose>
+    </xsl:variable>
+    <constant type="number" name="XCB{$ext}{@name}" value="{@number}" />
+    <xsl:choose>
+      <xsl:when test="self::event|self::error">
+        <struct name="XCB{$ext}{@name}{$suffix}">
+          <field type="BYTE" name="response_type" />
+          <xsl:if test="self::error">
+            <field type="BYTE" name="error_code" />
+          </xsl:if>
+          <xsl:apply-templates select="*" mode="field" />
+          <xsl:if test="not(self::event and boolean(@no-sequence-number))">
+            <middle>
+              <field type="CARD16" name="sequence" />
+            </middle>
+          </xsl:if>
+        </struct>
+      </xsl:when>
+      <xsl:when test="self::eventcopy|self::errorcopy">
+        <typedef newname="XCB{$ext}{@name}{$suffix}">
+          <xsl:attribute name="oldname">
+            <xsl:call-template name="canonical-type-name">
+              <xsl:with-param name="type" select="@ref" />
+            </xsl:call-template>
+            <xsl:value-of select="$suffix" />
+          </xsl:attribute>
+        </typedef>
+      </xsl:when>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="typedef" mode="pass1">
+    <typedef>
+      <xsl:attribute name="oldname">
+        <xsl:call-template name="canonical-type-name">
+          <xsl:with-param name="type" select="@oldname" />
+        </xsl:call-template>
+      </xsl:attribute>
+      <xsl:attribute name="newname">
+        <xsl:call-template name="canonical-type-name">
+          <xsl:with-param name="type" select="@newname" />
+        </xsl:call-template>
+      </xsl:attribute>
+    </typedef>
+    <iterator ref="XCB{$ext}{@newname}" />
+    <iterator-functions ref="XCB{$ext}{@newname}" />
+  </xsl:template>
+
+  <xsl:template match="enum" mode="pass1">
+    <enum name="XCB{$ext}{@name}">
+      <xsl:for-each select="item">
+        <item name="XCB{$ext}{../@name}{@name}">
+          <xsl:copy-of select="*" />
+        </item>
+      </xsl:for-each>
+    </enum>
+  </xsl:template>
+
+  <!--
+    Templates for processing fields.
+  -->
+
+  <xsl:template match="pad" mode="field">
+    <xsl:copy-of select="." />
+  </xsl:template>
+  
+  <xsl:template match="field|exprfield" mode="field">
+    <xsl:copy>
+      <xsl:attribute name="type">
+        <xsl:call-template name="canonical-type-name" />
+      </xsl:attribute>
+      <xsl:attribute name="name">
+        <xsl:call-template name="canonical-var-name" />
+      </xsl:attribute>
+      <xsl:copy-of select="*" />
+    </xsl:copy>
+  </xsl:template>
+
+  <xsl:template match="list" mode="field">
+    <xsl:variable name="type"><!--
+      --><xsl:call-template name="canonical-type-name" /><!--
+    --></xsl:variable>
+    <list type="{$type}">
+      <xsl:attribute name="name">
+        <xsl:call-template name="canonical-var-name" />
+      </xsl:attribute>
+      <xsl:if test="not(parent::request) and node()
+                    and not(.//*[not(self::value or self::op)])">
+        <xsl:attribute name="fixed">true</xsl:attribute>
+      </xsl:if>
+      <!-- Handle lists with no length expressions. -->
+      <xsl:if test="not(node())">
+        <xsl:choose>
+          <!-- In a request, refer to an implicit localparam for length. -->
+          <xsl:when test="parent::request">
+            <fieldref>
+              <xsl:value-of select="concat(@name, '_len')" />
+            </fieldref>
+          </xsl:when>
+          <!-- In a reply, use the length of the reply to determine the length
+               of the list. -->
+          <xsl:when test="parent::reply">
+            <op op="/">
+              <op op="&lt;&lt;">
+                <fieldref>length</fieldref>
+                <value>2</value>
+              </op>
+              <function-call name="sizeof">
+                <param><xsl:value-of select="$type" /></param>
+              </function-call>
+            </op>
+          </xsl:when>
+          <!-- Other cases generate an error. -->
+          <xsl:otherwise>
+            <xsl:message terminate="yes"><!--
+              -->Encountered a list with no length expresssion outside a<!--
+              --> request or reply.<!--
+            --></xsl:message>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:if>
+      <xsl:copy-of select="*" />
+    </list>
+  </xsl:template>
+
+  <xsl:template match="valueparam" mode="field">
+    <field>
+      <xsl:attribute name="type">
+        <xsl:call-template name="canonical-type-name">
+          <xsl:with-param name="type" select="@value-mask-type" />
+        </xsl:call-template>
+      </xsl:attribute>
+      <xsl:attribute name="name">
+        <xsl:call-template name="canonical-var-name">
+          <xsl:with-param name="name" select="@value-mask-name" />
+        </xsl:call-template>
+      </xsl:attribute>
+    </field>
+    <list type="CARD32">
+      <xsl:attribute name="name">
+        <xsl:call-template name="canonical-var-name">
+          <xsl:with-param name="name" select="@value-list-name" />
+        </xsl:call-template>
+      </xsl:attribute>
+      <function-call name="XCBPopcount">
+        <param>
+          <fieldref>
+            <xsl:call-template name="canonical-var-name">
+              <xsl:with-param name="name" select="@value-mask-name" />
+            </xsl:call-template>
+          </fieldref>
+        </param>
+      </function-call>
+    </list>
+  </xsl:template>
+
+  <xsl:template match="field|localfield" mode="param">
+    <field>
+      <xsl:attribute name="type">
+        <xsl:call-template name="canonical-type-name" />
+      </xsl:attribute>
+      <xsl:attribute name="name">
+        <xsl:call-template name="canonical-var-name" />
+      </xsl:attribute>
+    </field>
+  </xsl:template>
+
+  <xsl:template match="list" mode="param">
+    <!-- If no length expression is provided, use a CARD32 localfield. -->
+    <xsl:if test="not(node())">
+      <field type="CARD32" name="{@name}_len" />
+    </xsl:if>
+    <field>
+      <xsl:attribute name="type">
+        <xsl:text>const </xsl:text>
+        <xsl:call-template name="canonical-type-name" />
+        <xsl:text> *</xsl:text>
+      </xsl:attribute>
+      <xsl:attribute name="name">
+        <xsl:call-template name="canonical-var-name" />
+      </xsl:attribute>
+    </field>
+  </xsl:template>
+
+  <xsl:template match="valueparam" mode="param">
+    <field>
+      <xsl:attribute name="type">
+        <xsl:call-template name="canonical-type-name">
+          <xsl:with-param name="type" select="@value-mask-type" />
+        </xsl:call-template>
+      </xsl:attribute>
+      <xsl:attribute name="name">
+        <xsl:call-template name="canonical-var-name">
+          <xsl:with-param name="name" select="@value-mask-name" />
+        </xsl:call-template>
+      </xsl:attribute>
+    </field>
+    <field type="const CARD32 *">
+      <xsl:attribute name="name">
+        <xsl:call-template name="canonical-var-name">
+          <xsl:with-param name="name" select="@value-list-name" />
+        </xsl:call-template>
+      </xsl:attribute>
+    </field>
+  </xsl:template>
+
+  <!-- Second pass: Process the variable. -->
+  <xsl:variable name="result-rtf">
+    <xsl:apply-templates select="$pass1/*" mode="pass2" />
+  </xsl:variable>
+  <xsl:variable name="result" select="e:node-set($result-rtf)" />
+
+  <xsl:template match="xcb" mode="pass2">
+    <xcb>
+      <xsl:copy-of select="@*" />
+      <xsl:apply-templates mode="pass2"
+                           select="constant|enum|struct|typedef|iterator" />
+      <xsl:apply-templates mode="pass2"
+                           select="function|iterator-functions" />
+    </xcb>
+  </xsl:template>
+
+  <!-- Generic rules for nodes that don't need further processing: copy node
+       with attributes, and recursively process the child nodes. -->
+  <xsl:template match="*" mode="pass2">
+    <xsl:copy>
+      <xsl:copy-of select="@*" />
+      <xsl:apply-templates mode="pass2" />
+    </xsl:copy>
+  </xsl:template>
+
+  <xsl:template match="struct" mode="pass2">
+    <xsl:if test="@kind='union' and list[not(@fixed)]">
+      <xsl:message terminate="yes">Unions must be fixed length.</xsl:message>
+    </xsl:if>
+    <struct name="{@name}">
+      <xsl:if test="@kind">
+        <xsl:attribute name="kind">
+          <xsl:value-of select="@kind" />
+        </xsl:attribute>
+      </xsl:if>
+      <!-- FIXME: This should go by size, not number of fields. -->
+      <xsl:copy-of select="node()[not(self::middle)
+                   and position() &lt; 3]" />
+      <xsl:if test="middle and (count(*[not(self::middle)]) &lt; 2)">
+        <pad bytes="{2 - count(*[not(self::middle)])}" />
+      </xsl:if>
+      <xsl:copy-of select="middle/*" />
+      <xsl:copy-of select="node()[not(self::middle) and (position() > 2)]" />
+    </struct>
+  </xsl:template>
+
+  <xsl:template match="do-request" mode="pass2">
+    <xsl:variable name="struct"
+                  select="$pass1/xcb/struct[@name=current()/@ref]" />
+
+    <xsl:variable name="num-parts" select="1+count($struct/list)" />
+
+    <l>static const XCBProtocolRequest xcb_req = {</l>
+    <indent>
+      <l>/* count */ <xsl:value-of select="$num-parts" />,</l>
+      <l>/* ext */ <xsl:choose>
+                     <xsl:when test="$ext">
+                       <xsl:text>&amp;XCB</xsl:text>
+                       <xsl:value-of select="$ext" />
+                       <xsl:text>Id</xsl:text>
+                     </xsl:when>
+                     <xsl:otherwise>0</xsl:otherwise>
+                   </xsl:choose>,</l>
+      <l>/* opcode */ <xsl:value-of select="@opcode" />,</l>
+      <l>/* isvoid */ <xsl:value-of select="1-boolean(@has-reply)" /></l>
+    </indent>
+    <l>};</l>
+
+    <l />
+    <l>struct iovec xcb_parts[<xsl:value-of select="$num-parts" />];</l>
+    <l><xsl:value-of select="../@type" /> xcb_ret;</l>
+    <l><xsl:value-of select="@ref" /> xcb_out;</l>
+
+    <l />
+    <xsl:apply-templates select="$struct//*[(self::field or self::exprfield)
+                                            and not(boolean(@no-assign))]"
+                         mode="assign" />
+
+    <l />
+    <l>xcb_parts[0].iov_base = &amp;xcb_out;</l>
+    <l>xcb_parts[0].iov_len = sizeof(xcb_out);</l>
+
+    <xsl:for-each select="$struct/list">
+      <l>xcb_parts[<xsl:number />].iov_base = (void *) <!--
+      --><xsl:value-of select="@name" />;</l>
+      <l>xcb_parts[<xsl:number />].iov_len = <!--
+      --><xsl:apply-templates mode="output-expression" /><!--
+      --><xsl:if test="not(@type = 'void')">
+        <xsl:text> * sizeof(</xsl:text>
+        <xsl:value-of select="@type" />
+        <xsl:text>)</xsl:text>
+      </xsl:if>;</l>
+    </xsl:for-each>
+
+    <l>XCBSendRequest(c, &amp;xcb_ret.sequence, xcb_parts, &amp;xcb_req);</l>
+    <l>return xcb_ret;</l>
+  </xsl:template>
+
+  <xsl:template match="field" mode="assign">
+    <l>
+      <xsl:text>xcb_out.</xsl:text>
+      <xsl:value-of select="@name" />
+      <xsl:text> = </xsl:text>
+      <xsl:value-of select="@name" />
+      <xsl:text>;</xsl:text>
+    </l>
+  </xsl:template>
+
+  <xsl:template match="exprfield" mode="assign">
+    <l>
+      <xsl:text>xcb_out.</xsl:text>
+      <xsl:value-of select="@name" />
+      <xsl:text> = </xsl:text>
+      <xsl:apply-templates mode="output-expression" />
+      <xsl:text>;</xsl:text>
+    </l>
+  </xsl:template>
+
+  <xsl:template match="iterator" mode="pass2">
+    <struct name="{@ref}Iter">
+      <field type="{@ref} *" name="data" />
+      <field type="int" name="rem" />
+      <field type="int" name="index" />
+    </struct>
+  </xsl:template>
+
+  <!-- Change a_name_like_this to ANameLikeThis.  If the parameter name is not
+       given, it defaults to the name attribute of the context node. -->
+  <xsl:template name="capitalize">
+    <xsl:param name="name" select="string(@name)" />
+    <xsl:if test="$name">
+      <xsl:value-of select="translate(substring($name,1,1), $lcase, $ucase)" />
+      <xsl:choose>
+        <xsl:when test="contains($name, '_')">
+          <xsl:value-of select="substring(substring-before($name, '_'), 2)" />
+          <xsl:call-template name="capitalize">
+            <xsl:with-param name="name" select="substring-after($name, '_')" />
+          </xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:value-of select="substring($name, 2)" />
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template match="iterator-functions" mode="pass2">
+    <xsl:variable name="ref" select="@ref" />
+    <xsl:variable name="kind" select="@kind" />
+    <xsl:variable name="struct"
+                  select="$pass1/xcb/struct[@name=concat($ref,$kind)]" />
+    <xsl:variable name="nextfields-rtf">
+      <nextfield>R + 1</nextfield>
+      <xsl:for-each select="$struct/list[not(@fixed)]">
+        <xsl:choose>
+          <xsl:when test="substring(@type, 1, 3) = 'XCB'">
+            <nextfield><xsl:value-of select="@type" />End(<!--
+            --><xsl:value-of select="$ref" /><!--
+            --><xsl:call-template name="capitalize" />Iter(R))</nextfield>
+          </xsl:when>
+          <xsl:otherwise>
+            <nextfield><xsl:value-of select="$ref" /><!--
+            --><xsl:call-template name="capitalize" />End(R)</nextfield>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:for-each>
+    </xsl:variable>
+    <xsl:variable name="nextfields" select="e:node-set($nextfields-rtf)" />
+    <xsl:for-each select="$struct/list[not(@fixed)]">
+      <xsl:variable name="number"
+                    select="1+count(preceding-sibling::list[not(@fixed)])" />
+      <xsl:variable name="nextfield" select="$nextfields/nextfield[$number]" />
+      <xsl:variable name="is-first"
+                    select="not(preceding-sibling::list[not(@fixed)])" />
+      <xsl:variable name="field-name"><!--
+        --><xsl:call-template name="capitalize" /><!--
+      --></xsl:variable>
+      <xsl:variable name="is-variable"
+                    select="$pass1/xcb/struct[@name=current()/@type]/list
+                            or document($search-path)/xcb
+                               /struct[concat('XCB',
+                                              ancestor::xcb/@extension-name,
+                                              @name) = current()/@type]
+                               /*[self::valueparam or self::list]" />
+      <xsl:if test="not($is-variable)">
+        <function type="{@type} *" name="{$ref}{$field-name}">
+          <field type="{$ref}{$kind} *" name="R" />
+          <xsl:choose>
+            <xsl:when test="$is-first">
+              <l>return (<xsl:value-of select="@type" /> *) <!--
+              -->(<xsl:value-of select="$nextfield" />);</l>
+            </xsl:when>
+            <xsl:otherwise>
+              <l>XCBGenericIter prev = <!--
+              --><xsl:value-of select="$nextfield" />;</l>
+              <l>return (<xsl:value-of select="@type" /> *) <!--
+              -->((char *) prev.data + XCB_TYPE_PAD(<!--
+              --><xsl:value-of select="@type" />, prev.index));</l>
+            </xsl:otherwise>
+          </xsl:choose>
+        </function>
+      </xsl:if>
+      <function type="int" name="{$ref}{$field-name}Length">
+        <field type="{$ref}{$kind} *" name="R" />
+        <l>return <xsl:apply-templates mode="output-expression">
+                    <xsl:with-param name="field-prefix" select="'R->'" />
+                  </xsl:apply-templates>;</l>
+      </function>
+      <xsl:choose>
+        <xsl:when test="substring(@type, 1, 3) = 'XCB'">
+          <function type="{@type}Iter" name="{$ref}{$field-name}Iter">
+            <field type="{$ref}{$kind} *" name="R" />
+            <l><xsl:value-of select="@type" />Iter i;</l>
+            <xsl:choose>
+              <xsl:when test="$is-first">
+                <l>i.data = (<xsl:value-of select="@type" /> *) <!--
+                -->(<xsl:value-of select="$nextfield" />);</l>
+              </xsl:when>
+              <xsl:otherwise>
+                <l>XCBGenericIter prev = <!--
+                --><xsl:value-of select="$nextfield" />;</l>
+                <l>i.data = (<xsl:value-of select="@type" /> *) <!--
+                -->((char *) prev.data + XCB_TYPE_PAD(<!--
+                --><xsl:value-of select="@type" />, prev.index));</l>
+              </xsl:otherwise>
+            </xsl:choose>
+            <l>i.rem = <xsl:apply-templates mode="output-expression">
+                         <xsl:with-param name="field-prefix" select="'R->'" />
+                       </xsl:apply-templates>;</l>
+            <l>i.index = (char *) i.data - (char *) R;</l>
+            <l>return i;</l>
+          </function>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:variable name="cast">
+            <xsl:choose>
+              <xsl:when test="@type='void'">char</xsl:when>
+              <xsl:otherwise><xsl:value-of select="@type" /></xsl:otherwise>
+            </xsl:choose>
+          </xsl:variable>
+          <function type="XCBGenericIter" name="{$ref}{$field-name}End">
+            <field type="{$ref}{$kind} *" name="R" />
+            <l>XCBGenericIter i;</l>
+            <xsl:choose>
+              <xsl:when test="$is-first">
+                <l>i.data = ((<xsl:value-of select="$cast" /> *) <!--
+                -->(<xsl:value-of select="$nextfield" />)) + (<!--
+                --><xsl:apply-templates mode="output-expression">
+                     <xsl:with-param name="field-prefix" select="'R->'" />
+                   </xsl:apply-templates>);</l>
+              </xsl:when>
+              <xsl:otherwise>
+                <l>XCBGenericIter child = <!--
+                --><xsl:value-of select="$nextfield" />;</l>
+                <l>i.data = ((<xsl:value-of select="$cast" /> *) <!--
+                -->child.data) + (<!--
+                --><xsl:apply-templates mode="output-expression">
+                     <xsl:with-param name="field-prefix" select="'R->'" />
+                   </xsl:apply-templates>);</l>
+              </xsl:otherwise>
+            </xsl:choose>
+            <l>i.rem = 0;</l>
+            <l>i.index = (char *) i.data - (char *) R;</l>
+            <l>return i;</l>
+          </function>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:for-each>
+    <xsl:if test="not($kind)">
+      <function type="void" name="{$ref}Next">
+        <field type="{$ref}Iter *" name="i" />
+        <xsl:choose>
+          <xsl:when test="$struct/list[not(@fixed)]">
+            <l><xsl:value-of select="$ref" /> *R = i->data;</l>
+            <l>XCBGenericIter child = <!--
+            --><xsl:value-of select="$nextfields/nextfield[last()]" />;</l>
+            <l>--i->rem;</l>
+            <l>i->data = (<xsl:value-of select="$ref" /> *) child.data;</l>
+            <l>i->index = child.index;</l>
+          </xsl:when>
+          <xsl:otherwise>
+            <l>--i->rem;</l>
+            <l>++i->data;</l>
+            <l>i->index += sizeof(<xsl:value-of select="$ref" />);</l>
+          </xsl:otherwise>
+        </xsl:choose>
+      </function>
+      <function type="XCBGenericIter" name="{$ref}End">
+        <field type="{$ref}Iter" name="i" />
+        <l>XCBGenericIter ret;</l>
+        <xsl:choose>
+          <xsl:when test="$struct/list[not(@fixed)]">
+            <l>while(i.rem > 0)</l>
+            <indent>
+              <l><xsl:value-of select="$ref" />Next(&amp;i);</l>
+            </indent>
+            <l>ret.data = i.data;</l>
+            <l>ret.rem = i.rem;</l>
+            <l>ret.index = i.index;</l>
+          </xsl:when>
+          <xsl:otherwise>
+            <l>ret.data = i.data + i.rem;</l>
+            <l>ret.index = i.index + ((char *) ret.data - (char *) i.data);</l>
+            <l>ret.rem = 0;</l>
+          </xsl:otherwise>
+        </xsl:choose>
+        <l>return ret;</l>
+      </function>
+    </xsl:if>
+  </xsl:template>
+
+  <!-- Output the results. -->
+  <xsl:template match="/">
+    <xsl:if test="not(function-available('e:node-set'))">
+      <xsl:message terminate="yes"><!--
+        -->Error: This stylesheet requires the EXSL node-set extension.<!--
+      --></xsl:message>
+    </xsl:if>
+
+    <xsl:if test="not($h) and not($c)">
+      <xsl:message terminate="yes"><!--
+        -->Error: Parameter "mode" must be "header" or "source".<!--
+      --></xsl:message>
+    </xsl:if>
+
+    <xsl:apply-templates select="$result/*" mode="output" />
+  </xsl:template>
+
+  <xsl:template match="xcb" mode="output">
+    <xsl:variable name="guard"><!--
+      -->__<xsl:value-of select="$ucase-header" />_H<!--
+    --></xsl:variable>
+
+<xsl:text>/*
+ * This file generated automatically from </xsl:text>
+<xsl:value-of select="$header" /><xsl:text>.xml by c-client.xsl using XSLT.
+ * Edit at your peril.
+ */
+</xsl:text>
+
+<xsl:if test="$h"><xsl:text>
+#ifndef </xsl:text><xsl:value-of select="$guard" /><xsl:text>
+#define </xsl:text><xsl:value-of select="$guard" /><xsl:text>
+</xsl:text>
+#include "xcb.h"
+<xsl:for-each select="$root/xcb/import">
+<xsl:text>#include "</xsl:text><xsl:value-of select="." /><xsl:text>.h"
+</xsl:text>
+</xsl:for-each>
+<xsl:text>
+</xsl:text>
+</xsl:if>
+
+<xsl:if test="$c"><xsl:text>
+#include &lt;assert.h&gt;
+#include "xcbext.h"
+#include "</xsl:text><xsl:value-of select="$header" /><xsl:text>.h"
+
+</xsl:text></xsl:if>
+
+    <xsl:apply-templates mode="output" />
+
+<xsl:if test="$h">
+<xsl:text>
+#endif
+</xsl:text>
+</xsl:if>
+  </xsl:template>
+
+  <xsl:template match="constant" mode="output">
+    <xsl:choose>
+      <xsl:when test="@type = 'number'">
+        <xsl:if test="$h">
+          <xsl:text>#define </xsl:text>
+          <xsl:value-of select="@name" />
+          <xsl:text> </xsl:text>
+          <xsl:value-of select="@value" />
+          <xsl:text>
+
+</xsl:text>
+        </xsl:if>
+      </xsl:when>
+      <xsl:when test="@type = 'string'">
+        <xsl:if test="$h">
+          <xsl:text>extern </xsl:text>
+        </xsl:if>
+        <xsl:text>const char </xsl:text>
+        <xsl:value-of select="@name" />
+        <xsl:text>[]</xsl:text>
+        <xsl:if test="$c">
+          <xsl:text> = "</xsl:text>
+          <xsl:value-of select="@value" />
+          <xsl:text>"</xsl:text>
+        </xsl:if>
+        <xsl:text>;
+
+</xsl:text>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:if test="$h">
+          <xsl:text>extern </xsl:text>
+        </xsl:if>
+        <xsl:call-template name="type-and-name" />
+        <xsl:if test="$c">
+          <xsl:text> = </xsl:text>
+          <xsl:value-of select="@value" />
+        </xsl:if>
+        <xsl:text>;
+
+</xsl:text>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="typedef" mode="output">
+    <xsl:if test="$h">
+      <xsl:text>typedef </xsl:text>
+      <xsl:value-of select="@oldname" />
+      <xsl:text> </xsl:text>
+      <xsl:value-of select="@newname" />
+      <xsl:text>;
+
+</xsl:text>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template match="struct" mode="output">
+    <xsl:if test="$h">
+      <xsl:variable name="type-lengths">
+        <xsl:call-template name="type-lengths">
+          <xsl:with-param name="items" select="field/@type" />
+        </xsl:call-template>
+      </xsl:variable>
+      <xsl:text>typedef </xsl:text>
+      <xsl:if test="not(@kind)">struct</xsl:if><xsl:value-of select="@kind" />
+      <xsl:text> {
+</xsl:text>
+      <xsl:for-each select="exprfield|field|list[@fixed]|pad">
+        <xsl:text>    </xsl:text>
+        <xsl:apply-templates select=".">
+          <xsl:with-param name="type-lengths" select="$type-lengths" />
+        </xsl:apply-templates>
+        <xsl:text>;
+</xsl:text>
+      </xsl:for-each>
+      <xsl:text>} </xsl:text>
+      <xsl:value-of select="@name" />
+      <xsl:text>;
+
+</xsl:text>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template match="enum" mode="output">
+    <xsl:if test="$h">
+      <xsl:text>typedef enum {
+    </xsl:text>
+      <xsl:call-template name="list">
+        <xsl:with-param name="separator"><xsl:text>,
+    </xsl:text></xsl:with-param>
+        <xsl:with-param name="items">
+          <xsl:for-each select="item">
+            <item>
+              <xsl:value-of select="@name" />
+              <xsl:if test="node()"> <!-- If there is an expression -->
+                <xsl:text> = </xsl:text>
+                <xsl:apply-templates mode="output-expression" />
+              </xsl:if>
+            </item>
+          </xsl:for-each>
+        </xsl:with-param>
+      </xsl:call-template>
+      <xsl:text>
+} </xsl:text><xsl:value-of select="@name" /><xsl:text>;
+
+</xsl:text>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template match="function" mode="output">
+    <xsl:variable name="decl-open" select="concat(@name, ' (')" />
+    <xsl:variable name="type-lengths">
+      <xsl:call-template name="type-lengths">
+        <xsl:with-param name="items" select="field/@type" />
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:value-of select="@type" />
+    <xsl:text>
+</xsl:text>
+    <xsl:value-of select="$decl-open" />
+    <xsl:call-template name="list">
+      <xsl:with-param name="separator">
+        <xsl:text>,
+</xsl:text>
+        <xsl:call-template name="repeat">
+          <xsl:with-param name="count" select="string-length($decl-open)" />
+        </xsl:call-template>
+      </xsl:with-param>
+      <xsl:with-param name="items">
+        <xsl:for-each select="field">
+          <item>
+            <xsl:apply-templates select=".">
+              <xsl:with-param name="type-lengths" select="$type-lengths" />
+            </xsl:apply-templates>
+          </item>
+        </xsl:for-each>
+      </xsl:with-param>
+    </xsl:call-template>
+    <xsl:text>)</xsl:text>
+
+    <xsl:if test="$h"><xsl:text>;
+
+</xsl:text></xsl:if>
+
+    <xsl:if test="$c">
+      <xsl:text>
+{
+</xsl:text>
+      <xsl:apply-templates select="l|indent" mode="function-body">
+        <xsl:with-param name="indent" select="$indent-string" />
+      </xsl:apply-templates>
+      <xsl:text>}
+
+</xsl:text>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template match="l" mode="function-body">
+    <xsl:param name="indent" />
+    <xsl:value-of select="concat($indent, .)" /><xsl:text>
+</xsl:text>
+  </xsl:template>
+
+  <xsl:template match="indent" mode="function-body">
+    <xsl:param name="indent" />
+    <xsl:apply-templates select="l|indent" mode="function-body">
+      <xsl:with-param name="indent" select="concat($indent, $indent-string)" />
+    </xsl:apply-templates>
+  </xsl:template>
+
+  <xsl:template match="value" mode="output-expression">
+    <xsl:value-of select="." />
+  </xsl:template>
+
+  <xsl:template match="fieldref" mode="output-expression">
+    <xsl:param name="field-prefix" />
+    <xsl:value-of select="concat($field-prefix, .)" />
+  </xsl:template>
+
+  <xsl:template match="op" mode="output-expression">
+    <xsl:param name="field-prefix" />
+    <xsl:text>(</xsl:text>
+    <xsl:apply-templates select="node()[1]" mode="output-expression">
+      <xsl:with-param name="field-prefix" select="$field-prefix" />
+    </xsl:apply-templates>
+    <xsl:text> </xsl:text>
+    <xsl:value-of select="@op" />
+    <xsl:text> </xsl:text>
+    <xsl:apply-templates select="node()[2]" mode="output-expression">
+      <xsl:with-param name="field-prefix" select="$field-prefix" />
+    </xsl:apply-templates>
+    <xsl:text>)</xsl:text>
+  </xsl:template>
+
+  <xsl:template match="function-call" mode="output-expression">
+    <xsl:param name="field-prefix" />
+    <xsl:value-of select="@name" />
+    <xsl:text>(</xsl:text>
+    <xsl:call-template name="list">
+      <xsl:with-param name="separator" select="', '" />
+      <xsl:with-param name="items">
+        <xsl:for-each select="param">
+          <item><xsl:apply-templates mode="output-expression">
+            <xsl:with-param name="field-prefix" select="$field-prefix" />
+          </xsl:apply-templates></item>
+        </xsl:for-each>
+      </xsl:with-param>
+    </xsl:call-template>
+    <xsl:text>)</xsl:text>
+  </xsl:template>
+
+  <!-- Catch invalid elements in expressions. -->
+  <xsl:template match="*" mode="output-expression">
+    <xsl:message terminate="yes">
+      <xsl:text>Invalid element in expression: </xsl:text>
+      <xsl:value-of select="name()" />
+    </xsl:message>
+  </xsl:template>
+
+  <xsl:template match="field|exprfield">
+    <xsl:param name="type-lengths" select="0" />
+    <xsl:call-template name="type-and-name">
+      <xsl:with-param name="type-lengths" select="$type-lengths" />
+    </xsl:call-template>
+  </xsl:template>
+
+  <xsl:template match="list[@fixed]">
+    <xsl:param name="type-lengths" select="0" />
+    <xsl:call-template name="type-and-name">
+      <xsl:with-param name="type-lengths" select="$type-lengths" />
+    </xsl:call-template>
+    <xsl:text>[</xsl:text>
+    <xsl:apply-templates mode="output-expression" />
+    <xsl:text>]</xsl:text>
+  </xsl:template>
+
+  <xsl:template match="pad">
+    <xsl:param name="type-lengths" select="0" />
+
+    <xsl:variable name="padnum"><xsl:number /></xsl:variable>
+
+    <xsl:call-template name="type-and-name">
+      <xsl:with-param name="type" select="'CARD8'" />
+      <xsl:with-param name="name">
+        <xsl:text>pad</xsl:text>
+        <xsl:value-of select="$padnum - 1" />
+      </xsl:with-param>
+      <xsl:with-param name="type-lengths" select="$type-lengths" />
+    </xsl:call-template>
+    <xsl:if test="@bytes > 1">
+      <xsl:text>[</xsl:text>
+      <xsl:value-of select="@bytes" />
+      <xsl:text>]</xsl:text>
+    </xsl:if>
+  </xsl:template>
+
+  <!-- Output the given type and name (defaulting to the corresponding
+       attributes of the context node), with the appropriate spacing.  The
+       type must consist of a base type (which may contain spaces), then
+       optionally a single space and a suffix of one or more '*' characters.
+       If the type-lengths parameter is provided, use it to line up the base
+       types and suffixs of the type declarations. -->
+  <xsl:template name="type-and-name">
+    <xsl:param name="type" select="@type" />
+    <xsl:param name="name" select="@name" />
+    <xsl:param name="type-lengths">
+      <max-type-length>0</max-type-length>
+      <max-suffix-length>0</max-suffix-length>
+    </xsl:param>
+    
+    <xsl:variable name="type-lengths-ns" select="e:node-set($type-lengths)" />
+    <xsl:variable name="min-type-length"
+                  select="$type-lengths-ns/max-type-length" />
+    <xsl:variable name="min-suffix-length"
+                  select="$type-lengths-ns/max-suffix-length" />
+
+    <xsl:variable name="base-type">
+      <xsl:choose>
+        <xsl:when test="contains($type, ' *')">
+          <xsl:value-of select="substring-before($type, ' *')" />
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:value-of select="$type" />
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:variable name="suffix">
+      <xsl:if test="contains($type, ' *')">
+        <xsl:text>*</xsl:text>
+        <xsl:value-of select="substring-after($type, ' *')" />
+      </xsl:if>
+    </xsl:variable>
+
+    <xsl:value-of select="$base-type" />
+    <xsl:if test="string-length($base-type) &lt; $min-type-length">
+      <xsl:call-template name="repeat">
+        <xsl:with-param name="count" select="$min-type-length
+                                             - string-length($base-type)" />
+      </xsl:call-template>
+    </xsl:if>
+    <xsl:text> </xsl:text>
+    <xsl:if test="string-length($suffix) &lt; $min-suffix-length">
+      <xsl:call-template name="repeat">
+        <xsl:with-param name="count" select="$min-suffix-length
+                                             - string-length($suffix)" />
+      </xsl:call-template>
+    </xsl:if>
+    <xsl:value-of select="$suffix" />
+    <xsl:value-of select="$name" />
+  </xsl:template>
+
+  <!-- Output a list with a given separator.  Empty items are skipped. -->
+  <xsl:template name="list">
+    <xsl:param name="separator" />
+    <xsl:param name="items" />
+
+    <xsl:for-each select="e:node-set($items)/*">
+      <xsl:value-of select="." />
+      <xsl:if test="not(position() = last())">
+        <xsl:value-of select="$separator" />
+      </xsl:if>
+    </xsl:for-each>
+  </xsl:template>
+
+  <!-- Repeat a string (space by default) a given number of times. -->
+  <xsl:template name="repeat">
+    <xsl:param name="str" select="' '" />
+    <xsl:param name="count" />
+
+    <xsl:if test="$count &gt; 0">
+      <xsl:value-of select="$str" />
+      <xsl:call-template name="repeat">
+        <xsl:with-param name="str"   select="$str" />
+        <xsl:with-param name="count" select="$count - 1" />
+      </xsl:call-template>
+    </xsl:if>
+  </xsl:template>
+
+  <!-- Record the maximum type lengths of a set of types for use as the
+       max-type-lengths parameter of type-and-name. -->
+  <xsl:template name="type-lengths">
+    <xsl:param name="items" />
+    <xsl:variable name="type-lengths-rtf">
+      <xsl:for-each select="$items">
+        <item>
+          <xsl:choose>
+            <xsl:when test="contains(., ' *')">
+              <xsl:value-of select="string-length(
+                                    substring-before(., ' *'))" />
+            </xsl:when>
+            <xsl:otherwise>
+              <xsl:value-of select="string-length(.)" />
+            </xsl:otherwise>
+          </xsl:choose>
+        </item>
+      </xsl:for-each>
+    </xsl:variable>
+    <xsl:variable name="suffix-lengths-rtf">
+      <xsl:for-each select="$items">
+        <item>
+          <xsl:choose>
+            <xsl:when test="contains(., ' *')">
+              <xsl:value-of select="string-length(substring-after(., ' *'))
+                                    + 1" />
+            </xsl:when>
+            <xsl:otherwise>
+              <xsl:text>0</xsl:text>
+            </xsl:otherwise>
+          </xsl:choose>
+        </item>
+      </xsl:for-each>
+    </xsl:variable>
+    <max-type-length>
+      <xsl:call-template name="max">
+        <xsl:with-param name="items"
+                        select="e:node-set($type-lengths-rtf)/*" />
+      </xsl:call-template>
+    </max-type-length>
+    <max-suffix-length>
+      <xsl:call-template name="max">
+        <xsl:with-param name="items"
+                        select="e:node-set($suffix-lengths-rtf)/*" />
+      </xsl:call-template>
+    </max-suffix-length>
+  </xsl:template>
+
+  <!-- Return the maximum number in a set of numbers. -->
+  <xsl:template name="max">
+    <xsl:param name="items" />
+    <xsl:choose>
+      <xsl:when test="count($items) = 0">
+        <xsl:text>0</xsl:text>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:variable name="head" select="number($items[1])" />
+        <xsl:variable name="tail-max">
+          <xsl:call-template name="max">
+            <xsl:with-param name="items" select="$items[position() > 1]" />
+          </xsl:call-template>
+        </xsl:variable>
+        <xsl:choose>
+          <xsl:when test="$head > number($tail-max)">
+            <xsl:value-of select="$head" />
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:value-of select="$tail-max" />
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+</xsl:transform>
diff --git a/src/xcb.h b/src/xcb.h
new file mode 100644 (file)
index 0000000..8dd308a
--- /dev/null
+++ b/src/xcb.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2001-2004 Bart Massey, Jamey Sharp, and Josh Triplett.
+ * All Rights Reserved.
+ *
+ * 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
+ * AUTHORS 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 names of the authors or their
+ * institutions 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 authors.
+ */
+
+#ifndef __XCB_H
+#define __XCB_H
+#include <X11/Xmd.h>
+#include <X11/X.h>
+#include <sys/uio.h>
+#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+#define deprecated __attribute__((__deprecated__))
+#else
+#define deprecated
+#endif
+
+/* Pre-defined constants */
+
+/* current protocol version */
+#define X_PROTOCOL 11
+
+/* current minor version */
+#define X_PROTOCOL_REVISION 0
+
+/* X_TCP_PORT + display number = server port for TCP transport */
+#define X_TCP_PORT 6000
+
+#define XCB_TYPE_PAD(T,I) (-(I) & (sizeof(T) > 4 ? 3 : sizeof(T) - 1))
+
+
+/* Opaque structures */
+
+typedef struct XCBConnection XCBConnection;
+
+
+/* Other types */
+
+typedef struct {
+    void *data;
+    int rem;
+    int index;
+} XCBGenericIter;
+
+typedef struct {
+    BYTE response_type;
+    CARD8 pad0;
+    CARD16 sequence;
+    CARD32 length;
+} XCBGenericRep;
+
+typedef struct {
+    BYTE response_type;
+    CARD8 pad0;
+    CARD16 sequence;
+} XCBGenericEvent;
+
+typedef struct {
+    BYTE response_type;
+    BYTE error_code;
+    CARD16 sequence;
+} XCBGenericError;
+
+typedef struct {
+    unsigned int sequence;
+} XCBVoidCookie;
+
+
+/* Include the generated xproto and xcb_types headers. */
+#include "xcb_types.h"
+#include "xproto.h"
+
+
+/* xcb_auth.c */
+
+typedef struct XCBAuthInfo {
+    int namelen;
+    char *name;
+    int datalen;
+    char *data;
+} XCBAuthInfo;
+
+int XCBGetAuthInfo(int fd, XCBAuthInfo *info) deprecated;
+
+
+/* xcb_out.c */
+
+int XCBFlush(XCBConnection *c);
+CARD32 XCBGetMaximumRequestLength(XCBConnection *c);
+
+
+/* xcb_in.c */
+
+XCBGenericEvent *XCBWaitEvent(XCBConnection *c) deprecated;
+XCBGenericEvent *XCBWaitForEvent(XCBConnection *c);
+XCBGenericEvent *XCBPollForEvent(XCBConnection *c, int *error);
+unsigned int XCBGetRequestRead(XCBConnection *c);
+
+
+/* xcb_ext.c */
+
+typedef struct XCBExtension XCBExtension;
+
+/* Do not free the returned XCBQueryExtensionRep - on return, it's aliased
+ * from the cache. */
+const XCBQueryExtensionRep *XCBGetExtensionData(XCBConnection *c, XCBExtension *ext);
+
+void XCBPrefetchExtensionData(XCBConnection *c, XCBExtension *ext);
+
+
+/* xcb_conn.c */
+
+XCBConnSetupSuccessRep *XCBGetSetup(XCBConnection *c);
+int XCBGetFileDescriptor(XCBConnection *c);
+
+XCBConnection *XCBConnectToFD(int fd, XCBAuthInfo *auth_info);
+void XCBDisconnect(XCBConnection *c);
+
+
+/* xcb_util.c */
+
+int XCBParseDisplay(const char *name, char **host, int *display, int *screen);
+int XCBOpen(const char *host, int display) deprecated;
+int XCBOpenTCP(const char *host, unsigned short port) deprecated;
+int XCBOpenUnix(const char *file) deprecated;
+
+XCBConnection *XCBConnectBasic(void) deprecated;
+XCBConnection *XCBConnect(const char *displayname, int *screenp);
+XCBConnection *XCBConnectToDisplayWithAuthInfo(const char *display, XCBAuthInfo *auth, int *screen);
+
+int XCBSync(XCBConnection *c, XCBGenericError **e);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/xcb_auth.c b/src/xcb_auth.c
new file mode 100644 (file)
index 0000000..9f2cb5a
--- /dev/null
@@ -0,0 +1,296 @@
+/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
+ *
+ * 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
+ * AUTHORS 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 names of the authors or their
+ * institutions 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 authors.
+ */
+
+/* Authorization systems for the X protocol. */
+
+#include <assert.h>
+#include <X11/Xauth.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "xcb.h"
+#include "xcbint.h"
+
+#ifdef HAS_AUTH_XA1
+#include "xcb_des.h"
+#endif
+
+enum auth_protos {
+#ifdef HAS_AUTH_XA1
+    AUTH_XA1,
+#endif
+    AUTH_MC1,
+    N_AUTH_PROTOS
+};
+
+static char *authnames[N_AUTH_PROTOS] = {
+#ifdef HAS_AUTH_XA1
+    "XDM-AUTHORIZATION-1",
+#endif
+    "MIT-MAGIC-COOKIE-1",
+};
+
+#ifdef HAS_AUTH_XA1
+
+static int next_nonce(void)
+{
+    static int nonce = 0;
+    static pthread_mutex_t nonce_mutex = PTHREAD_MUTEX_INITIALIZER;
+    int ret;
+    pthread_mutex_lock(&nonce_mutex);
+    ret = nonce++;
+    pthread_mutex_unlock(&nonce_mutex);
+    return ret;
+}
+
+/*
+ * This code and the code it calls is taken from libXdmcp,
+ * specifically from Wrap.c, Wrap.h, and Wraphelp.c.  The US
+ * has changed, thank goodness, and it should be OK to bury
+ * DES code in an open source product without a maze of
+ * twisty wrapper functions stored offshore.  Or maybe
+ * not. --Bart Massey 2003/11/5
+ */
+
+static void
+Wrap (
+    des_cblock         input,
+    des_cblock          key,
+    des_cblock          output,
+    int                        bytes)
+{
+    int                        i, j;
+    int                        len;
+    des_cblock          tmp;
+    des_cblock          expand_key;
+    des_key_schedule   schedule;
+
+    XCBDESKeyToOddParity (key, expand_key);
+    XCBDESKeySchedule (expand_key, schedule);
+    for (j = 0; j < bytes; j += 8)
+    {
+       len = 8;
+       if (bytes - j < len)
+           len = bytes - j;
+       /* block chaining */
+       for (i = 0; i < len; i++)
+       {
+           if (j == 0)
+               tmp[i] = input[i];
+           else
+               tmp[i] = input[j + i] ^ output[j - 8 + i];
+       }
+       for (; i < 8; i++)
+       {
+           if (j == 0)
+               tmp[i] = 0;
+           else
+               tmp[i] = 0 ^ output[j - 8 + i];
+       }
+       XCBDESEncrypt (tmp, (output + j), schedule, 1);
+    }
+}
+
+#endif
+
+static size_t memdup(char **dst, void *src, size_t len)
+{
+    if(len)
+       *dst = malloc(len);
+    else
+       *dst = 0;
+    if(!*dst)
+       return 0;
+    memcpy(*dst, src, len);
+    return len;
+}
+
+static int authname_match(enum auth_protos kind, char *name, int namelen)
+{
+    if(strlen(authnames[kind]) != namelen)
+       return 0;
+    if(memcmp(authnames[kind], name, namelen))
+       return 0;
+    return 1;
+}
+
+static Xauth *get_authptr(struct sockaddr *sockname, unsigned int socknamelen)
+{
+    char *addr = 0;
+    int addrlen = 0;
+    unsigned short family;
+    char hostnamebuf[256];   /* big enough for max hostname */
+    char dispbuf[40];   /* big enough to hold more than 2^64 base 10 */
+    char *display;
+    int authnamelens[N_AUTH_PROTOS];
+    int i;
+
+    family = FamilyLocal; /* 256 */
+    switch (sockname->sa_family) {
+    case AF_INET:
+       /*block*/ {
+             struct sockaddr_in *si = (struct sockaddr_in *) sockname;
+            assert(sizeof(*si) == socknamelen);
+            addr = (char *) &si->sin_addr;
+            addrlen = 4;
+            if (ntohl(si->sin_addr.s_addr) != 0x7f000001)
+                family = FamilyInternet; /* 0 */
+            snprintf(dispbuf, sizeof(dispbuf), "%d", ntohs(si->sin_port) - X_TCP_PORT);
+            display = dispbuf;
+        }
+       break;
+    case AF_UNIX:
+       /*block*/ { 
+           struct sockaddr_un *su = (struct sockaddr_un *) sockname;
+           assert(sizeof(*su) >= socknamelen);
+           display = strrchr(su->sun_path, 'X');
+           if (display == 0)
+               return 0;   /* sockname is mangled somehow */
+           display++;
+       }
+       break;
+    default:
+        return 0;   /* cannot authenticate this family */
+    }
+    if (family == FamilyLocal) {
+        if (gethostname(hostnamebuf, sizeof(hostnamebuf)) == -1)
+            return 0;   /* do not know own hostname */
+        addr = hostnamebuf;
+        addrlen = strlen(addr);
+    }
+
+    for (i = 0; i < N_AUTH_PROTOS; i++)
+       authnamelens[i] = strlen(authnames[i]);
+    return XauGetBestAuthByAddr (family,
+                                 (unsigned short) addrlen, addr,
+                                 (unsigned short) strlen(display), display,
+                                 N_AUTH_PROTOS, authnames, authnamelens);
+}
+
+#ifdef HAS_AUTH_XA1
+static void do_append(char *buf, int *idxp, void *val, size_t valsize) {
+    memcpy(buf + *idxp, val, valsize);
+    *idxp += valsize;
+}
+#endif
+     
+static int compute_auth(XCBAuthInfo *info, Xauth *authptr, struct sockaddr *sockname)
+{
+    if (authname_match(AUTH_MC1, authptr->name, authptr->name_length)) {
+        info->datalen = memdup(&info->data, authptr->data, authptr->data_length);
+        if(!info->datalen)
+            return 0;
+        return 1;
+    }
+#ifdef HAS_AUTH_XA1
+#define APPEND(buf,idx,val) do_append((buf),&(idx),(val),sizeof(val))
+    if (authname_match(AUTH_XA1, authptr->name, authptr->name_length)) {
+       int j;
+
+       info->data = malloc(192 / 8);
+       if(!info->data)
+           return 0;
+
+       for (j = 0; j < 8; j++)
+           info->data[j] = authptr->data[j];
+       switch(sockname->sa_family) {
+        case AF_INET:
+            /*block*/ {
+           struct sockaddr_in *si = (struct sockaddr_in *) sockname;
+           APPEND(info->data, j, si->sin_addr.s_addr);
+           APPEND(info->data, j, si->sin_port);
+       }
+       break;
+        case AF_UNIX:
+            /*block*/ {
+           long fakeaddr = htonl(0xffffffff - next_nonce());
+           short fakeport = htons(getpid());
+           APPEND(info->data, j, fakeaddr);
+           APPEND(info->data, j, fakeport);
+       }
+       break;
+        default:
+            free(info->data);
+            return 0;   /* do not know how to build this */
+       }
+       {
+           long now;
+           time(&now);
+           now = htonl(now);
+           APPEND(info->data, j, now);
+       }
+       assert(j <= 192 / 8);
+       while (j < 192 / 8)
+           info->data[j++] = 0;
+       info->datalen = j;
+       Wrap (info->data, authptr->data + 8, info->data, info->datalen);
+       return 1;
+    }
+#undef APPEND
+#endif
+
+    return 0;   /* Unknown authorization type */
+}
+
+int XCBGetAuthInfo(int fd, XCBAuthInfo *info)
+{
+    /* code adapted from Xlib/ConnDis.c, xtrans/Xtranssocket.c,
+       xtrans/Xtransutils.c */
+    char sockbuf[sizeof(struct sockaddr) + MAXPATHLEN];
+    unsigned int socknamelen = sizeof(sockbuf);   /* need extra space */
+    struct sockaddr *sockname = (struct sockaddr *) &sockbuf;
+    Xauth *authptr = 0;
+    int ret = 1;
+
+    /* ensure info has reasonable contents */
+    /* XXX This should be removed, but Jamey depends on it
+       somehow but can't remember how.  Principle: don't touch
+       someone else's data if you're borken. */
+    info->namelen = info->datalen = 0;
+    info->name = info->data = 0;
+
+    if (getpeername(fd, sockname, &socknamelen) == -1)
+        return 0;  /* can only authenticate sockets */
+
+    authptr = get_authptr(sockname, socknamelen);
+    if (authptr == 0)
+        return 0;   /* cannot find good auth data */
+
+    info->namelen = memdup(&info->name, authptr->name, authptr->name_length);
+    if(info->namelen)
+       ret = compute_auth(info, authptr, sockname);
+    if(!ret)
+    {
+       free(info->name);
+       info->name = 0;
+       info->namelen = 0;
+    }
+    XauDisposeAuth(authptr);
+    return ret;
+}
diff --git a/src/xcb_conn.c b/src/xcb_conn.c
new file mode 100644 (file)
index 0000000..0148abf
--- /dev/null
@@ -0,0 +1,239 @@
+/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
+ *
+ * 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
+ * AUTHORS 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 names of the authors or their
+ * institutions 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 authors.
+ */
+
+/* Connection management: the core of XCB. */
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <sys/select.h>
+
+#include "xcb.h"
+#include "xcbint.h"
+
+static int write_setup(XCBConnection *c, XCBAuthInfo *auth_info)
+{
+    XCBConnSetupReq out;
+    struct iovec parts[3];
+    int count = 0;
+    int endian = 0x01020304;
+    int ret;
+
+    memset(&out, 0, sizeof(out));
+
+    /* B = 0x42 = MSB first, l = 0x6c = LSB first */
+    if(htonl(endian) == endian)
+        out.byte_order = 0x42;
+    else
+        out.byte_order = 0x6c;
+    out.protocol_major_version = X_PROTOCOL;
+    out.protocol_minor_version = X_PROTOCOL_REVISION;
+    out.authorization_protocol_name_len = 0;
+    out.authorization_protocol_data_len = 0;
+    parts[count].iov_len = sizeof(XCBConnSetupReq);
+    parts[count++].iov_base = &out;
+
+    if(auth_info)
+    {
+        parts[count].iov_len = out.authorization_protocol_name_len = auth_info->namelen;
+        parts[count++].iov_base = auth_info->name;
+        parts[count].iov_len = out.authorization_protocol_data_len = auth_info->datalen;
+        parts[count++].iov_base = auth_info->data;
+    }
+
+    pthread_mutex_lock(&c->iolock);
+    _xcb_out_write_block(c, parts, count);
+    ret = _xcb_out_flush(c);
+    pthread_mutex_unlock(&c->iolock);
+    if(ret <= 0)
+        return 0;
+    return 1;
+}
+
+static int read_setup(XCBConnection *c)
+{
+    /* Read the server response */
+    c->setup = malloc(sizeof(XCBConnSetupGenericRep));
+    if(!c->setup)
+        return 0;
+
+    if(_xcb_read_block(c->fd, c->setup, sizeof(XCBConnSetupGenericRep)) != sizeof(XCBConnSetupGenericRep))
+        return 0;
+
+    {
+        void *tmp = realloc(c->setup, c->setup->length * 4 + sizeof(XCBConnSetupGenericRep));
+        if(!tmp)
+            return 0;
+        c->setup = tmp;
+    }
+
+    if(_xcb_read_block(c->fd, (char *) c->setup + sizeof(XCBConnSetupGenericRep), c->setup->length * 4) <= 0)
+        return 0;
+
+    /* 0 = failed, 2 = authenticate, 1 = success */
+    switch(c->setup->status)
+    {
+    case 0: /* failed */
+        {
+            XCBConnSetupFailedRep *setup = (XCBConnSetupFailedRep *) c->setup;
+            write(STDERR_FILENO, XCBConnSetupFailedRepReason(setup), XCBConnSetupFailedRepReasonLength(setup));
+            return 0;
+        }
+
+    case 2: /* authenticate */
+        {
+            XCBConnSetupAuthenticateRep *setup = (XCBConnSetupAuthenticateRep *) c->setup;
+            write(STDERR_FILENO, XCBConnSetupAuthenticateRepReason(setup), XCBConnSetupAuthenticateRepReasonLength(setup));
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+/* Public interface */
+
+XCBConnSetupSuccessRep *XCBGetSetup(XCBConnection *c)
+{
+    /* doesn't need locking because it's never written to. */
+    return c->setup;
+}
+
+int XCBGetFileDescriptor(XCBConnection *c)
+{
+    /* doesn't need locking because it's never written to. */
+    return c->fd;
+}
+
+XCBConnection *XCBConnectToFD(int fd, XCBAuthInfo *auth_info)
+{
+    XCBConnection* c;
+
+    c = calloc(1, sizeof(XCBConnection));
+    if(!c)
+        return 0;
+
+    c->fd = fd;
+
+    if(!(
+        _xcb_set_fd_flags(fd) &&
+        pthread_mutex_init(&c->iolock, 0) == 0 &&
+        _xcb_in_init(&c->in) &&
+        _xcb_out_init(&c->out) &&
+        write_setup(c, auth_info) &&
+        read_setup(c) &&
+        _xcb_ext_init(c) &&
+        _xcb_xid_init(c)
+        ))
+    {
+        XCBDisconnect(c);
+        return 0;
+    }
+
+    return c;
+}
+
+void XCBDisconnect(XCBConnection *c)
+{
+    if(!c)
+        return;
+
+    free(c->setup);
+    close(c->fd);
+
+    pthread_mutex_destroy(&c->iolock);
+    _xcb_in_destroy(&c->in);
+    _xcb_out_destroy(&c->out);
+
+    _xcb_ext_destroy(c);
+    _xcb_xid_destroy(c);
+
+    free(c);
+}
+
+/* Private interface */
+
+int _xcb_conn_wait(XCBConnection *c, const int should_write, pthread_cond_t *cond)
+{
+    int ret = 1;
+    fd_set rfds, wfds;
+#if USE_THREAD_ASSERT
+    static __thread int already_here = 0;
+
+    assert(!already_here);
+    ++already_here;
+#endif
+
+    _xcb_assert_valid_sequence(c);
+
+    /* If the thing I should be doing is already being done, wait for it. */
+    if(should_write ? c->out.writing : c->in.reading)
+    {
+        pthread_cond_wait(cond, &c->iolock);
+#if USE_THREAD_ASSERT
+        --already_here;
+#endif
+        return 1;
+    }
+
+    FD_ZERO(&rfds);
+    FD_SET(c->fd, &rfds);
+    ++c->in.reading;
+
+    FD_ZERO(&wfds);
+    if(should_write)
+    {
+        FD_SET(c->fd, &wfds);
+        ++c->out.writing;
+    }
+
+    pthread_mutex_unlock(&c->iolock);
+    ret = select(c->fd + 1, &rfds, &wfds, 0, 0);
+    pthread_mutex_lock(&c->iolock);
+
+    if(ret <= 0) /* error: select failed */
+        goto done;
+
+    if(FD_ISSET(c->fd, &rfds))
+        if((ret = _xcb_in_read(c)) <= 0)
+            goto done;
+
+    if(FD_ISSET(c->fd, &wfds))
+        if((ret = _xcb_out_write(c)) <= 0)
+            goto done;
+
+done:
+    if(should_write)
+        --c->out.writing;
+    --c->in.reading;
+
+#if USE_THREAD_ASSERT
+    --already_here;
+#endif
+    return ret;
+}
diff --git a/src/xcb_ext.c b/src/xcb_ext.c
new file mode 100644 (file)
index 0000000..46a5519
--- /dev/null
@@ -0,0 +1,122 @@
+/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
+ *
+ * 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
+ * AUTHORS 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 names of the authors or their
+ * institutions 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 authors.
+ */
+
+/* A cache for QueryExtension results. */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "xcb.h"
+#include "xcbext.h"
+#include "xcbint.h"
+
+typedef struct {
+    enum { LAZY_COOKIE, LAZY_FORCED } tag;
+    union {
+        XCBQueryExtensionCookie cookie;
+        XCBQueryExtensionRep *reply;
+    } value;
+} lazyreply;
+
+static lazyreply *get_lazyreply(XCBConnection *c, XCBExtension *ext)
+{
+    static pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER;
+    static int next_global_id;
+
+    lazyreply *data;
+
+    pthread_mutex_lock(&global_lock);
+    if(!ext->global_id)
+        ext->global_id = ++next_global_id;
+    pthread_mutex_unlock(&global_lock);
+
+    data = _xcb_map_get(c->ext.extensions, ext->global_id);
+    if(!data)
+    {
+        /* cache miss: query the server */
+        data = malloc(sizeof(lazyreply));
+        if(!data)
+            return 0;
+        data->tag = LAZY_COOKIE;
+        data->value.cookie = XCBQueryExtension(c, strlen(ext->name), ext->name);
+        _xcb_map_put(c->ext.extensions, ext->global_id, data);
+    }
+    return data;
+}
+
+static void free_lazyreply(void *p)
+{
+    lazyreply *data = p;
+    if(data->tag == LAZY_FORCED)
+        free(data->value.reply);
+    free(data);
+}
+
+/* Public interface */
+
+/* Do not free the returned XCBQueryExtensionRep - on return, it's aliased
+ * from the cache. */
+const XCBQueryExtensionRep *XCBGetExtensionData(XCBConnection *c, XCBExtension *ext)
+{
+    lazyreply *data;
+
+    pthread_mutex_lock(&c->ext.lock);
+    data = get_lazyreply(c, ext);
+    if(data && data->tag == LAZY_COOKIE)
+    {
+        data->tag = LAZY_FORCED;
+        data->value.reply = XCBQueryExtensionReply(c, data->value.cookie, 0);
+    }
+    pthread_mutex_unlock(&c->ext.lock);
+
+    return data ? data->value.reply : 0;
+}
+
+void XCBPrefetchExtensionData(XCBConnection *c, XCBExtension *ext)
+{
+    pthread_mutex_lock(&c->ext.lock);
+    get_lazyreply(c, ext);
+    pthread_mutex_unlock(&c->ext.lock);
+}
+
+/* Private interface */
+
+int _xcb_ext_init(XCBConnection *c)
+{
+    if(pthread_mutex_init(&c->ext.lock, 0))
+        return 0;
+
+    c->ext.extensions = _xcb_map_new();
+    if(!c->ext.extensions)
+        return 0;
+
+    return 1;
+}
+
+void _xcb_ext_destroy(XCBConnection *c)
+{
+    pthread_mutex_destroy(&c->ext.lock);
+    _xcb_map_delete(c->ext.extensions, free_lazyreply);
+}
diff --git a/src/xcb_in.c b/src/xcb_in.c
new file mode 100644 (file)
index 0000000..c260b7b
--- /dev/null
@@ -0,0 +1,319 @@
+/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
+ *
+ * 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
+ * AUTHORS 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 names of the authors or their
+ * institutions 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 authors.
+ */
+
+/* Stuff that reads stuff from the server. */
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "xcb.h"
+#include "xcbext.h"
+#include "xcbint.h"
+
+typedef struct XCBReplyData {
+    unsigned int request;
+    void *data;
+    XCBGenericError **error;
+} XCBReplyData;
+
+static int match_request_error(const void *request, const void *data)
+{
+    const XCBGenericError *e = data;
+    return e->response_type == 0 && e->sequence == ((*(unsigned int *) request) & 0xffff);
+}
+
+static int match_reply(const void *request, const void *data)
+{
+    return ((XCBReplyData *) data)->request == *(unsigned int *) request;
+}
+
+static void wake_up_next_reader(XCBConnection *c)
+{
+    XCBReplyData *cur = _xcb_list_peek_head(c->in.readers);
+    int pthreadret;
+    if(cur)
+        pthreadret = pthread_cond_signal(cur->data);
+    else
+        pthreadret = pthread_cond_signal(&c->in.event_cond);
+    assert(pthreadret == 0);
+}
+
+/* Public interface */
+
+void *XCBWaitForReply(XCBConnection *c, unsigned int request, XCBGenericError **e)
+{
+    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+    XCBReplyData reader;
+    void *ret = 0;
+    if(e)
+        *e = 0;
+
+    pthread_mutex_lock(&c->iolock);
+
+    /* If this request has not been written yet, write it. */
+    if((signed int) (c->out.request_written - request) < 0)
+        if(_xcb_out_flush(c) <= 0)
+            goto done; /* error */
+
+    if(_xcb_list_find(c->in.readers, match_reply, &request))
+        goto done; /* error */
+
+    if(e)
+    {
+        *e = _xcb_list_remove(c->in.events, match_request_error, &request);
+        if(*e)
+            goto done;
+    }
+
+    reader.request = request;
+    reader.data = &cond;
+    reader.error = e;
+    _xcb_list_append(c->in.readers, &reader);
+
+    /* If this request has not been read yet, wait for it. */
+    while(!(e && *e) && ((signed int) (c->in.request_read - request) < 0 ||
+            (c->in.request_read == request &&
+            _xcb_queue_is_empty(c->in.current_reply))))
+        if(_xcb_conn_wait(c, /*should_write*/ 0, &cond) <= 0)
+            goto done;
+
+    if(c->in.request_read != request)
+    {
+        _xcb_queue *q = _xcb_map_get(c->in.replies, request);
+        if(q)
+        {
+            ret = _xcb_queue_dequeue(q);
+            if(_xcb_queue_is_empty(q))
+                _xcb_queue_delete(_xcb_map_remove(c->in.replies, request), free);
+        }
+    }
+    else
+        ret = _xcb_queue_dequeue(c->in.current_reply);
+
+done:
+    _xcb_list_remove(c->in.readers, match_reply, &request);
+    pthread_cond_destroy(&cond);
+
+    wake_up_next_reader(c);
+    pthread_mutex_unlock(&c->iolock);
+    return ret;
+}
+
+XCBGenericEvent *XCBWaitEvent(XCBConnection *c)
+{
+    return XCBWaitForEvent(c);
+}
+
+XCBGenericEvent *XCBWaitForEvent(XCBConnection *c)
+{
+    XCBGenericEvent *ret;
+
+#if XCBTRACEEVENT
+    fprintf(stderr, "Entering XCBWaitEvent\n");
+#endif
+
+    pthread_mutex_lock(&c->iolock);
+    /* _xcb_list_remove_head returns 0 on empty list. */
+    while(!(ret = _xcb_queue_dequeue(c->in.events)))
+        if(_xcb_conn_wait(c, /*should_write*/ 0, &c->in.event_cond) <= 0)
+            break;
+
+    wake_up_next_reader(c);
+    pthread_mutex_unlock(&c->iolock);
+
+#if XCBTRACEEVENT
+    fprintf(stderr, "Leaving XCBWaitEvent, event type %d\n", ret ? ret->response_type : -1);
+#endif
+
+    return ret;
+}
+
+XCBGenericEvent *XCBPollForEvent(XCBConnection *c, int *error)
+{
+    XCBGenericEvent *ret = 0;
+    pthread_mutex_lock(&c->iolock);
+    if(error)
+        *error = 0;
+    /* FIXME: follow X meets Z architecture changes. */
+    if(_xcb_in_read(c) >= 0)
+        ret = _xcb_queue_dequeue(c->in.events);
+    else if(error)
+        *error = -1;
+    else
+    {
+        fprintf(stderr, "XCBPollForEvent: I/O error occured, but no handler provided.\n");
+        abort();
+    }
+    pthread_mutex_unlock(&c->iolock);
+    return ret;
+}
+
+unsigned int XCBGetRequestRead(XCBConnection *c)
+{
+    unsigned int ret;
+    pthread_mutex_lock(&c->iolock);
+    /* FIXME: follow X meets Z architecture changes. */
+    _xcb_in_read(c);
+    ret = c->in.request_read;
+    pthread_mutex_unlock(&c->iolock);
+    return ret;
+}
+
+/* Private interface */
+
+int _xcb_in_init(_xcb_in *in)
+{
+    if(pthread_cond_init(&in->event_cond, 0))
+        return 0;
+    in->reading = 0;
+
+    in->queue_len = 0;
+
+    in->request_read = 0;
+    in->current_reply = _xcb_queue_new();
+
+    in->replies = _xcb_map_new();
+    in->events = _xcb_queue_new();
+    in->readers = _xcb_list_new();
+    if(!in->current_reply || !in->replies || !in->events || !in->readers)
+        return 0;
+
+    return 1;
+}
+
+void _xcb_in_destroy(_xcb_in *in)
+{
+    pthread_cond_destroy(&in->event_cond);
+    _xcb_queue_delete(in->current_reply, free);
+    _xcb_map_delete(in->replies, free);
+    _xcb_queue_delete(in->events, free);
+    _xcb_list_delete(in->readers, 0);
+}
+
+int _xcb_in_expect_reply(XCBConnection *c, unsigned int request)
+{
+    /* XXX: currently a no-op */
+    return 1;
+}
+
+int _xcb_in_read_packet(XCBConnection *c)
+{
+    XCBGenericRep genrep;
+    int length = 32;
+    unsigned char *buf;
+
+    /* Wait for there to be enough data for us to read a whole packet */
+    if(c->in.queue_len < length)
+        return 0;
+
+    /* Get the response type, length, and sequence number. */
+    memcpy(&genrep, c->in.queue, sizeof(genrep));
+
+    /* For reply packets, check that the entire packet is available. */
+    if(genrep.response_type == 1)
+        length += genrep.length * 4;
+
+    buf = malloc(length);
+    if(!buf)
+        return 0;
+    if(_xcb_in_read_block(c, buf, length) <= 0)
+    {
+        free(buf);
+        return 0;
+    }
+
+    /* Compute 32-bit sequence number of this packet. */
+    /* XXX: do "sequence lost" check here */
+    if((genrep.response_type & 0x7f) != KeymapNotify)
+    {
+        int lastread = c->in.request_read;
+        c->in.request_read = (lastread & 0xffff0000) | genrep.sequence;
+        if(c->in.request_read != lastread && !_xcb_queue_is_empty(c->in.current_reply))
+        {
+            _xcb_map_put(c->in.replies, lastread, c->in.current_reply);
+            c->in.current_reply = _xcb_queue_new();
+        }
+        if(c->in.request_read < lastread)
+            c->in.request_read += 0x10000;
+    }
+
+    if(buf[0] == 1) /* response is a reply */
+    {
+        XCBReplyData *reader = _xcb_list_find(c->in.readers, match_reply, &c->in.request_read);
+        _xcb_queue_enqueue(c->in.current_reply, buf);
+        if(reader)
+            pthread_cond_signal(reader->data);
+        return 1;
+    }
+
+    if(buf[0] == 0) /* response is an error */
+    {
+        XCBReplyData *reader = _xcb_list_find(c->in.readers, match_reply, &c->in.request_read);
+        if(reader && reader->error)
+        {
+            *reader->error = (XCBGenericError *) buf;
+            pthread_cond_signal(reader->data);
+            return 1;
+        }
+    }
+
+    /* event, or error without a waiting reader */
+    _xcb_queue_enqueue(c->in.events, buf);
+    pthread_cond_signal(&c->in.event_cond);
+    return 1; /* I have something for you... */
+}
+
+int _xcb_in_read(XCBConnection *c)
+{
+    int n = _xcb_readn(c->fd, c->in.queue, sizeof(c->in.queue), &c->in.queue_len);
+    if(n < 0 && errno == EAGAIN)
+        n = 1;
+    while(_xcb_in_read_packet(c) > 0)
+        /* empty */;
+    return n;
+}
+
+int _xcb_in_read_block(XCBConnection *c, void *buf, int len)
+{
+    int done = c->in.queue_len;
+    if(len < done)
+        done = len;
+
+    memcpy(buf, c->in.queue, done);
+    c->in.queue_len -= done;
+    memmove(c->in.queue, c->in.queue + done, c->in.queue_len);
+
+    if(len > done)
+    {
+        int ret = _xcb_read_block(c->fd, (char *) buf + done, len - done);
+        if(ret <= 0)
+            return ret;
+    }
+
+    return len;
+}
diff --git a/src/xcb_list.c b/src/xcb_list.c
new file mode 100644 (file)
index 0000000..5b2edc0
--- /dev/null
@@ -0,0 +1,215 @@
+/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
+ *
+ * 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
+ * AUTHORS 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 names of the authors or their
+ * institutions 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 authors.
+ */
+
+/* A generic implementation of a list of void-pointers. */
+
+#include <stdlib.h>
+
+#include "xcb.h"
+#include "xcbint.h"
+
+typedef struct node {
+    struct node *next;
+    void *data;
+} node;
+
+struct _xcb_list {
+    node *head;
+    node **tail;
+};
+
+/* Private interface */
+
+_xcb_list *_xcb_list_new()
+{
+    _xcb_list *list;
+    list = malloc(sizeof(_xcb_list));
+    if(!list)
+        return 0;
+    list->head = 0;
+    list->tail = &list->head;
+    return list;
+}
+
+static void _xcb_list_clear(_xcb_list *list, XCBListFreeFunc do_free)
+{
+    void *tmp;
+    while((tmp = _xcb_list_remove_head(list)))
+        if(do_free)
+            do_free(tmp);
+}
+
+void _xcb_list_delete(_xcb_list *list, XCBListFreeFunc do_free)
+{
+    if(!list)
+        return;
+    _xcb_list_clear(list, do_free);
+    free(list);
+}
+
+int _xcb_list_insert(_xcb_list *list, void *data)
+{
+    node *cur;
+    cur = malloc(sizeof(node));
+    if(!cur)
+        return 0;
+    cur->data = data;
+
+    cur->next = list->head;
+    list->head = cur;
+    return 1;
+}
+
+int _xcb_list_append(_xcb_list *list, void *data)
+{
+    node *cur;
+    cur = malloc(sizeof(node));
+    if(!cur)
+        return 0;
+    cur->data = data;
+    cur->next = 0;
+
+    *list->tail = cur;
+    list->tail = &cur->next;
+    return 1;
+}
+
+void *_xcb_list_peek_head(_xcb_list *list)
+{
+    if(!list->head)
+        return 0;
+    return list->head->data;
+}
+
+void *_xcb_list_remove_head(_xcb_list *list)
+{
+    void *ret;
+    node *tmp = list->head;
+    if(!tmp)
+        return 0;
+    ret = tmp->data;
+    list->head = tmp->next;
+    if(!list->head)
+        list->tail = &list->head;
+    free(tmp);
+    return ret;
+}
+
+void *_xcb_list_remove(_xcb_list *list, int (*cmp)(const void *, const void *), const void *data)
+{
+    node **cur;
+    for(cur = &list->head; *cur; cur = &(*cur)->next)
+        if(cmp(data, (*cur)->data))
+        {
+            node *tmp = *cur;
+            void *ret = (*cur)->data;
+            *cur = (*cur)->next;
+            if(!*cur)
+                list->tail = cur;
+
+            free(tmp);
+            return ret;
+        }
+    return 0;
+}
+
+void *_xcb_list_find(_xcb_list *list, int (*cmp)(const void *, const void *), const void *data)
+{
+    node *cur;
+    for(cur = list->head; cur; cur = cur->next)
+        if(cmp(data, cur->data))
+            return cur->data;
+    return 0;
+}
+
+_xcb_queue *_xcb_queue_new(void) __attribute__ ((alias ("_xcb_list_new")));
+void _xcb_queue_delete(_xcb_queue *q, XCBListFreeFunc do_free) __attribute__ ((alias ("_xcb_list_delete")));
+int _xcb_queue_enqueue(_xcb_queue *q, void *data) __attribute__ ((alias ("_xcb_list_append")));
+void *_xcb_queue_dequeue(_xcb_queue *q) __attribute__ ((alias ("_xcb_list_remove_head")));
+
+int _xcb_queue_is_empty(_xcb_queue *q)
+{
+    return q->head == 0;
+}
+
+typedef struct {
+    unsigned int key;
+    void *value;
+} map_pair;
+
+_xcb_map *_xcb_map_new(void) __attribute__ ((alias ("_xcb_list_new")));
+
+void _xcb_map_delete(_xcb_map *q, XCBListFreeFunc do_free)
+{
+    map_pair *tmp;
+    if(!q)
+        return;
+    while((tmp = _xcb_list_remove_head(q)))
+    {
+        if(do_free)
+            do_free(tmp->value);
+        free(tmp);
+    }
+    free(q);
+}
+
+int _xcb_map_put(_xcb_map *q, unsigned int key, void *data)
+{
+    map_pair *cur = malloc(sizeof(map_pair));
+    if(!cur)
+        return 0;
+    cur->key = key;
+    cur->value = data;
+    if(!_xcb_list_append(q, cur))
+    {
+        free(cur);
+        return 0;
+    }
+    return 1;
+}
+
+static int match_map_pair(const void *key, const void *pair)
+{
+    return ((map_pair *) pair)->key == *(unsigned int *) key;
+}
+
+void *_xcb_map_get(_xcb_map *q, unsigned int key)
+{
+    map_pair *cur = _xcb_list_find(q, match_map_pair, &key);
+    if(!cur)
+        return 0;
+    return cur->value;
+}
+
+void *_xcb_map_remove(_xcb_map *q, unsigned int key)
+{
+    map_pair *cur = _xcb_list_remove(q, match_map_pair, &key);
+    void *ret;
+    if(!cur)
+        return 0;
+    ret = cur->value;
+    free(cur);
+    return ret;
+}
diff --git a/src/xcb_out.c b/src/xcb_out.c
new file mode 100644 (file)
index 0000000..b3a556a
--- /dev/null
@@ -0,0 +1,272 @@
+/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
+ *
+ * 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
+ * AUTHORS 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 names of the authors or their
+ * institutions 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 authors.
+ */
+
+/* Stuff that sends stuff to the server. */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "xcb.h"
+#include "xcbext.h"
+#include "xcbint.h"
+#include "extensions/bigreq.h"
+
+static int force_sequence_wrap(XCBConnection *c)
+{
+    int ret = 1;
+    if((c->out.request - c->in.request_read) > 65530)
+    {
+        pthread_mutex_unlock(&c->iolock);
+        ret = XCBSync(c, 0);
+        pthread_mutex_lock(&c->iolock);
+    }
+    return ret;
+}
+
+/* Public interface */
+
+CARD32 XCBGetMaximumRequestLength(XCBConnection *c)
+{
+    pthread_mutex_lock(&c->out.reqlenlock);
+    if(!c->out.maximum_request_length)
+    {
+        const XCBQueryExtensionRep *ext;
+        c->out.maximum_request_length = c->setup->maximum_request_length;
+        ext = XCBGetExtensionData(c, &XCBBigRequestsId);
+        if(ext && ext->present)
+        {
+            XCBBigRequestsEnableRep *r = XCBBigRequestsEnableReply(c, XCBBigRequestsEnable(c), 0);
+            c->out.maximum_request_length = r->maximum_request_length;
+            free(r);
+        }
+    }
+    pthread_mutex_unlock(&c->out.reqlenlock);
+    return c->out.maximum_request_length;
+}
+
+int XCBSendRequest(XCBConnection *c, unsigned int *request, struct iovec *vector, const XCBProtocolRequest *req)
+{
+    int ret;
+    int i;
+    struct iovec prefix[2];
+    CARD16 shortlen = 0;
+    CARD32 longlen = 0;
+
+    assert(c != 0);
+    assert(request != 0);
+    assert(vector != 0);
+    assert(req->count > 0);
+
+    /* put together the length field, possibly using BIGREQUESTS */
+    for(i = 0; i < req->count; ++i)
+        longlen += XCB_CEIL(vector[i].iov_len) >> 2;
+
+    if(longlen > c->setup->maximum_request_length)
+    {
+        if(longlen > XCBGetMaximumRequestLength(c))
+            return 0; /* server can't take this; maybe need BIGREQUESTS? */
+    }
+    else
+    {
+        /* we don't need BIGREQUESTS. */
+        shortlen = longlen;
+        longlen = 0;
+    }
+
+    /* set the length field. */
+    i = 0;
+    prefix[i].iov_base = vector[0].iov_base;
+    prefix[i].iov_len = sizeof(CARD32);
+    vector[0].iov_base = ((char *) vector[0].iov_base) + sizeof(CARD32);
+    vector[0].iov_len -= sizeof(CARD32);
+    ((CARD16 *) prefix[i].iov_base)[1] = shortlen;
+    ++i;
+    if(!shortlen)
+    {
+        ++longlen;
+        prefix[i].iov_base = &longlen;
+        prefix[i].iov_len = sizeof(CARD32);
+        ++i;
+    }
+
+    /* set the major opcode, and the minor opcode for extensions */
+    if(req->ext)
+    {
+        const XCBQueryExtensionRep *extension = XCBGetExtensionData(c, req->ext);
+        /* TODO: better error handling here, please! */
+        assert(extension && extension->present);
+        ((CARD8 *) prefix[0].iov_base)[0] = extension->major_opcode;
+        ((CARD8 *) prefix[0].iov_base)[1] = req->opcode;
+    }
+    else
+        ((CARD8 *) prefix[0].iov_base)[0] = req->opcode;
+
+    /* get a sequence number and arrange for delivery. */
+    pthread_mutex_lock(&c->iolock);
+    if(req->isvoid && !force_sequence_wrap(c))
+    {
+        pthread_mutex_unlock(&c->iolock);
+        return -1;
+    }
+
+    *request = ++c->out.request;
+
+    if(!req->isvoid)
+        _xcb_in_expect_reply(c, *request);
+
+    ret = _xcb_out_write_block(c, prefix, i);
+    if(ret > 0)
+        ret = _xcb_out_write_block(c, vector, req->count);
+    pthread_mutex_unlock(&c->iolock);
+
+    return ret;
+}
+
+int XCBFlush(XCBConnection *c)
+{
+    int ret;
+    pthread_mutex_lock(&c->iolock);
+    ret = _xcb_out_flush(c);
+    pthread_mutex_unlock(&c->iolock);
+    return ret;
+}
+
+/* Private interface */
+
+int _xcb_out_init(_xcb_out *out)
+{
+    if(pthread_cond_init(&out->cond, 0))
+        return 0;
+    out->writing = 0;
+
+    out->queue_len = 0;
+    out->vec = 0;
+    out->vec_len = 0;
+
+    out->last_request = 0;
+    out->request = 0;
+    out->request_written = 0;
+
+    if(pthread_mutex_init(&out->reqlenlock, 0))
+        return 0;
+    out->maximum_request_length = 0;
+
+    return 1;
+}
+
+void _xcb_out_destroy(_xcb_out *out)
+{
+    pthread_cond_destroy(&out->cond);
+    pthread_mutex_destroy(&out->reqlenlock);
+    free(out->vec);
+}
+
+int _xcb_out_write(XCBConnection *c)
+{
+    int n;
+    if(c->out.vec_len)
+        n = _xcb_writev(c->fd, c->out.vec, c->out.vec_len);
+    else
+        n = _xcb_write(c->fd, &c->out.queue, &c->out.queue_len);
+
+    if(n < 0 && errno == EAGAIN)
+        n = 1;
+
+    if(c->out.vec_len)
+    {
+        int i;
+        for(i = 0; i < c->out.vec_len; ++i)
+            if(c->out.vec[i].iov_len)
+                return n;
+        c->out.vec_len = 0;
+    }
+    return n;
+}
+
+int _xcb_out_write_block(XCBConnection *c, struct iovec *vector, size_t count)
+{
+    static const char pad[3];
+    int i;
+    int len = 0;
+
+    for(i = 0; i < count; ++i)
+        len += XCB_CEIL(vector[i].iov_len);
+
+    /* Is the queue about to overflow? */
+    if(c->out.queue_len + len < sizeof(c->out.queue))
+    {
+        /* No, this will fit. */
+        for(i = 0; i < count; ++i)
+        {
+            memcpy(c->out.queue + c->out.queue_len, vector[i].iov_base, vector[i].iov_len);
+            if(vector[i].iov_len & 3)
+                memset(c->out.queue + c->out.queue_len + vector[i].iov_len, 0, XCB_PAD(vector[i].iov_len));
+            c->out.queue_len += XCB_CEIL(vector[i].iov_len);
+        }
+        return len;
+    }
+
+    assert(!c->out.vec_len);
+    assert(!c->out.vec);
+    c->out.vec = malloc(sizeof(struct iovec) * (1 + count * 2));
+    if(!c->out.vec)
+        return -1;
+    if(c->out.queue_len)
+    {
+        c->out.vec[c->out.vec_len].iov_base = c->out.queue;
+        c->out.vec[c->out.vec_len++].iov_len = c->out.queue_len;
+        c->out.queue_len = 0;
+    }
+    for(i = 0; i < count; ++i)
+    {
+        if(!vector[i].iov_len)
+            continue;
+        c->out.vec[c->out.vec_len].iov_base = vector[i].iov_base;
+        c->out.vec[c->out.vec_len++].iov_len = vector[i].iov_len;
+        if(!XCB_PAD(vector[i].iov_len))
+            continue;
+        c->out.vec[c->out.vec_len].iov_base = (void *) pad;
+        c->out.vec[c->out.vec_len++].iov_len = XCB_PAD(vector[i].iov_len);
+    }
+    if(_xcb_out_flush(c) <= 0)
+        len = -1;
+    free(c->out.vec);
+    c->out.vec = 0;
+
+    return len;
+}
+
+int _xcb_out_flush(XCBConnection *c)
+{
+    int ret = 1;
+    while(ret > 0 && (c->out.queue_len || c->out.vec_len))
+        ret = _xcb_conn_wait(c, /*should_write*/ 1, &c->out.cond);
+    c->out.last_request = 0;
+    c->out.request_written = c->out.request;
+    pthread_cond_broadcast(&c->out.cond);
+    return ret;
+}
diff --git a/src/xcb_util.c b/src/xcb_util.c
new file mode 100644 (file)
index 0000000..b25a2d8
--- /dev/null
@@ -0,0 +1,279 @@
+/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
+ *
+ * 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
+ * AUTHORS 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 names of the authors or their
+ * institutions 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 authors.
+ */
+
+/* Utility functions implementable using only public APIs. */
+
+#include <assert.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/fcntl.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "xcb.h"
+#include "xcbext.h"
+
+int XCBPopcount(CARD32 mask)
+{
+    unsigned long y;
+    y = (mask >> 1) & 033333333333;
+    y = mask - y - ((y >> 1) & 033333333333);
+    return ((y + (y >> 3)) & 030707070707) % 077;
+}
+
+int XCBParseDisplay(const char *name, char **host, int *displayp, int *screenp)
+{
+    int len, display, screen;
+    char *colon, *dot, *end;
+    if(!name || !*name)
+        name = getenv("DISPLAY");
+    if(!name)
+        return 0;
+    colon = strrchr(name, ':');
+    if(!colon)
+        return 0;
+    len = colon - name;
+    ++colon;
+    display = strtoul(colon, &dot, 10);
+    if(dot == colon)
+        return 0;
+    if(*dot == '\0')
+        screen = 0;
+    else
+    {
+        if(*dot != '.')
+            return 0;
+        ++dot;
+        screen = strtoul(dot, &end, 10);
+        if(end == dot || *end != '\0')
+            return 0;
+    }
+    /* At this point, the display string is fully parsed and valid, but
+     * the caller's memory is untouched. */
+
+    *host = malloc(len + 1);
+    if(!*host)
+        return 0;
+    memcpy(*host, name, len);
+    (*host)[len] = '\0';
+    *displayp = display;
+    if(screenp)
+        *screenp = screen;
+    return 1;
+}
+
+int XCBOpen(const char *host, const int display)
+{
+    int fd;
+
+    if(*host)
+    {
+        /* display specifies TCP */
+        unsigned short port = X_TCP_PORT + display;
+        fd = XCBOpenTCP(host, port);
+    }
+    else
+    {
+        /* display specifies Unix socket */
+        static const char base[] = "/tmp/.X11-unix/X";
+        char file[sizeof(base) + 20];
+        snprintf(file, sizeof(file), "%s%d", base, display);
+        fd = XCBOpenUnix(file);
+    }
+
+    return fd;
+}
+
+int XCBOpenTCP(const char *host, const unsigned short port)
+{
+    int fd;
+    struct sockaddr_in addr;
+    struct hostent *hostaddr = gethostbyname(host);
+    if(!hostaddr)
+        return -1;
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+    memcpy(&addr.sin_addr, hostaddr->h_addr_list[0], sizeof(addr.sin_addr));
+
+    fd = socket(PF_INET, SOCK_STREAM, 0);
+    if(fd == -1)
+        return -1;
+    if(connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
+        return -1;
+    return fd;
+}
+
+int XCBOpenUnix(const char *file)
+{
+    int fd;
+    struct sockaddr_un addr = { AF_UNIX };
+    strcpy(addr.sun_path, file);
+
+    fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if(fd == -1)
+        return -1;
+    if(connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
+        return -1;
+    return fd;
+}
+
+XCBConnection *XCBConnect(const char *displayname, int *screenp)
+{
+    int fd, display = 0;
+    char *host;
+    XCBConnection *c;
+    XCBAuthInfo auth;
+
+    if(!XCBParseDisplay(displayname, &host, &display, screenp))
+        return 0;
+    fd = XCBOpen(host, display);
+    free(host);
+    if(fd == -1)
+        return 0;
+
+    XCBGetAuthInfo(fd, &auth);
+    c = XCBConnectToFD(fd, &auth);
+    free(auth.name);
+    free(auth.data);
+    return c;
+}
+
+XCBConnection *XCBConnectToDisplayWithAuthInfo(const char *displayname, XCBAuthInfo *auth, int *screenp)
+{
+    int fd, display = 0;
+    char *host;
+
+    if(!XCBParseDisplay(displayname, &host, &display, screenp))
+        return 0;
+    fd = XCBOpen(host, display);
+    free(host);
+    if(fd == -1)
+        return 0;
+
+    return XCBConnectToFD(fd, auth);
+}
+
+/* backwards compatible interface: remove before 1.0 release */
+XCBConnection *XCBConnectBasic()
+{
+    XCBConnection *c = XCBConnect(0, 0);
+    if(c)
+        return c;
+    perror("XCBConnect");
+    abort();
+}
+
+int XCBSync(XCBConnection *c, XCBGenericError **e)
+{
+    XCBGetInputFocusRep *reply = XCBGetInputFocusReply(c, XCBGetInputFocus(c), e);
+    free(reply);
+    return reply != 0;
+}
+
+/* The functions beyond this point still use only public interfaces,
+ * but are not themselves part of the public interface. So their
+ * prototypes are in xcbint.h. */
+
+#include "xcbint.h"
+
+int _xcb_set_fd_flags(const int fd)
+{
+    long flags = fcntl(fd, F_GETFL, 0);
+    if(flags == -1)
+        return 0;
+    flags |= O_NONBLOCK;
+    if(fcntl(fd, F_SETFL, flags) == -1)
+        return 0;
+    if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
+        return 0;
+    return 1;
+}
+
+int _xcb_readn(const int fd, void *buf, const int buflen, int *count)
+{
+    int n = read(fd, ((char *) buf) + *count, buflen - *count);
+    if(n > 0)
+        *count += n;
+    return n;
+}
+
+int _xcb_read_block(const int fd, void *buf, const size_t len)
+{
+    int done = 0;
+    while(done < len)
+    {
+        int ret = _xcb_readn(fd, buf, len, &done);
+        if(ret < 0 && errno == EAGAIN)
+        {
+            fd_set fds;
+            FD_ZERO(&fds);
+            FD_SET(fd, &fds);
+            ret = select(fd + 1, &fds, 0, 0, 0);
+        }
+        if(ret <= 0)
+            return ret;
+    }
+    return len;
+}
+
+int _xcb_write(const int fd, char (*buf)[], int *count)
+{
+    int n = write(fd, *buf, *count);
+    if(n > 0)
+    {
+        *count -= n;
+        if(*count)
+            memmove(*buf, *buf + n, *count);
+    }
+    return n;
+}
+
+int _xcb_writev(const int fd, struct iovec *vec, int count)
+{
+    int n = writev(fd, vec, count);
+    if(n > 0)
+    {
+        int rem = n;
+        for(; count; --count, ++vec)
+        {
+            int cur = vec->iov_len;
+            if(cur > rem)
+                cur = rem;
+            vec->iov_len -= cur;
+            vec->iov_base = (char *) vec->iov_base + cur;
+            rem -= cur;
+            if(vec->iov_len)
+                break;
+        }
+        assert(rem == 0);
+    }
+    return n;
+}
diff --git a/src/xcb_xid.c b/src/xcb_xid.c
new file mode 100644 (file)
index 0000000..7d7f784
--- /dev/null
@@ -0,0 +1,70 @@
+/* Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
+ *
+ * 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
+ * AUTHORS 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 names of the authors or their
+ * institutions 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 authors.
+ */
+
+/* XID allocators. */
+
+#include <stdlib.h>
+#include "xcb.h"
+#include "xcbext.h"
+#include "xcbint.h"
+#include "extensions/xc_misc.h"
+
+/* Public interface */
+
+CARD32 XCBGenerateID(XCBConnection *c)
+{
+    CARD32 ret;
+    pthread_mutex_lock(&c->xid.lock);
+    if(c->xid.last == c->xid.max)
+    {
+           XCBXCMiscGetXIDRangeRep *range;
+           range = XCBXCMiscGetXIDRangeReply(c, XCBXCMiscGetXIDRange(c), 0);
+           c->xid.last = range->start_id;
+           c->xid.max = range->start_id + (range->count - 1) * c->xid.inc;
+           free(range);
+    }
+    ret = c->xid.last | c->xid.base;
+    c->xid.last += c->xid.inc;
+    pthread_mutex_unlock(&c->xid.lock);
+    return ret;
+}
+
+/* Private interface */
+
+int _xcb_xid_init(XCBConnection *c)
+{
+    if(pthread_mutex_init(&c->xid.lock, 0))
+        return 0;
+    c->xid.last = 0;
+    c->xid.base = c->setup->resource_id_base;
+    c->xid.max = c->setup->resource_id_mask;
+    c->xid.inc = c->setup->resource_id_mask & -(c->setup->resource_id_mask);
+    return 1;
+}
+
+void _xcb_xid_destroy(XCBConnection *c)
+{
+    pthread_mutex_destroy(&c->xid.lock);
+}
diff --git a/src/xcb_xlib.c b/src/xcb_xlib.c
new file mode 100644 (file)
index 0000000..8cc6837
--- /dev/null
@@ -0,0 +1,41 @@
+/* Copyright (C) 2005 Bart Massey and Jamey Sharp.
+ *
+ * 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
+ * AUTHORS 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 names of the authors or their
+ * institutions 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 authors.
+ */
+
+#include "xcbxlib.h"
+#include "xcbint.h"
+
+unsigned int XCBGetRequestSent(XCBConnection *c)
+{
+    unsigned int ret;
+    pthread_mutex_lock(&c->iolock);
+    ret = c->out.request;
+    pthread_mutex_unlock(&c->iolock);
+    return ret;
+}
+
+pthread_mutex_t *XCBGetIOLock(XCBConnection *c)
+{
+    return &c->iolock;
+}
diff --git a/src/xcbext.h b/src/xcbext.h
new file mode 100644 (file)
index 0000000..c8f532c
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
+ * All Rights Reserved.
+ *
+ * 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
+ * AUTHORS 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 names of the authors or their
+ * institutions 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 authors.
+ */
+
+#ifndef __XCBEXT_H
+#define __XCBEXT_H
+
+#include "xcb.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* xcb_ext.c */
+
+struct XCBExtension {
+    const char *name;
+    int global_id;
+};
+
+
+/* xcb_out.c */
+
+typedef struct {
+    size_t count;
+    XCBExtension *ext;
+    CARD8 opcode;
+    BOOL isvoid;
+} XCBProtocolRequest;
+
+int XCBSendRequest(XCBConnection *c, unsigned int *sequence, struct iovec *vector, const XCBProtocolRequest *request);
+
+
+/* xcb_in.c */
+
+void *XCBWaitForReply(XCBConnection *c, unsigned int request, XCBGenericError **e);
+
+
+/* xcb_xid.c */
+
+CARD32 XCBGenerateID(XCBConnection *c);
+
+
+/* xcb_util.c */
+
+int XCBPopcount(CARD32 mask);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/xcbint.h b/src/xcbint.h
new file mode 100644 (file)
index 0000000..057a315
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
+ * All Rights Reserved.
+ *
+ * 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
+ * AUTHORS 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 names of the authors or their
+ * institutions 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 authors.
+ */
+
+#ifndef __XCBINT_H
+#define __XCBINT_H
+
+/* Not simply (a <= b) because eventually the 32-bit sequence number
+ * will wrap, causing earlier sequence numbers to be higher than later
+ * ones for a brief but fatal period. (a and b must be unsigned.) */
+#define _xcb_assert_sequence_less(a,b) assert((b) - (a) < 65536)
+
+#define _xcb_assert_valid_sequence(c) do { \
+    _xcb_assert_sequence_less((c)->in.request_read, (c)->out.request_written); \
+    _xcb_assert_sequence_less((c)->out.request_written, (c)->out.request); \
+} while(0)
+
+/* xcb_list.c */
+
+typedef struct _xcb_list _xcb_list;
+typedef void (*XCBListFreeFunc)(void *);
+
+_xcb_list *_xcb_list_new(void);
+void _xcb_list_delete(_xcb_list *list, XCBListFreeFunc do_free);
+int _xcb_list_insert(_xcb_list *list, void *data);
+int _xcb_list_append(_xcb_list *list, void *data);
+void *_xcb_list_peek_head(_xcb_list *list);
+void *_xcb_list_remove_head(_xcb_list *list);
+void *_xcb_list_remove(_xcb_list *list, int (*cmp)(const void *, const void *), const void *data);
+void *_xcb_list_find(_xcb_list *list, int (*cmp)(const void *, const void *), const void *data);
+
+typedef _xcb_list _xcb_queue;
+
+_xcb_queue *_xcb_queue_new(void);
+void _xcb_queue_delete(_xcb_queue *q, XCBListFreeFunc do_free);
+int _xcb_queue_enqueue(_xcb_queue *q, void *data);
+void *_xcb_queue_dequeue(_xcb_queue *q);
+int _xcb_queue_is_empty(_xcb_queue *q);
+
+typedef _xcb_list _xcb_map;
+
+_xcb_map *_xcb_map_new(void);
+void _xcb_map_delete(_xcb_map *q, XCBListFreeFunc do_free);
+int _xcb_map_put(_xcb_map *q, unsigned int key, void *data);
+void *_xcb_map_get(_xcb_map *q, unsigned int key);
+void *_xcb_map_remove(_xcb_map *q, unsigned int key);
+
+
+/* xcb_util.c */
+
+/* Index of nearest 4-byte boundary following E. */
+#define XCB_CEIL(E) (((E)+3)&~3)
+
+#define XCB_PAD(i) ((4 - (i & 3)) & 3)
+
+int _xcb_set_fd_flags(const int fd);
+int _xcb_readn(const int fd, void *buf, const int buflen, int *count);
+int _xcb_read_block(const int fd, void *buf, const size_t len);
+int _xcb_write(const int fd, char (*buf)[], int *count);
+int _xcb_writev(const int fd, struct iovec *vec, int count);
+
+
+/* xcb_out.c */
+
+typedef struct _xcb_out {
+    pthread_cond_t cond;
+    int writing;
+
+    char queue[4096];
+    int queue_len;
+    struct iovec *vec;
+    int vec_len;
+
+    void *last_request;
+    unsigned int request;
+    unsigned int request_written;
+
+    pthread_mutex_t reqlenlock;
+    CARD32 maximum_request_length;
+} _xcb_out;
+
+int _xcb_out_init(_xcb_out *out);
+void _xcb_out_destroy(_xcb_out *out);
+
+int _xcb_out_write(XCBConnection *c);
+int _xcb_out_write_block(XCBConnection *c, struct iovec *vector, size_t count);
+int _xcb_out_flush(XCBConnection *c);
+
+
+/* xcb_in.c */
+
+typedef struct _xcb_in {
+    pthread_cond_t event_cond;
+    int reading;
+
+    char queue[4096];
+    int queue_len;
+
+    unsigned int request_read;
+    _xcb_queue *current_reply;
+
+    _xcb_map *replies;
+    _xcb_queue *events;
+    _xcb_list *readers;
+} _xcb_in;
+
+int _xcb_in_init(_xcb_in *in);
+void _xcb_in_destroy(_xcb_in *in);
+
+int _xcb_in_expect_reply(XCBConnection *c, unsigned int request);
+
+int _xcb_in_read_packet(XCBConnection *c);
+int _xcb_in_read(XCBConnection *c);
+int _xcb_in_read_block(XCBConnection *c, void *buf, int nread);
+
+
+/* xcb_xid.c */
+
+typedef struct _xcb_xid {
+    pthread_mutex_t lock;
+    CARD32 last;
+    CARD32 base;
+    CARD32 max;
+    CARD32 inc;
+} _xcb_xid;
+
+int _xcb_xid_init(XCBConnection *c);
+void _xcb_xid_destroy(XCBConnection *c);
+
+
+/* xcb_ext.c */
+
+typedef struct _xcb_ext {
+    pthread_mutex_t lock;
+    _xcb_map *extensions;
+} _xcb_ext;
+
+int _xcb_ext_init(XCBConnection *c);
+void _xcb_ext_destroy(XCBConnection *c);
+
+
+/* xcb_conn.c */
+
+struct XCBConnection {
+    /* constant data */
+    XCBConnSetupSuccessRep *setup;
+    int fd;
+
+    /* I/O data */
+    pthread_mutex_t iolock;
+    _xcb_in in;
+    _xcb_out out;
+
+    /* misc data */
+    _xcb_ext ext;
+    _xcb_xid xid;
+};
+
+int _xcb_conn_wait(XCBConnection *c, const int should_write, pthread_cond_t *cond);
+#endif
diff --git a/src/xcbxlib.h b/src/xcbxlib.h
new file mode 100644 (file)
index 0000000..e9f7140
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2005 Bart Massey and Jamey Sharp.
+ * All Rights Reserved.
+ *
+ * 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
+ * AUTHORS 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 names of the authors or their
+ * institutions 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 authors.
+ */
+
+#ifndef __XCBXLIB_H
+#define __XCBXLIB_H
+
+#include <pthread.h>
+#include "xcb.h"
+
+unsigned int XCBGetRequestSent(XCBConnection *c);
+
+pthread_mutex_t *XCBGetIOLock(XCBConnection *c);
+
+#endif
diff --git a/tests/.cvsignore b/tests/.cvsignore
new file mode 100644 (file)
index 0000000..bfa26dd
--- /dev/null
@@ -0,0 +1,2 @@
+Makefile.in
+CheckLog.html
diff --git a/tests/CheckLog.xsl b/tests/CheckLog.xsl
new file mode 100644 (file)
index 0000000..3daebaa
--- /dev/null
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<xsl:stylesheet
+       version="1.0"
+       xmlns:check="http://check.sourceforge.net/ns"
+       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+       xmlns="http://www.w3.org/TR/REC-html40">
+
+<xsl:output method="html"/>
+
+<xsl:template match="/">
+<html>
+ <head>
+  <title>Test Suite Results</title>
+ </head>
+
+ <body>
+  <xsl:apply-templates/>
+ </body>
+</html>
+</xsl:template>
+
+<xsl:template match="datetime">
+ <xsl:apply-templates/>
+</xsl:template>
+
+<xsl:template match="duration">
+ <xsl:apply-templates/>
+</xsl:template>
+
+<xsl:template match="check:suite">
+ <xsl:apply-templates select="check:title"/>
+ <center>
+ <table width="80%" border="1">
+  <thead>
+   <tr>
+    <td>Test Path</td>
+    <td>Test Function Location</td>
+    <td>C Identifier</td>
+    <td>Test Case</td>
+    <td>Result</td>
+   </tr>
+  </thead>
+  <tbody>
+   <xsl:apply-templates select="check:test"/>
+  </tbody>
+ </table>
+ </center>
+</xsl:template>
+
+<xsl:template match="check:testsuites">
+ <xsl:apply-templates select="check:suite"/>
+ <h3>Unit Test Statistics</h3>
+ <ul>
+  <li>date/time: <xsl:apply-templates select="check:datetime"/></li>
+  <li>duration: <xsl:apply-templates select="check:duration"/></li>
+ </ul>
+ <hr></hr>
+</xsl:template>
+
+<xsl:template match="check:title">
+ <h2>Test Suite: <xsl:apply-templates/></h2>
+</xsl:template>
+
+<xsl:template match="check:test[@result='success']">
+ <tr bgcolor="lime">
+  <xsl:apply-templates/>
+ </tr>
+</xsl:template>
+
+<xsl:template match="check:test[@result='failure']">
+ <tr bgcolor="red">
+  <xsl:apply-templates/>
+ </tr>
+</xsl:template>
+
+<xsl:template match="check:test[@result='error']">
+ <tr bgcolor="yellow">
+  <xsl:apply-templates/>
+ </tr>
+</xsl:template>
+
+<xsl:template match="check:path">
+ <td><xsl:apply-templates/></td>
+</xsl:template>
+
+<xsl:template match="check:fn">
+ <td><xsl:apply-templates/></td>
+</xsl:template>
+
+<xsl:template match="check:id">
+ <td><xsl:apply-templates/></td>
+</xsl:template>
+
+<xsl:template match="check:description">
+ <td><xsl:apply-templates/></td>
+</xsl:template>
+
+<xsl:template match="check:message">
+ <td><xsl:apply-templates/></td>
+</xsl:template>
+
+</xsl:stylesheet>
+
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644 (file)
index 0000000..fceaf13
--- /dev/null
@@ -0,0 +1,32 @@
+########################
+## tests/Makefile.am
+########################
+SUBDIRS = 
+EXTRA_DIST = CheckLog.xsl
+AM_MAKEFLAGS = -k
+AM_CFLAGS = -Wall -Werror $(XPROTO_CFLAGS) @CHECK_CFLAGS@ -I$(top_srcdir)/src
+LDADD = @CHECK_LIBS@ $(top_builddir)/src/libXCB.la
+
+if HAVE_CHECK
+TESTS = check_all
+check_PROGRAMS = check_all
+check_all_SOURCES =  check_all.c check_suites.h check_public.c
+
+all-local::
+       $(RM) CheckLog*.xml
+
+check-local:
+       $(RM) CheckLog.html
+       if test x$(HTML_CHECK_RESULT) = xtrue; then \
+               $(XSLTPROC) $(srcdir)/CheckLog.xsl CheckLog*.xml > CheckLog.html; \
+       else \
+               touch CheckLog.html; \
+       fi
+
+CheckLog.html: $(check_PROGRAMS)
+       $(MAKE) $(AM_MAKEFLAGS) check;
+
+endif
+
+clean-local::
+       $(RM) CheckLog.html CheckLog*.txt CheckLog*.xml
diff --git a/tests/check_all.c b/tests/check_all.c
new file mode 100644 (file)
index 0000000..4393422
--- /dev/null
@@ -0,0 +1,20 @@
+#include <stdlib.h>
+#include "check_suites.h"
+
+void suite_add_test(Suite *s, TFun tf, const char *name)
+{
+       TCase *tc = tcase_create(name);
+       tcase_add_test(tc, tf);
+       suite_add_tcase(s, tc);
+}
+
+int main(void)
+{
+       int nf;
+       SRunner *sr = srunner_create(public_suite());
+       srunner_set_xml(sr, "CheckLog_xcb.xml");
+       srunner_run_all(sr, CK_NORMAL);
+       nf = srunner_ntests_failed(sr);
+       srunner_free(sr);
+       return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/tests/check_public.c b/tests/check_public.c
new file mode 100644 (file)
index 0000000..9a32ba9
--- /dev/null
@@ -0,0 +1,129 @@
+#include <check.h>
+#include <string.h>
+#include <stdlib.h>
+#include "check_suites.h"
+#include "xcb.h"
+
+/* XCBParseDisplay tests {{{ */
+
+static void parse_display_pass(const char *name, const char *host, const int display, const int screen)
+{
+       int success;
+       char *got_host;
+       int got_display, got_screen;
+
+       got_host = (char *) -1;
+       got_display = got_screen = -42;
+       mark_point();
+       success = XCBParseDisplay(name, &got_host, &got_display, &got_screen);
+       fail_unless(success, "unexpected parse failure for '%s'", name);
+       fail_unless(strcmp(host, got_host) == 0, "parse produced unexpected hostname '%s' for '%s': expected '%s'", got_host, name, host);
+       fail_unless(display == got_display, "parse produced unexpected display '%d' for '%s': expected '%d'", got_display, name, display);
+       fail_unless(screen == got_screen, "parse produced unexpected screen '%d' for '%s': expected '%d'", got_screen, name, screen);
+
+       got_host = (char *) -1;
+       got_display = got_screen = -42;
+       mark_point();
+       success = XCBParseDisplay(name, &got_host, &got_display, 0);
+       fail_unless(success, "unexpected screenless parse failure for '%s'", name);
+       fail_unless(strcmp(host, got_host) == 0, "screenless parse produced unexpected hostname '%s' for '%s': expected '%s'", got_host, name, host);
+       fail_unless(display == got_display, "screenless parse produced unexpected display '%d' for '%s': expected '%d'", got_display, name, display);
+}
+
+static void parse_display_fail(const char *name)
+{
+       int success;
+       char *got_host;
+       int got_display, got_screen;
+
+       got_host = (char *) -1;
+       got_display = got_screen = -42;
+       mark_point();
+       success = XCBParseDisplay(name, &got_host, &got_display, &got_screen);
+       fail_unless(!success, "unexpected parse success for '%s'", name);
+       fail_unless(got_host == (char *) -1, "host changed on failure for '%s': got %p", got_host);
+       fail_unless(got_display == -42, "display changed on failure for '%s': got %d", got_display);
+       fail_unless(got_screen == -42, "screen changed on failure for '%s': got %d", got_screen);
+
+       got_host = (char *) -1;
+       got_display = got_screen = -42;
+       mark_point();
+       success = XCBParseDisplay(name, &got_host, &got_display, 0);
+       fail_unless(!success, "unexpected screenless parse success for '%s'", name);
+       fail_unless(got_host == (char *) -1, "host changed on failure for '%s': got %p", got_host);
+       fail_unless(got_display == -42, "display changed on failure for '%s': got %d", got_display);
+}
+
+START_TEST(parse_display_unix)
+{
+       parse_display_pass(":0", "", 0, 0);
+       parse_display_pass(":1", "", 1, 0);
+       parse_display_pass(":0.1", "", 0, 1);
+}
+END_TEST
+
+START_TEST(parse_display_ip)
+{
+       parse_display_pass("x.org:0", "x.org", 0, 0);
+       parse_display_pass("expo:0", "expo", 0, 0);
+       parse_display_pass("bigmachine:1", "bigmachine", 1, 0);
+       parse_display_pass("hydra:0.1", "hydra", 0, 1);
+}
+END_TEST
+
+START_TEST(parse_display_ipv4)
+{
+       parse_display_pass("198.112.45.11:0", "198.112.45.11", 0, 0);
+       parse_display_pass("198.112.45.11:0.1", "198.112.45.11", 0, 1);
+}
+END_TEST
+
+START_TEST(parse_display_ipv6)
+{
+       parse_display_pass("::1:0", "::1", 0, 0);
+       parse_display_pass("::1:0.1", "::1", 0, 1);
+       parse_display_pass("2002:83fc:d052::1:0", "2002:83fc:d052::1", 0, 0);
+       parse_display_pass("2002:83fc:d052::1:0.1", "2002:83fc:d052::1", 0, 1);
+}
+END_TEST
+
+START_TEST(parse_display_decnet)
+{
+       parse_display_pass("myws::0", "myws:", 0, 0);
+       parse_display_pass("big::1", "big:", 1, 0);
+       parse_display_pass("hydra::0.1", "hydra:", 0, 1);
+}
+END_TEST
+
+START_TEST(parse_display_negative)
+{
+       parse_display_fail(0);
+       parse_display_fail("");
+       parse_display_fail(":");
+       parse_display_fail("::");
+       parse_display_fail(":.");
+       parse_display_fail(":a");
+       parse_display_fail(":a.");
+       parse_display_fail(":0.");
+       parse_display_fail(":0.a");
+       parse_display_fail(":0.0.");
+
+       parse_display_fail("localhost");
+       parse_display_fail("localhost:");
+}
+END_TEST
+
+/* }}} */
+
+Suite *public_suite(void)
+{
+       Suite *s = suite_create("Public API");
+       putenv("DISPLAY");
+       suite_add_test(s, parse_display_unix, "XCBParseDisplay unix");
+       suite_add_test(s, parse_display_ip, "XCBParseDisplay ip");
+       suite_add_test(s, parse_display_ipv4, "XCBParseDisplay ipv4");
+       suite_add_test(s, parse_display_ipv6, "XCBParseDisplay ipv6");
+       suite_add_test(s, parse_display_decnet, "XCBParseDisplay decnet");
+       suite_add_test(s, parse_display_negative, "XCBParseDisplay negative");
+       return s;
+}
diff --git a/tests/check_suites.h b/tests/check_suites.h
new file mode 100644 (file)
index 0000000..499f1af
--- /dev/null
@@ -0,0 +1,4 @@
+#include <check.h>
+
+void suite_add_test(Suite *s, TFun tf, const char *name);
+Suite *public_suite(void);
diff --git a/xcb.pc.in b/xcb.pc.in
new file mode 100644 (file)
index 0000000..108165d
--- /dev/null
+++ b/xcb.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: XCB
+Description: X-protocol C Binding
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -lXCB @XPROTO_LIBS@ @LIBS@
+Cflags: -I${includedir} @XPROTO_CFLAGS@