From: Sehong Na Date: Sat, 31 May 2014 03:46:04 +0000 (+0900) Subject: Initialize Tizen 2.3 X-Git-Tag: submit/tizen_2.3/20150202.065921 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Ftags%2Fsubmit%2Ftizen_2.3%2F20150202.065921;p=framework%2Fuifw%2Fxorg%2Flib%2Flibxcursor.git Initialize Tizen 2.3 --- cb507ca888032304660b13254bdb397e265ebe39 diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..57c4efd --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Keith Packard, HP + diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..8d01a81 --- /dev/null +++ b/COPYING @@ -0,0 +1,19 @@ +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. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..95b6b1a --- /dev/null +++ b/ChangeLog @@ -0,0 +1,801 @@ +commit 2a9eaf3305d1577ad763d56dddd46e10f8d0676b +Author: Alan Coopersmith +Date: Wed Mar 7 18:54:15 2012 -0800 + + libXcursor 1.1.13 + + Signed-off-by: Alan Coopersmith + +commit 8229cf75b34c2991eaf973f05326be9bfa16ef0c +Author: Alan Coopersmith +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 + Reviewed-by: Jeremy Huddleston + +commit 2b8d373bddf427bcd95e2595cb64740ebd1d0d30 +Author: Alan Coopersmith +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 + Reviewed-by: Jeremy Huddleston + +commit bcfb8e8ce56cf47bc6a61bd8c896bafba9e2a9c2 +Author: Jon TURNEY +Date: Thu Sep 22 14:43:38 2011 +0100 + + Add generated Xcursor.h to .gitignore + + Signed-off-by: Jon TURNEY + Reviewed-by: Gaetan Nadon + Tested-by: Gaetan Nadon + Reviewed-by: Alan Coopersmith + +commit 862b9ce4aa819bf87b6e24db9d7d5867cbaa577c +Author: Jon TURNEY +Date: Wed Sep 21 20:50:46 2011 +0100 + + Fix install of generated Xcursor.h when builddir != srcdir + + Signed-off-by: Jon TURNEY + Reviewed-by: Gaetan Nadon + Tested-by: Gaetan Nadon + Reviewed-by: Alan Coopersmith + +commit 334dc4f4df69d780f312f23b860df11bee5e9009 +Author: Alan Coopersmith +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 + Reviewed-by: Gaetan Nadon + +commit e086eb1bf49f2a8c270eaebd5beb595c1dc2973e +Author: Alan Coopersmith +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 + +commit d79ddc01e4b247ae95af3581b93aef2b93e76888 +Author: Alan Coopersmith +Date: Wed Jun 29 21:41:09 2011 -0700 + + libXcursor 1.1.12 + + Signed-off-by: Alan Coopersmith + +commit 4ce23fcd978ed389ea30315c0e02629a31bda265 +Author: Alan Coopersmith +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 + +commit 047993c76a677ca12a2b575990b99e3ddbc0dd58 +Author: Jeremy Huddleston +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 + +commit bee68e54e5c3a4b9f46c81366a720531e3e07a82 +Author: Chris Wilson +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 + +commit f49e7e1608f2dac140f60bcae21d5c37f79fc41b +Author: Chris Wilson +Date: Fri Apr 1 12:15:46 2011 +0100 + + Free the partial header after failing to open the cursor. + + Signed-off-by: Chris Wilson + +commit 073eb2c56f4794275eee40a825dbfe1232bb2690 +Author: Chris Wilson +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 + +commit de50317ec4e0e8da7de84e85d1f7a6d2e184d58b +Author: Gaetan Nadon +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 + +commit a929c3621b9da8e56ce1223afd3e487fc488fa47 +Author: Gaetan Nadon +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 + +commit 96c5877fd7ebc59569f140d9e2cb30fdb8371ef1 +Author: Gaetan Nadon +Date: Fri Jan 28 19:41:37 2011 -0500 + + config: replace deprecated AM_CONFIG_HEADER with AC_CONFIG_HEADERS + + Signed-off-by: Gaetan Nadon + +commit 4f7a749fcb7a8e93d40a7621fa1c159e003b2f5c +Author: Gaetan Nadon +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 + +commit c38adc6bf116146fa1e291b9f4deed45497e5c2e +Author: Gaetan Nadon +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 + +commit 731e84d79e83b59d022d0f453b245696b4d2750f +Author: Alan Coopersmith +Date: Wed Oct 27 22:48:19 2010 -0700 + + libXcursor 1.1.11 + + Signed-off-by: Alan Coopersmith + +commit 42b7717c32b3c7097180667a9ba2f62e40fc6506 +Author: Gaetan Nadon +Date: Mon Aug 16 19:28:57 2010 -0400 + + man: whitespace management + + Signed-off-by: Gaetan Nadon + +commit 862bc06d58152e74e85fc29db7eaec06af20e00b +Author: Gaetan Nadon +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 + +commit b18568dd5b5a11ae49cad66a54ec50465c6ffa77 +Author: Gaetan Nadon +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 + +commit 68d830bcf67632b474c8996b6a2c9bcde8e27f97 +Author: Gaetan Nadon +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 + +commit 0caadca51ca56a2ae2cfe67cbd2b29e89b6a68d8 +Author: Gaetan Nadon +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 + +commit b511b260ddcec34035c1d97285f27f3182663a6a +Author: Gaetan Nadon +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 + +commit a3e03bb23bf7a92bf20d51eebe692e0a4f667065 +Author: Gaetan Nadon +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 + +commit 8198d1490959d49573790405e205a471ac7a5b98 +Author: Gaetan Nadon +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 +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 +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 +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 +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 +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 + +commit fbf229879370a96a070ebf087426f6f6c0dbe5a2 +Author: Peter Hutterer +Date: Fri Aug 28 14:49:15 2009 +1000 + + libXcursor 1.1.10 + + Signed-off-by: Peter Hutterer + +commit 59e3f6520f4d1682d3242d1d5656e7972cf11944 +Author: Alan Coopersmith +Date: Mon Feb 2 20:34:32 2009 -0800 + + Add README with pointers to mailing list, bugzilla & git repos + + Signed-off-by: Alan Coopersmith + +commit f00ae32322d2b3c5d97724b80c72d3e2d0812935 +Author: Paulo Cesar Pereira de Andrade +Date: Thu Jan 29 15:34:11 2009 -0200 + + Janitor: make distcheck, compiler warnings, extra .gitignore files. + +commit 04641d3cc3e2f7389c5a3ea6e1d55543e033153f +Author: Matthieu Herrb +Date: Sun Mar 9 00:34:36 2008 +0100 + + nuke RCS Ids + +commit 94531dc8f6eff9c9f5cbb18ca6b3d4ff79eec752 +Author: James Cloos +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 +Date: Fri Aug 24 14:01:07 2007 -0700 + + Version bump: 1.1.9 + +commit 5a2601740d04d4180e77695c4b60f2cf5c84be6c +Author: Alan Coopersmith +Date: Wed Aug 22 19:40:55 2007 -0700 + + Make shadow man pages for each function + +commit fef474da694ea3c1fd184d93cc07bf8d95f89327 +Author: Alan Coopersmith +Date: Tue Aug 21 19:45:35 2007 -0700 + + Add XCURSOR_PATH to man page + +commit a9ccf1bd91ad6e06f7b7116efe836c365b68645b +Author: Alan Coopersmith +Date: Tue Aug 21 19:33:00 2007 -0700 + + Use cursorpath found by configure in man page + +commit 110131bd40d0fc042f4a81922372307a1582b591 +Author: Tilman Sauerbeck +Date: Sat May 12 22:42:08 2007 +0200 + + Added object files to .gitignore. + +commit 3c5d4f591ce0b473af9f693cfe25a1506cc573d6 +Author: Tilman Sauerbeck +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 +Date: Fri Oct 13 16:01:17 2006 -0400 + + Bump to 1.1.8 + +commit 9df9640643fae7b922b18ee219d6d9694345df14 +Author: Alan Coopersmith +Date: Tue Oct 10 14:57:16 2006 -0700 + + Fix many sparse warnings: Using plain integer as NULL pointer + +commit b6b9f5885566e4c2df8e3319fe092c22f319983f +Author: Alan Coopersmith +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 +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 +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 +Date: Fri Oct 6 16:22:52 2006 -0700 + + Xcursor.man formatting cleanups + +commit 3c5f5860d6f85230f417ce6af30fc73ab75c437b +Author: Bart Massey +Date: Tue Sep 12 09:02:54 2006 -0700 + + Added missing dependency + +commit c7d048dacf3fce6f3121cf0114fd08bb130130b8 +Author: Alan Coopersmith +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 +Date: Thu Aug 24 18:42:36 2006 -0700 + + Add *~ to .gitignore to skip over emacs droppings + +commit c7886900f180da2c460d0a5926daee787e7258ea +Author: Alan Coopersmith +Date: Thu Aug 24 18:42:03 2006 -0700 + + Man page typo fixes (pimaps, directorys) + +commit e0a501e91c270c0e99a55aa568f6df0d3d6e541d +Author: Chris Wilson +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 +Date: Thu Jul 13 14:58:50 2006 -0700 + + renamed: .cvsignore -> .gitignore + +commit c6f65af419d14a753459a71a671baafd84fa1330 +Author: Daniel Stone +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 +Date: Thu Apr 27 17:26:28 2006 +0000 + + Look for cursors in datadir, not always /usr/share. + +commit 3c69a6ef12aa43d5c9cc5cfbd76c6bea1fa2bd00 +Author: Adam Jackson +Date: Thu Apr 27 00:04:48 2006 +0000 + + Bump to 1.1.6 + +commit f9bc007d71f58db93b7eadeb8c77d0f90379c620 +Author: Adam Jackson +Date: Fri Apr 7 00:58:59 2006 +0000 + + Coverity #159: Prevent a possible NULL chase. + +commit 1f862e619f12b54bee2efbb66f77c750184b191f +Author: Daniel Stone +Date: Sat Mar 4 21:00:40 2006 +0000 + + Bug #4439: Include Xlib.h. + +commit 461b3c5c0e47eed1b4abf5189ba92bb70d700fa1 +Author: Kevin E Martin +Date: Thu Dec 15 00:24:29 2005 +0000 + + Update package version number for final X11R7 release candidate. + +commit aed42762a9fcfcf1b7729dc0a7014ea679d309eb +Author: Kevin E Martin +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 +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 +Date: Thu Dec 8 17:54:40 2005 +0000 + + Allow hard-coded paths to be configurable. + +commit af09e8d8edb7d68367399336ca3163df4c713ffa +Author: Kevin E Martin +Date: Tue Dec 6 22:48:42 2005 +0000 + + Change *man_SOURCES ==> *man_PRE to fix autotools warnings. + +commit 47043f5e93df6a806bf298eca309e05159c271df +Author: Kevin E Martin +Date: Sat Dec 3 05:49:43 2005 +0000 + + Update package version number for X11R7 RC3 release. + +commit a3ddd7c6aa895dd373a73957f0b18181d7f8f486 +Author: Alan Coopersmith +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 +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 +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 +Date: Wed Nov 9 21:31:19 2005 +0000 + + Bump version numbers for X11R6.9/X11R7 RC2. + +commit c0773eea4b50162ae0b9b624a46079e71b8e49c2 +Author: Kevin E Martin +Date: Wed Nov 9 21:19:12 2005 +0000 + + Update package version number for X11R7 RC2 release. + +commit 345cf369206f0a2a03e842a108bd8f068da36d3f +Author: Kevin E Martin +Date: Tue Nov 1 15:11:51 2005 +0000 + + Update pkgcheck dependencies to work with separate build roots. + +commit 7c7bdccde9d2208a9330099e3cd21060c60638be +Author: Adam Jackson +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 +Date: Wed Oct 19 02:48:09 2005 +0000 + + Update package version number for RC1 release. + +commit b1bc7d7328ff2741e1c13151799422fee9e6d0cd +Author: Alan Coopersmith +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 +Date: Tue Oct 11 01:37:44 2005 +0000 + + Define HAVE_XFIXES + +commit 7a5e36017905a3b7fe70362dc9712654c816c6a5 +Author: Adam Jackson +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 +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 +Date: Sat Jul 16 06:35:32 2005 +0000 + + Change soversion to 1.0.2 with -version-number. + +commit 9ffefcd641352900f9bf7cb06cbe04e91714b490 +Author: Keith Packard +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 +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 +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 or , 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 + . + +commit c010a3f076b2f93e2baf4a9472bf5f132266d2db +Author: Eric Anholt +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 +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 +Date: Wed Jun 29 18:46:53 2005 +0000 + + Import Xcursor 1.1.4 from freedesktop.org xlibs tree. + +commit e67de73f5ca7ae854c18fa1500c8eaf412b44c6c +Author: Daniel Stone +Date: Mon Jun 13 16:44:53 2005 +0000 + + Bug #1043: Fix leak when creating animated cursors. + +commit 89e52cde6eaf5e2d46198ee2fa16b67ef7e1dd32 +Author: Søren Sandmann Pedersen +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 +Date: Wed Jun 8 20:44:18 2005 +0000 + + Remove all the not found with pkgconfig stuff + +commit 4070c0af6c7bfe12218181d56e8e3cbb86006d27 +Author: Søren Sandmann Pedersen +Date: Wed Jun 8 19:15:43 2005 +0000 + + - Add Xcursor build system + +commit 50911b052ce90d41cd0ae71f83352ffa45e7c0a4 +Author: Markus Kuhn +Date: Sat Dec 4 00:42:47 2004 +0000 + + Encoding of numerous files changed to UTF-8 + +commit cbcf471d9157c88a506cd3f067253c8e64cb8e08 +Author: Egbert Eich +Date: Fri Apr 23 18:43:40 2004 +0000 + + Merging XORG-CURRENT into trunk + +commit fb1739bd2272fa45d9c04fe40517468a49660b37 +Author: Egbert Eich +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 +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 +Date: Thu Feb 26 13:35:32 2004 +0000 + + readding XFree86's cvs IDs + +commit 79b8e8b996311665ae1fc8fa7e7d38270b3d9570 +Author: Egbert Eich +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 +Date: Thu Dec 4 22:02:56 2003 +0000 + + XFree86 4.3.99.901 (RC 1) + +commit 969878fc6fed5e43b4f7e2e3ee46835d93d30dfd +Author: Kaleb Keithley +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 +Date: Fri Nov 14 16:48:48 2003 +0000 + + XFree86 4.3.0.1 + +commit 3b84b14bf06840d5cd446f2aba495108d23d66d7 +Author: Kaleb Keithley +Date: Fri Nov 14 16:48:48 2003 +0000 + + Initial revision diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..8b82ade --- /dev/null +++ b/INSTALL @@ -0,0 +1,291 @@ +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 `' 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. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..e67a693 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,45 @@ +# +# 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 diff --git a/README b/README new file mode 100644 index 0000000..a60d8fe --- /dev/null +++ b/README @@ -0,0 +1,25 @@ +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 + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..16c753b --- /dev/null +++ b/configure.ac @@ -0,0 +1,89 @@ +# +# 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=], + [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=], + [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 diff --git a/include/X11/Xcursor/Xcursor.h b/include/X11/Xcursor/Xcursor.h new file mode 100644 index 0000000..d0cae62 --- /dev/null +++ b/include/X11/Xcursor/Xcursor.h @@ -0,0 +1,500 @@ +/* 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 +#include +#include + +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 + * + * + * + * 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 diff --git a/include/X11/Xcursor/Xcursor.h.in b/include/X11/Xcursor/Xcursor.h.in new file mode 100644 index 0000000..1a14386 --- /dev/null +++ b/include/X11/Xcursor/Xcursor.h.in @@ -0,0 +1,499 @@ +/* + * 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 +#include +#include + +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 + * + * + * + * 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 diff --git a/man/Makefile.am b/man/Makefile.am new file mode 100644 index 0000000..f3f4599 --- /dev/null +++ b/man/Makefile.am @@ -0,0 +1,53 @@ +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) < $< > $@ diff --git a/man/Xcursor.man b/man/Xcursor.man new file mode 100644 index 0000000..4f01c7e --- /dev/null +++ b/man/Xcursor.man @@ -0,0 +1,384 @@ +.\" +.\" 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 +.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 diff --git a/man/XcursorCursorsCreate.man b/man/XcursorCursorsCreate.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorCursorsCreate.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorCursorsDestroy.man b/man/XcursorCursorsDestroy.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorCursorsDestroy.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorFilenameLoad.man b/man/XcursorFilenameLoad.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorFilenameLoad.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorFilenameLoadAllImages.man b/man/XcursorFilenameLoadAllImages.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorFilenameLoadAllImages.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorFilenameLoadCursor.man b/man/XcursorFilenameLoadCursor.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorFilenameLoadCursor.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorFilenameLoadImage.man b/man/XcursorFilenameLoadImage.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorFilenameLoadImage.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorFilenameLoadImages.man b/man/XcursorFilenameLoadImages.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorFilenameLoadImages.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorFilenameSave.man b/man/XcursorFilenameSave.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorFilenameSave.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorFilenameSaveImages.man b/man/XcursorFilenameSaveImages.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorFilenameSaveImages.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorGetDefaultSize.man b/man/XcursorGetDefaultSize.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorGetDefaultSize.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorGetTheme.man b/man/XcursorGetTheme.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorGetTheme.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorImageCreate.man b/man/XcursorImageCreate.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorImageCreate.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorImageDestroy.man b/man/XcursorImageDestroy.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorImageDestroy.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorImagesCreate.man b/man/XcursorImagesCreate.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorImagesCreate.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorImagesDestroy.man b/man/XcursorImagesDestroy.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorImagesDestroy.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorLibraryLoadCursor.man b/man/XcursorLibraryLoadCursor.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorLibraryLoadCursor.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorLibraryLoadCursors.man b/man/XcursorLibraryLoadCursors.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorLibraryLoadCursors.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorLibraryLoadImage.man b/man/XcursorLibraryLoadImage.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorLibraryLoadImage.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorLibraryLoadImages.man b/man/XcursorLibraryLoadImages.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorLibraryLoadImages.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorSetDefaultSize.man b/man/XcursorSetDefaultSize.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorSetDefaultSize.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorSetTheme.man b/man/XcursorSetTheme.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorSetTheme.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorShapeLoadCursor.man b/man/XcursorShapeLoadCursor.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorShapeLoadCursor.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorShapeLoadCursors.man b/man/XcursorShapeLoadCursors.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorShapeLoadCursors.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorShapeLoadImage.man b/man/XcursorShapeLoadImage.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorShapeLoadImage.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorShapeLoadImages.man b/man/XcursorShapeLoadImages.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorShapeLoadImages.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorSupportsARGB.man b/man/XcursorSupportsARGB.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorSupportsARGB.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorXcFileLoad.man b/man/XcursorXcFileLoad.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorXcFileLoad.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorXcFileLoadAllImages.man b/man/XcursorXcFileLoadAllImages.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorXcFileLoadAllImages.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorXcFileLoadImage.man b/man/XcursorXcFileLoadImage.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorXcFileLoadImage.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorXcFileLoadImages.man b/man/XcursorXcFileLoadImages.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorXcFileLoadImages.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/man/XcursorXcFileSave.man b/man/XcursorXcFileSave.man new file mode 100644 index 0000000..690dab2 --- /dev/null +++ b/man/XcursorXcFileSave.man @@ -0,0 +1 @@ +.so man__libmansuffix__/Xcursor.__libmansuffix__ diff --git a/packaging/libXcursor.spec b/packaging/libXcursor.spec new file mode 100644 index 0000000..9218a7b --- /dev/null +++ b/packaging/libXcursor.spec @@ -0,0 +1,87 @@ +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* diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..a44dcb3 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,31 @@ +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 diff --git a/src/cursor.c b/src/cursor.c new file mode 100644 index 0000000..92bd417 --- /dev/null +++ b/src/cursor.c @@ -0,0 +1,823 @@ +/* + * 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 +#include + +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. 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); +} + diff --git a/src/display.c b/src/display.c new file mode 100644 index 0000000..7998fe7 --- /dev/null +++ b/src/display.c @@ -0,0 +1,388 @@ +/* + * 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 +#include + +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; +} diff --git a/src/file.c b/src/file.c new file mode 100644 index 0000000..efe6d4b --- /dev/null +++ b/src/file.c @@ -0,0 +1,1108 @@ +/* + * 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 +#include + +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; +} diff --git a/src/library.c b/src/library.c new file mode 100644 index 0000000..48b75bf --- /dev/null +++ b/src/library.c @@ -0,0 +1,550 @@ +/* + * 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 +#include + +#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; +} diff --git a/src/xcursorint.h b/src/xcursorint.h new file mode 100644 index 0000000..d8f9ea3 --- /dev/null +++ b/src/xcursorint.h @@ -0,0 +1,107 @@ +/* + * 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 +#include +#include + +#ifdef HAVE_XFIXES +#include +#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_ */ diff --git a/src/xlib.c b/src/xlib.c new file mode 100644 index 0000000..15716b2 --- /dev/null +++ b/src/xlib.c @@ -0,0 +1,421 @@ +/* + * 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 +#include +#include + +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; +} diff --git a/xcursor.pc.in b/xcursor.pc.in new file mode 100644 index 0000000..f55bed3 --- /dev/null +++ b/xcursor.pc.in @@ -0,0 +1,14 @@ +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