--- /dev/null
+Keith Packard, HP
+
--- /dev/null
+Copyright © 2002 Keith Packard
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of Keith Packard not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Keith Packard makes no
+representations about the suitability of this software for any purpose. It
+is provided "as is" without express or implied warranty.
+
+KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
--- /dev/null
+commit 2a9eaf3305d1577ad763d56dddd46e10f8d0676b
+Author: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Wed Mar 7 18:54:15 2012 -0800
+
+ libXcursor 1.1.13
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+
+commit 8229cf75b34c2991eaf973f05326be9bfa16ef0c
+Author: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Thu Nov 24 13:10:15 2011 -0800
+
+ XcursorImageLoadCursor: return failure if _XcursorGetDisplayInfo fails
+
+ Error: Null pointer dereference (CWE 476)
+ Read from null pointer 'info'
+ at line 615 of src/cursor.c in function 'XcursorImageLoadCursor'.
+ Function '_XcursorGetDisplayInfo' may return constant 'NULL' at line 134, called at line 597.
+ Null pointer introduced at line 134 of src/display.c in function '_XcursorGetDisplayInfo'.
+
+ [ This bug was found by the Parfait 0.3.7 bug checking tool.
+ For more information see http://labs.oracle.com/projects/parfait/ ]
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+ Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com>
+
+commit 2b8d373bddf427bcd95e2595cb64740ebd1d0d30
+Author: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Thu Nov 24 12:59:56 2011 -0800
+
+ XcursorFileSaveImages: plug memory leak on invalid input
+
+ Error: Memory leak (CWE 401)
+ Memory leak of pointer 'comments' allocated with XcursorCommentsCreate(0)
+ at line 982 of src/file.c in function 'XcursorFileSaveImages'.
+ 'comments' allocated at line 978 with XcursorCommentsCreate(0).
+ comments leaks when comments != 0 at line 981.
+
+ [ This bug was found by the Parfait 0.3.7 bug checking tool.
+ For more information see http://labs.oracle.com/projects/parfait/ ]
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+ Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com>
+
+commit bcfb8e8ce56cf47bc6a61bd8c896bafba9e2a9c2
+Author: Jon TURNEY <jon.turney@dronecode.org.uk>
+Date: Thu Sep 22 14:43:38 2011 +0100
+
+ Add generated Xcursor.h to .gitignore
+
+ Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk>
+ Reviewed-by: Gaetan Nadon <memsize@videotron.ca>
+ Tested-by: Gaetan Nadon <memsize@videotron.ca>
+ Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+
+commit 862b9ce4aa819bf87b6e24db9d7d5867cbaa577c
+Author: Jon TURNEY <jon.turney@dronecode.org.uk>
+Date: Wed Sep 21 20:50:46 2011 +0100
+
+ Fix install of generated Xcursor.h when builddir != srcdir
+
+ Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk>
+ Reviewed-by: Gaetan Nadon <memsize@videotron.ca>
+ Tested-by: Gaetan Nadon <memsize@videotron.ca>
+ Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+
+commit 334dc4f4df69d780f312f23b860df11bee5e9009
+Author: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Fri Sep 16 21:41:41 2011 -0700
+
+ Set Xcursor.h version numbers from configure.ac
+
+ Based on similar commit dac73a519816 to libXft
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+ Reviewed-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit e086eb1bf49f2a8c270eaebd5beb595c1dc2973e
+Author: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Fri Sep 16 21:26:17 2011 -0700
+
+ Strip trailing whitespace
+
+ Performed with: find * -type f | xargs perl -i -p -e 's{\s+$}{\n}'
+ git diff -w & git diff -b show no diffs from this change
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+
+commit d79ddc01e4b247ae95af3581b93aef2b93e76888
+Author: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Wed Jun 29 21:41:09 2011 -0700
+
+ libXcursor 1.1.12
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+
+commit 4ce23fcd978ed389ea30315c0e02629a31bda265
+Author: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Sun May 22 12:55:31 2011 -0700
+
+ Mark bitmasks as unsigned ints
+
+ Clears Sun compiler warnings from shifting 8 bits by 24 bits:
+ "cursor.c", line 215: warning: integer overflow detected: op "<<"
+ "cursor.c", line 280: warning: integer overflow detected: op "<<"
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+
+commit 047993c76a677ca12a2b575990b99e3ddbc0dd58
+Author: Jeremy Huddleston <jeremyhu@apple.com>
+Date: Sat May 7 10:16:18 2011 -0700
+
+ Correct error handling in _XcursorAverageColor
+
+ Previously it would either div-zero or get stuck in a loop until int overflow
+ if called with a bad value.
+
+ cursor.c:214:32: warning: Division by zero
+ return (0xff << 24) | ((red/npixels) << 16) | ((green/npixels) << 8) | (blue/npixels);
+
+ Found-by: clang static analyzer
+ Signed-off-by: Jeremy Huddleston <jeremyhu@apple.com>
+
+commit bee68e54e5c3a4b9f46c81366a720531e3e07a82
+Author: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Fri Apr 1 12:16:23 2011 +0100
+
+ Free the FontInfo structure after loading the cursor from it.
+
+ References: https://bugs.freedesktop.org/show_bug.cgi?id=2731
+ Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit f49e7e1608f2dac140f60bcae21d5c37f79fc41b
+Author: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Fri Apr 1 12:15:46 2011 +0100
+
+ Free the partial header after failing to open the cursor.
+
+ Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 073eb2c56f4794275eee40a825dbfe1232bb2690
+Author: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Fri Apr 1 12:14:51 2011 +0100
+
+ Free list on shutdown.
+
+ We freed the parent structure without freeing the list contained within,
+ making valgrind unhappy.
+
+ Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit de50317ec4e0e8da7de84e85d1f7a6d2e184d58b
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Wed Feb 2 17:08:19 2011 -0500
+
+ config: perform XCURSORPATH formatting in man/Makefile.am
+
+ We can skip the extra step of using XCURSORPATH_LIST in configure.ac.
+
+ Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit a929c3621b9da8e56ce1223afd3e487fc488fa47
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Wed Feb 2 11:43:41 2011 -0500
+
+ config: comment, minor upgrade, quote and layout configure.ac
+
+ Group statements per section as per Autoconf standard layout
+ Quote statements where appropriate.
+ Autoconf recommends not using dnl instead of # for comments
+
+ Use AC_CONFIG_FILES to replace the deprecated AC_OUTPUT with parameters.
+
+ This helps automated maintenance and release activities.
+ Details can be found in http://wiki.x.org/wiki/NewModuleGuidelines
+
+ Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit 96c5877fd7ebc59569f140d9e2cb30fdb8371ef1
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Fri Jan 28 19:41:37 2011 -0500
+
+ config: replace deprecated AM_CONFIG_HEADER with AC_CONFIG_HEADERS
+
+ Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit 4f7a749fcb7a8e93d40a7621fa1c159e003b2f5c
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Fri Jan 28 16:07:07 2011 -0500
+
+ config: replace deprecated AC_HELP_STRING with AS_HELP_STRING
+
+ This silences an Automake warning.
+
+ Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit c38adc6bf116146fa1e291b9f4deed45497e5c2e
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Thu Jan 27 18:50:14 2011 -0500
+
+ config: remove AC_PROG_CC as it overrides AC_PROG_C_C99
+
+ XORG_STRICT_OPTION from XORG_DEFAULT_OPTIONS calls
+ AC_PROG_C_C99. This sets gcc with -std=gnu99.
+ If AC_PROG_CC macro is called afterwards, it resets CC to gcc.
+
+ Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit 731e84d79e83b59d022d0f453b245696b4d2750f
+Author: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Wed Oct 27 22:48:19 2010 -0700
+
+ libXcursor 1.1.11
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+
+commit 42b7717c32b3c7097180667a9ba2f62e40fc6506
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Mon Aug 16 19:28:57 2010 -0400
+
+ man: whitespace management
+
+ Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit 862bc06d58152e74e85fc29db7eaec06af20e00b
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Mon Aug 16 19:25:25 2010 -0400
+
+ man: reorder makefile statements
+
+ No functional change. Shadows are part of libman_PRE.
+
+ Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit b18568dd5b5a11ae49cad66a54ec50465c6ffa77
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Mon Aug 16 19:17:21 2010 -0400
+
+ man: store shadow man pages in git rather than generating them
+
+ Simplify the build process and the makefile.
+
+ Local fix in CVS for bug 5628 is not required
+ as the problem has been fixed in
+ util-macros d9062e4077ebfd0985baf8418f3d0f111b9ddbba
+
+ Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit 68d830bcf67632b474c8996b6a2c9bcde8e27f97
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Mon Aug 16 19:05:35 2010 -0400
+
+ config: upgrade to util-macros 1.8 for additional man page support
+
+ Use MAN_SUBST now supplied in XORG_MANPAGE_SECTIONS
+ The value of MAN_SUBST is the same for all X.Org packages.
+
+ Use AC_PROG_SED now supplied by XORG_DEFAULT_OPTIONS
+
+ Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit 0caadca51ca56a2ae2cfe67cbd2b29e89b6a68d8
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Mon Mar 29 16:50:33 2010 -0400
+
+ config: update AC_PREREQ statement to 2.60
+
+ Unrelated to the previous patches, the new value simply reflects
+ the reality that the minimum level for autoconf to configure
+ all x.org modules is 2.60 dated June 2006.
+
+ ftp://ftp.gnu.org/gnu/autoconf/autoconf-2.60.tar.gz
+
+ Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit b511b260ddcec34035c1d97285f27f3182663a6a
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Mon Mar 29 14:53:48 2010 -0400
+
+ config: remove the pkgconfig pc.in file from EXTRA_DIST
+
+ Automake always includes it in the tarball.
+
+ Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit a3e03bb23bf7a92bf20d51eebe692e0a4f667065
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Tue Feb 16 10:37:21 2010 -0500
+
+ config: move CWARNFLAGS from configure.ac to Makefile.am
+
+ Compiler warning flags should be explicitly set in the makefile
+ rather than being merged with other packages compiler flags.
+
+ Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit 8198d1490959d49573790405e205a471ac7a5b98
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Fri Nov 27 20:56:04 2009 -0500
+
+ Makefile.am: add ChangeLog and INSTALL on MAINTAINERCLEANFILES
+
+ Now that the INSTALL file is generated.
+ Allows running make maintainer-clean.
+
+commit ecddb70049a1e79b88d4d647f7e944237055fa2e
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Wed Oct 28 14:09:10 2009 -0400
+
+ INSTALL, NEWS, README or AUTHORS files are missing/incorrect #24206
+
+ Add missing INSTALL file. Use standard GNU file on building tarball
+ README may have been updated
+ Remove AUTHORS file as it is empty and no content available yet.
+ Remove NEWS file as it is empty and no content available yet.
+
+commit 02cd3d7a617c71dbc13023f91f41b896dc260c50
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Tue Oct 27 15:07:25 2009 -0400
+
+ Deploy the new XORG_DEFAULT_OPTIONS #24242
+
+ This macro aggregate a number of existing macros that sets commmon
+ X.Org components configuration options. It shields the configuration file from
+ future changes.
+
+commit 1ca6aefa6690930b336490525f5ed515ddad26ac
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Mon Oct 26 22:08:42 2009 -0400
+
+ Makefile.am: ChangeLog not required: EXTRA_DIST or *CLEANFILES #24432
+
+ ChangeLog filename is known to Automake and requires no further
+ coding in the makefile.
+
+commit 1c158db62ad2c7584d88e840f3c7fe151de84150
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Thu Oct 22 12:34:19 2009 -0400
+
+ .gitignore: use common defaults with custom section # 24239
+
+ Using common defaults will reduce errors and maintenance.
+ Only the very small or inexistent custom section need periodic maintenance
+ when the structure of the component changes. Do not edit defaults.
+
+commit 5e14cd9bd8a8f9266ecaa69d58c15d8e298d8a78
+Author: Jeremy Huddleston <jeremyhu@freedesktop.org>
+Date: Wed Oct 21 12:47:24 2009 -0700
+
+ This is not a GNU project, so declare it foreign.
+
+ On Wed, 2009-10-21 at 13:36 +1000, Peter Hutterer wrote:
+ > On Tue, Oct 20, 2009 at 08:23:55PM -0700, Jeremy Huddleston wrote:
+ > > I noticed an INSTALL file in xlsclients and libXvMC today, and it
+ > > was quite annoying to work around since 'autoreconf -fvi' replaces
+ > > it and git wants to commit it. Should these files even be in git?
+ > > Can I nuke them for the betterment of humanity and since they get
+ > > created by autoreconf anyways?
+ >
+ > See https://bugs.freedesktop.org/show_bug.cgi?id=24206
+
+ As an interim measure, replace AM_INIT_AUTOMAKE([dist-bzip2]) with
+ AM_INIT_AUTOMAKE([foreign dist-bzip2]). This will prevent the generation
+ of the INSTALL file. It is also part of the 24206 solution.
+
+ Signed-off-by: Jeremy Huddleston <jeremyhu@freedesktop.org>
+
+commit fbf229879370a96a070ebf087426f6f6c0dbe5a2
+Author: Peter Hutterer <peter.hutterer@who-t.net>
+Date: Fri Aug 28 14:49:15 2009 +1000
+
+ libXcursor 1.1.10
+
+ Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
+
+commit 59e3f6520f4d1682d3242d1d5656e7972cf11944
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Mon Feb 2 20:34:32 2009 -0800
+
+ Add README with pointers to mailing list, bugzilla & git repos
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
+
+commit f00ae32322d2b3c5d97724b80c72d3e2d0812935
+Author: Paulo Cesar Pereira de Andrade <pcpa@mandriva.com.br>
+Date: Thu Jan 29 15:34:11 2009 -0200
+
+ Janitor: make distcheck, compiler warnings, extra .gitignore files.
+
+commit 04641d3cc3e2f7389c5a3ea6e1d55543e033153f
+Author: Matthieu Herrb <matthieu.herrb@laas.fr>
+Date: Sun Mar 9 00:34:36 2008 +0100
+
+ nuke RCS Ids
+
+commit 94531dc8f6eff9c9f5cbb18ca6b3d4ff79eec752
+Author: James Cloos <cloos@jhcloos.com>
+Date: Thu Dec 6 16:38:25 2007 -0500
+
+ Replace static ChangeLog with dist-hook to generate from git log
+
+commit a4f29e6deef2bf46cae811aaac1f535945cd9fee
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Fri Aug 24 14:01:07 2007 -0700
+
+ Version bump: 1.1.9
+
+commit 5a2601740d04d4180e77695c4b60f2cf5c84be6c
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Wed Aug 22 19:40:55 2007 -0700
+
+ Make shadow man pages for each function
+
+commit fef474da694ea3c1fd184d93cc07bf8d95f89327
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Tue Aug 21 19:45:35 2007 -0700
+
+ Add XCURSOR_PATH to man page
+
+commit a9ccf1bd91ad6e06f7b7116efe836c365b68645b
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Tue Aug 21 19:33:00 2007 -0700
+
+ Use cursorpath found by configure in man page
+
+commit 110131bd40d0fc042f4a81922372307a1582b591
+Author: Tilman Sauerbeck <tilman@code-monkey.de>
+Date: Sat May 12 22:42:08 2007 +0200
+
+ Added object files to .gitignore.
+
+commit 3c5d4f591ce0b473af9f693cfe25a1506cc573d6
+Author: Tilman Sauerbeck <tilman@code-monkey.de>
+Date: Sat May 12 22:41:27 2007 +0200
+
+ Store the cursor names in one large string.
+
+ This means the compiler doesn't need to place the array in the
+ read-write sections of the DSO, which means less relocations
+ when the library is loaded and a smaller memory footprint.
+
+commit 8b73dc04111c1910a6467417133a44d0aa29c6ac
+Author: Adam Jackson <ajax@benzedrine.nwnk.net>
+Date: Fri Oct 13 16:01:17 2006 -0400
+
+ Bump to 1.1.8
+
+commit 9df9640643fae7b922b18ee219d6d9694345df14
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Tue Oct 10 14:57:16 2006 -0700
+
+ Fix many sparse warnings: Using plain integer as NULL pointer
+
+commit b6b9f5885566e4c2df8e3319fe092c22f319983f
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Tue Oct 10 13:46:17 2006 -0700
+
+ Fix lint warning: deallocating a pointer that could be NULL: library.c(266)
+
+commit d0e12a97849871b0b2af04bf8d7a3839c54b31a8
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Tue Oct 10 13:33:33 2006 -0700
+
+ Add XORG_WITH_LINT to allow checking code with lint/sparse/etc.
+
+commit 932965298c244553f303fab3bdf23941cc40bb23
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Fri Oct 6 16:44:37 2006 -0700
+
+ Use $prefix & $ICONDIR settings from configure for default path in manpage
+
+ (Stop hardcoding /usr/X11R6 & /usr/share in the paths shown.)
+
+commit f591196271e53c64e27cf41e5b6ae844a480cb3d
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Fri Oct 6 16:22:52 2006 -0700
+
+ Xcursor.man formatting cleanups
+
+commit 3c5f5860d6f85230f417ce6af30fc73ab75c437b
+Author: Bart Massey <bart@po8.org>
+Date: Tue Sep 12 09:02:54 2006 -0700
+
+ Added missing dependency
+
+commit c7d048dacf3fce6f3121cf0114fd08bb130130b8
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Thu Aug 24 19:21:47 2006 -0700
+
+ Use version number from configure.ac in Xcursor.man instead of "Version 1.0"
+
+commit 8c73ee726016dae6f56195d44339b4729121bcf2
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Thu Aug 24 18:42:36 2006 -0700
+
+ Add *~ to .gitignore to skip over emacs droppings
+
+commit c7886900f180da2c460d0a5926daee787e7258ea
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Thu Aug 24 18:42:03 2006 -0700
+
+ Man page typo fixes (pimaps, directorys)
+
+commit e0a501e91c270c0e99a55aa568f6df0d3d6e541d
+Author: Chris Wilson <cpwilson@taz.qinetiq.com>
+Date: Sat Aug 12 19:55:44 2006 +0300
+
+ fix leak in header destruction
+ Fix a couple of if (!foo) free(foo); tests.
+
+commit 2f08984396552c0719fbc3d3e1148157a1423376
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Thu Jul 13 14:58:50 2006 -0700
+
+ renamed: .cvsignore -> .gitignore
+
+commit c6f65af419d14a753459a71a671baafd84fa1330
+Author: Daniel Stone <daniel@fooishbar.org>
+Date: Sat Jun 3 10:23:57 2006 +0000
+
+ Bug #5268: Fix small memory leak. (Matthias Clasen). Change some return 0s
+ to NULL. Bump to 1.1.7.
+
+commit 8adc6fe181991af8befb0f365360e9a68357da29
+Author: Eric Anholt <anholt@freebsd.org>
+Date: Thu Apr 27 17:26:28 2006 +0000
+
+ Look for cursors in datadir, not always /usr/share.
+
+commit 3c69a6ef12aa43d5c9cc5cfbd76c6bea1fa2bd00
+Author: Adam Jackson <ajax@nwnk.net>
+Date: Thu Apr 27 00:04:48 2006 +0000
+
+ Bump to 1.1.6
+
+commit f9bc007d71f58db93b7eadeb8c77d0f90379c620
+Author: Adam Jackson <ajax@nwnk.net>
+Date: Fri Apr 7 00:58:59 2006 +0000
+
+ Coverity #159: Prevent a possible NULL chase.
+
+commit 1f862e619f12b54bee2efbb66f77c750184b191f
+Author: Daniel Stone <daniel@fooishbar.org>
+Date: Sat Mar 4 21:00:40 2006 +0000
+
+ Bug #4439: Include Xlib.h.
+
+commit 461b3c5c0e47eed1b4abf5189ba92bb70d700fa1
+Author: Kevin E Martin <kem@kem.org>
+Date: Thu Dec 15 00:24:29 2005 +0000
+
+ Update package version number for final X11R7 release candidate.
+
+commit aed42762a9fcfcf1b7729dc0a7014ea679d309eb
+Author: Kevin E Martin <kem@kem.org>
+Date: Fri Dec 9 19:28:41 2005 +0000
+
+ Add icondir to xcursor.pc to be used when installing cursors.
+
+commit 189c9672264c4b62f18f9da9422375b216dc7037
+Author: Kevin E Martin <kem@kem.org>
+Date: Thu Dec 8 17:55:19 2005 +0000
+
+ Add configure options to allow hard-coded paths to be changed.
+
+commit b8c92a26d01b14cb9d27cd30d261e24833d0c728
+Author: Kevin E Martin <kem@kem.org>
+Date: Thu Dec 8 17:54:40 2005 +0000
+
+ Allow hard-coded paths to be configurable.
+
+commit af09e8d8edb7d68367399336ca3163df4c713ffa
+Author: Kevin E Martin <kem@kem.org>
+Date: Tue Dec 6 22:48:42 2005 +0000
+
+ Change *man_SOURCES ==> *man_PRE to fix autotools warnings.
+
+commit 47043f5e93df6a806bf298eca309e05159c271df
+Author: Kevin E Martin <kem@kem.org>
+Date: Sat Dec 3 05:49:43 2005 +0000
+
+ Update package version number for X11R7 RC3 release.
+
+commit a3ddd7c6aa895dd373a73957f0b18181d7f8f486
+Author: Alan Coopersmith <Alan.Coopersmith@sun.com>
+Date: Mon Nov 28 22:03:05 2005 +0000
+
+ Change *mandir targets to use new *_MAN_DIR variables set by xorg-macros.m4
+ update to fix bug #5167 (Linux prefers *.1x man pages in man1 subdir)
+
+commit 328e88110f43b18268c1fde62e9ce7247a797699
+Author: Kevin E Martin <kem@kem.org>
+Date: Sat Nov 19 07:15:41 2005 +0000
+
+ Update pkgconfig files to separate library build-time dependencies from
+ application build-time dependencies, and update package deps to work
+ with separate build roots.
+
+commit 54d9a60a1891c1c1938db00d835b8fe0a12327c6
+Author: Alan Coopersmith <Alan.Coopersmith@sun.com>
+Date: Sun Nov 13 17:59:28 2005 +0000
+
+ Use $(LIB_MAN_SUFFIX) instead of forcing man page into section 3.
+
+commit f0dfdfc7b4ee020ffb83a9179b9d4d4a6139b5e1
+Author: Kevin E Martin <kem@kem.org>
+Date: Wed Nov 9 21:31:19 2005 +0000
+
+ Bump version numbers for X11R6.9/X11R7 RC2.
+
+commit c0773eea4b50162ae0b9b624a46079e71b8e49c2
+Author: Kevin E Martin <kem@kem.org>
+Date: Wed Nov 9 21:19:12 2005 +0000
+
+ Update package version number for X11R7 RC2 release.
+
+commit 345cf369206f0a2a03e842a108bd8f068da36d3f
+Author: Kevin E Martin <kem@kem.org>
+Date: Tue Nov 1 15:11:51 2005 +0000
+
+ Update pkgcheck dependencies to work with separate build roots.
+
+commit 7c7bdccde9d2208a9330099e3cd21060c60638be
+Author: Adam Jackson <ajax@nwnk.net>
+Date: Wed Oct 19 22:26:55 2005 +0000
+
+ Bug #4244: Make XcursorSetTheme(dpy, NULL) restore the default theme.
+ (Frederico Mena-Quintero)
+
+commit 4d4de72c697217ac155231d1761db065c9a778ee
+Author: Kevin E Martin <kem@kem.org>
+Date: Wed Oct 19 02:48:09 2005 +0000
+
+ Update package version number for RC1 release.
+
+commit b1bc7d7328ff2741e1c13151799422fee9e6d0cd
+Author: Alan Coopersmith <Alan.Coopersmith@sun.com>
+Date: Thu Oct 13 02:22:47 2005 +0000
+
+ Use troff macros to prevent cpp eating C comments & #defines that are
+ supposed to appear in man page output.
+
+commit 08ccddfa98d3e4daa9993a206ec0fa3cf9329cd1
+Author: Alan Coopersmith <Alan.Coopersmith@sun.com>
+Date: Tue Oct 11 01:37:44 2005 +0000
+
+ Define HAVE_XFIXES
+
+commit 7a5e36017905a3b7fe70362dc9712654c816c6a5
+Author: Adam Jackson <ajax@nwnk.net>
+Date: Wed Aug 3 03:28:01 2005 +0000
+
+ Do PKG_CHECK_MODULES on a unique token instead of on "DEP", so builds with
+ a global configure cache don't get confused.
+
+commit af4b88bba232af55484e8b82ce8abab6013e985e
+Author: Kevin E Martin <kem@kem.org>
+Date: Fri Jul 29 21:22:51 2005 +0000
+
+ Various changes preparing packages for RC0:
+ - Verify and update package version numbers as needed
+ - Implement versioning scheme
+ - Change bug address to point to bugzilla bug entry form
+ - Disable loadable i18n in libX11 by default (use --enable-loadable-i18n to
+ reenable it)
+ - Fix makedepend to use pkgconfig and pass distcheck
+ - Update build script to build macros first
+ - Update modular Xorg version
+
+commit b34368c667bd47db56bc7e2b36710a22bc3862b0
+Author: Daniel Stone <daniel@fooishbar.org>
+Date: Sat Jul 16 06:35:32 2005 +0000
+
+ Change soversion to 1.0.2 with -version-number.
+
+commit 9ffefcd641352900f9bf7cb06cbe04e91714b490
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jul 9 06:13:36 2005 +0000
+
+ Add .cvsignore files Switch _la_CFLAGS for AM_CFLAGS to clean up directory
+
+commit b5a724c201e0881fcb22738560597e333c39ba12
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jul 8 05:02:01 2005 +0000
+
+ Make sure XFIXES appears in LIBS line, fix up other pkg-config usage.
+
+commit 45b0f06f132347e5eaabbc5ff294bc9016de75dd
+Author: Daniel Stone <daniel@fooishbar.org>
+Date: Sun Jul 3 07:00:56 2005 +0000
+
+ Add Xtrans definitions (FONT_t, TRANS_CLIENT) to clean up warnings.
+ Add XSERV_t, TRANS_SERVER, TRANS_REOPEN to quash warnings.
+ Add #include <dix-config.h> or <xorg-config.h>, as appropriate, to all
+ source files in the xserver/xorg tree, predicated on defines of
+ HAVE_{DIX,XORG}_CONFIG_H. Change all Xfont includes to
+ <X11/fonts/foo.h>.
+
+commit c010a3f076b2f93e2baf4a9472bf5f132266d2db
+Author: Eric Anholt <anholt@freebsd.org>
+Date: Sun Jul 3 00:02:27 2005 +0000
+
+ There are no manpages in this directory, so don't try to include them in
+ EXTRA_DIST. Should fix the build.
+ Reported by: tinderbox
+
+commit 0881bb3ce0ea793e279fcc8ddd16de6ed7e17471
+Author: Kevin E Martin <kem@kem.org>
+Date: Sat Jul 2 06:35:03 2005 +0000
+
+ Add appropriate lib*_CFLAGS to Makefile.am's -- fixes build problems
+
+commit caa910e492e4d15208f3d179021687c25a84f36e
+Author: Daniel Stone <daniel@fooishbar.org>
+Date: Wed Jun 29 18:46:53 2005 +0000
+
+ Import Xcursor 1.1.4 from freedesktop.org xlibs tree.
+
+commit e67de73f5ca7ae854c18fa1500c8eaf412b44c6c
+Author: Daniel Stone <daniel@fooishbar.org>
+Date: Mon Jun 13 16:44:53 2005 +0000
+
+ Bug #1043: Fix leak when creating animated cursors.
+
+commit 89e52cde6eaf5e2d46198ee2fa16b67ef7e1dd32
+Author: Søren Sandmann Pedersen <sandmann@daimi.au.dk>
+Date: Wed Jun 8 20:51:37 2005 +0000
+
+ Remove experiment with calling the man page file 4x
+
+commit 5589b4f6a36f2c039adc81fa4d406574eeef35b3
+Author: Søren Sandmann Pedersen <sandmann@daimi.au.dk>
+Date: Wed Jun 8 20:44:18 2005 +0000
+
+ Remove all the not found with pkgconfig stuff
+
+commit 4070c0af6c7bfe12218181d56e8e3cbb86006d27
+Author: Søren Sandmann Pedersen <sandmann@daimi.au.dk>
+Date: Wed Jun 8 19:15:43 2005 +0000
+
+ - Add Xcursor build system
+
+commit 50911b052ce90d41cd0ae71f83352ffa45e7c0a4
+Author: Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk>
+Date: Sat Dec 4 00:42:47 2004 +0000
+
+ Encoding of numerous files changed to UTF-8
+
+commit cbcf471d9157c88a506cd3f067253c8e64cb8e08
+Author: Egbert Eich <eich@suse.de>
+Date: Fri Apr 23 18:43:40 2004 +0000
+
+ Merging XORG-CURRENT into trunk
+
+commit fb1739bd2272fa45d9c04fe40517468a49660b37
+Author: Egbert Eich <eich@suse.de>
+Date: Sun Mar 14 08:32:05 2004 +0000
+
+ Importing vendor version xf86-4_4_99_1 on Sun Mar 14 00:26:39 PST 2004
+
+commit bfcfbe061fb492f58ee6bd6dc6e90cedd1cccbbb
+Author: Egbert Eich <eich@suse.de>
+Date: Wed Mar 3 12:11:23 2004 +0000
+
+ Importing vendor version xf86-4_4_0 on Wed Mar 3 04:09:24 PST 2004
+
+commit c450b7450372fa2f6660dafcbd3fb7cec9e046df
+Author: Egbert Eich <eich@suse.de>
+Date: Thu Feb 26 13:35:32 2004 +0000
+
+ readding XFree86's cvs IDs
+
+commit 79b8e8b996311665ae1fc8fa7e7d38270b3d9570
+Author: Egbert Eich <eich@suse.de>
+Date: Thu Feb 26 09:22:42 2004 +0000
+
+ Importing vendor version xf86-4_3_99_903 on Wed Feb 26 01:21:00 PST 2004
+
+commit b39c8ec34b4464f78db534355541a4eb5688a999
+Author: Kaleb Keithley <kaleb@freedesktop.org>
+Date: Thu Dec 4 22:02:56 2003 +0000
+
+ XFree86 4.3.99.901 (RC 1)
+
+commit 969878fc6fed5e43b4f7e2e3ee46835d93d30dfd
+Author: Kaleb Keithley <kaleb@freedesktop.org>
+Date: Tue Nov 25 19:28:09 2003 +0000
+
+ XFree86 4.3.99.16 Bring the tree up to date for the Cygwin folks
+
+commit 8387908965317cc3cf2072187c20f617609a13b7
+Author: Kaleb Keithley <kaleb@freedesktop.org>
+Date: Fri Nov 14 16:48:48 2003 +0000
+
+ XFree86 4.3.0.1
+
+commit 3b84b14bf06840d5cd446f2aba495108d23d66d7
+Author: Kaleb Keithley <kaleb@freedesktop.org>
+Date: Fri Nov 14 16:48:48 2003 +0000
+
+ Initial revision
--- /dev/null
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006, 2007, 2008 Free Software Foundation, Inc.
+
+ This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+ Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package. The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
+
+ 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 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.
+
+ Running `configure' might take a while. 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.
+
+ 6. Often, you can also type `make uninstall' to remove the installed
+ files again.
+
+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=c99 CFLAGS=-g 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 can use 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 `..'.
+
+ With a non-GNU `make', it is safer 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.
+
+ On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple `-arch' options to the
+compiler but only a single `-arch' option to the preprocessor. Like
+this:
+
+ ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CPP="gcc -E" CXXCPP="g++ -E"
+
+ This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the `lipo' tool if you have problems.
+
+Installation Names
+==================
+
+ By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' 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.
+
+Particular systems
+==================
+
+ On HP-UX, the default C compiler is not ANSI C compatible. If GNU
+CC is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+ ./configure CC="cc -Ae"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+ On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its `<wchar.h>' header file. The option `-nodtk' can be used as
+a workaround. If GNU CC is not installed, it is therefore recommended
+to try
+
+ ./configure CC="cc"
+
+and if that doesn't work, try
+
+ ./configure CC="cc -nodtk"
+
+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 option `--target=TYPE' 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
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug. Until the bug is fixed you can use this workaround:
+
+ CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+ Print a summary of all of the options to `configure', and exit.
+
+`--help=short'
+`--help=recursive'
+ Print a summary of the options unique to this package's
+ `configure', and exit. The `short' variant lists options used
+ only in the top level, while the `recursive' variant lists options
+ also present in any nested packages.
+
+`--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.
+
+`--prefix=DIR'
+ Use DIR as the installation prefix. *Note Installation Names::
+ for more details, including other options available for fine-tuning
+ the installation locations.
+
+`--no-create'
+`-n'
+ Run the configure checks, but stop before creating any output
+ files.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
--- /dev/null
+#
+# Copyright © 2003 Keith Packard, Noah Levitt
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of Keith Packard not be used in
+# advertising or publicity pertaining to distribution of the software without
+# specific, written prior permission. Keith Packard makes no
+# representations about the suitability of this software for any purpose. It
+# is provided "as is" without express or implied warranty.
+#
+# KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+# EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+SUBDIRS = src man
+
+AM_CFLAGS = $(XRENDER_CFLAGS) $(XFIXES_CFLAGS) $(X_CFLAGS)
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = xcursor.pc
+
+MAINTAINERCLEANFILES = ChangeLog INSTALL
+
+if LINT
+lint:
+ (cd src && $(MAKE) $(MFLAGS) lint)
+endif LINT
+
+
+.PHONY: ChangeLog INSTALL
+
+INSTALL:
+ $(INSTALL_CMD)
+
+ChangeLog:
+ $(CHANGELOG_CMD)
+
+dist-hook: ChangeLog INSTALL
--- /dev/null
+libXcursor - X Window System Cursor management library
+
+All questions regarding this software should be directed at the
+Xorg mailing list:
+
+ http://lists.freedesktop.org/mailman/listinfo/xorg
+
+Please submit bug reports to the Xorg bugzilla:
+
+ https://bugs.freedesktop.org/enter_bug.cgi?product=xorg
+
+The master development code repository can be found at:
+
+ git://anongit.freedesktop.org/git/xorg/lib/libXcursor
+
+ http://cgit.freedesktop.org/xorg/lib/libXcursor
+
+For patch submission instructions, see:
+
+ http://www.x.org/wiki/Development/Documentation/SubmittingPatches
+
+For more information on the git code manager, see:
+
+ http://wiki.x.org/wiki/GitPage
+
--- /dev/null
+#
+# Copyright © 2003 Keith Packard
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of Keith Packard not be used in
+# advertising or publicity pertaining to distribution of the software without
+# specific, written prior permission. Keith Packard makes no
+# representations about the suitability of this software for any purpose. It
+# is provided "as is" without express or implied warranty.
+#
+# KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+# EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+#
+
+# Initialize Autoconf
+AC_PREREQ([2.60])
+#
+# This is the package version number, not the shared library
+# version. This version number will be substituted into Xcursor.h
+#
+AC_INIT([libXcursor], [1.1.13],
+ [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],[libXcursor])
+AC_CONFIG_SRCDIR([Makefile.am])
+AC_CONFIG_HEADERS([config.h include/X11/Xcursor/Xcursor.h])
+
+# Initialize Automake
+AM_INIT_AUTOMAKE([foreign dist-bzip2])
+AM_MAINTAINER_MODE
+
+# Initialize libtool
+AC_PROG_LIBTOOL
+
+# Require X.Org macros 1.8 or later for MAN_SUBSTS set by XORG_MANPAGE_SECTIONS
+m4_ifndef([XORG_MACROS_VERSION],
+ [m4_fatal([must install xorg-macros 1.8 or later before running autoconf/autogen])])
+XORG_MACROS_VERSION(1.8)
+XORG_DEFAULT_OPTIONS
+
+# Set library version for Xcursor.h from package version set in AC_INIT
+# copied from PACKAGE_VERSION_* settings in XORG_VERSION
+AC_DEFINE_UNQUOTED([XCURSOR_LIB_MAJOR],
+ [`echo $PACKAGE_VERSION | cut -d . -f 1`],
+ [Major version of libXcursor])
+AC_DEFINE_UNQUOTED([XCURSOR_LIB_MINOR],
+ [`echo $PACKAGE_VERSION | cut -d . -f 2 | cut -d - -f 1`],
+ [Minor version of libXcursor])
+AC_DEFINE_UNQUOTED([XCURSOR_LIB_REVISION],
+ [`echo $PACKAGE_VERSION | cut -d . -f 3 | cut -d - -f 1`],
+ [Micro revision of libXcursor])
+
+
+AC_ARG_WITH(icondir,
+ AS_HELP_STRING([--with-icondir=<path>],
+ [Set default icon directory (default: ${datadir}/icons)]),
+ [ICONDIR="$withval"],
+ [ICONDIR=${datadir}/icons])
+AC_SUBST([ICONDIR])
+
+DEF_CURSORPATH="~/.icons:${datadir}/icons:${datadir}/pixmaps"
+if test "x${ICONDIR}" != "x${datadir}/icons"; then
+ DEF_CURSORPATH="${DEF_CURSORPATH}:${ICONDIR}"
+fi
+AC_ARG_WITH(cursorpath,
+ AS_HELP_STRING([--with-cursorpath=<paths>],
+ [Set default search path for cursors]),
+ [XCURSORPATH="$withval"],
+ [XCURSORPATH=$DEF_CURSORPATH])
+AC_SUBST([XCURSORPATH])
+
+# Obtain compiler/linker options for depedencies
+PKG_CHECK_MODULES(XCURSOR, xrender >= 0.8.2 xfixes x11 fixesproto)
+AC_DEFINE(HAVE_XFIXES, 1, [Define to 1 if you have Xfixes])
+
+# Allow checking code with lint, sparse, etc.
+XORG_WITH_LINT
+
+AC_CONFIG_FILES([Makefile
+ src/Makefile
+ man/Makefile
+ xcursor.pc])
+AC_OUTPUT
--- /dev/null
+/* include/X11/Xcursor/Xcursor.h. Generated from Xcursor.h.in by configure. */
+/*
+ * Copyright © 2002 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _XCURSOR_H_
+#define _XCURSOR_H_
+#include <stdio.h>
+#include <X11/Xfuncproto.h>
+#include <X11/Xlib.h>
+
+typedef int XcursorBool;
+typedef unsigned int XcursorUInt;
+
+typedef XcursorUInt XcursorDim;
+typedef XcursorUInt XcursorPixel;
+
+#define XcursorTrue 1
+#define XcursorFalse 0
+
+/*
+ * Cursor files start with a header. The header
+ * contains a magic number, a version number and a
+ * table of contents which has type and offset information
+ * for the remaining tables in the file.
+ *
+ * File minor versions increment for compatible changes
+ * File major versions increment for incompatible changes (never, we hope)
+ *
+ * Chunks of the same type are always upward compatible. Incompatible
+ * changes are made with new chunk types; the old data can remain under
+ * the old type. Upward compatible changes can add header data as the
+ * header lengths are specified in the file.
+ *
+ * File:
+ * FileHeader
+ * LISTofChunk
+ *
+ * FileHeader:
+ * CARD32 magic magic number
+ * CARD32 header bytes in file header
+ * CARD32 version file version
+ * CARD32 ntoc number of toc entries
+ * LISTofFileToc toc table of contents
+ *
+ * FileToc:
+ * CARD32 type entry type
+ * CARD32 subtype entry subtype (size for images)
+ * CARD32 position absolute file position
+ */
+
+#define XCURSOR_MAGIC 0x72756358 /* "Xcur" LSBFirst */
+
+/*
+ * Current Xcursor version number. Will be substituted by configure
+ * from the version in the libXcursor configure.ac file.
+ */
+
+#define XCURSOR_LIB_MAJOR 1
+#define XCURSOR_LIB_MINOR 1
+#define XCURSOR_LIB_REVISION 13
+#define XCURSOR_LIB_VERSION ((XCURSOR_LIB_MAJOR * 10000) + \
+ (XCURSOR_LIB_MINOR * 100) + \
+ (XCURSOR_LIB_REVISION))
+
+/*
+ * This version number is stored in cursor files; changes to the
+ * file format require updating this version number
+ */
+#define XCURSOR_FILE_MAJOR 1
+#define XCURSOR_FILE_MINOR 0
+#define XCURSOR_FILE_VERSION ((XCURSOR_FILE_MAJOR << 16) | (XCURSOR_FILE_MINOR))
+#define XCURSOR_FILE_HEADER_LEN (4 * 4)
+#define XCURSOR_FILE_TOC_LEN (3 * 4)
+
+typedef struct _XcursorFileToc {
+ XcursorUInt type; /* chunk type */
+ XcursorUInt subtype; /* subtype (size for images) */
+ XcursorUInt position; /* absolute position in file */
+} XcursorFileToc;
+
+typedef struct _XcursorFileHeader {
+ XcursorUInt magic; /* magic number */
+ XcursorUInt header; /* byte length of header */
+ XcursorUInt version; /* file version number */
+ XcursorUInt ntoc; /* number of toc entries */
+ XcursorFileToc *tocs; /* table of contents */
+} XcursorFileHeader;
+
+/*
+ * The rest of the file is a list of chunks, each tagged by type
+ * and version.
+ *
+ * Chunk:
+ * ChunkHeader
+ * <extra type-specific header fields>
+ * <type-specific data>
+ *
+ * ChunkHeader:
+ * CARD32 header bytes in chunk header + type header
+ * CARD32 type chunk type
+ * CARD32 subtype chunk subtype
+ * CARD32 version chunk type version
+ */
+
+#define XCURSOR_CHUNK_HEADER_LEN (4 * 4)
+
+typedef struct _XcursorChunkHeader {
+ XcursorUInt header; /* bytes in chunk header */
+ XcursorUInt type; /* chunk type */
+ XcursorUInt subtype; /* chunk subtype (size for images) */
+ XcursorUInt version; /* version of this type */
+} XcursorChunkHeader;
+
+/*
+ * Here's a list of the known chunk types
+ */
+
+/*
+ * Comments consist of a 4-byte length field followed by
+ * UTF-8 encoded text
+ *
+ * Comment:
+ * ChunkHeader header chunk header
+ * CARD32 length bytes in text
+ * LISTofCARD8 text UTF-8 encoded text
+ */
+
+#define XCURSOR_COMMENT_TYPE 0xfffe0001
+#define XCURSOR_COMMENT_VERSION 1
+#define XCURSOR_COMMENT_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (1 *4))
+#define XCURSOR_COMMENT_COPYRIGHT 1
+#define XCURSOR_COMMENT_LICENSE 2
+#define XCURSOR_COMMENT_OTHER 3
+#define XCURSOR_COMMENT_MAX_LEN 0x100000
+
+typedef struct _XcursorComment {
+ XcursorUInt version;
+ XcursorUInt comment_type;
+ char *comment;
+} XcursorComment;
+
+/*
+ * Each cursor image occupies a separate image chunk.
+ * The length of the image header follows the chunk header
+ * so that future versions can extend the header without
+ * breaking older applications
+ *
+ * Image:
+ * ChunkHeader header chunk header
+ * CARD32 width actual width
+ * CARD32 height actual height
+ * CARD32 xhot hot spot x
+ * CARD32 yhot hot spot y
+ * CARD32 delay animation delay
+ * LISTofCARD32 pixels ARGB pixels
+ */
+
+#define XCURSOR_IMAGE_TYPE 0xfffd0002
+#define XCURSOR_IMAGE_VERSION 1
+#define XCURSOR_IMAGE_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (5*4))
+#define XCURSOR_IMAGE_MAX_SIZE 0x7fff /* 32767x32767 max cursor size */
+
+typedef struct _XcursorImage {
+ XcursorUInt version; /* version of the image data */
+ XcursorDim size; /* nominal size for matching */
+ XcursorDim width; /* actual width */
+ XcursorDim height; /* actual height */
+ XcursorDim xhot; /* hot spot x (must be inside image) */
+ XcursorDim yhot; /* hot spot y (must be inside image) */
+ XcursorUInt delay; /* animation delay to next frame (ms) */
+ XcursorPixel *pixels; /* pointer to pixels */
+} XcursorImage;
+
+/*
+ * Other data structures exposed by the library API
+ */
+typedef struct _XcursorImages {
+ int nimage; /* number of images */
+ XcursorImage **images; /* array of XcursorImage pointers */
+ char *name; /* name used to load images */
+} XcursorImages;
+
+typedef struct _XcursorCursors {
+ Display *dpy; /* Display holding cursors */
+ int ref; /* reference count */
+ int ncursor; /* number of cursors */
+ Cursor *cursors; /* array of cursors */
+} XcursorCursors;
+
+typedef struct _XcursorAnimate {
+ XcursorCursors *cursors; /* list of cursors to use */
+ int sequence; /* which cursor is next */
+} XcursorAnimate;
+
+typedef struct _XcursorFile XcursorFile;
+
+struct _XcursorFile {
+ void *closure;
+ int (*read) (XcursorFile *file, unsigned char *buf, int len);
+ int (*write) (XcursorFile *file, unsigned char *buf, int len);
+ int (*seek) (XcursorFile *file, long offset, int whence);
+};
+
+typedef struct _XcursorComments {
+ int ncomment; /* number of comments */
+ XcursorComment **comments; /* array of XcursorComment pointers */
+} XcursorComments;
+
+#define XCURSOR_CORE_THEME "core"
+
+_XFUNCPROTOBEGIN
+
+/*
+ * Manage Image objects
+ */
+XcursorImage *
+XcursorImageCreate (int width, int height);
+
+void
+XcursorImageDestroy (XcursorImage *image);
+
+/*
+ * Manage Images objects
+ */
+XcursorImages *
+XcursorImagesCreate (int size);
+
+void
+XcursorImagesDestroy (XcursorImages *images);
+
+void
+XcursorImagesSetName (XcursorImages *images, const char *name);
+
+/*
+ * Manage Cursor objects
+ */
+XcursorCursors *
+XcursorCursorsCreate (Display *dpy, int size);
+
+void
+XcursorCursorsDestroy (XcursorCursors *cursors);
+
+/*
+ * Manage Animate objects
+ */
+XcursorAnimate *
+XcursorAnimateCreate (XcursorCursors *cursors);
+
+void
+XcursorAnimateDestroy (XcursorAnimate *animate);
+
+Cursor
+XcursorAnimateNext (XcursorAnimate *animate);
+
+/*
+ * Manage Comment objects
+ */
+XcursorComment *
+XcursorCommentCreate (XcursorUInt comment_type, int length);
+
+void
+XcursorCommentDestroy (XcursorComment *comment);
+
+XcursorComments *
+XcursorCommentsCreate (int size);
+
+void
+XcursorCommentsDestroy (XcursorComments *comments);
+
+/*
+ * XcursorFile/Image APIs
+ */
+XcursorImage *
+XcursorXcFileLoadImage (XcursorFile *file, int size);
+
+XcursorImages *
+XcursorXcFileLoadImages (XcursorFile *file, int size);
+
+XcursorImages *
+XcursorXcFileLoadAllImages (XcursorFile *file);
+
+XcursorBool
+XcursorXcFileLoad (XcursorFile *file,
+ XcursorComments **commentsp,
+ XcursorImages **imagesp);
+
+XcursorBool
+XcursorXcFileSave (XcursorFile *file,
+ const XcursorComments *comments,
+ const XcursorImages *images);
+
+/*
+ * FILE/Image APIs
+ */
+XcursorImage *
+XcursorFileLoadImage (FILE *file, int size);
+
+XcursorImages *
+XcursorFileLoadImages (FILE *file, int size);
+
+XcursorImages *
+XcursorFileLoadAllImages (FILE *file);
+
+XcursorBool
+XcursorFileLoad (FILE *file,
+ XcursorComments **commentsp,
+ XcursorImages **imagesp);
+
+XcursorBool
+XcursorFileSaveImages (FILE *file, const XcursorImages *images);
+
+XcursorBool
+XcursorFileSave (FILE * file,
+ const XcursorComments *comments,
+ const XcursorImages *images);
+
+/*
+ * Filename/Image APIs
+ */
+XcursorImage *
+XcursorFilenameLoadImage (const char *filename, int size);
+
+XcursorImages *
+XcursorFilenameLoadImages (const char *filename, int size);
+
+XcursorImages *
+XcursorFilenameLoadAllImages (const char *filename);
+
+XcursorBool
+XcursorFilenameLoad (const char *file,
+ XcursorComments **commentsp,
+ XcursorImages **imagesp);
+
+XcursorBool
+XcursorFilenameSaveImages (const char *filename, const XcursorImages *images);
+
+XcursorBool
+XcursorFilenameSave (const char *file,
+ const XcursorComments *comments,
+ const XcursorImages *images);
+
+/*
+ * Library/Image APIs
+ */
+XcursorImage *
+XcursorLibraryLoadImage (const char *library, const char *theme, int size);
+
+XcursorImages *
+XcursorLibraryLoadImages (const char *library, const char *theme, int size);
+
+/*
+ * Library/shape API
+ */
+
+const char *
+XcursorLibraryPath (void);
+
+int
+XcursorLibraryShape (const char *library);
+
+/*
+ * Image/Cursor APIs
+ */
+
+Cursor
+XcursorImageLoadCursor (Display *dpy, const XcursorImage *image);
+
+XcursorCursors *
+XcursorImagesLoadCursors (Display *dpy, const XcursorImages *images);
+
+Cursor
+XcursorImagesLoadCursor (Display *dpy, const XcursorImages *images);
+
+/*
+ * Filename/Cursor APIs
+ */
+Cursor
+XcursorFilenameLoadCursor (Display *dpy, const char *file);
+
+XcursorCursors *
+XcursorFilenameLoadCursors (Display *dpy, const char *file);
+
+/*
+ * Library/Cursor APIs
+ */
+Cursor
+XcursorLibraryLoadCursor (Display *dpy, const char *file);
+
+XcursorCursors *
+XcursorLibraryLoadCursors (Display *dpy, const char *file);
+
+/*
+ * Shape/Image APIs
+ */
+
+XcursorImage *
+XcursorShapeLoadImage (unsigned int shape, const char *theme, int size);
+
+XcursorImages *
+XcursorShapeLoadImages (unsigned int shape, const char *theme, int size);
+
+/*
+ * Shape/Cursor APIs
+ */
+Cursor
+XcursorShapeLoadCursor (Display *dpy, unsigned int shape);
+
+XcursorCursors *
+XcursorShapeLoadCursors (Display *dpy, unsigned int shape);
+
+/*
+ * This is the function called by Xlib when attempting to
+ * load cursors from XCreateGlyphCursor. The interface must
+ * not change as Xlib loads 'libXcursor.so' instead of
+ * a specific major version
+ */
+Cursor
+XcursorTryShapeCursor (Display *dpy,
+ Font source_font,
+ Font mask_font,
+ unsigned int source_char,
+ unsigned int mask_char,
+ XColor _Xconst *foreground,
+ XColor _Xconst *background);
+
+void
+XcursorNoticeCreateBitmap (Display *dpy,
+ Pixmap pid,
+ unsigned int width,
+ unsigned int height);
+
+void
+XcursorNoticePutBitmap (Display *dpy,
+ Drawable draw,
+ XImage *image);
+
+Cursor
+XcursorTryShapeBitmapCursor (Display *dpy,
+ Pixmap source,
+ Pixmap mask,
+ XColor *foreground,
+ XColor *background,
+ unsigned int x,
+ unsigned int y);
+
+#define XCURSOR_BITMAP_HASH_SIZE 16
+
+void
+XcursorImageHash (XImage *image,
+ unsigned char hash[XCURSOR_BITMAP_HASH_SIZE]);
+
+/*
+ * Display information APIs
+ */
+XcursorBool
+XcursorSupportsARGB (Display *dpy);
+
+XcursorBool
+XcursorSupportsAnim (Display *dpy);
+
+XcursorBool
+XcursorSetDefaultSize (Display *dpy, int size);
+
+int
+XcursorGetDefaultSize (Display *dpy);
+
+XcursorBool
+XcursorSetTheme (Display *dpy, const char *theme);
+
+char *
+XcursorGetTheme (Display *dpy);
+
+XcursorBool
+XcursorGetThemeCore (Display *dpy);
+
+XcursorBool
+XcursorSetThemeCore (Display *dpy, XcursorBool theme_core);
+
+_XFUNCPROTOEND
+
+#endif
--- /dev/null
+/*
+ * Copyright © 2002 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _XCURSOR_H_
+#define _XCURSOR_H_
+#include <stdio.h>
+#include <X11/Xfuncproto.h>
+#include <X11/Xlib.h>
+
+typedef int XcursorBool;
+typedef unsigned int XcursorUInt;
+
+typedef XcursorUInt XcursorDim;
+typedef XcursorUInt XcursorPixel;
+
+#define XcursorTrue 1
+#define XcursorFalse 0
+
+/*
+ * Cursor files start with a header. The header
+ * contains a magic number, a version number and a
+ * table of contents which has type and offset information
+ * for the remaining tables in the file.
+ *
+ * File minor versions increment for compatible changes
+ * File major versions increment for incompatible changes (never, we hope)
+ *
+ * Chunks of the same type are always upward compatible. Incompatible
+ * changes are made with new chunk types; the old data can remain under
+ * the old type. Upward compatible changes can add header data as the
+ * header lengths are specified in the file.
+ *
+ * File:
+ * FileHeader
+ * LISTofChunk
+ *
+ * FileHeader:
+ * CARD32 magic magic number
+ * CARD32 header bytes in file header
+ * CARD32 version file version
+ * CARD32 ntoc number of toc entries
+ * LISTofFileToc toc table of contents
+ *
+ * FileToc:
+ * CARD32 type entry type
+ * CARD32 subtype entry subtype (size for images)
+ * CARD32 position absolute file position
+ */
+
+#define XCURSOR_MAGIC 0x72756358 /* "Xcur" LSBFirst */
+
+/*
+ * Current Xcursor version number. Will be substituted by configure
+ * from the version in the libXcursor configure.ac file.
+ */
+
+#undef XCURSOR_LIB_MAJOR
+#undef XCURSOR_LIB_MINOR
+#undef XCURSOR_LIB_REVISION
+#define XCURSOR_LIB_VERSION ((XCURSOR_LIB_MAJOR * 10000) + \
+ (XCURSOR_LIB_MINOR * 100) + \
+ (XCURSOR_LIB_REVISION))
+
+/*
+ * This version number is stored in cursor files; changes to the
+ * file format require updating this version number
+ */
+#define XCURSOR_FILE_MAJOR 1
+#define XCURSOR_FILE_MINOR 0
+#define XCURSOR_FILE_VERSION ((XCURSOR_FILE_MAJOR << 16) | (XCURSOR_FILE_MINOR))
+#define XCURSOR_FILE_HEADER_LEN (4 * 4)
+#define XCURSOR_FILE_TOC_LEN (3 * 4)
+
+typedef struct _XcursorFileToc {
+ XcursorUInt type; /* chunk type */
+ XcursorUInt subtype; /* subtype (size for images) */
+ XcursorUInt position; /* absolute position in file */
+} XcursorFileToc;
+
+typedef struct _XcursorFileHeader {
+ XcursorUInt magic; /* magic number */
+ XcursorUInt header; /* byte length of header */
+ XcursorUInt version; /* file version number */
+ XcursorUInt ntoc; /* number of toc entries */
+ XcursorFileToc *tocs; /* table of contents */
+} XcursorFileHeader;
+
+/*
+ * The rest of the file is a list of chunks, each tagged by type
+ * and version.
+ *
+ * Chunk:
+ * ChunkHeader
+ * <extra type-specific header fields>
+ * <type-specific data>
+ *
+ * ChunkHeader:
+ * CARD32 header bytes in chunk header + type header
+ * CARD32 type chunk type
+ * CARD32 subtype chunk subtype
+ * CARD32 version chunk type version
+ */
+
+#define XCURSOR_CHUNK_HEADER_LEN (4 * 4)
+
+typedef struct _XcursorChunkHeader {
+ XcursorUInt header; /* bytes in chunk header */
+ XcursorUInt type; /* chunk type */
+ XcursorUInt subtype; /* chunk subtype (size for images) */
+ XcursorUInt version; /* version of this type */
+} XcursorChunkHeader;
+
+/*
+ * Here's a list of the known chunk types
+ */
+
+/*
+ * Comments consist of a 4-byte length field followed by
+ * UTF-8 encoded text
+ *
+ * Comment:
+ * ChunkHeader header chunk header
+ * CARD32 length bytes in text
+ * LISTofCARD8 text UTF-8 encoded text
+ */
+
+#define XCURSOR_COMMENT_TYPE 0xfffe0001
+#define XCURSOR_COMMENT_VERSION 1
+#define XCURSOR_COMMENT_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (1 *4))
+#define XCURSOR_COMMENT_COPYRIGHT 1
+#define XCURSOR_COMMENT_LICENSE 2
+#define XCURSOR_COMMENT_OTHER 3
+#define XCURSOR_COMMENT_MAX_LEN 0x100000
+
+typedef struct _XcursorComment {
+ XcursorUInt version;
+ XcursorUInt comment_type;
+ char *comment;
+} XcursorComment;
+
+/*
+ * Each cursor image occupies a separate image chunk.
+ * The length of the image header follows the chunk header
+ * so that future versions can extend the header without
+ * breaking older applications
+ *
+ * Image:
+ * ChunkHeader header chunk header
+ * CARD32 width actual width
+ * CARD32 height actual height
+ * CARD32 xhot hot spot x
+ * CARD32 yhot hot spot y
+ * CARD32 delay animation delay
+ * LISTofCARD32 pixels ARGB pixels
+ */
+
+#define XCURSOR_IMAGE_TYPE 0xfffd0002
+#define XCURSOR_IMAGE_VERSION 1
+#define XCURSOR_IMAGE_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (5*4))
+#define XCURSOR_IMAGE_MAX_SIZE 0x7fff /* 32767x32767 max cursor size */
+
+typedef struct _XcursorImage {
+ XcursorUInt version; /* version of the image data */
+ XcursorDim size; /* nominal size for matching */
+ XcursorDim width; /* actual width */
+ XcursorDim height; /* actual height */
+ XcursorDim xhot; /* hot spot x (must be inside image) */
+ XcursorDim yhot; /* hot spot y (must be inside image) */
+ XcursorUInt delay; /* animation delay to next frame (ms) */
+ XcursorPixel *pixels; /* pointer to pixels */
+} XcursorImage;
+
+/*
+ * Other data structures exposed by the library API
+ */
+typedef struct _XcursorImages {
+ int nimage; /* number of images */
+ XcursorImage **images; /* array of XcursorImage pointers */
+ char *name; /* name used to load images */
+} XcursorImages;
+
+typedef struct _XcursorCursors {
+ Display *dpy; /* Display holding cursors */
+ int ref; /* reference count */
+ int ncursor; /* number of cursors */
+ Cursor *cursors; /* array of cursors */
+} XcursorCursors;
+
+typedef struct _XcursorAnimate {
+ XcursorCursors *cursors; /* list of cursors to use */
+ int sequence; /* which cursor is next */
+} XcursorAnimate;
+
+typedef struct _XcursorFile XcursorFile;
+
+struct _XcursorFile {
+ void *closure;
+ int (*read) (XcursorFile *file, unsigned char *buf, int len);
+ int (*write) (XcursorFile *file, unsigned char *buf, int len);
+ int (*seek) (XcursorFile *file, long offset, int whence);
+};
+
+typedef struct _XcursorComments {
+ int ncomment; /* number of comments */
+ XcursorComment **comments; /* array of XcursorComment pointers */
+} XcursorComments;
+
+#define XCURSOR_CORE_THEME "core"
+
+_XFUNCPROTOBEGIN
+
+/*
+ * Manage Image objects
+ */
+XcursorImage *
+XcursorImageCreate (int width, int height);
+
+void
+XcursorImageDestroy (XcursorImage *image);
+
+/*
+ * Manage Images objects
+ */
+XcursorImages *
+XcursorImagesCreate (int size);
+
+void
+XcursorImagesDestroy (XcursorImages *images);
+
+void
+XcursorImagesSetName (XcursorImages *images, const char *name);
+
+/*
+ * Manage Cursor objects
+ */
+XcursorCursors *
+XcursorCursorsCreate (Display *dpy, int size);
+
+void
+XcursorCursorsDestroy (XcursorCursors *cursors);
+
+/*
+ * Manage Animate objects
+ */
+XcursorAnimate *
+XcursorAnimateCreate (XcursorCursors *cursors);
+
+void
+XcursorAnimateDestroy (XcursorAnimate *animate);
+
+Cursor
+XcursorAnimateNext (XcursorAnimate *animate);
+
+/*
+ * Manage Comment objects
+ */
+XcursorComment *
+XcursorCommentCreate (XcursorUInt comment_type, int length);
+
+void
+XcursorCommentDestroy (XcursorComment *comment);
+
+XcursorComments *
+XcursorCommentsCreate (int size);
+
+void
+XcursorCommentsDestroy (XcursorComments *comments);
+
+/*
+ * XcursorFile/Image APIs
+ */
+XcursorImage *
+XcursorXcFileLoadImage (XcursorFile *file, int size);
+
+XcursorImages *
+XcursorXcFileLoadImages (XcursorFile *file, int size);
+
+XcursorImages *
+XcursorXcFileLoadAllImages (XcursorFile *file);
+
+XcursorBool
+XcursorXcFileLoad (XcursorFile *file,
+ XcursorComments **commentsp,
+ XcursorImages **imagesp);
+
+XcursorBool
+XcursorXcFileSave (XcursorFile *file,
+ const XcursorComments *comments,
+ const XcursorImages *images);
+
+/*
+ * FILE/Image APIs
+ */
+XcursorImage *
+XcursorFileLoadImage (FILE *file, int size);
+
+XcursorImages *
+XcursorFileLoadImages (FILE *file, int size);
+
+XcursorImages *
+XcursorFileLoadAllImages (FILE *file);
+
+XcursorBool
+XcursorFileLoad (FILE *file,
+ XcursorComments **commentsp,
+ XcursorImages **imagesp);
+
+XcursorBool
+XcursorFileSaveImages (FILE *file, const XcursorImages *images);
+
+XcursorBool
+XcursorFileSave (FILE * file,
+ const XcursorComments *comments,
+ const XcursorImages *images);
+
+/*
+ * Filename/Image APIs
+ */
+XcursorImage *
+XcursorFilenameLoadImage (const char *filename, int size);
+
+XcursorImages *
+XcursorFilenameLoadImages (const char *filename, int size);
+
+XcursorImages *
+XcursorFilenameLoadAllImages (const char *filename);
+
+XcursorBool
+XcursorFilenameLoad (const char *file,
+ XcursorComments **commentsp,
+ XcursorImages **imagesp);
+
+XcursorBool
+XcursorFilenameSaveImages (const char *filename, const XcursorImages *images);
+
+XcursorBool
+XcursorFilenameSave (const char *file,
+ const XcursorComments *comments,
+ const XcursorImages *images);
+
+/*
+ * Library/Image APIs
+ */
+XcursorImage *
+XcursorLibraryLoadImage (const char *library, const char *theme, int size);
+
+XcursorImages *
+XcursorLibraryLoadImages (const char *library, const char *theme, int size);
+
+/*
+ * Library/shape API
+ */
+
+const char *
+XcursorLibraryPath (void);
+
+int
+XcursorLibraryShape (const char *library);
+
+/*
+ * Image/Cursor APIs
+ */
+
+Cursor
+XcursorImageLoadCursor (Display *dpy, const XcursorImage *image);
+
+XcursorCursors *
+XcursorImagesLoadCursors (Display *dpy, const XcursorImages *images);
+
+Cursor
+XcursorImagesLoadCursor (Display *dpy, const XcursorImages *images);
+
+/*
+ * Filename/Cursor APIs
+ */
+Cursor
+XcursorFilenameLoadCursor (Display *dpy, const char *file);
+
+XcursorCursors *
+XcursorFilenameLoadCursors (Display *dpy, const char *file);
+
+/*
+ * Library/Cursor APIs
+ */
+Cursor
+XcursorLibraryLoadCursor (Display *dpy, const char *file);
+
+XcursorCursors *
+XcursorLibraryLoadCursors (Display *dpy, const char *file);
+
+/*
+ * Shape/Image APIs
+ */
+
+XcursorImage *
+XcursorShapeLoadImage (unsigned int shape, const char *theme, int size);
+
+XcursorImages *
+XcursorShapeLoadImages (unsigned int shape, const char *theme, int size);
+
+/*
+ * Shape/Cursor APIs
+ */
+Cursor
+XcursorShapeLoadCursor (Display *dpy, unsigned int shape);
+
+XcursorCursors *
+XcursorShapeLoadCursors (Display *dpy, unsigned int shape);
+
+/*
+ * This is the function called by Xlib when attempting to
+ * load cursors from XCreateGlyphCursor. The interface must
+ * not change as Xlib loads 'libXcursor.so' instead of
+ * a specific major version
+ */
+Cursor
+XcursorTryShapeCursor (Display *dpy,
+ Font source_font,
+ Font mask_font,
+ unsigned int source_char,
+ unsigned int mask_char,
+ XColor _Xconst *foreground,
+ XColor _Xconst *background);
+
+void
+XcursorNoticeCreateBitmap (Display *dpy,
+ Pixmap pid,
+ unsigned int width,
+ unsigned int height);
+
+void
+XcursorNoticePutBitmap (Display *dpy,
+ Drawable draw,
+ XImage *image);
+
+Cursor
+XcursorTryShapeBitmapCursor (Display *dpy,
+ Pixmap source,
+ Pixmap mask,
+ XColor *foreground,
+ XColor *background,
+ unsigned int x,
+ unsigned int y);
+
+#define XCURSOR_BITMAP_HASH_SIZE 16
+
+void
+XcursorImageHash (XImage *image,
+ unsigned char hash[XCURSOR_BITMAP_HASH_SIZE]);
+
+/*
+ * Display information APIs
+ */
+XcursorBool
+XcursorSupportsARGB (Display *dpy);
+
+XcursorBool
+XcursorSupportsAnim (Display *dpy);
+
+XcursorBool
+XcursorSetDefaultSize (Display *dpy, int size);
+
+int
+XcursorGetDefaultSize (Display *dpy);
+
+XcursorBool
+XcursorSetTheme (Display *dpy, const char *theme);
+
+char *
+XcursorGetTheme (Display *dpy);
+
+XcursorBool
+XcursorGetThemeCore (Display *dpy);
+
+XcursorBool
+XcursorSetThemeCore (Display *dpy, XcursorBool theme_core);
+
+_XFUNCPROTOEND
+
+#endif
--- /dev/null
+libmandir = $(LIB_MAN_DIR)
+
+libman_PRE = \
+ Xcursor.man \
+ $(Xcursor_shadows:=.man)
+
+Xcursor_shadows = \
+ XcursorImageCreate \
+ XcursorImageDestroy \
+ XcursorImagesCreate \
+ XcursorImagesDestroy \
+ XcursorCursorsCreate \
+ XcursorCursorsDestroy \
+ XcursorXcFileLoadImage \
+ XcursorXcFileLoadImages \
+ XcursorXcFileLoadAllImages \
+ XcursorXcFileLoad \
+ XcursorXcFileSave \
+ XcursorFilenameLoadImage \
+ XcursorFilenameLoadImages \
+ XcursorFilenameLoadAllImages \
+ XcursorFilenameLoad \
+ XcursorFilenameSaveImages \
+ XcursorFilenameSave \
+ XcursorLibraryLoadImage \
+ XcursorLibraryLoadImages \
+ XcursorFilenameLoadCursor \
+ XcursorLibraryLoadCursor \
+ XcursorLibraryLoadCursors \
+ XcursorShapeLoadImage \
+ XcursorShapeLoadImages \
+ XcursorShapeLoadCursor \
+ XcursorShapeLoadCursors \
+ XcursorSupportsARGB \
+ XcursorSetDefaultSize \
+ XcursorGetDefaultSize \
+ XcursorSetTheme \
+ XcursorGetTheme
+
+libman_DATA = $(libman_PRE:man=@LIB_MAN_SUFFIX@)
+
+EXTRA_DIST = $(libman_PRE)
+CLEANFILES = $(libman_DATA)
+
+SUFFIXES = .$(LIB_MAN_SUFFIX) .man
+
+# String replacements in MAN_SUBSTS now come from xorg-macros.m4 via configure
+# 's/:/, /g' will add comma and a space to help path formatting
+MAN_SUBSTS += -e 's|__XCURSORPATH__|$(XCURSORPATH)|g' \
+ -e '\|$(XCURSORPATH)| s/:/, /g'
+
+.man.$(LIB_MAN_SUFFIX):
+ $(AM_V_GEN)$(SED) $(MAN_SUBSTS) < $< > $@
--- /dev/null
+.\"
+.\" Copyright © 2002 Keith Packard
+.\"
+.\" Permission to use, copy, modify, distribute, and sell this software and its
+.\" documentation for any purpose is hereby granted without fee, provided that
+.\" the above copyright notice appear in all copies and that both that
+.\" copyright notice and this permission notice appear in supporting
+.\" documentation, and that the name of Keith Packard not be used in
+.\" advertising or publicity pertaining to distribution of the software without
+.\" specific, written prior permission. Keith Packard makes no
+.\" representations about the suitability of this software for any purpose. It
+.\" is provided "as is" without express or implied warranty.
+.\"
+.\" KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+.\" INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+.\" EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+.\" CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+.\" DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+.\" TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+.\" PERFORMANCE OF THIS SOFTWARE.
+.\"
+.de TQ
+.br
+.ns
+.TP \\$1
+..
+.TH XCURSOR __libmansuffix__ __xorgversion__ "Keith Packard"
+
+.SH NAME
+XCURSOR \- Cursor management library
+
+.SH SYNOPSIS
+.nf
+.B #include <X11/Xcursor/Xcursor.h>
+.fi
+.SH DESCRIPTION
+.B Xcursor
+is a simple library designed to help locate and load cursors. Cursors can
+be loaded from files or memory. A library of common cursors exists which
+map to the standard X cursor names. Cursors can exist in several sizes and
+the library automatically picks the best size.
+
+.SH FUNCTIONAL OVERVIEW
+Xcursor is built in a couple of layers; at the bottom layer is code which
+can load cursor images from files. Above that is a layer which locates
+cursor files based on the library path and theme. At the top is a layer
+which builds cursors either out of an image loaded from a file or one of the
+standard X cursors. When using images loaded from files, Xcursor prefers
+to use the Render extension CreateCursor request if supported by the X
+server. Where not supported, Xcursor maps the cursor image to a standard X
+cursor and uses the core CreateCursor request.
+
+.SS CURSOR FILES
+Xcursor defines a new format for cursors on disk. Each file holds
+one or more cursor images. Each cursor image is tagged with a nominal size
+so that the best size can be selected automatically. Multiple cursors of
+the same nominal size can be loaded together; applications are expected to
+use them as an animated sequence.
+.P
+Cursor files are stored as a header containing a table of contents followed
+by a sequence of chunks. The table of contents indicates the type, subtype
+and position in the file of each chunk. The file header looks like:
+.LP
+.in +.2i
+\fImagic\fP\^: CARD32 'Xcur' (0x58, 0x63, 0x75, 0x72)
+.br
+\fIheader\fP\^: CARD32 bytes in this header
+.br
+\fIversion\fP\^: CARD32 file version number
+.br
+\fIntoc\fP\^: CARD32 number of toc entries
+.br
+\fItoc\fP\^: LISTofTOC table of contents
+.in -.2i
+.P
+Each table of contents entry looks like:
+.LP
+.in +.2i
+\fItype\fP\^: CARD32 entry type
+.br
+\fIsubtype\fP\^: CARD32 type-specific label - size for images
+.br
+\fIposition\fP\^: CARD32 absolute byte position of table in file
+.in -.2i
+.P
+.P
+Each chunk in the file has set of common header fields followed by
+additional type-specific fields:
+.LP
+.in +.2i
+\fIheader\fP\^: CARD32 bytes in chunk header (including type-specific fields)
+.br
+\fItype\fP\^: CARD32 must match type in TOC for this chunk
+.br
+\fIsubtype\fP\^: CARD32 must match subtype in TOC for this chunk
+.br
+\fIversion\fP\^: CARD32 version number for this chunk type
+.in -.2i
+.P
+There are currently two chunk types defined for cursor files; comments and
+images. Comments look like:
+.LP
+.in +.2i
+\fIheader\fP\^: 20 Comment headers are 20 bytes
+.br
+\fItype\fP\^: 0xfffe0001 Comment type is 0xfffe0001
+.br
+\fIsubtype\fP\^: { 1 (COPYRIGHT), 2 (LICENSE), 3 (OTHER) }
+.br
+\fIversion\fP\^: 1
+.br
+\fIlength\fP\^: CARD32 byte length of UTF-8 string
+.br
+\fIstring\fP\^: LISTofCARD8 UTF-8 string
+.in -.2i
+.P
+Images look like:
+.LP
+.in +.2i
+\fIheader\fP\^: 36 Image headers are 36 bytes
+.br
+\fItype\fP\^: 0xfffd0002 Image type is 0xfffd0002
+.br
+\fIsubtype\fP\^: CARD32 Image subtype is the nominal size
+.br
+\fIversion\fP\^: 1
+.br
+\fIwidth\fP\^: CARD32 Must be less than or equal to 0x7fff
+.br
+\fIheight\fP\^: CARD32 Must be less than or equal to 0x7fff
+.br
+\fIxhot\fP\^: CARD32 Must be less than or equal to width
+.br
+\fIyhot\fP\^: CARD32 Must be less than or equal to height
+.br
+\fIdelay\fP\^: CARD32 Delay between animation frames in milliseconds
+.br
+\fIpixels\fP\^: LISTofCARD32 Packed ARGB format pixels
+.in -.2i
+
+.SS THEMES
+Xcursor (mostly) follows the freedesktop.org spec for theming icons. The
+default search path it uses is __XCURSORPATH__. Within each of these
+directories, it searches for a directory using the theme name. Within the
+theme directory, it looks for cursor files in the 'cursors' subdirectory.
+It uses the first cursor file found along the path.
+.PP
+If necessary, Xcursor also looks for a "index.theme" file in each theme
+directory to find inherited themes and searches along the path for those
+themes as well.
+.PP
+If no theme is set, or if no cursor is found for the specified theme,
+Xcursor checks the "default" theme.
+
+.SH DATATYPES
+
+.TP
+.B XcursorImage
+holds a single cursor image in memory. Each pixel in the cursor is a 32-bit
+value containing ARGB with A in the high byte.
+.sp
+.nf
+.ft CR
+ typedef struct _XcursorImage {
+ XcursorDim size; /\(** nominal size for matching */
+ XcursorDim width; /\(** actual width */
+ XcursorDim height; /\(** actual height */
+ XcursorDim xhot; /\(** hot spot x (must be inside image) */
+ XcursorDim yhot; /\(** hot spot y (must be inside image) */
+ XcursorPixel *pixels; /\(** pointer to pixels */
+ } XcursorImage;
+.ft
+.fi
+
+.TP
+.B XcursorImages
+holds multiple XcursorImage structures. They're all freed when the
+XcursorImages is freed.
+.sp
+.nf
+.ft CR
+ typedef struct _XcursorImages {
+ int nimage; /\(** number of images */
+ XcursorImage **images; /\(** array of XcursorImage pointers */
+ } XcursorImages;
+.ft
+.fi
+
+.TP
+.B XcursorCursors
+Holds multiple Cursor objects. They're all freed when the XcursorCursors is
+freed. These are reference counted so that multiple XcursorAnimate
+structures can use the same XcursorCursors.
+.sp
+.nf
+.ft CR
+ typedef struct _XcursorCursors {
+ Display *dpy; /\(** Display holding cursors */
+ int ref; /\(** reference count */
+ int ncursor; /\(** number of cursors */
+ Cursor *cursors; /\(** array of cursors */
+ } XcursorCursors;
+.ft
+.fi
+
+.TP
+.B XcursorAnimate
+References a set of cursors and a sequence within that set. Multiple
+XcursorAnimate structures may reference the same XcursorCursors; each
+holds a reference which is removed when the XcursorAnimate is freed.
+.sp
+.nf
+.ft CR
+ typedef struct _XcursorAnimate {
+ XcursorCursors *cursors; /\(** list of cursors to use */
+ int sequence; /\(** which cursor is next */
+ } XcursorAnimate;
+.ft
+.fi
+
+.TP
+.B XcursorFile
+Xcursor provides an abstract API for accessing the file data. Xcursor
+provides a stdio implementation of this abstract API; applications
+are free to create additional implementations. These functions
+parallel the stdio functions in return value and expected argument values;
+the read and write functions flip the arguments around to match the POSIX
+versions.
+.sp
+.nf
+.ft CR
+ typedef struct _XcursorFile {
+ void *closure;
+ int (*read) (XcursorFile *file, unsigned char *buf, int len);
+ int (*write) (XcursorFile *file, unsigned char *buf, int len);
+ int (*seek) (XcursorFile *file, long offset, int whence);
+ };
+.ft
+.fi
+
+.SH FUNCTIONS
+
+.SS Object Management
+.TP
+XcursorImage *XcursorImageCreate (int width, int height)
+.TQ
+void XcursorImageDestroy (XcursorImage *image)
+Allocate and free images. On allocation, the hotspot and the pixels are
+left uninitialized. The size is set to the maximum of width and height.
+
+.TP
+XcursorImages *XcursorImagesCreate (int size)
+.TQ
+void XcursorImagesDestroy (XcursorImages *images)
+Allocate and free arrays to hold multiple cursor images. On allocation,
+nimage is set to zero.
+
+.TP
+XcursorCursors *XcursorCursorsCreate (Display *dpy, int size)
+.TQ
+void XcursorCursorsDestroy (XcursorCursors *cursors)
+Allocate and free arrays to hold multiple cursors. On allocation,
+ncursor is set to zero, ref is set to one.
+
+.SS Reading and writing images.
+
+.TP
+XcursorImage *XcursorXcFileLoadImage (XcursorFile *file, int size)
+.TQ
+XcursorImages *XcursorXcFileLoadImages (XcursorFile *file, int size)
+.TQ
+XcursorImages *XcursorXcFileLoadAllImages (XcursorFile *file)
+.TQ
+XcursorBool XcursorXcFileLoad (XcursorFile *file, XcursorComments **commentsp, XcursorImages **imagesp)
+.TQ
+XcursorBool XcursorXcFileSave (XcursorFile *file, const XcursorComments *comments, const XcursorImages *images)
+These read and write cursors from an XcursorFile handle. After reading, the
+file pointer will be left at some random place in the file.
+
+.TP
+XcursorImage *XcursorFileLoadImage (FILE *file, int size)
+.TQ
+XcursorImages *XcursorFileLoadImages (FILE *file, int size)
+.TQ
+XcursorImages *XcursorFileLoadAllImages (FILE *file)
+.TQ
+XcursorBool XcursorFileLoad (FILE *file, XcursorComments **commentsp, XcursorImages **imagesp)
+.TQ
+XcursorBool XcursorFileSaveImages (FILE *file, const XcursorImages *images)
+.TQ
+XcursorBool XcursorFileSave (FILE * file, const XcursorComments *comments, const XcursorImages *images)
+These read and write cursors from a stdio FILE handle. Writing flushes
+before returning so that any errors should be detected.
+
+.TP
+XcursorImage *XcursorFilenameLoadImage (const char *filename, int size)
+.TQ
+XcursorImages *XcursorFilenameLoadImages (const char *filename, int size)
+.TQ
+XcursorImages *XcursorFilenameLoadAllImages (FILE *file)
+.TQ
+XcursorBool XcursorFilenameLoad (const char *file, XcursorComments **commentsp, XcursorImages **imagesp)
+.TQ
+XcursorBool XcursorFilenameSaveImages (const char *filename, const XcursorImages *images)
+.TQ
+XcursorBool XcursorFilenameSave (const char *file, const XcursorComments *comments, const XcursorImages *images)
+These parallel the stdio FILE interfaces above, but take filenames.
+
+.SS Reading library images
+.TP
+XcursorImage *XcursorLibraryLoadImage (const char *name, const char *theme, int size)
+.TQ
+XcursorImages *XcursorLibraryLoadImages (const char *name, const char *theme, int size)
+These search the library path, loading the first file found. If 'theme' is
+not NULL, these functions first try appending -theme to name and then
+name alone.
+
+.SS Cursor APIs
+
+.TP
+Cursor XcursorFilenameLoadCursor (Display *dpy, const char *file)
+.TQ
+XcursorCursors *XcursorFilenameLoadCursors (Display *dpy, const char *file)
+These load cursors from the specified file.
+
+.TP
+Cursor XcursorLibraryLoadCursor (Display *dpy, const char *name)
+.TQ
+XcursorCursors *XcursorLibraryLoadCursors (Display *dpy, const char *name)
+These load cursors using the specified library name. The theme
+comes from the display.
+
+.SS X Cursor Name APIs
+
+.TP
+XcursorImage *XcursorShapeLoadImage (unsigned int shape, const char *theme, int size)
+.TQ
+XcursorImages *XcursorShapeLoadImages (unsigned int shape, const char *theme, int size)
+These map 'shape' to a library name using the standard X cursor names and
+then load the images.
+
+.TP
+Cursor XcursorShapeLoadCursor (Display *dpy, unsigned int shape)
+.TQ
+XcursorCursors *XcursorShapeLoadCursors (Display *dpy, unsigned int shape)
+These map 'shape' to a library name and then load the cursors.
+
+.SS Display Information APIs
+
+.TP
+XcursorBool XcursorSupportsARGB (Display *dpy)
+Returns whether the display supports ARGB cursors or whether cursors will be
+mapped to a core X cursor.
+
+.TP
+XcursorBool XcursorSetDefaultSize (Display *dpy, int size)
+Sets the default size for cursors on the specified display. When loading
+cursors, those whose nominal size is closest to this size will be preferred.
+
+.TP
+int XcursorGetDefaultSize (Display *dpy)
+Gets the default cursor size.
+
+.TP
+XcursorBool XcursorSetTheme (Display *dpy, const char *theme)
+Sets the current theme name.
+
+.TP
+char *XcursorGetTheme (Display *dpy)
+Gets the current theme name.
+
+.SH "ENVIRONMENT VARIABLES"
+.TP 15
+.B XCURSOR_PATH
+This variable sets the list of paths to look for cursors in.
+Directories in this path are separated by colons (:).
+
+.SH RESTRICTIONS
+.B Xcursor
+will probably change radically in the future; weak attempts will be made to
+retain some level of source-file compatibility.
+
+.SH AUTHOR
+Keith Packard
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+.so man__libmansuffix__/Xcursor.__libmansuffix__
--- /dev/null
+Summary: Cursor management library
+Name: libXcursor
+Version: 1.1.13
+Release: 1
+License: MIT
+Group: System Environment/Libraries
+URL: http://www.x.org
+#VCS: git:git://anongit.freedesktop.org/xorg/lib/libXcursor
+Source0: %{name}-%{version}.tar.gz
+
+BuildRequires: xorg-x11-xutils-dev
+BuildRequires: pkgconfig(xorg-macros)
+BuildRequires: pkgconfig(xproto)
+BuildRequires: libX11-devel
+BuildRequires: libXfixes-devel
+BuildRequires: libXrender-devel >= 0.8.2
+
+
+%description
+This is a simple library designed to help locate and load cursors.
+Cursors can be loaded from files or memory. A library of common cursors
+exists which map to the standard X cursor names.Cursors can exist in
+several sizes and the library automatically picks the best size.
+
+%package devel
+Summary: Development files for %{name}
+Group: Development/Libraries
+Provides: libxcursor-devel
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+libXcursor development package.
+
+%prep
+%setup -q
+iconv --from=ISO-8859-2 --to=UTF-8 COPYING > COPYING.new && \
+touch -r COPYING COPYING.new && \
+mv COPYING.new COPYING
+
+# Disable static library creation by default.
+%define with_static 0
+
+%build
+#export CFLAGS="${CFLAGS} $RPM_OPT_FLAGS -DICONDIR=\"%{_datadir}/icons\""
+%reconfigure --disable-static \
+ LDFLAGS="${LDFLAGS} -Wl,--hash-style=both -Wl,--as-needed"
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p %{buildroot}/usr/share/license
+cp -af COPYING %{buildroot}/usr/share/license/%{name}
+make install DESTDIR=$RPM_BUILD_ROOT INSTALL="install -p"
+
+mkdir -p $RPM_BUILD_ROOT%{_datadir}/icons/default
+
+# We intentionally don't ship *.la files
+rm -f $RPM_BUILD_ROOT%{_libdir}/*.la
+
+%remove_docs
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post -p /sbin/ldconfig
+%postun -p /sbin/ldconfig
+
+%files
+%defattr(-,root,root,-)
+/usr/share/license/%{name}
+#%doc AUTHORS COPYING README ChangeLog
+%{_libdir}/libXcursor.so.1
+%{_libdir}/libXcursor.so.1.0.2
+%dir %{_datadir}/icons/default
+#%{_datadir}/icons/default/index.theme
+
+%files devel
+%defattr(-,root,root,-)
+%dir %{_includedir}/X11/Xcursor
+%{_includedir}/X11/Xcursor/Xcursor.h
+%if %{with_static}
+%{_libdir}/libXcursor.a
+%endif
+%{_libdir}/libXcursor.so
+%{_libdir}/pkgconfig/xcursor.pc
+#%dir %{_mandir}/man3x
+#%{_mandir}/man3/Xcursor*.3*
--- /dev/null
+lib_LTLIBRARIES = libXcursor.la
+
+libXcursor_la_SOURCES = xcursorint.h cursor.c display.c file.c library.c xlib.c
+
+ICONDIR=@ICONDIR@
+XCURSORPATH=@XCURSORPATH@
+
+libXcursor_la_LIBADD = $(XCURSOR_LIBS)
+AM_CFLAGS = \
+ $(XCURSOR_CFLAGS) \
+ $(CWARNFLAGS)\
+ -DICONDIR=\"$(ICONDIR)\" \
+ -DXCURSORPATH=\"$(XCURSORPATH)\"
+
+INCLUDES = -I$(top_srcdir)/include/X11/Xcursor
+
+#
+# Shared library version info. This is not the same as the package version
+#
+libXcursor_la_LDFLAGS = -version-number 1:0:2 -no-undefined
+
+libXcursorincludedir = $(includedir)/X11/Xcursor
+libXcursorinclude_HEADERS = $(top_builddir)/include/X11/Xcursor/Xcursor.h
+
+if LINT
+ALL_LINT_FLAGS=$(LINT_FLAGS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS)
+
+lint:
+ $(LINT) $(ALL_LINT_FLAGS) $(libXcursor_la_SOURCES) $(XCURSOR_LIBS)
+endif LINT
--- /dev/null
+/*
+ * Copyright © 2002 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "xcursorint.h"
+#include <X11/Xlibint.h>
+#include <X11/Xutil.h>
+
+XcursorCursors *
+XcursorCursorsCreate (Display *dpy, int size)
+{
+ XcursorCursors *cursors;
+
+ cursors = malloc (sizeof (XcursorCursors) +
+ size * sizeof (Cursor));
+ if (!cursors)
+ return NULL;
+ cursors->ref = 1;
+ cursors->dpy = dpy;
+ cursors->ncursor = 0;
+ cursors->cursors = (Cursor *) (cursors + 1);
+ return cursors;
+}
+
+void
+XcursorCursorsDestroy (XcursorCursors *cursors)
+{
+ int n;
+
+ if (!cursors)
+ return;
+
+ --cursors->ref;
+ if (cursors->ref > 0)
+ return;
+
+ for (n = 0; n < cursors->ncursor; n++)
+ XFreeCursor (cursors->dpy, cursors->cursors[n]);
+ free (cursors);
+}
+
+XcursorAnimate *
+XcursorAnimateCreate (XcursorCursors *cursors)
+{
+ XcursorAnimate *animate;
+
+ animate = malloc (sizeof (XcursorAnimate));
+ if (!animate)
+ return NULL;
+ animate->cursors = cursors;
+ cursors->ref++;
+ animate->sequence = 0;
+ return animate;
+}
+
+void
+XcursorAnimateDestroy (XcursorAnimate *animate)
+{
+ if (!animate)
+ return;
+
+ XcursorCursorsDestroy (animate->cursors);
+ free (animate);
+}
+
+Cursor
+XcursorAnimateNext (XcursorAnimate *animate)
+{
+ Cursor cursor = animate->cursors->cursors[animate->sequence++];
+
+ if (animate->sequence >= animate->cursors->ncursor)
+ animate->sequence = 0;
+ return cursor;
+}
+
+static int
+nativeByteOrder (void)
+{
+ int x = 1;
+
+ return (*((char *) &x) == 1) ? LSBFirst : MSBFirst;
+}
+
+static XcursorUInt
+_XcursorPixelBrightness (XcursorPixel p)
+{
+ XcursorPixel alpha = p >> 24;
+ XcursorPixel r, g, b;
+
+ if (!alpha)
+ return 0;
+ r = ((p >> 8) & 0xff00) / alpha;
+ if (r > 0xff) r = 0xff;
+ g = ((p >> 0) & 0xff00) / alpha;
+ if (g > 0xff) g = 0xff;
+ b = ((p << 8) & 0xff00) / alpha;
+ if (b > 0xff) b = 0xff;
+ return (r * 153 + g * 301 + b * 58) >> 9;
+}
+
+static unsigned short
+_XcursorDivideAlpha (XcursorUInt value, XcursorUInt alpha)
+{
+ if (!alpha)
+ return 0;
+ value = value * 255 / alpha;
+ if (value > 255)
+ value = 255;
+ return value | (value << 8);
+}
+
+static void
+_XcursorPixelToColor (XcursorPixel p, XColor *color)
+{
+ XcursorPixel alpha = p >> 24;
+
+ color->pixel = 0;
+ color->red = _XcursorDivideAlpha ((p >> 16) & 0xff, alpha);
+ color->green = _XcursorDivideAlpha ((p >> 8) & 0xff, alpha);
+ color->blue = _XcursorDivideAlpha ((p >> 0) & 0xff, alpha);
+ color->flags = DoRed|DoGreen|DoBlue;
+}
+
+#undef DEBUG_IMAGE
+#ifdef DEBUG_IMAGE
+static void
+_XcursorDumpImage (XImage *image)
+{
+ FILE *f = fopen ("/tmp/images", "a");
+ int x, y;
+ if (!f)
+ return;
+ fprintf (f, "%d x %x\n", image->width, image->height);
+ for (y = 0; y < image->height; y++)
+ {
+ for (x = 0; x < image->width; x++)
+ fprintf (f, "%c", XGetPixel (image, x, y) ? '*' : ' ');
+ fprintf (f, "\n");
+ }
+ fflush (f);
+ fclose (f);
+}
+
+static void
+_XcursorDumpColor (XColor *color, char *name)
+{
+ FILE *f = fopen ("/tmp/images", "a");
+ fprintf (f, "%s: %x %x %x\n", name,
+ color->red, color->green, color->blue);
+ fflush (f);
+ fclose (f);
+}
+#endif
+
+static int
+_XcursorCompareRed (const void *a, const void *b)
+{
+ const XcursorPixel *ap = a, *bp = b;
+
+ return (int) (((*ap >> 16) & 0xff) - ((*bp >> 16) & 0xff));
+}
+
+static int
+_XcursorCompareGreen (const void *a, const void *b)
+{
+ const XcursorPixel *ap = a, *bp = b;
+
+ return (int) (((*ap >> 8) & 0xff) - ((*bp >> 8) & 0xff));
+}
+
+static int
+_XcursorCompareBlue (const void *a, const void *b)
+{
+ const XcursorPixel *ap = a, *bp = b;
+
+ return (int) (((*ap >> 0) & 0xff) - ((*bp >> 0) & 0xff));
+}
+
+static XcursorPixel
+_XcursorAverageColor (XcursorPixel *pixels, int npixels)
+{
+ XcursorPixel p;
+ XcursorPixel red, green, blue;
+ int n = npixels;
+
+ if (n < 1)
+ return 0;
+
+ blue = green = red = 0;
+ while (n--)
+ {
+ p = *pixels++;
+ red += (p >> 16) & 0xff;
+ green += (p >> 8) & 0xff;
+ blue += (p >> 0) & 0xff;
+ }
+ return (0xffU << 24) | ((red/npixels) << 16) | ((green/npixels) << 8) | (blue/npixels);
+}
+
+typedef struct XcursorCoreCursor {
+ XImage *src_image;
+ XImage *msk_image;
+ XColor on_color;
+ XColor off_color;
+} XcursorCoreCursor;
+
+static Bool
+_XcursorHeckbertMedianCut (const XcursorImage *image, XcursorCoreCursor *core)
+{
+ XImage *src_image = core->src_image, *msk_image = core->msk_image;
+ int npixels = image->width * image->height;
+ int ncolors;
+ int n;
+ XcursorPixel *po, *pn, *pc;
+ XcursorPixel p;
+ XcursorPixel red, green, blue, alpha;
+ XcursorPixel max_red, min_red, max_green, min_green, max_blue, min_blue;
+ XcursorPixel *temp, *pixels, *colors;
+ int split;
+ XcursorPixel leftColor, centerColor, rightColor;
+ int (*compare) (const void *, const void *);
+ int x, y;
+
+ /*
+ * Temp space for converted image and converted colors
+ */
+ temp = malloc (npixels * sizeof (XcursorPixel) * 2);
+ if (!temp)
+ return False;
+
+ pixels = temp;
+ colors = pixels + npixels;
+
+ /*
+ * Convert to 2-value alpha and build
+ * array of opaque color values and an
+ */
+ po = image->pixels;
+ pn = pixels;
+ pc = colors;
+ max_blue = max_green = max_red = 0;
+ min_blue = min_green = min_red = 255;
+ n = npixels;
+ while (n--)
+ {
+ p = *po++;
+ alpha = (p >> 24) & 0xff;
+ red = (p >> 16) & 0xff;
+ green = (p >> 8) & 0xff;
+ blue = (p >> 0) & 0xff;
+ if (alpha >= 0x80)
+ {
+ red = red * 255 / alpha;
+ green = green * 255 / alpha;
+ blue = blue * 255 / alpha;
+ if (red < min_red) min_red = red;
+ if (red > max_red) max_red = red;
+ if (green < min_green) min_green = green;
+ if (green > max_green) max_green = green;
+ if (blue < min_blue) min_blue = blue;
+ if (blue > max_blue) max_blue = blue;
+ p = ((0xffU << 24) | (red << 16) |
+ (green << 8) | (blue << 0));
+ *pc++ = p;
+ }
+ else
+ p = 0;
+ *pn++ = p;
+ }
+ ncolors = pc - colors;
+
+ /*
+ * Compute longest dimension and sort
+ */
+ if ((max_green - min_green) >= (max_red - min_red) &&
+ (max_green - min_green) >= (max_blue - min_blue))
+ compare = _XcursorCompareGreen;
+ else if ((max_red - min_red) >= (max_blue - min_blue))
+ compare = _XcursorCompareRed;
+ else
+ compare = _XcursorCompareBlue;
+ qsort (colors, ncolors, sizeof (XcursorPixel), compare);
+ /*
+ * Compute average colors on both sides of the cut
+ */
+ split = ncolors >> 1;
+ leftColor = _XcursorAverageColor (colors, split);
+ centerColor = colors[split];
+ rightColor = _XcursorAverageColor (colors + split, ncolors - split);
+ /*
+ * Select best color for each pixel
+ */
+ pn = pixels;
+ for (y = 0; y < image->height; y++)
+ for (x = 0; x < image->width; x++)
+ {
+ p = *pn++;
+ if (p & 0xff000000)
+ {
+ XPutPixel (msk_image, x, y, 1);
+ if ((*compare) (&p, ¢erColor) >= 0)
+ XPutPixel (src_image, x, y, 0);
+ else
+ XPutPixel (src_image, x, y, 1);
+ }
+ else
+ {
+ XPutPixel (msk_image, x, y, 0);
+ XPutPixel (src_image, x, y, 0);
+ }
+ }
+ free (temp);
+ _XcursorPixelToColor (rightColor, &core->off_color);
+ _XcursorPixelToColor (leftColor, &core->on_color);
+ return True;
+}
+
+#if 0
+#define DITHER_DIM 4
+static XcursorPixel orderedDither[4][4] = {
+ { 1, 9, 3, 11 },
+ { 13, 5, 15, 7 },
+ { 4, 12, 2, 10 },
+ { 16, 8, 14, 6 }
+};
+#else
+#define DITHER_DIM 2
+static XcursorPixel orderedDither[2][2] = {
+ { 1, 3, },
+ { 4, 2, },
+};
+#endif
+
+#define DITHER_SIZE ((sizeof orderedDither / sizeof orderedDither[0][0]) + 1)
+
+static Bool
+_XcursorBayerOrderedDither (const XcursorImage *image, XcursorCoreCursor *core)
+{
+ int x, y;
+ XcursorPixel *pixel, p;
+ XcursorPixel a, i, d;
+
+ pixel = image->pixels;
+ for (y = 0; y < image->height; y++)
+ for (x = 0; x < image->width; x++)
+ {
+ p = *pixel++;
+ a = ((p >> 24) * DITHER_SIZE + 127) / 255;
+ i = (_XcursorPixelBrightness (p) * DITHER_SIZE + 127) / 255;
+ d = orderedDither[y&(DITHER_DIM-1)][x&(DITHER_DIM-1)];
+ if (a > d)
+ {
+ XPutPixel (core->msk_image, x, y, 1);
+ if (i > d)
+ XPutPixel (core->src_image, x, y, 0); /* white */
+ else
+ XPutPixel (core->src_image, x, y, 1); /* black */
+ }
+ else
+ {
+ XPutPixel (core->msk_image, x, y, 0);
+ XPutPixel (core->src_image, x, y, 0);
+ }
+ }
+ core->on_color.red = 0;
+ core->on_color.green = 0;
+ core->on_color.blue = 0;
+ core->off_color.red = 0xffff;
+ core->off_color.green = 0xffff;
+ core->off_color.blue = 0xffff;
+ return True;
+}
+
+static Bool
+_XcursorFloydSteinberg (const XcursorImage *image, XcursorCoreCursor *core)
+{
+ int *aPicture, *iPicture, *aP, *iP;
+ XcursorPixel *pixel, p;
+ int aR, iR, aA, iA;
+ int npixels = image->width * image->height;
+ int n;
+ int right = 1;
+ int belowLeft = image->width - 1;
+ int below = image->width;
+ int belowRight = image->width + 1;
+ int iError, aError;
+ int iErrorRight, aErrorRight;
+ int iErrorBelowLeft, aErrorBelowLeft;
+ int iErrorBelow, aErrorBelow;
+ int iErrorBelowRight, aErrorBelowRight;
+ int x, y;
+ int max_inten, min_inten, mean_inten;
+
+ iPicture = malloc (npixels * sizeof (int) * 2);
+ if (!iPicture)
+ return False;
+ aPicture = iPicture + npixels;
+
+ /*
+ * Compute raw gray and alpha arrays
+ */
+ pixel = image->pixels;
+ iP = iPicture;
+ aP = aPicture;
+ n = npixels;
+ max_inten = 0;
+ min_inten = 0xff;
+ while (n--)
+ {
+ p = *pixel++;
+ *aP++ = (int) (p >> 24);
+ iR = (int) _XcursorPixelBrightness (p);
+ if (iR > max_inten) max_inten = iR;
+ if (iR < min_inten) min_inten = iR;
+ *iP++ = iR;
+ }
+ /*
+ * Draw the image while diffusing the error
+ */
+ iP = iPicture;
+ aP = aPicture;
+ mean_inten = (max_inten + min_inten + 1) >> 1;
+ for (y = 0; y < image->height; y++)
+ for (x = 0; x < image->width; x++)
+ {
+ aR = *aP;
+ iR = *iP;
+ if (aR >= 0x80)
+ {
+ XPutPixel (core->msk_image, x, y, 1);
+ aA = 0xff;
+ }
+ else
+ {
+ XPutPixel (core->msk_image, x, y, 0);
+ aA = 0x00;
+ }
+ if (iR >= mean_inten)
+ {
+ XPutPixel (core->src_image, x, y, 0);
+ iA = max_inten;
+ }
+ else
+ {
+ XPutPixel (core->src_image, x, y, 1);
+ iA = min_inten;
+ }
+ iError = iR - iA;
+ aError = aR - aA;
+ iErrorRight = (iError * 7) >> 4;
+ iErrorBelowLeft = (iError * 3) >> 4;
+ iErrorBelow = (iError * 5) >> 4;
+ iErrorBelowRight = (iError - iErrorRight -
+ iErrorBelowLeft - iErrorBelow);
+ aErrorRight = (aError * 7) >> 4;
+ aErrorBelowLeft = (aError * 3) >> 4;
+ aErrorBelow = (aError * 5) >> 4;
+ aErrorBelowRight = (aError - aErrorRight -
+ aErrorBelowLeft - aErrorBelow);
+ if (x < image->width - 1)
+ {
+ iP[right] += iErrorRight;
+ aP[right] += aErrorRight;
+ }
+ if (y < image->height - 1)
+ {
+ if (x)
+ {
+ iP[belowLeft] += iErrorBelowLeft;
+ aP[belowLeft] += aErrorBelowLeft;
+ }
+ iP[below] += iErrorBelow;
+ aP[below] += aErrorBelow;
+ if (x < image->width - 1)
+ {
+ iP[belowRight] += iErrorBelowRight;
+ aP[belowRight] += aErrorBelowRight;
+ }
+ }
+ aP++;
+ iP++;
+ }
+ free (iPicture);
+ core->on_color.red =
+ core->on_color.green =
+ core->on_color.blue = (min_inten | min_inten << 8);
+ core->off_color.red =
+ core->off_color.green =
+ core->off_color.blue = (max_inten | max_inten << 8);
+ return True;
+}
+
+static Bool
+_XcursorThreshold (const XcursorImage *image, XcursorCoreCursor *core)
+{
+ XcursorPixel *pixel, p;
+ int x, y;
+
+ /*
+ * Draw the image, picking black for dark pixels and white for light
+ */
+ pixel = image->pixels;
+ for (y = 0; y < image->height; y++)
+ for (x = 0; x < image->width; x++)
+ {
+ p = *pixel++;
+ if ((p >> 24) >= 0x80)
+ {
+ XPutPixel (core->msk_image, x, y, 1);
+ if (_XcursorPixelBrightness (p) > 0x80)
+ XPutPixel (core->src_image, x, y, 0);
+ else
+ XPutPixel (core->src_image, x, y, 1);
+ }
+ else
+ {
+ XPutPixel (core->msk_image, x, y, 0);
+ XPutPixel (core->src_image, x, y, 0);
+ }
+ }
+ core->on_color.red =
+ core->on_color.green =
+ core->on_color.blue = 0;
+ core->off_color.red =
+ core->off_color.green =
+ core->off_color.blue = 0xffff;
+ return True;
+}
+
+Cursor
+XcursorImageLoadCursor (Display *dpy, const XcursorImage *image)
+{
+ Cursor cursor;
+
+#if RENDER_MAJOR > 0 || RENDER_MINOR >= 5
+ if (XcursorSupportsARGB (dpy))
+ {
+ XImage ximage;
+ int screen = DefaultScreen (dpy);
+ Pixmap pixmap;
+ Picture picture;
+ GC gc;
+ XRenderPictFormat *format;
+
+ ximage.width = image->width;
+ ximage.height = image->height;
+ ximage.xoffset = 0;
+ ximage.format = ZPixmap;
+ ximage.data = (char *) image->pixels;
+ ximage.byte_order = nativeByteOrder ();
+ ximage.bitmap_unit = 32;
+ ximage.bitmap_bit_order = ximage.byte_order;
+ ximage.bitmap_pad = 32;
+ ximage.depth = 32;
+ ximage.bits_per_pixel = 32;
+ ximage.bytes_per_line = image->width * 4;
+ ximage.red_mask = 0xff0000;
+ ximage.green_mask = 0x00ff00;
+ ximage.blue_mask = 0x0000ff;
+ ximage.obdata = NULL;
+ if (!XInitImage (&ximage))
+ return None;
+ pixmap = XCreatePixmap (dpy, RootWindow (dpy, screen),
+ image->width, image->height, 32);
+ gc = XCreateGC (dpy, pixmap, 0, NULL);
+ XPutImage (dpy, pixmap, gc, &ximage,
+ 0, 0, 0, 0, image->width, image->height);
+ XFreeGC (dpy, gc);
+ format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
+ picture = XRenderCreatePicture (dpy, pixmap, format, 0, NULL);
+ XFreePixmap (dpy, pixmap);
+ cursor = XRenderCreateCursor (dpy, picture,
+ image->xhot, image->yhot);
+ XRenderFreePicture (dpy, picture);
+ }
+ else
+#endif
+ {
+ XcursorDisplayInfo *info = _XcursorGetDisplayInfo (dpy);
+ int screen = DefaultScreen (dpy);
+ XcursorCoreCursor core;
+ Pixmap src_pixmap, msk_pixmap;
+ GC gc;
+ XGCValues gcv;
+
+ if (!info)
+ return 0;
+
+ core.src_image = XCreateImage (dpy, NULL, 1, ZPixmap,
+ 0, NULL, image->width, image->height,
+ 32, 0);
+ core.src_image->data = Xmalloc (image->height *
+ core.src_image->bytes_per_line);
+ core.msk_image = XCreateImage (dpy, NULL, 1, ZPixmap,
+ 0, NULL, image->width, image->height,
+ 32, 0);
+ core.msk_image->data = Xmalloc (image->height *
+ core.msk_image->bytes_per_line);
+
+ switch (info->dither) {
+ case XcursorDitherThreshold:
+ if (!_XcursorThreshold (image, &core))
+ return 0;
+ break;
+ case XcursorDitherMedian:
+ if (!_XcursorHeckbertMedianCut (image, &core))
+ return 0;
+ break;
+ case XcursorDitherOrdered:
+ if (!_XcursorBayerOrderedDither (image, &core))
+ return 0;
+ break;
+ case XcursorDitherDiffuse:
+ if (!_XcursorFloydSteinberg (image, &core))
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+
+ /*
+ * Create the cursor
+ */
+ src_pixmap = XCreatePixmap (dpy, RootWindow (dpy, screen),
+ image->width, image->height, 1);
+ msk_pixmap = XCreatePixmap (dpy, RootWindow (dpy, screen),
+ image->width, image->height, 1);
+ gcv.foreground = 1;
+ gcv.background = 0;
+ gc = XCreateGC (dpy, src_pixmap,
+ GCForeground|GCBackground,
+ &gcv);
+ XPutImage (dpy, src_pixmap, gc, core.src_image,
+ 0, 0, 0, 0, image->width, image->height);
+
+ XPutImage (dpy, msk_pixmap, gc, core.msk_image,
+ 0, 0, 0, 0, image->width, image->height);
+ XFreeGC (dpy, gc);
+
+#ifdef DEBUG_IMAGE
+ _XcursorDumpColor (&core.on_color, "on_color");
+ _XcursorDumpColor (&core.off_color, "off_color");
+ _XcursorDumpImage (core.src_image);
+ _XcursorDumpImage (core.msk_image);
+#endif
+ XDestroyImage (core.src_image);
+ XDestroyImage (core.msk_image);
+
+ cursor = XCreatePixmapCursor (dpy, src_pixmap, msk_pixmap,
+ &core.on_color, &core.off_color,
+ image->xhot, image->yhot);
+ XFreePixmap (dpy, src_pixmap);
+ XFreePixmap (dpy, msk_pixmap);
+ }
+ return cursor;
+}
+
+XcursorCursors *
+XcursorImagesLoadCursors (Display *dpy, const XcursorImages *images)
+{
+ XcursorCursors *cursors = XcursorCursorsCreate (dpy, images->nimage);
+ int n;
+
+ if (!cursors)
+ return NULL;
+ for (n = 0; n < images->nimage; n++)
+ {
+ cursors->cursors[n] = XcursorImageLoadCursor (dpy, images->images[n]);
+ if (!cursors->cursors[n])
+ {
+ XcursorCursorsDestroy (cursors);
+ return NULL;
+ }
+ cursors->ncursor++;
+ }
+ return cursors;
+}
+
+Cursor
+XcursorImagesLoadCursor (Display *dpy, const XcursorImages *images)
+{
+ Cursor cursor;
+ if (images->nimage == 1 || !XcursorSupportsAnim (dpy))
+ cursor = XcursorImageLoadCursor (dpy, images->images[0]);
+ else
+ {
+ XcursorCursors *cursors = XcursorImagesLoadCursors (dpy, images);
+ XAnimCursor *anim;
+ int n;
+
+ if (!cursors)
+ return 0;
+ anim = malloc (cursors->ncursor * sizeof (XAnimCursor));
+ if (!anim)
+ {
+ XcursorCursorsDestroy (cursors);
+ return 0;
+ }
+ for (n = 0; n < cursors->ncursor; n++)
+ {
+ anim[n].cursor = cursors->cursors[n];
+ anim[n].delay = images->images[n]->delay;
+ }
+ cursor = XRenderCreateAnimCursor (dpy, cursors->ncursor, anim);
+ XcursorCursorsDestroy(cursors);
+ free (anim);
+ }
+#if defined HAVE_XFIXES && XFIXES_MAJOR >= 2
+ if (images->name)
+ XFixesSetCursorName (dpy, cursor, images->name);
+#endif
+ return cursor;
+}
+
+
+Cursor
+XcursorFilenameLoadCursor (Display *dpy, const char *file)
+{
+ int size = XcursorGetDefaultSize (dpy);
+ XcursorImages *images = XcursorFilenameLoadImages (file, size);
+ Cursor cursor;
+
+ if (!images)
+ return None;
+ cursor = XcursorImagesLoadCursor (dpy, images);
+ XcursorImagesDestroy (images);
+ return cursor;
+}
+
+XcursorCursors *
+XcursorFilenameLoadCursors (Display *dpy, const char *file)
+{
+ int size = XcursorGetDefaultSize (dpy);
+ XcursorImages *images = XcursorFilenameLoadImages (file, size);
+ XcursorCursors *cursors;
+
+ if (!images)
+ return NULL;
+ cursors = XcursorImagesLoadCursors (dpy, images);
+ XcursorImagesDestroy (images);
+ return cursors;
+}
+
+/*
+ * Stolen from XCreateGlyphCursor (which we cruelly override)
+ */
+
+Cursor
+_XcursorCreateGlyphCursor(Display *dpy,
+ Font source_font,
+ Font mask_font,
+ unsigned int source_char,
+ unsigned int mask_char,
+ XColor _Xconst *foreground,
+ XColor _Xconst *background)
+{
+ Cursor cid;
+ register xCreateGlyphCursorReq *req;
+
+ LockDisplay(dpy);
+ GetReq(CreateGlyphCursor, req);
+ cid = req->cid = XAllocID(dpy);
+ req->source = source_font;
+ req->mask = mask_font;
+ req->sourceChar = source_char;
+ req->maskChar = mask_char;
+ req->foreRed = foreground->red;
+ req->foreGreen = foreground->green;
+ req->foreBlue = foreground->blue;
+ req->backRed = background->red;
+ req->backGreen = background->green;
+ req->backBlue = background->blue;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return (cid);
+}
+
+/*
+ * Stolen from XCreateFontCursor (which we cruelly override)
+ */
+
+Cursor
+_XcursorCreateFontCursor (Display *dpy, unsigned int shape)
+{
+ static XColor _Xconst foreground = { 0, 0, 0, 0 }; /* black */
+ static XColor _Xconst background = { 0, 65535, 65535, 65535 }; /* white */
+
+ /*
+ * the cursor font contains the shape glyph followed by the mask
+ * glyph; so character position 0 contains a shape, 1 the mask for 0,
+ * 2 a shape, etc. <X11/cursorfont.h> contains hash define names
+ * for all of these.
+ */
+
+ if (dpy->cursor_font == None)
+ {
+ dpy->cursor_font = XLoadFont (dpy, CURSORFONT);
+ if (dpy->cursor_font == None)
+ return None;
+ }
+
+ return _XcursorCreateGlyphCursor (dpy, dpy->cursor_font, dpy->cursor_font,
+ shape, shape + 1, &foreground, &background);
+}
+
--- /dev/null
+/*
+ * Copyright © 2002 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "xcursorint.h"
+#include <X11/Xlibint.h>
+#include <ctype.h>
+
+static XcursorDisplayInfo *_XcursorDisplayInfo;
+
+static void
+_XcursorFreeDisplayInfo (XcursorDisplayInfo *info)
+{
+ if (info->theme)
+ free (info->theme);
+
+ if (info->theme_from_config)
+ free (info->theme_from_config);
+
+ while (info->fonts)
+ {
+ XcursorFontInfo *fi = info->fonts;
+ info->fonts = fi->next;
+ free (fi);
+ }
+
+ free (info);
+}
+
+static int
+_XcursorCloseDisplay (Display *dpy, XExtCodes *codes)
+{
+ XcursorDisplayInfo *info, **prev;
+
+ /*
+ * Unhook from the global list
+ */
+ _XLockMutex (_Xglobal_lock);
+ for (prev = &_XcursorDisplayInfo; (info = *prev); prev = &(*prev)->next)
+ if (info->display == dpy)
+ {
+ *prev = info->next;
+ break;
+ }
+ _XUnlockMutex (_Xglobal_lock);
+
+ if (info)
+ _XcursorFreeDisplayInfo (info);
+ return 0;
+}
+
+static int
+_XcursorDefaultParseBool (char *v)
+{
+ char c0, c1;
+
+ c0 = *v;
+ if (isupper ((int)c0))
+ c0 = tolower (c0);
+ if (c0 == 't' || c0 == 'y' || c0 == '1')
+ return 1;
+ if (c0 == 'f' || c0 == 'n' || c0 == '0')
+ return 0;
+ if (c0 == 'o')
+ {
+ c1 = v[1];
+ if (isupper ((int)c1))
+ c1 = tolower (c1);
+ if (c1 == 'n')
+ return 1;
+ if (c1 == 'f')
+ return 0;
+ }
+ return -1;
+}
+
+XcursorDisplayInfo *
+_XcursorGetDisplayInfo (Display *dpy)
+{
+ XcursorDisplayInfo *info, **prev, *old;
+ int event_base, error_base;
+ int major, minor;
+ char *v;
+ int i;
+
+ _XLockMutex (_Xglobal_lock);
+ for (prev = &_XcursorDisplayInfo; (info = *prev); prev = &(*prev)->next)
+ {
+ if (info->display == dpy)
+ {
+ /*
+ * MRU the list
+ */
+ if (prev != &_XcursorDisplayInfo)
+ {
+ *prev = info->next;
+ info->next = _XcursorDisplayInfo;
+ _XcursorDisplayInfo = info;
+ }
+ break;
+ }
+ }
+ _XUnlockMutex (_Xglobal_lock);
+ if (info)
+ return info;
+ info = (XcursorDisplayInfo *) malloc (sizeof (XcursorDisplayInfo));
+ if (!info)
+ return NULL;
+ info->next = NULL;
+ info->display = dpy;
+
+ info->codes = XAddExtension (dpy);
+ if (!info->codes)
+ {
+ free (info);
+ return NULL;
+ }
+ (void) XESetCloseDisplay (dpy, info->codes->extension, _XcursorCloseDisplay);
+
+ /*
+ * Check whether the display supports the Render CreateCursor request
+ */
+ info->has_render_cursor = XcursorFalse;
+ info->has_anim_cursor = XcursorFalse;
+ if (XRenderQueryExtension (dpy, &event_base, &error_base) &&
+ XRenderQueryVersion (dpy, &major, &minor))
+ {
+ if (major > 0 || minor >= 5)
+ {
+ info->has_render_cursor = XcursorTrue;
+ v = getenv ("XCURSOR_CORE");
+ if (!v)
+ v = XGetDefault (dpy, "Xcursor", "core");
+ if (v && _XcursorDefaultParseBool (v) == 1)
+ info->has_render_cursor = XcursorFalse;
+ }
+ if (info->has_render_cursor && (major > 0 || minor >= 8))
+ {
+ info->has_anim_cursor = XcursorTrue;
+ v = getenv ("XCURSOR_ANIM");
+ if (!v)
+ v = XGetDefault (dpy, "Xcursor", "anim");
+ if (v && _XcursorDefaultParseBool (v) == 0)
+ info->has_anim_cursor = XcursorFalse;
+ }
+ }
+
+ info->size = 0;
+
+ /*
+ * Get desired cursor size
+ */
+ v = getenv ("XCURSOR_SIZE");
+ if (!v)
+ v = XGetDefault (dpy, "Xcursor", "size");
+ if (v)
+ info->size = atoi (v);
+
+ /*
+ * Use the Xft size to guess a size; make cursors 16 "points" tall
+ */
+ if (info->size == 0)
+ {
+ int dpi = 0;
+ v = XGetDefault (dpy, "Xft", "dpi");
+ if (v)
+ dpi = atoi (v);
+ if (dpi)
+ info->size = dpi * 16 / 72;
+ }
+
+ /*
+ * Use display size to guess a size
+ */
+ if (info->size == 0)
+ {
+ int dim;
+
+ if (DisplayHeight (dpy, DefaultScreen (dpy)) <
+ DisplayWidth (dpy, DefaultScreen (dpy)))
+ dim = DisplayHeight (dpy, DefaultScreen (dpy));
+ else
+ dim = DisplayWidth (dpy, DefaultScreen (dpy));
+ /*
+ * 16 pixels on a display of dimension 768
+ */
+ info->size = dim / 48;
+ }
+
+ info->theme = NULL;
+ info->theme_from_config = NULL;
+
+ /*
+ * Get the desired theme
+ */
+ v = getenv ("XCURSOR_THEME");
+ if (!v)
+ v = XGetDefault (dpy, "Xcursor", "theme");
+ if (v)
+ {
+ int len;
+
+ len = strlen (v) + 1;
+
+ info->theme = malloc (len);
+ if (info->theme)
+ strcpy (info->theme, v);
+
+ info->theme_from_config = malloc (len);
+ if (info->theme_from_config)
+ strcpy (info->theme_from_config, v);
+ }
+
+ /*
+ * Get the desired dither
+ */
+ info->dither = XcursorDitherThreshold;
+ v = getenv ("XCURSOR_DITHER");
+ if (!v)
+ v = XGetDefault (dpy, "Xcursor", "dither");
+ if (v)
+ {
+ if (!strcmp (v, "threshold"))
+ info->dither = XcursorDitherThreshold;
+ if (!strcmp (v, "median"))
+ info->dither = XcursorDitherMedian;
+ if (!strcmp (v, "ordered"))
+ info->dither = XcursorDitherOrdered;
+ if (!strcmp (v, "diffuse"))
+ info->dither = XcursorDitherDiffuse;
+ }
+
+ info->theme_core = False;
+ /*
+ * Find out if core cursors should
+ * be themed
+ */
+ v = getenv ("XCURSOR_THEME_CORE");
+ if (!v)
+ v = XGetDefault (dpy, "Xcursor", "theme_core");
+ if (v)
+ {
+ i = _XcursorDefaultParseBool (v);
+ if (i >= 0)
+ info->theme_core = i;
+ }
+
+ info->fonts = NULL;
+ for (i = 0; i < NUM_BITMAPS; i++)
+ info->bitmaps[i].bitmap = None;
+
+ /*
+ * Link new info info list, making sure another
+ * thread hasn't inserted something into the list while
+ * this one was busy setting up the data
+ */
+ _XLockMutex (_Xglobal_lock);
+ for (old = _XcursorDisplayInfo; old; old = old->next)
+ if (old->display == dpy)
+ break;
+ if (old)
+ {
+ _XcursorFreeDisplayInfo (info);
+ info = old;
+ }
+ else
+ {
+ info->next = _XcursorDisplayInfo;
+ _XcursorDisplayInfo = info;
+ }
+ _XUnlockMutex (_Xglobal_lock);
+
+ return info;
+}
+
+XcursorBool
+XcursorSupportsARGB (Display *dpy)
+{
+ XcursorDisplayInfo *info = _XcursorGetDisplayInfo (dpy);
+
+ return info && info->has_render_cursor;
+}
+
+XcursorBool
+XcursorSupportsAnim (Display *dpy)
+{
+ XcursorDisplayInfo *info = _XcursorGetDisplayInfo (dpy);
+
+ return info && info->has_anim_cursor;
+}
+
+XcursorBool
+XcursorSetDefaultSize (Display *dpy, int size)
+{
+ XcursorDisplayInfo *info = _XcursorGetDisplayInfo (dpy);
+
+ if (!info)
+ return XcursorFalse;
+ info->size = size;
+ return XcursorTrue;
+}
+
+int
+XcursorGetDefaultSize (Display *dpy)
+{
+ XcursorDisplayInfo *info = _XcursorGetDisplayInfo (dpy);
+
+ if (!info)
+ return 0;
+ return info->size;
+}
+
+XcursorBool
+XcursorSetTheme (Display *dpy, const char *theme)
+{
+ XcursorDisplayInfo *info = _XcursorGetDisplayInfo (dpy);
+ char *copy;
+
+ if (!info)
+ return XcursorFalse;
+
+ if (!theme)
+ theme = info->theme_from_config;
+
+ if (theme)
+ {
+ copy = malloc (strlen (theme) + 1);
+ if (!copy)
+ return XcursorFalse;
+ strcpy (copy, theme);
+ }
+ else
+ copy = NULL;
+ if (info->theme)
+ free (info->theme);
+ info->theme = copy;
+ return XcursorTrue;
+}
+
+char *
+XcursorGetTheme (Display *dpy)
+{
+ XcursorDisplayInfo *info = _XcursorGetDisplayInfo (dpy);
+
+ if (!info)
+ return NULL;
+ return info->theme;
+}
+
+XcursorBool
+XcursorGetThemeCore (Display *dpy)
+{
+ XcursorDisplayInfo *info = _XcursorGetDisplayInfo (dpy);
+
+ if (!info)
+ return XcursorFalse;
+ return info->theme_core;
+
+}
+
+XcursorBool
+XcursorSetThemeCore (Display *dpy, XcursorBool theme_core)
+{
+ XcursorDisplayInfo *info = _XcursorGetDisplayInfo (dpy);
+
+ if (!info)
+ return XcursorFalse;
+ info->theme_core = theme_core;
+ return XcursorTrue;
+}
--- /dev/null
+/*
+ * Copyright © 2002 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "xcursorint.h"
+#include <stdlib.h>
+#include <string.h>
+
+XcursorImage *
+XcursorImageCreate (int width, int height)
+{
+ XcursorImage *image;
+
+ image = malloc (sizeof (XcursorImage) +
+ width * height * sizeof (XcursorPixel));
+ if (!image)
+ return NULL;
+ image->version = XCURSOR_IMAGE_VERSION;
+ image->pixels = (XcursorPixel *) (image + 1);
+ image->size = width > height ? width : height;
+ image->width = width;
+ image->height = height;
+ image->delay = 0;
+ return image;
+}
+
+void
+XcursorImageDestroy (XcursorImage *image)
+{
+ free (image);
+}
+
+XcursorImages *
+XcursorImagesCreate (int size)
+{
+ XcursorImages *images;
+
+ images = malloc (sizeof (XcursorImages) +
+ size * sizeof (XcursorImage *));
+ if (!images)
+ return NULL;
+ images->nimage = 0;
+ images->images = (XcursorImage **) (images + 1);
+ images->name = NULL;
+ return images;
+}
+
+void
+XcursorImagesDestroy (XcursorImages *images)
+{
+ int n;
+
+ if (!images)
+ return;
+
+ for (n = 0; n < images->nimage; n++)
+ XcursorImageDestroy (images->images[n]);
+ if (images->name)
+ free (images->name);
+ free (images);
+}
+
+void
+XcursorImagesSetName (XcursorImages *images, const char *name)
+{
+ char *new;
+
+ if (!images || !name)
+ return;
+
+ new = malloc (strlen (name) + 1);
+
+ if (!new)
+ return;
+
+ strcpy (new, name);
+ if (images->name)
+ free (images->name);
+ images->name = new;
+}
+
+XcursorComment *
+XcursorCommentCreate (XcursorUInt comment_type, int length)
+{
+ XcursorComment *comment;
+
+ if (length > XCURSOR_COMMENT_MAX_LEN)
+ return NULL;
+
+ comment = malloc (sizeof (XcursorComment) + length + 1);
+ if (!comment)
+ return NULL;
+ comment->version = XCURSOR_COMMENT_VERSION;
+ comment->comment_type = comment_type;
+ comment->comment = (char *) (comment + 1);
+ comment->comment[0] = '\0';
+ return comment;
+}
+
+void
+XcursorCommentDestroy (XcursorComment *comment)
+{
+ free (comment);
+}
+
+XcursorComments *
+XcursorCommentsCreate (int size)
+{
+ XcursorComments *comments;
+
+ comments = malloc (sizeof (XcursorComments) +
+ size * sizeof (XcursorComment *));
+ if (!comments)
+ return NULL;
+ comments->ncomment = 0;
+ comments->comments = (XcursorComment **) (comments + 1);
+ return comments;
+}
+
+void
+XcursorCommentsDestroy (XcursorComments *comments)
+{
+ int n;
+
+ if (!comments)
+ return;
+
+ for (n = 0; n < comments->ncomment; n++)
+ XcursorCommentDestroy (comments->comments[n]);
+ free (comments);
+}
+
+static XcursorBool
+_XcursorReadUInt (XcursorFile *file, XcursorUInt *u)
+{
+ unsigned char bytes[4];
+
+ if (!file || !u)
+ return XcursorFalse;
+
+ if ((*file->read) (file, bytes, 4) != 4)
+ return XcursorFalse;
+ *u = ((bytes[0] << 0) |
+ (bytes[1] << 8) |
+ (bytes[2] << 16) |
+ (bytes[3] << 24));
+ return XcursorTrue;
+}
+
+static XcursorBool
+_XcursorReadBytes (XcursorFile *file, char *bytes, int length)
+{
+ if (!file || !bytes || (*file->read) (file, (unsigned char *) bytes, length) != length)
+ return XcursorFalse;
+ return XcursorTrue;
+}
+
+static XcursorBool
+_XcursorWriteUInt (XcursorFile *file, XcursorUInt u)
+{
+ unsigned char bytes[4];
+
+ if (!file)
+ return XcursorFalse;
+
+ bytes[0] = u;
+ bytes[1] = u >> 8;
+ bytes[2] = u >> 16;
+ bytes[3] = u >> 24;
+ if ((*file->write) (file, bytes, 4) != 4)
+ return XcursorFalse;
+ return XcursorTrue;
+}
+
+static XcursorBool
+_XcursorWriteBytes (XcursorFile *file, char *bytes, int length)
+{
+ if (!file || !bytes || (*file->write) (file, (unsigned char *) bytes, length) != length)
+ return XcursorFalse;
+ return XcursorTrue;
+}
+
+static void
+_XcursorFileHeaderDestroy (XcursorFileHeader *fileHeader)
+{
+ free (fileHeader);
+}
+
+static XcursorFileHeader *
+_XcursorFileHeaderCreate (int ntoc)
+{
+ XcursorFileHeader *fileHeader;
+
+ if (ntoc > 0x10000)
+ return NULL;
+ fileHeader = malloc (sizeof (XcursorFileHeader) +
+ ntoc * sizeof (XcursorFileToc));
+ if (!fileHeader)
+ return NULL;
+ fileHeader->magic = XCURSOR_MAGIC;
+ fileHeader->header = XCURSOR_FILE_HEADER_LEN;
+ fileHeader->version = XCURSOR_FILE_VERSION;
+ fileHeader->ntoc = ntoc;
+ fileHeader->tocs = (XcursorFileToc *) (fileHeader + 1);
+ return fileHeader;
+}
+
+static XcursorFileHeader *
+_XcursorReadFileHeader (XcursorFile *file)
+{
+ XcursorFileHeader head, *fileHeader;
+ XcursorUInt skip;
+ int n;
+
+ if (!file)
+ return NULL;
+
+ if (!_XcursorReadUInt (file, &head.magic))
+ return NULL;
+ if (head.magic != XCURSOR_MAGIC)
+ return NULL;
+ if (!_XcursorReadUInt (file, &head.header))
+ return NULL;
+ if (!_XcursorReadUInt (file, &head.version))
+ return NULL;
+ if (!_XcursorReadUInt (file, &head.ntoc))
+ return NULL;
+ skip = head.header - XCURSOR_FILE_HEADER_LEN;
+ if (skip)
+ if ((*file->seek) (file, skip, SEEK_CUR) == EOF)
+ return NULL;
+ fileHeader = _XcursorFileHeaderCreate (head.ntoc);
+ if (!fileHeader)
+ return NULL;
+ fileHeader->magic = head.magic;
+ fileHeader->header = head.header;
+ fileHeader->version = head.version;
+ fileHeader->ntoc = head.ntoc;
+ for (n = 0; n < fileHeader->ntoc; n++)
+ {
+ if (!_XcursorReadUInt (file, &fileHeader->tocs[n].type))
+ break;
+ if (!_XcursorReadUInt (file, &fileHeader->tocs[n].subtype))
+ break;
+ if (!_XcursorReadUInt (file, &fileHeader->tocs[n].position))
+ break;
+ }
+ if (n != fileHeader->ntoc)
+ {
+ _XcursorFileHeaderDestroy (fileHeader);
+ return NULL;
+ }
+ return fileHeader;
+}
+
+static XcursorUInt
+_XcursorFileHeaderLength (XcursorFileHeader *fileHeader)
+{
+ return (XCURSOR_FILE_HEADER_LEN +
+ fileHeader->ntoc * XCURSOR_FILE_TOC_LEN);
+}
+
+static XcursorBool
+_XcursorWriteFileHeader (XcursorFile *file, XcursorFileHeader *fileHeader)
+{
+ int toc;
+
+ if (!file || !fileHeader)
+ return XcursorFalse;
+
+ if (!_XcursorWriteUInt (file, fileHeader->magic))
+ return XcursorFalse;
+ if (!_XcursorWriteUInt (file, fileHeader->header))
+ return XcursorFalse;
+ if (!_XcursorWriteUInt (file, fileHeader->version))
+ return XcursorFalse;
+ if (!_XcursorWriteUInt (file, fileHeader->ntoc))
+ return XcursorFalse;
+ for (toc = 0; toc < fileHeader->ntoc; toc++)
+ {
+ if (!_XcursorWriteUInt (file, fileHeader->tocs[toc].type))
+ return XcursorFalse;
+ if (!_XcursorWriteUInt (file, fileHeader->tocs[toc].subtype))
+ return XcursorFalse;
+ if (!_XcursorWriteUInt (file, fileHeader->tocs[toc].position))
+ return XcursorFalse;
+ }
+ return XcursorTrue;
+}
+
+static XcursorBool
+_XcursorSeekToToc (XcursorFile *file,
+ XcursorFileHeader *fileHeader,
+ int toc)
+{
+ if (!file || !fileHeader || \
+ (*file->seek) (file, fileHeader->tocs[toc].position, SEEK_SET) == EOF)
+ return XcursorFalse;
+ return XcursorTrue;
+}
+
+static XcursorBool
+_XcursorFileReadChunkHeader (XcursorFile *file,
+ XcursorFileHeader *fileHeader,
+ int toc,
+ XcursorChunkHeader *chunkHeader)
+{
+ if (!file || !fileHeader || !chunkHeader)
+ return XcursorFalse;
+ if (!_XcursorSeekToToc (file, fileHeader, toc))
+ return XcursorFalse;
+ if (!_XcursorReadUInt (file, &chunkHeader->header))
+ return XcursorFalse;
+ if (!_XcursorReadUInt (file, &chunkHeader->type))
+ return XcursorFalse;
+ if (!_XcursorReadUInt (file, &chunkHeader->subtype))
+ return XcursorFalse;
+ if (!_XcursorReadUInt (file, &chunkHeader->version))
+ return XcursorFalse;
+ /* sanity check */
+ if (chunkHeader->type != fileHeader->tocs[toc].type ||
+ chunkHeader->subtype != fileHeader->tocs[toc].subtype)
+ return XcursorFalse;
+ return XcursorTrue;
+}
+
+static XcursorBool
+_XcursorFileWriteChunkHeader (XcursorFile *file,
+ XcursorFileHeader *fileHeader,
+ int toc,
+ XcursorChunkHeader *chunkHeader)
+{
+ if (!file || !fileHeader || !chunkHeader)
+ return XcursorFalse;
+ if (!_XcursorSeekToToc (file, fileHeader, toc))
+ return XcursorFalse;
+ if (!_XcursorWriteUInt (file, chunkHeader->header))
+ return XcursorFalse;
+ if (!_XcursorWriteUInt (file, chunkHeader->type))
+ return XcursorFalse;
+ if (!_XcursorWriteUInt (file, chunkHeader->subtype))
+ return XcursorFalse;
+ if (!_XcursorWriteUInt (file, chunkHeader->version))
+ return XcursorFalse;
+ return XcursorTrue;
+}
+
+#define dist(a,b) ((a) > (b) ? (a) - (b) : (b) - (a))
+
+static XcursorDim
+_XcursorFindBestSize (XcursorFileHeader *fileHeader,
+ XcursorDim size,
+ int *nsizesp)
+{
+ int n;
+ int nsizes = 0;
+ XcursorDim bestSize = 0;
+ XcursorDim thisSize;
+
+ if (!fileHeader || !nsizesp)
+ return 0;
+
+ for (n = 0; n < fileHeader->ntoc; n++)
+ {
+ if (fileHeader->tocs[n].type != XCURSOR_IMAGE_TYPE)
+ continue;
+ thisSize = fileHeader->tocs[n].subtype;
+ if (!bestSize || dist (thisSize, size) < dist (bestSize, size))
+ {
+ bestSize = thisSize;
+ nsizes = 1;
+ }
+ else if (thisSize == bestSize)
+ nsizes++;
+ }
+ *nsizesp = nsizes;
+ return bestSize;
+}
+
+static int
+_XcursorFindImageToc (XcursorFileHeader *fileHeader,
+ XcursorDim size,
+ int count)
+{
+ int toc;
+ XcursorDim thisSize;
+
+ if (!fileHeader)
+ return 0;
+
+ for (toc = 0; toc < fileHeader->ntoc; toc++)
+ {
+ if (fileHeader->tocs[toc].type != XCURSOR_IMAGE_TYPE)
+ continue;
+ thisSize = fileHeader->tocs[toc].subtype;
+ if (thisSize != size)
+ continue;
+ if (!count)
+ break;
+ count--;
+ }
+ if (toc == fileHeader->ntoc)
+ return -1;
+ return toc;
+}
+
+static XcursorImage *
+_XcursorReadImage (XcursorFile *file,
+ XcursorFileHeader *fileHeader,
+ int toc)
+{
+ XcursorChunkHeader chunkHeader;
+ XcursorImage head;
+ XcursorImage *image;
+ int n;
+ XcursorPixel *p;
+
+ if (!file || !fileHeader)
+ return NULL;
+
+ if (!_XcursorFileReadChunkHeader (file, fileHeader, toc, &chunkHeader))
+ return NULL;
+ if (!_XcursorReadUInt (file, &head.width))
+ return NULL;
+ if (!_XcursorReadUInt (file, &head.height))
+ return NULL;
+ if (!_XcursorReadUInt (file, &head.xhot))
+ return NULL;
+ if (!_XcursorReadUInt (file, &head.yhot))
+ return NULL;
+ if (!_XcursorReadUInt (file, &head.delay))
+ return NULL;
+ /* sanity check data */
+ if (head.width >= 0x10000 || head.height > 0x10000)
+ return NULL;
+ if (head.width == 0 || head.height == 0)
+ return NULL;
+ if (head.xhot > head.width || head.yhot > head.height)
+ return NULL;
+
+ /* Create the image and initialize it */
+ image = XcursorImageCreate (head.width, head.height);
+ if (chunkHeader.version < image->version)
+ image->version = chunkHeader.version;
+ image->size = chunkHeader.subtype;
+ image->xhot = head.xhot;
+ image->yhot = head.yhot;
+ image->delay = head.delay;
+ n = image->width * image->height;
+ p = image->pixels;
+ while (n--)
+ {
+ if (!_XcursorReadUInt (file, p))
+ {
+ XcursorImageDestroy (image);
+ return NULL;
+ }
+ p++;
+ }
+ return image;
+}
+
+static XcursorUInt
+_XcursorImageLength (XcursorImage *image)
+{
+ if (!image)
+ return 0;
+
+ return XCURSOR_IMAGE_HEADER_LEN + (image->width * image->height) * 4;
+}
+
+static XcursorBool
+_XcursorWriteImage (XcursorFile *file,
+ XcursorFileHeader *fileHeader,
+ int toc,
+ XcursorImage *image)
+{
+ XcursorChunkHeader chunkHeader;
+ int n;
+ XcursorPixel *p;
+
+ if (!file || !fileHeader || !image)
+ return XcursorFalse;
+
+ /* sanity check data */
+ if (image->width > XCURSOR_IMAGE_MAX_SIZE ||
+ image->height > XCURSOR_IMAGE_MAX_SIZE)
+ return XcursorFalse;
+ if (image->width == 0 || image->height == 0)
+ return XcursorFalse;
+ if (image->xhot > image->width || image->yhot > image->height)
+ return XcursorFalse;
+
+ /* write chunk header */
+ chunkHeader.header = XCURSOR_IMAGE_HEADER_LEN;
+ chunkHeader.type = XCURSOR_IMAGE_TYPE;
+ chunkHeader.subtype = image->size;
+ chunkHeader.version = XCURSOR_IMAGE_VERSION;
+
+ if (!_XcursorFileWriteChunkHeader (file, fileHeader, toc, &chunkHeader))
+ return XcursorFalse;
+
+ /* write extra image header fields */
+ if (!_XcursorWriteUInt (file, image->width))
+ return XcursorFalse;
+ if (!_XcursorWriteUInt (file, image->height))
+ return XcursorFalse;
+ if (!_XcursorWriteUInt (file, image->xhot))
+ return XcursorFalse;
+ if (!_XcursorWriteUInt (file, image->yhot))
+ return XcursorFalse;
+ if (!_XcursorWriteUInt (file, image->delay))
+ return XcursorFalse;
+
+ /* write the image */
+ n = image->width * image->height;
+ p = image->pixels;
+ while (n--)
+ {
+ if (!_XcursorWriteUInt (file, *p))
+ return XcursorFalse;
+ p++;
+ }
+ return XcursorTrue;
+}
+
+static XcursorComment *
+_XcursorReadComment (XcursorFile *file,
+ XcursorFileHeader *fileHeader,
+ int toc)
+{
+ XcursorChunkHeader chunkHeader;
+ XcursorUInt length;
+ XcursorComment *comment;
+
+ if (!file || !fileHeader)
+ return NULL;
+
+ /* read chunk header */
+ if (!_XcursorFileReadChunkHeader (file, fileHeader, toc, &chunkHeader))
+ return NULL;
+ /* read extra comment header fields */
+ if (!_XcursorReadUInt (file, &length))
+ return NULL;
+ comment = XcursorCommentCreate (chunkHeader.subtype, length);
+ if (!comment)
+ return NULL;
+ if (!_XcursorReadBytes (file, comment->comment, length))
+ {
+ XcursorCommentDestroy (comment);
+ return NULL;
+ }
+ comment->comment[length] = '\0';
+ return comment;
+}
+
+static XcursorUInt
+_XcursorCommentLength (XcursorComment *comment)
+{
+ return XCURSOR_COMMENT_HEADER_LEN + strlen (comment->comment);
+}
+
+static XcursorBool
+_XcursorWriteComment (XcursorFile *file,
+ XcursorFileHeader *fileHeader,
+ int toc,
+ XcursorComment *comment)
+{
+ XcursorChunkHeader chunkHeader;
+ XcursorUInt length;
+
+ if (!file || !fileHeader || !comment || !comment->comment)
+ return XcursorFalse;
+
+ length = strlen (comment->comment);
+
+ /* sanity check data */
+ if (length > XCURSOR_COMMENT_MAX_LEN)
+ return XcursorFalse;
+
+ /* read chunk header */
+ chunkHeader.header = XCURSOR_COMMENT_HEADER_LEN;
+ chunkHeader.type = XCURSOR_COMMENT_TYPE;
+ chunkHeader.subtype = comment->comment_type;
+ chunkHeader.version = XCURSOR_COMMENT_VERSION;
+
+ if (!_XcursorFileWriteChunkHeader (file, fileHeader, toc, &chunkHeader))
+ return XcursorFalse;
+
+ /* write extra comment header fields */
+ if (!_XcursorWriteUInt (file, length))
+ return XcursorFalse;
+
+ if (!_XcursorWriteBytes (file, comment->comment, length))
+ return XcursorFalse;
+ return XcursorTrue;
+}
+
+XcursorImage *
+XcursorXcFileLoadImage (XcursorFile *file, int size)
+{
+ XcursorFileHeader *fileHeader;
+ XcursorDim bestSize;
+ int nsize;
+ int toc;
+ XcursorImage *image;
+
+ if (size < 0)
+ return NULL;
+ fileHeader = _XcursorReadFileHeader (file);
+ if (!fileHeader)
+ return NULL;
+ bestSize = _XcursorFindBestSize (fileHeader, (XcursorDim) size, &nsize);
+ if (!bestSize)
+ return NULL;
+ toc = _XcursorFindImageToc (fileHeader, bestSize, 0);
+ if (toc < 0)
+ return NULL;
+ image = _XcursorReadImage (file, fileHeader, toc);
+ _XcursorFileHeaderDestroy (fileHeader);
+ return image;
+}
+
+XcursorImages *
+XcursorXcFileLoadImages (XcursorFile *file, int size)
+{
+ XcursorFileHeader *fileHeader;
+ XcursorDim bestSize;
+ int nsize;
+ XcursorImages *images;
+ int n;
+ int toc;
+
+ if (!file || size < 0)
+ return NULL;
+ fileHeader = _XcursorReadFileHeader (file);
+ if (!fileHeader)
+ return NULL;
+ bestSize = _XcursorFindBestSize (fileHeader, (XcursorDim) size, &nsize);
+ if (!bestSize)
+ {
+ _XcursorFileHeaderDestroy (fileHeader);
+ return NULL;
+ }
+ images = XcursorImagesCreate (nsize);
+ if (!images)
+ {
+ _XcursorFileHeaderDestroy (fileHeader);
+ return NULL;
+ }
+ for (n = 0; n < nsize; n++)
+ {
+ toc = _XcursorFindImageToc (fileHeader, bestSize, n);
+ if (toc < 0)
+ break;
+ images->images[images->nimage] = _XcursorReadImage (file, fileHeader,
+ toc);
+ if (!images->images[images->nimage])
+ break;
+ images->nimage++;
+ }
+ _XcursorFileHeaderDestroy (fileHeader);
+ if (images->nimage != nsize)
+ {
+ XcursorImagesDestroy (images);
+ images = NULL;
+ }
+ return images;
+}
+
+XcursorImages *
+XcursorXcFileLoadAllImages (XcursorFile *file)
+{
+ XcursorFileHeader *fileHeader;
+ XcursorImage *image;
+ XcursorImages *images;
+ int nimage;
+ int n;
+ int toc;
+
+ if (!file)
+ return NULL;
+
+ fileHeader = _XcursorReadFileHeader (file);
+ if (!fileHeader)
+ return NULL;
+ nimage = 0;
+ for (n = 0; n < fileHeader->ntoc; n++)
+ {
+ switch (fileHeader->tocs[n].type) {
+ case XCURSOR_IMAGE_TYPE:
+ nimage++;
+ break;
+ }
+ }
+ images = XcursorImagesCreate (nimage);
+ if (!images)
+ {
+ _XcursorFileHeaderDestroy (fileHeader);
+ return NULL;
+ }
+ for (toc = 0; toc < fileHeader->ntoc; toc++)
+ {
+ switch (fileHeader->tocs[toc].type) {
+ case XCURSOR_IMAGE_TYPE:
+ image = _XcursorReadImage (file, fileHeader, toc);
+ if (image)
+ {
+ images->images[images->nimage] = image;
+ images->nimage++;
+ }
+ break;
+ }
+ }
+ _XcursorFileHeaderDestroy (fileHeader);
+ if (images->nimage != nimage)
+ {
+ XcursorImagesDestroy (images);
+ images = NULL;
+ }
+ return images;
+}
+
+XcursorBool
+XcursorXcFileLoad (XcursorFile *file,
+ XcursorComments **commentsp,
+ XcursorImages **imagesp)
+{
+ XcursorFileHeader *fileHeader;
+ int nimage;
+ int ncomment;
+ XcursorImages *images;
+ XcursorImage *image;
+ XcursorComment *comment;
+ XcursorComments *comments;
+ int toc;
+
+ if (!file)
+ return 0;
+ fileHeader = _XcursorReadFileHeader (file);
+ if (!fileHeader)
+ return 0;
+ nimage = 0;
+ ncomment = 0;
+ for (toc = 0; toc < fileHeader->ntoc; toc++)
+ {
+ switch (fileHeader->tocs[toc].type) {
+ case XCURSOR_COMMENT_TYPE:
+ ncomment++;
+ break;
+ case XCURSOR_IMAGE_TYPE:
+ nimage++;
+ break;
+ }
+ }
+ images = XcursorImagesCreate (nimage);
+ if (!images)
+ return 0;
+ comments = XcursorCommentsCreate (ncomment);
+ if (!comments)
+ {
+ XcursorImagesDestroy (images);
+ return 0;
+ }
+ for (toc = 0; toc < fileHeader->ntoc; toc++)
+ {
+ switch (fileHeader->tocs[toc].type) {
+ case XCURSOR_COMMENT_TYPE:
+ comment = _XcursorReadComment (file, fileHeader, toc);
+ if (comment)
+ {
+ comments->comments[comments->ncomment] = comment;
+ comments->ncomment++;
+ }
+ break;
+ case XCURSOR_IMAGE_TYPE:
+ image = _XcursorReadImage (file, fileHeader, toc);
+ if (image)
+ {
+ images->images[images->nimage] = image;
+ images->nimage++;
+ }
+ break;
+ }
+ }
+ _XcursorFileHeaderDestroy (fileHeader);
+ if (images->nimage != nimage || comments->ncomment != ncomment)
+ {
+ XcursorImagesDestroy (images);
+ XcursorCommentsDestroy (comments);
+ images = NULL;
+ comments = NULL;
+ return XcursorFalse;
+ }
+ *imagesp = images;
+ *commentsp = comments;
+ return XcursorTrue;
+}
+
+XcursorBool
+XcursorXcFileSave (XcursorFile *file,
+ const XcursorComments *comments,
+ const XcursorImages *images)
+{
+ XcursorFileHeader *fileHeader;
+ XcursorUInt position;
+ int n;
+ int toc;
+
+ if (!file || !comments || !images)
+ return XcursorFalse;
+
+ fileHeader = _XcursorFileHeaderCreate (comments->ncomment + images->nimage);
+ if (!fileHeader)
+ return XcursorFalse;
+
+ position = _XcursorFileHeaderLength (fileHeader);
+
+ /*
+ * Compute the toc. Place the images before the comments
+ * as they're more often read
+ */
+
+ toc = 0;
+ for (n = 0; n < images->nimage; n++)
+ {
+ fileHeader->tocs[toc].type = XCURSOR_IMAGE_TYPE;
+ fileHeader->tocs[toc].subtype = images->images[n]->size;
+ fileHeader->tocs[toc].position = position;
+ position += _XcursorImageLength (images->images[n]);
+ toc++;
+ }
+
+ for (n = 0; n < comments->ncomment; n++)
+ {
+ fileHeader->tocs[toc].type = XCURSOR_COMMENT_TYPE;
+ fileHeader->tocs[toc].subtype = comments->comments[n]->comment_type;
+ fileHeader->tocs[toc].position = position;
+ position += _XcursorCommentLength (comments->comments[n]);
+ toc++;
+ }
+
+ /*
+ * Write the header and the toc
+ */
+ if (!_XcursorWriteFileHeader (file, fileHeader))
+ goto bail;
+
+ /*
+ * Write the images
+ */
+ toc = 0;
+ for (n = 0; n < images->nimage; n++)
+ {
+ if (!_XcursorWriteImage (file, fileHeader, toc, images->images[n]))
+ goto bail;
+ toc++;
+ }
+
+ /*
+ * Write the comments
+ */
+ for (n = 0; n < comments->ncomment; n++)
+ {
+ if (!_XcursorWriteComment (file, fileHeader, toc, comments->comments[n]))
+ goto bail;
+ toc++;
+ }
+
+ _XcursorFileHeaderDestroy (fileHeader);
+ return XcursorTrue;
+bail:
+ _XcursorFileHeaderDestroy (fileHeader);
+ return XcursorFalse;
+}
+
+static int
+_XcursorStdioFileRead (XcursorFile *file, unsigned char *buf, int len)
+{
+ FILE *f = file->closure;
+ return fread (buf, 1, len, f);
+}
+
+static int
+_XcursorStdioFileWrite (XcursorFile *file, unsigned char *buf, int len)
+{
+ FILE *f = file->closure;
+ return fwrite (buf, 1, len, f);
+}
+
+static int
+_XcursorStdioFileSeek (XcursorFile *file, long offset, int whence)
+{
+ FILE *f = file->closure;
+ return fseek (f, offset, whence);
+}
+
+static void
+_XcursorStdioFileInitialize (FILE *stdfile, XcursorFile *file)
+{
+ file->closure = stdfile;
+ file->read = _XcursorStdioFileRead;
+ file->write = _XcursorStdioFileWrite;
+ file->seek = _XcursorStdioFileSeek;
+}
+
+XcursorImage *
+XcursorFileLoadImage (FILE *file, int size)
+{
+ XcursorFile f;
+
+ if (!file)
+ return NULL;
+
+ _XcursorStdioFileInitialize (file, &f);
+ return XcursorXcFileLoadImage (&f, size);
+}
+
+XcursorImages *
+XcursorFileLoadImages (FILE *file, int size)
+{
+ XcursorFile f;
+
+ if (!file)
+ return NULL;
+
+ _XcursorStdioFileInitialize (file, &f);
+ return XcursorXcFileLoadImages (&f, size);
+}
+
+XcursorImages *
+XcursorFileLoadAllImages (FILE *file)
+{
+ XcursorFile f;
+
+ if (!file)
+ return NULL;
+
+ _XcursorStdioFileInitialize (file, &f);
+ return XcursorXcFileLoadAllImages (&f);
+}
+
+XcursorBool
+XcursorFileLoad (FILE *file,
+ XcursorComments **commentsp,
+ XcursorImages **imagesp)
+{
+ XcursorFile f;
+
+ if (!file || !commentsp || !imagesp)
+ return XcursorFalse;
+
+ _XcursorStdioFileInitialize (file, &f);
+ return XcursorXcFileLoad (&f, commentsp, imagesp);
+}
+
+XcursorBool
+XcursorFileSaveImages (FILE *file, const XcursorImages *images)
+{
+ XcursorComments *comments;
+ XcursorFile f;
+ XcursorBool ret;
+
+ if (!file || !images)
+ return 0;
+ if ((comments = XcursorCommentsCreate (0)) == NULL)
+ return 0;
+ _XcursorStdioFileInitialize (file, &f);
+ ret = XcursorXcFileSave (&f, comments, images) && fflush (file) != EOF;
+ XcursorCommentsDestroy (comments);
+ return ret;
+}
+
+XcursorBool
+XcursorFileSave (FILE * file,
+ const XcursorComments *comments,
+ const XcursorImages *images)
+{
+ XcursorFile f;
+
+ if (!file || !comments || !images)
+ return XcursorFalse;
+
+ _XcursorStdioFileInitialize (file, &f);
+ return XcursorXcFileSave (&f, comments, images) && fflush (file) != EOF;
+}
+
+XcursorImage *
+XcursorFilenameLoadImage (const char *file, int size)
+{
+ FILE *f;
+ XcursorImage *image;
+
+ if (!file || size < 0)
+ return NULL;
+
+ f = fopen (file, "r");
+ if (!f)
+ return NULL;
+ image = XcursorFileLoadImage (f, size);
+ fclose (f);
+ return image;
+}
+
+XcursorImages *
+XcursorFilenameLoadImages (const char *file, int size)
+{
+ FILE *f;
+ XcursorImages *images;
+
+ if (!file || size < 0)
+ return NULL;
+
+ f = fopen (file, "r");
+ if (!f)
+ return NULL;
+ images = XcursorFileLoadImages (f, size);
+ fclose (f);
+ return images;
+}
+
+XcursorImages *
+XcursorFilenameLoadAllImages (const char *file)
+{
+ FILE *f;
+ XcursorImages *images;
+
+ if (!file)
+ return NULL;
+
+ f = fopen (file, "r");
+ if (!f)
+ return NULL;
+ images = XcursorFileLoadAllImages (f);
+ fclose (f);
+ return images;
+}
+
+XcursorBool
+XcursorFilenameLoad (const char *file,
+ XcursorComments **commentsp,
+ XcursorImages **imagesp)
+{
+ FILE *f;
+ XcursorBool ret;
+
+ if (!file)
+ return XcursorFalse;
+
+ f = fopen (file, "r");
+ if (!f)
+ return 0;
+ ret = XcursorFileLoad (f, commentsp, imagesp);
+ fclose (f);
+ return ret;
+}
+
+XcursorBool
+XcursorFilenameSaveImages (const char *file, const XcursorImages *images)
+{
+ FILE *f;
+ XcursorBool ret;
+
+ if (!file || !images)
+ return XcursorFalse;
+
+ f = fopen (file, "w");
+ if (!f)
+ return 0;
+ ret = XcursorFileSaveImages (f, images);
+ return fclose (f) != EOF && ret;
+}
+
+XcursorBool
+XcursorFilenameSave (const char *file,
+ const XcursorComments *comments,
+ const XcursorImages *images)
+{
+ FILE *f;
+ XcursorBool ret;
+
+ if (!file || !comments || !images)
+ return XcursorFalse;
+
+ f = fopen (file, "w");
+ if (!f)
+ return 0;
+ ret = XcursorFileSave (f, comments, images);
+ return fclose (f) != EOF && ret;
+}
--- /dev/null
+/*
+ * Copyright © 2002 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "xcursorint.h"
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef ICONDIR
+#define ICONDIR "/usr/X11R6/lib/X11/icons"
+#endif
+
+#ifndef XCURSORPATH
+#define XCURSORPATH "~/.icons:/usr/share/icons:/usr/share/pixmaps:"ICONDIR
+#endif
+
+const char *
+XcursorLibraryPath (void)
+{
+ static const char *path;
+
+ if (!path)
+ {
+ path = getenv ("XCURSOR_PATH");
+ if (!path)
+ path = XCURSORPATH;
+ }
+ return path;
+}
+
+static void
+_XcursorAddPathElt (char *path, const char *elt, int len)
+{
+ int pathlen = strlen (path);
+
+ /* append / if the path doesn't currently have one */
+ if (path[0] == '\0' || path[pathlen - 1] != '/')
+ {
+ strcat (path, "/");
+ pathlen++;
+ }
+ if (len == -1)
+ len = strlen (elt);
+ /* strip leading slashes */
+ while (len && elt[0] == '/')
+ {
+ elt++;
+ len--;
+ }
+ strncpy (path + pathlen, elt, len);
+ path[pathlen + len] = '\0';
+}
+
+static char *
+_XcursorBuildThemeDir (const char *dir, const char *theme)
+{
+ const char *colon;
+ const char *tcolon;
+ char *full;
+ char *home;
+ int dirlen;
+ int homelen;
+ int themelen;
+ int len;
+
+ if (!dir || !theme)
+ return NULL;
+
+ colon = strchr (dir, ':');
+ if (!colon)
+ colon = dir + strlen (dir);
+
+ dirlen = colon - dir;
+
+ tcolon = strchr (theme, ':');
+ if (!tcolon)
+ tcolon = theme + strlen (theme);
+
+ themelen = tcolon - theme;
+
+ home = NULL;
+ homelen = 0;
+ if (*dir == '~')
+ {
+ home = getenv ("HOME");
+ if (!home)
+ return NULL;
+ homelen = strlen (home);
+ dir++;
+ dirlen--;
+ }
+
+ /*
+ * add space for any needed directory separators, one per component,
+ * and one for the trailing null
+ */
+ len = 1 + homelen + 1 + dirlen + 1 + themelen + 1;
+
+ full = malloc (len);
+ if (!full)
+ return NULL;
+ full[0] = '\0';
+
+ if (home)
+ _XcursorAddPathElt (full, home, -1);
+ _XcursorAddPathElt (full, dir, dirlen);
+ _XcursorAddPathElt (full, theme, themelen);
+ return full;
+}
+
+static char *
+_XcursorBuildFullname (const char *dir, const char *subdir, const char *file)
+{
+ char *full;
+
+ if (!dir || !subdir || !file)
+ return NULL;
+
+ full = malloc (strlen (dir) + 1 + strlen (subdir) + 1 + strlen (file) + 1);
+ if (!full)
+ return NULL;
+ full[0] = '\0';
+ _XcursorAddPathElt (full, dir, -1);
+ _XcursorAddPathElt (full, subdir, -1);
+ _XcursorAddPathElt (full, file, -1);
+ return full;
+}
+
+static const char *
+_XcursorNextPath (const char *path)
+{
+ char *colon = strchr (path, ':');
+
+ if (!colon)
+ return NULL;
+ return colon + 1;
+}
+
+#define XcursorWhite(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
+#define XcursorSep(c) ((c) == ';' || (c) == ',')
+
+static char *
+_XcursorThemeInherits (const char *full)
+{
+ char line[8192];
+ char *result = NULL;
+ FILE *f;
+
+ if (!full)
+ return NULL;
+
+ f = fopen (full, "r");
+ if (f)
+ {
+ while (fgets (line, sizeof (line), f))
+ {
+ if (!strncmp (line, "Inherits", 8))
+ {
+ char *l = line + 8;
+ char *r;
+ while (*l == ' ') l++;
+ if (*l != '=') continue;
+ l++;
+ while (*l == ' ') l++;
+ result = malloc (strlen (l));
+ if (result)
+ {
+ r = result;
+ while (*l)
+ {
+ while (XcursorSep(*l) || XcursorWhite (*l)) l++;
+ if (!*l)
+ break;
+ if (r != result)
+ *r++ = ':';
+ while (*l && !XcursorWhite(*l) &&
+ !XcursorSep(*l))
+ *r++ = *l++;
+ }
+ *r++ = '\0';
+ }
+ break;
+ }
+ }
+ fclose (f);
+ }
+ return result;
+}
+
+#define XCURSOR_SCAN_CORE ((FILE *) 1)
+
+static FILE *
+XcursorScanTheme (const char *theme, const char *name)
+{
+ FILE *f = NULL;
+ char *full;
+ char *dir;
+ const char *path;
+ char *inherits = NULL;
+ const char *i;
+
+ if (!theme || !name)
+ return NULL;
+
+ /*
+ * XCURSOR_CORE_THEME is a magic name; cursors from the core set
+ * are never found in any directory. Instead, a magic value is
+ * returned which truncates any search so that overlying functions
+ * can switch to equivalent core cursors
+ */
+ if (!strcmp (theme, XCURSOR_CORE_THEME) && XcursorLibraryShape (name) >= 0)
+ return XCURSOR_SCAN_CORE;
+ /*
+ * Scan this theme
+ */
+ for (path = XcursorLibraryPath ();
+ path && f == NULL;
+ path = _XcursorNextPath (path))
+ {
+ dir = _XcursorBuildThemeDir (path, theme);
+ if (dir)
+ {
+ full = _XcursorBuildFullname (dir, "cursors", name);
+ if (full)
+ {
+ f = fopen (full, "r");
+ free (full);
+ }
+ if (!f && !inherits)
+ {
+ full = _XcursorBuildFullname (dir, "", "index.theme");
+ if (full)
+ {
+ inherits = _XcursorThemeInherits (full);
+ free (full);
+ }
+ }
+ free (dir);
+ }
+ }
+ /*
+ * Recurse to scan inherited themes
+ */
+ for (i = inherits; i && f == NULL; i = _XcursorNextPath (i))
+ f = XcursorScanTheme (i, name);
+ if (inherits != NULL)
+ free (inherits);
+ return f;
+}
+
+XcursorImage *
+XcursorLibraryLoadImage (const char *file, const char *theme, int size)
+{
+ FILE *f = NULL;
+ XcursorImage *image = NULL;
+
+ if (!file)
+ return NULL;
+
+ if (theme)
+ f = XcursorScanTheme (theme, file);
+ if (!f)
+ f = XcursorScanTheme ("default", file);
+ if (f == XCURSOR_SCAN_CORE)
+ return NULL;
+ if (f)
+ {
+ image = XcursorFileLoadImage (f, size);
+ fclose (f);
+ }
+ return image;
+}
+
+XcursorImages *
+XcursorLibraryLoadImages (const char *file, const char *theme, int size)
+{
+ FILE *f = NULL;
+ XcursorImages *images = NULL;
+
+ if (!file)
+ return NULL;
+
+ if (theme)
+ f = XcursorScanTheme (theme, file);
+ if (!f)
+ f = XcursorScanTheme ("default", file);
+ if (f == XCURSOR_SCAN_CORE)
+ return NULL;
+ if (f)
+ {
+ images = XcursorFileLoadImages (f, size);
+ if (images)
+ XcursorImagesSetName (images, file);
+ fclose (f);
+ }
+ return images;
+}
+
+Cursor
+XcursorLibraryLoadCursor (Display *dpy, const char *file)
+{
+ int size = XcursorGetDefaultSize (dpy);
+ char *theme = XcursorGetTheme (dpy);
+ XcursorImages *images = XcursorLibraryLoadImages (file, theme, size);
+ Cursor cursor;
+
+ if (!file)
+ return 0;
+
+ if (!images)
+ {
+ int id = XcursorLibraryShape (file);
+
+ if (id >= 0)
+ return _XcursorCreateFontCursor (dpy, id);
+ else
+ return 0;
+ }
+ cursor = XcursorImagesLoadCursor (dpy, images);
+ XcursorImagesDestroy (images);
+#if defined HAVE_XFIXES && XFIXES_MAJOR >= 2
+ XFixesSetCursorName (dpy, cursor, file);
+#endif
+ return cursor;
+}
+
+XcursorCursors *
+XcursorLibraryLoadCursors (Display *dpy, const char *file)
+{
+ int size = XcursorGetDefaultSize (dpy);
+ char *theme = XcursorGetTheme (dpy);
+ XcursorImages *images = XcursorLibraryLoadImages (file, theme, size);
+ XcursorCursors *cursors;
+
+ if (!file)
+ return NULL;
+
+ if (!images)
+ {
+ int id = XcursorLibraryShape (file);
+
+ if (id >= 0)
+ {
+ cursors = XcursorCursorsCreate (dpy, 1);
+ if (cursors)
+ {
+ cursors->cursors[0] = _XcursorCreateFontCursor (dpy, id);
+ if (cursors->cursors[0] == None)
+ {
+ XcursorCursorsDestroy (cursors);
+ cursors = NULL;
+ }
+ else
+ cursors->ncursor = 1;
+ }
+ }
+ else
+ cursors = NULL;
+ }
+ else
+ {
+ cursors = XcursorImagesLoadCursors (dpy, images);
+ XcursorImagesDestroy (images);
+ }
+ return cursors;
+}
+
+static const char _XcursorStandardNames[] =
+ "X_cursor\0"
+ "arrow\0"
+ "based_arrow_down\0"
+ "based_arrow_up\0"
+ "boat\0"
+ "bogosity\0"
+ "bottom_left_corner\0"
+ "bottom_right_corner\0"
+ "bottom_side\0"
+ "bottom_tee\0"
+ "box_spiral\0"
+ "center_ptr\0"
+ "circle\0"
+ "clock\0"
+ "coffee_mug\0"
+ "cross\0"
+ "cross_reverse\0"
+ "crosshair\0"
+ "diamond_cross\0"
+ "dot\0"
+ "dotbox\0"
+ "double_arrow\0"
+ "draft_large\0"
+ "draft_small\0"
+ "draped_box\0"
+ "exchange\0"
+ "fleur\0"
+ "gobbler\0"
+ "gumby\0"
+ "hand1\0"
+ "hand2\0"
+ "heart\0"
+ "icon\0"
+ "iron_cross\0"
+ "left_ptr\0"
+ "left_side\0"
+ "left_tee\0"
+ "leftbutton\0"
+ "ll_angle\0"
+ "lr_angle\0"
+ "man\0"
+ "middlebutton\0"
+ "mouse\0"
+ "pencil\0"
+ "pirate\0"
+ "plus\0"
+ "question_arrow\0"
+ "right_ptr\0"
+ "right_side\0"
+ "right_tee\0"
+ "rightbutton\0"
+ "rtl_logo\0"
+ "sailboat\0"
+ "sb_down_arrow\0"
+ "sb_h_double_arrow\0"
+ "sb_left_arrow\0"
+ "sb_right_arrow\0"
+ "sb_up_arrow\0"
+ "sb_v_double_arrow\0"
+ "shuttle\0"
+ "sizing\0"
+ "spider\0"
+ "spraycan\0"
+ "star\0"
+ "target\0"
+ "tcross\0"
+ "top_left_arrow\0"
+ "top_left_corner\0"
+ "top_right_corner\0"
+ "top_side\0"
+ "top_tee\0"
+ "trek\0"
+ "ul_angle\0"
+ "umbrella\0"
+ "ur_angle\0"
+ "watch\0"
+ "xterm";
+
+static const unsigned short _XcursorStandardNameOffsets[] = {
+ 0, 9, 15, 32, 47, 52, 61, 80, 100, 112, 123, 134, 145, 152, 158,
+ 169, 175, 189, 199, 213, 217, 224, 237, 249, 261, 272, 281, 287,
+ 295, 301, 307, 313, 319, 324, 335, 344, 354, 363, 374, 383, 392,
+ 396, 409, 415, 422, 429, 434, 449, 459, 470, 480, 492, 501, 510,
+ 524, 542, 556, 571, 583, 601, 609, 616, 623, 632, 637, 644, 651,
+ 666, 682, 699, 708, 716, 721, 730, 739, 748, 754
+};
+
+#define NUM_STANDARD_NAMES (sizeof _XcursorStandardNameOffsets / sizeof _XcursorStandardNameOffsets[0])
+
+#define STANDARD_NAME(id) \
+ _XcursorStandardNames + _XcursorStandardNameOffsets[id]
+
+XcursorImage *
+XcursorShapeLoadImage (unsigned int shape, const char *theme, int size)
+{
+ unsigned int id = shape >> 1;
+
+ if (id < NUM_STANDARD_NAMES)
+ return XcursorLibraryLoadImage (STANDARD_NAME (id), theme, size);
+ else
+ return NULL;
+}
+
+XcursorImages *
+XcursorShapeLoadImages (unsigned int shape, const char *theme, int size)
+{
+ unsigned int id = shape >> 1;
+
+ if (id < NUM_STANDARD_NAMES)
+ return XcursorLibraryLoadImages (STANDARD_NAME (id), theme, size);
+ else
+ return NULL;
+}
+
+Cursor
+XcursorShapeLoadCursor (Display *dpy, unsigned int shape)
+{
+ unsigned int id = shape >> 1;
+
+ if (id < NUM_STANDARD_NAMES)
+ return XcursorLibraryLoadCursor (dpy, STANDARD_NAME (id));
+ else
+ return 0;
+}
+
+XcursorCursors *
+XcursorShapeLoadCursors (Display *dpy, unsigned int shape)
+{
+ unsigned int id = shape >> 1;
+
+ if (id < NUM_STANDARD_NAMES)
+ return XcursorLibraryLoadCursors (dpy, STANDARD_NAME (id));
+ else
+ return NULL;
+}
+
+int
+XcursorLibraryShape (const char *library)
+{
+ int low, high;
+ int mid;
+ int c;
+
+ low = 0;
+ high = NUM_STANDARD_NAMES - 1;
+ while (low < high - 1)
+ {
+ mid = (low + high) >> 1;
+ c = strcmp (library, STANDARD_NAME (mid));
+ if (c == 0)
+ return (mid << 1);
+ if (c > 0)
+ low = mid;
+ else
+ high = mid;
+ }
+ while (low <= high)
+ {
+ if (!strcmp (library, STANDARD_NAME (low)))
+ return (low << 1);
+ low++;
+ }
+ return -1;
+}
--- /dev/null
+/*
+ * Copyright © 2002 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _XCURSORINT_H_
+#define _XCURSORINT_H_
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/cursorfont.h>
+#include <X11/extensions/Xrender.h>
+
+#ifdef HAVE_XFIXES
+#include <X11/extensions/Xfixes.h>
+#endif
+
+#include "Xcursor.h"
+#include "config.h"
+
+typedef struct _XcursorFontInfo {
+ struct _XcursorFontInfo *next;
+ Font font;
+ XcursorBool is_cursor_font;
+} XcursorFontInfo;
+
+/*
+ * Track a few recently created bitmaps to see
+ * if they get used to create cursors. This
+ * is done by hooking into Xlib and watching
+ * for XCreatePixmap, XPutImage, XCreatePixmapCursor
+ * with appropriate arguments. When this happens
+ * Xcursor computes a hash value for the source image
+ * and tries to load a library cursor of that name.
+ */
+
+/* large bitmaps are unlikely to be cursors */
+#define MAX_BITMAP_CURSOR_SIZE 64
+/* don't need to remember very many; in fact, 2 is likely sufficient */
+#define NUM_BITMAPS 8
+
+typedef struct _XcursorBitmapInfo {
+ Pixmap bitmap;
+ unsigned long sequence;
+ unsigned int width, height;
+ Bool has_image;
+ unsigned char hash[XCURSOR_BITMAP_HASH_SIZE];
+} XcursorBitmapInfo;
+
+typedef enum _XcursorDither {
+ XcursorDitherThreshold,
+ XcursorDitherMedian,
+ XcursorDitherOrdered,
+ XcursorDitherDiffuse
+} XcursorDither;
+
+typedef struct _XcursorDisplayInfo {
+ struct _XcursorDisplayInfo *next;
+ Display *display;
+ XExtCodes *codes;
+ XcursorBool has_render_cursor;
+ XcursorBool has_anim_cursor;
+ XcursorBool theme_core;
+ int size;
+ XcursorFontInfo *fonts;
+ char *theme;
+ char *theme_from_config;
+ XcursorDither dither;
+ XcursorBitmapInfo bitmaps[NUM_BITMAPS];
+} XcursorDisplayInfo;
+
+XcursorDisplayInfo *
+_XcursorGetDisplayInfo (Display *dpy);
+
+Cursor
+_XcursorCreateGlyphCursor(Display *dpy,
+ Font source_font,
+ Font mask_font,
+ unsigned int source_char,
+ unsigned int mask_char,
+ XColor _Xconst *foreground,
+ XColor _Xconst *background);
+
+Cursor
+_XcursorCreateFontCursor (Display *dpy, unsigned int shape);
+
+#endif /* _XCURSORINT_H_ */
--- /dev/null
+/*
+ * Copyright © 2002 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "xcursorint.h"
+#include <X11/Xlibint.h>
+#include <X11/Xatom.h>
+#include <stdlib.h>
+
+static XcursorBool
+_XcursorFontIsCursor (Display *dpy, Font font)
+{
+ XcursorFontInfo *fi;
+ XcursorDisplayInfo *info;
+ XcursorBool ret;
+ XFontStruct *fs;
+ int n;
+ Atom cursor;
+
+ if (!dpy || !font)
+ return XcursorFalse;
+
+ if (font == dpy->cursor_font)
+ return XcursorTrue;
+
+ info = _XcursorGetDisplayInfo (dpy);
+ if (!info)
+ return XcursorFalse;
+ LockDisplay (dpy);
+ for (fi = info->fonts; fi; fi = fi->next)
+ if (fi->font == font)
+ {
+ ret = fi->is_cursor_font;
+ UnlockDisplay (dpy);
+ return ret;
+ }
+ UnlockDisplay (dpy);
+ ret = XcursorFalse;
+ fs = XQueryFont (dpy, font);
+ if (fs)
+ {
+ cursor = XInternAtom (dpy, "cursor", False);
+ for (n = 0; n < fs->n_properties; n++)
+ if (fs->properties[n].name == XA_FONT)
+ {
+ ret = (fs->properties[n].card32 == cursor);
+ break;
+ }
+ XFreeFontInfo (NULL, fs, 1);
+ }
+ fi = malloc (sizeof (XcursorFontInfo));
+ if (fi)
+ {
+ fi->font = font;
+ fi->is_cursor_font = ret;
+ LockDisplay (dpy);
+ fi->next = info->fonts;
+ info->fonts = fi;
+ UnlockDisplay (dpy);
+ }
+ return ret;
+}
+
+Cursor
+XcursorTryShapeCursor (Display *dpy,
+ Font source_font,
+ Font mask_font,
+ unsigned int source_char,
+ unsigned int mask_char,
+ XColor _Xconst *foreground,
+ XColor _Xconst *background)
+{
+ Cursor cursor = None;
+
+ if (!dpy || !source_font || !mask_font || !foreground || !background)
+ return 0;
+
+ if (!XcursorSupportsARGB (dpy) && !XcursorGetThemeCore (dpy))
+ return None;
+
+ if (source_font == mask_font &&
+ _XcursorFontIsCursor (dpy, source_font) &&
+ source_char + 1 == mask_char)
+ {
+ int size = XcursorGetDefaultSize (dpy);
+ char *theme = XcursorGetTheme (dpy);
+ XcursorImages *images = XcursorShapeLoadImages (source_char, theme, size);
+
+ if (images)
+ {
+ cursor = XcursorImagesLoadCursor (dpy, images);
+ XcursorImagesDestroy (images);
+ }
+ }
+ return cursor;
+}
+
+void
+XcursorNoticeCreateBitmap (Display *dpy,
+ Pixmap pid,
+ unsigned int width,
+ unsigned int height)
+{
+ XcursorDisplayInfo *info;
+ unsigned long oldest;
+ unsigned long now;
+ int i;
+ int replace = 0;
+ XcursorBitmapInfo *bmi;
+
+ if (!dpy)
+ return;
+
+ if (!XcursorSupportsARGB (dpy) && !XcursorGetThemeCore (dpy))
+ return;
+
+ if (width > MAX_BITMAP_CURSOR_SIZE || height > MAX_BITMAP_CURSOR_SIZE)
+ return;
+
+ info = _XcursorGetDisplayInfo (dpy);
+ if (!info)
+ return;
+
+ LockDisplay (dpy);
+ replace = 0;
+ now = dpy->request;
+ oldest = now;
+ for (i = 0; i < NUM_BITMAPS; i++)
+ {
+ if (!info->bitmaps[i].bitmap)
+ {
+ replace = i;
+ break;
+ }
+ if ((long) (now - info->bitmaps[i].sequence) >
+ (long) (now - oldest))
+ {
+ replace = i;
+ oldest = info->bitmaps[i].sequence;
+ }
+ }
+ bmi = &info->bitmaps[replace];
+ bmi->bitmap = pid;
+ bmi->sequence = now;
+ bmi->width = width;
+ bmi->height = height;
+ bmi->has_image = False;
+ UnlockDisplay (dpy);
+}
+
+static XcursorBitmapInfo *
+_XcursorGetBitmap (Display *dpy, Pixmap bitmap)
+{
+ XcursorDisplayInfo *info;
+ int i;
+
+ if (!dpy || !bitmap)
+ return NULL;
+
+ info = _XcursorGetDisplayInfo (dpy);
+
+ if (!info)
+ return NULL;
+ LockDisplay (dpy);
+ for (i = 0; i < NUM_BITMAPS; i++)
+ if (info->bitmaps[i].bitmap == bitmap)
+ {
+ info->bitmaps[i].sequence = dpy->request;
+ UnlockDisplay (dpy);
+ return &info->bitmaps[i];
+ }
+ UnlockDisplay (dpy);
+ return NULL;
+}
+
+static Bool
+_XcursorClientLSB (void)
+{
+ int v = 1;
+ return *((char *) &v) == 1;
+}
+
+/* stolen from Xlib */
+static unsigned char const _reverse_byte[0x100] = {
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+};
+
+#define RotByte(t,i) (((t) << (i)) | ((t) >> (8 - (i))))
+
+void
+XcursorImageHash (XImage *image,
+ unsigned char hash[XCURSOR_BITMAP_HASH_SIZE])
+{
+ int i;
+ int x, y;
+ unsigned char *line;
+ unsigned char t;
+ int low_addr;
+ Bool bit_swap;
+
+ if (!image)
+ return;
+
+ for (i = 0; i < XCURSOR_BITMAP_HASH_SIZE; i++)
+ hash[i] = 0;
+ /*
+ * Flip byte order on MSB machines where the bitmap_unit isn't
+ * in bytes
+ */
+ low_addr = 0;
+ if (image->bitmap_unit != 8)
+ {
+ if (!_XcursorClientLSB())
+ switch (image->bitmap_unit) {
+ case 16:
+ low_addr = 1;
+ break;
+ case 32:
+ low_addr = 3;
+ break;
+ }
+ }
+ /*
+ * Flip bit order on MSB images
+ */
+ bit_swap = (image->bitmap_bit_order != LSBFirst);
+
+ line = (unsigned char *) image->data;
+ i = 0;
+ /*
+ * Compute the hash. Yes, it might be nice to use
+ * a stronger hash function, but MD5 and SHA1 are both
+ * a bit to expensive in time and space for this,
+ * and cursors are generally small enough that a weak
+ * hash is sufficient to distinguish among them.
+ */
+ for (y = 0; y < image->height; y++)
+ {
+ for (x = 0; x < image->bytes_per_line; x++)
+ {
+ t = line[x^low_addr];
+ if (bit_swap)
+ t = _reverse_byte[t];
+ if (t)
+ hash[(i++) & (XCURSOR_BITMAP_HASH_SIZE - 1)] ^= RotByte (t, y & 7);
+ }
+ line += image->bytes_per_line;
+ }
+}
+
+static Bool
+_XcursorLogDiscover (void)
+{
+ static Bool been_here;
+ static Bool log;
+
+ if (!been_here)
+ {
+ been_here = True;
+
+ if (getenv ("XCURSOR_DISCOVER"))
+ log = True;
+ }
+ return log;
+}
+
+void
+XcursorNoticePutBitmap (Display *dpy,
+ Drawable draw,
+ XImage *image)
+{
+ XcursorBitmapInfo *bmi;
+
+ if (!dpy || !image)
+ return;
+
+ if (!XcursorSupportsARGB (dpy) && !XcursorGetThemeCore (dpy))
+ return;
+
+ if (image->width > MAX_BITMAP_CURSOR_SIZE ||
+ image->height > MAX_BITMAP_CURSOR_SIZE)
+ return;
+
+ bmi = _XcursorGetBitmap (dpy, (Pixmap) draw);
+ if (!bmi)
+ return;
+ /*
+ * Make sure the image fills the bitmap
+ */
+ if (image->width != bmi->width || image->height != bmi->height)
+ {
+ bmi->bitmap = 0;
+ return;
+ }
+ /*
+ * If multiple images are placed in the same bitmap,
+ * assume it's not going to be a cursor
+ */
+ if (bmi->has_image)
+ {
+ bmi->bitmap = 0;
+ return;
+ }
+ /*
+ * Make sure the image is valid
+ */
+ if (image->bytes_per_line & ((image->bitmap_unit >> 3) - 1))
+ {
+ bmi->bitmap = 0;
+ return;
+ }
+ /*
+ * Hash the image
+ */
+ XcursorImageHash (image, bmi->hash);
+ /*
+ * Display the hash value and the image if
+ * requested so that users can find out what
+ * cursor name is associated with each image
+ */
+ if (_XcursorLogDiscover())
+ {
+ int x, y;
+ int i;
+ XImage t = *image;
+
+ XInitImage (&t);
+
+ printf ("Cursor image name: ");
+ for (i = 0; i < XCURSOR_BITMAP_HASH_SIZE; i++)
+ printf ("%02x", bmi->hash[i]);
+ printf ("\n");
+ for (y = 0; y < image->height; y++)
+ {
+ for (x = 0; x < image->width; x++)
+ putchar (XGetPixel (&t, x, y) ? '*' : ' ');
+ putchar ('\n');
+ }
+ }
+ bmi->has_image = True;
+}
+
+Cursor
+XcursorTryShapeBitmapCursor (Display *dpy,
+ Pixmap source,
+ Pixmap mask,
+ XColor *foreground,
+ XColor *background,
+ unsigned int x,
+ unsigned int y)
+{
+ XcursorBitmapInfo *bmi;
+ char name[8 * XCURSOR_BITMAP_HASH_SIZE];
+ int i;
+ Cursor cursor;
+
+ if (!dpy || !foreground || !background)
+ return 0;
+
+ if (!XcursorSupportsARGB (dpy) && !XcursorGetThemeCore (dpy))
+ return None;
+
+ bmi = _XcursorGetBitmap (dpy, source);
+ if (!bmi || !bmi->has_image)
+ return None;
+ for (i = 0; i < XCURSOR_BITMAP_HASH_SIZE; i++)
+ sprintf (name + 2 * i, "%02x", bmi->hash[i]);
+ cursor = XcursorLibraryLoadCursor (dpy, name);
+ if (_XcursorLogDiscover())
+ printf ("Cursor hash %s returns 0x%x\n", name, (unsigned int) cursor);
+ return cursor;
+}
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@datarootdir@
+icondir=@ICONDIR@
+
+Name: Xcursor
+Description: X Cursor Library
+Version: @VERSION@
+Requires: xproto
+Requires.private: x11 xrender xfixes
+Cflags: -I${includedir}
+Libs: -L${libdir} -lXcursor