17914d74bSmrg/* 26b7436aeSmrg * Copyright © 2024 Thomas E. Dickey 37914d74bSmrg * Copyright © 2002 Keith Packard 47914d74bSmrg * 57914d74bSmrg * Permission to use, copy, modify, distribute, and sell this software and its 67914d74bSmrg * documentation for any purpose is hereby granted without fee, provided that 77914d74bSmrg * the above copyright notice appear in all copies and that both that 87914d74bSmrg * copyright notice and this permission notice appear in supporting 97914d74bSmrg * documentation, and that the name of Keith Packard not be used in 107914d74bSmrg * advertising or publicity pertaining to distribution of the software without 117914d74bSmrg * specific, written prior permission. Keith Packard makes no 127914d74bSmrg * representations about the suitability of this software for any purpose. It 137914d74bSmrg * is provided "as is" without express or implied warranty. 147914d74bSmrg * 157914d74bSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 167914d74bSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 177914d74bSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 187914d74bSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 197914d74bSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 207914d74bSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 217914d74bSmrg * PERFORMANCE OF THIS SOFTWARE. 227914d74bSmrg */ 237914d74bSmrg 247914d74bSmrg#include "xcursorint.h" 257914d74bSmrg#include <stdlib.h> 267914d74bSmrg#include <string.h> 277914d74bSmrg 287914d74bSmrg#ifndef ICONDIR 297914d74bSmrg#define ICONDIR "/usr/X11R6/lib/X11/icons" 307914d74bSmrg#endif 317914d74bSmrg 327914d74bSmrg#ifndef XCURSORPATH 33cdce750aSmrg#define XCURSORPATH "~/.local/share/icons:~/.icons:/usr/share/icons:/usr/share/pixmaps:"ICONDIR 347914d74bSmrg#endif 357914d74bSmrg 364d939ec7Smrgtypedef struct XcursorInherit { 374d939ec7Smrg char *line; 384d939ec7Smrg const char *theme; 394d939ec7Smrg} XcursorInherit; 404d939ec7Smrg 417914d74bSmrgconst char * 427914d74bSmrgXcursorLibraryPath (void) 437914d74bSmrg{ 447914d74bSmrg static const char *path; 457914d74bSmrg 467914d74bSmrg if (!path) 477914d74bSmrg { 487914d74bSmrg path = getenv ("XCURSOR_PATH"); 497914d74bSmrg if (!path) 507914d74bSmrg path = XCURSORPATH; 516b7436aeSmrg traceOpts((T_OPTION(XCURSOR_PATH) ": %s\n", NonNull(path))); 527914d74bSmrg } 537914d74bSmrg return path; 547914d74bSmrg} 557914d74bSmrg 567914d74bSmrgstatic void 577914d74bSmrg_XcursorAddPathElt (char *path, const char *elt, int len) 587914d74bSmrg{ 599d0ccd10Smrg size_t pathlen = strlen (path); 60e6d5e4e0Smrg 617914d74bSmrg /* append / if the path doesn't currently have one */ 627914d74bSmrg if (path[0] == '\0' || path[pathlen - 1] != '/') 637914d74bSmrg { 647914d74bSmrg strcat (path, "/"); 657914d74bSmrg pathlen++; 667914d74bSmrg } 677914d74bSmrg if (len == -1) 684d939ec7Smrg len = (int) strlen (elt); 697914d74bSmrg /* strip leading slashes */ 707914d74bSmrg while (len && elt[0] == '/') 717914d74bSmrg { 727914d74bSmrg elt++; 737914d74bSmrg len--; 747914d74bSmrg } 754d939ec7Smrg strncpy (path + pathlen, elt, (size_t) len); 764d939ec7Smrg path[pathlen + (size_t) len] = '\0'; 777914d74bSmrg} 787914d74bSmrg 797914d74bSmrgstatic char * 807914d74bSmrg_XcursorBuildThemeDir (const char *dir, const char *theme) 817914d74bSmrg{ 827914d74bSmrg const char *colon; 837914d74bSmrg const char *tcolon; 847914d74bSmrg char *full; 857914d74bSmrg char *home; 867914d74bSmrg int dirlen; 877914d74bSmrg int homelen; 887914d74bSmrg int themelen; 897914d74bSmrg int len; 907914d74bSmrg 917914d74bSmrg if (!dir || !theme) 924d939ec7Smrg return NULL; 93e6d5e4e0Smrg 947914d74bSmrg colon = strchr (dir, ':'); 957914d74bSmrg if (!colon) 967914d74bSmrg colon = dir + strlen (dir); 97e6d5e4e0Smrg 984d939ec7Smrg dirlen = (int) (colon - dir); 997914d74bSmrg 1007914d74bSmrg tcolon = strchr (theme, ':'); 1017914d74bSmrg if (!tcolon) 1027914d74bSmrg tcolon = theme + strlen (theme); 1037914d74bSmrg 1044d939ec7Smrg themelen = (int) (tcolon - theme); 105e6d5e4e0Smrg 1067914d74bSmrg home = NULL; 1077914d74bSmrg homelen = 0; 1087914d74bSmrg if (*dir == '~') 1097914d74bSmrg { 1107914d74bSmrg home = getenv ("HOME"); 1117914d74bSmrg if (!home) 1127914d74bSmrg return NULL; 1134d939ec7Smrg homelen = (int) strlen (home); 1147914d74bSmrg dir++; 1157914d74bSmrg dirlen--; 1167914d74bSmrg } 1177914d74bSmrg 1187914d74bSmrg /* 1197914d74bSmrg * add space for any needed directory separators, one per component, 1207914d74bSmrg * and one for the trailing null 1217914d74bSmrg */ 1227914d74bSmrg len = 1 + homelen + 1 + dirlen + 1 + themelen + 1; 123e6d5e4e0Smrg 1244d939ec7Smrg full = malloc ((size_t)len); 1257914d74bSmrg if (!full) 1267914d74bSmrg return NULL; 1277914d74bSmrg full[0] = '\0'; 1287914d74bSmrg 1297914d74bSmrg if (home) 1307914d74bSmrg _XcursorAddPathElt (full, home, -1); 1317914d74bSmrg _XcursorAddPathElt (full, dir, dirlen); 1327914d74bSmrg _XcursorAddPathElt (full, theme, themelen); 1337914d74bSmrg return full; 1347914d74bSmrg} 1357914d74bSmrg 1367914d74bSmrgstatic char * 1377914d74bSmrg_XcursorBuildFullname (const char *dir, const char *subdir, const char *file) 1387914d74bSmrg{ 1397914d74bSmrg char *full; 1407914d74bSmrg 1417914d74bSmrg if (!dir || !subdir || !file) 1424d939ec7Smrg return NULL; 1437914d74bSmrg 1447914d74bSmrg full = malloc (strlen (dir) + 1 + strlen (subdir) + 1 + strlen (file) + 1); 1457914d74bSmrg if (!full) 1467914d74bSmrg return NULL; 1477914d74bSmrg full[0] = '\0'; 1487914d74bSmrg _XcursorAddPathElt (full, dir, -1); 1497914d74bSmrg _XcursorAddPathElt (full, subdir, -1); 1507914d74bSmrg _XcursorAddPathElt (full, file, -1); 1517914d74bSmrg return full; 1527914d74bSmrg} 1537914d74bSmrg 1547914d74bSmrgstatic const char * 1557914d74bSmrg_XcursorNextPath (const char *path) 1567914d74bSmrg{ 1577914d74bSmrg char *colon = strchr (path, ':'); 1587914d74bSmrg 1597914d74bSmrg if (!colon) 1607914d74bSmrg return NULL; 1617914d74bSmrg return colon + 1; 1627914d74bSmrg} 1637914d74bSmrg 1640ea508b1Smrg/* 1650ea508b1Smrg * _XcursorThemeInherits, XcursorWhite, & XcursorSep are copied in 1660ea508b1Smrg * libxcb-cursor/cursor/load_cursor.c. Please update that copy to 1670ea508b1Smrg * include any changes made to the code for those here. 1680ea508b1Smrg */ 1690ea508b1Smrg 1707914d74bSmrg#define XcursorWhite(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') 1717914d74bSmrg#define XcursorSep(c) ((c) == ';' || (c) == ',') 1727914d74bSmrg 1737914d74bSmrgstatic char * 1747914d74bSmrg_XcursorThemeInherits (const char *full) 1757914d74bSmrg{ 1767914d74bSmrg char line[8192]; 1777914d74bSmrg char *result = NULL; 1787914d74bSmrg FILE *f; 1797914d74bSmrg 1807914d74bSmrg if (!full) 1814d939ec7Smrg return NULL; 1827914d74bSmrg 1830ea508b1Smrg f = fopen (full, "r" FOPEN_CLOEXEC); 1847914d74bSmrg if (f) 1857914d74bSmrg { 1867914d74bSmrg while (fgets (line, sizeof (line), f)) 1877914d74bSmrg { 1887914d74bSmrg if (!strncmp (line, "Inherits", 8)) 1897914d74bSmrg { 1907914d74bSmrg char *l = line + 8; 1917914d74bSmrg while (*l == ' ') l++; 1927914d74bSmrg if (*l != '=') continue; 1937914d74bSmrg l++; 1947914d74bSmrg while (*l == ' ') l++; 1959d0ccd10Smrg result = malloc (strlen (l) + 1); 1967914d74bSmrg if (result) 1977914d74bSmrg { 1984d939ec7Smrg char *r = result; 199e6d5e4e0Smrg while (*l) 2007914d74bSmrg { 2017914d74bSmrg while (XcursorSep(*l) || XcursorWhite (*l)) l++; 2027914d74bSmrg if (!*l) 2037914d74bSmrg break; 2047914d74bSmrg if (r != result) 2057914d74bSmrg *r++ = ':'; 206e6d5e4e0Smrg while (*l && !XcursorWhite(*l) && 2077914d74bSmrg !XcursorSep(*l)) 2087914d74bSmrg *r++ = *l++; 2097914d74bSmrg } 2107914d74bSmrg *r++ = '\0'; 2117914d74bSmrg } 2127914d74bSmrg break; 2137914d74bSmrg } 2147914d74bSmrg } 2157914d74bSmrg fclose (f); 2167914d74bSmrg } 2177914d74bSmrg return result; 2187914d74bSmrg} 2197914d74bSmrg 2207914d74bSmrg#define XCURSOR_SCAN_CORE ((FILE *) 1) 2214d939ec7Smrg#define MAX_INHERITS_DEPTH 32 2227914d74bSmrg 2237914d74bSmrgstatic FILE * 2247914d74bSmrgXcursorScanTheme (const char *theme, const char *name) 2257914d74bSmrg{ 2264d939ec7Smrg FILE *f = NULL; 2274d939ec7Smrg char *full; 2284d939ec7Smrg char *dir; 2294d939ec7Smrg const char *path; 2304d939ec7Smrg XcursorInherit inherits[MAX_INHERITS_DEPTH + 1]; 2314d939ec7Smrg int d; 2327914d74bSmrg 2337914d74bSmrg if (!theme || !name) 2344d939ec7Smrg return NULL; 2357914d74bSmrg 2367914d74bSmrg /* 2377914d74bSmrg * XCURSOR_CORE_THEME is a magic name; cursors from the core set 2387914d74bSmrg * are never found in any directory. Instead, a magic value is 2397914d74bSmrg * returned which truncates any search so that overlying functions 2407914d74bSmrg * can switch to equivalent core cursors 2417914d74bSmrg */ 2427914d74bSmrg if (!strcmp (theme, XCURSOR_CORE_THEME) && XcursorLibraryShape (name) >= 0) 2437914d74bSmrg return XCURSOR_SCAN_CORE; 2444d939ec7Smrg 2454d939ec7Smrg memset (inherits, 0, sizeof (inherits)); 2464d939ec7Smrg 2474d939ec7Smrg d = 0; 2484d939ec7Smrg inherits[d].theme = theme; 2494d939ec7Smrg 2504d939ec7Smrg while (f == NULL && d >= 0 && inherits[d].theme != NULL) 2517914d74bSmrg { 2524d939ec7Smrg /* 2534d939ec7Smrg * Scan this theme 2544d939ec7Smrg */ 2554d939ec7Smrg for (path = XcursorLibraryPath (); 2564d939ec7Smrg path && f == NULL; 2574d939ec7Smrg path = _XcursorNextPath (path)) 2587914d74bSmrg { 2594d939ec7Smrg dir = _XcursorBuildThemeDir (path, inherits[d].theme); 2604d939ec7Smrg if (dir) 2617914d74bSmrg { 2624d939ec7Smrg full = _XcursorBuildFullname (dir, "cursors", name); 2637914d74bSmrg if (full) 2647914d74bSmrg { 2650ea508b1Smrg f = fopen (full, "r" FOPEN_CLOEXEC); 2667914d74bSmrg free (full); 2677914d74bSmrg } 2684d939ec7Smrg if (!f && inherits[d + 1].line == NULL) 2694d939ec7Smrg { 2704d939ec7Smrg if (d + 1 >= MAX_INHERITS_DEPTH) 2714d939ec7Smrg { 2724d939ec7Smrg free (dir); 2734d939ec7Smrg goto finish; 2744d939ec7Smrg } 2754d939ec7Smrg full = _XcursorBuildFullname (dir, "", "index.theme"); 2764d939ec7Smrg if (full) 2774d939ec7Smrg { 2784d939ec7Smrg inherits[d + 1].line = _XcursorThemeInherits (full); 2794d939ec7Smrg inherits[d + 1].theme = inherits[d + 1].line; 2804d939ec7Smrg free (full); 2814d939ec7Smrg } 2824d939ec7Smrg } 2834d939ec7Smrg free (dir); 2847914d74bSmrg } 2857914d74bSmrg } 2864d939ec7Smrg 2874d939ec7Smrg d++; 2884d939ec7Smrg while (d > 0 && inherits[d].theme == NULL) 2894d939ec7Smrg { 2904d939ec7Smrg free (inherits[d].line); 2914d939ec7Smrg inherits[d].line = NULL; 2924d939ec7Smrg 2934d939ec7Smrg if (--d == 0) 2944d939ec7Smrg inherits[d].theme = NULL; 2954d939ec7Smrg else 2964d939ec7Smrg inherits[d].theme = _XcursorNextPath (inherits[d].theme); 2974d939ec7Smrg } 2984d939ec7Smrg 2994d939ec7Smrg /* 3004d939ec7Smrg * Detect and break self reference loop early on. 3014d939ec7Smrg */ 3024d939ec7Smrg if (inherits[d].theme != NULL && strcmp (inherits[d].theme, theme) == 0) 3034d939ec7Smrg break; 3047914d74bSmrg } 3054d939ec7Smrg 3064d939ec7Smrgfinish: 3074d939ec7Smrg for (d = 1; d <= MAX_INHERITS_DEPTH; d++) 3084d939ec7Smrg free (inherits[d].line); 3094d939ec7Smrg 3107914d74bSmrg return f; 3117914d74bSmrg} 3127914d74bSmrg 3137914d74bSmrgXcursorImage * 3147914d74bSmrgXcursorLibraryLoadImage (const char *file, const char *theme, int size) 3157914d74bSmrg{ 3167914d74bSmrg FILE *f = NULL; 3177914d74bSmrg XcursorImage *image = NULL; 3187914d74bSmrg 3196b7436aeSmrg enterFunc((T_CALLED(XcursorLibraryLoadImage) "(\"%s\",\"%s\", %d)\n", 3206b7436aeSmrg NonNull(file), NonNull(theme), size)); 3216b7436aeSmrg 3227914d74bSmrg if (!file) 3236b7436aeSmrg returnAddr(NULL); 3247914d74bSmrg 3257914d74bSmrg if (theme) 3267914d74bSmrg f = XcursorScanTheme (theme, file); 3277914d74bSmrg if (!f) 3287914d74bSmrg f = XcursorScanTheme ("default", file); 3294d939ec7Smrg if (f != NULL && f != XCURSOR_SCAN_CORE) 3307914d74bSmrg { 3317914d74bSmrg image = XcursorFileLoadImage (f, size); 3327914d74bSmrg fclose (f); 3337914d74bSmrg } 3346b7436aeSmrg returnAddr(image); 3356b7436aeSmrg} 3366b7436aeSmrg 3376b7436aeSmrgstatic XcursorImages * 3386b7436aeSmrg_XcursorLibraryLoadImages (Display *dpy, const char *file) 3396b7436aeSmrg{ 3406b7436aeSmrg int size = XcursorGetDefaultSize (dpy); 3416b7436aeSmrg char *theme = XcursorGetTheme (dpy); 3426b7436aeSmrg XcursorBool resized = XcursorGetResizable (dpy); 3436b7436aeSmrg FILE *f = NULL; 3446b7436aeSmrg XcursorImages *images = NULL; 3456b7436aeSmrg 3466b7436aeSmrg if (!file) 3476b7436aeSmrg return NULL; 3486b7436aeSmrg 3496b7436aeSmrg if (theme) 3506b7436aeSmrg f = XcursorScanTheme (theme, file); 3516b7436aeSmrg if (!f) 3526b7436aeSmrg f = XcursorScanTheme ("default", file); 3536b7436aeSmrg if (f != NULL && f != XCURSOR_SCAN_CORE) 3546b7436aeSmrg { 3556b7436aeSmrg images = _XcursorFileLoadImages (f, size, resized); 3566b7436aeSmrg if (images) 3576b7436aeSmrg XcursorImagesSetName (images, file); 3586b7436aeSmrg fclose (f); 3596b7436aeSmrg } 3606b7436aeSmrg return images; 3617914d74bSmrg} 3627914d74bSmrg 3637914d74bSmrgXcursorImages * 3647914d74bSmrgXcursorLibraryLoadImages (const char *file, const char *theme, int size) 3657914d74bSmrg{ 3667914d74bSmrg FILE *f = NULL; 3677914d74bSmrg XcursorImages *images = NULL; 3687914d74bSmrg 3696b7436aeSmrg enterFunc((T_CALLED(XcursorLibraryLoadImages) "(\"%s\", \"%s\", %d)\n", 3706b7436aeSmrg NonNull(file), NonNull(theme), size)); 3716b7436aeSmrg 3727914d74bSmrg if (!file) 3736b7436aeSmrg returnAddr(NULL); 3747914d74bSmrg 3757914d74bSmrg if (theme) 3767914d74bSmrg f = XcursorScanTheme (theme, file); 3777914d74bSmrg if (!f) 3787914d74bSmrg f = XcursorScanTheme ("default", file); 3794d939ec7Smrg if (f != NULL && f != XCURSOR_SCAN_CORE) 3807914d74bSmrg { 3817914d74bSmrg images = XcursorFileLoadImages (f, size); 3827914d74bSmrg if (images) 3837914d74bSmrg XcursorImagesSetName (images, file); 3847914d74bSmrg fclose (f); 3857914d74bSmrg } 3866b7436aeSmrg returnAddr(images); 3877914d74bSmrg} 3887914d74bSmrg 3897914d74bSmrgCursor 3907914d74bSmrgXcursorLibraryLoadCursor (Display *dpy, const char *file) 3917914d74bSmrg{ 3926b7436aeSmrg XcursorImages *images; 3936b7436aeSmrg Cursor cursor = 0; 3946b7436aeSmrg 3956b7436aeSmrg enterFunc((T_CALLED(XcursorLibraryLoadCursor) "(%p, \"%s\")\n", 3966b7436aeSmrg (void*)dpy, NonNull(file))); 3977914d74bSmrg 3987914d74bSmrg if (!file) 3996b7436aeSmrg returnLong(cursor); 400e6d5e4e0Smrg 4016b7436aeSmrg images = _XcursorLibraryLoadImages (dpy, file); 4027914d74bSmrg if (!images) 4037914d74bSmrg { 4047914d74bSmrg int id = XcursorLibraryShape (file); 4057914d74bSmrg 4067914d74bSmrg if (id >= 0) 4076b7436aeSmrg cursor = _XcursorCreateFontCursor (dpy, (unsigned) id); 4087914d74bSmrg } 4096b7436aeSmrg else 4106b7436aeSmrg { 4116b7436aeSmrg cursor = XcursorImagesLoadCursor (dpy, images); 4126b7436aeSmrg XcursorImagesDestroy (images); 4137914d74bSmrg#if defined HAVE_XFIXES && XFIXES_MAJOR >= 2 4146b7436aeSmrg XFixesSetCursorName (dpy, cursor, file); 4157914d74bSmrg#endif 4166b7436aeSmrg } 4176b7436aeSmrg returnLong(cursor); 4187914d74bSmrg} 4197914d74bSmrg 4207914d74bSmrgXcursorCursors * 4217914d74bSmrgXcursorLibraryLoadCursors (Display *dpy, const char *file) 4227914d74bSmrg{ 4236b7436aeSmrg XcursorImages *images; 4247914d74bSmrg XcursorCursors *cursors; 425e6d5e4e0Smrg 4266b7436aeSmrg enterFunc((T_CALLED(XcursorLibraryLoadCursors) "(%p, \"%s\")\n", 4276b7436aeSmrg (void*)dpy, NonNull(file))); 4286b7436aeSmrg 4297914d74bSmrg if (!file) 4306b7436aeSmrg returnAddr(NULL); 431e6d5e4e0Smrg 4326b7436aeSmrg images = _XcursorLibraryLoadImages (dpy, file); 4337914d74bSmrg if (!images) 4347914d74bSmrg { 4357914d74bSmrg int id = XcursorLibraryShape (file); 4367914d74bSmrg 4377914d74bSmrg if (id >= 0) 4387914d74bSmrg { 4397914d74bSmrg cursors = XcursorCursorsCreate (dpy, 1); 4407914d74bSmrg if (cursors) 4417914d74bSmrg { 4424d939ec7Smrg cursors->cursors[0] = _XcursorCreateFontCursor (dpy, (unsigned) id); 4437914d74bSmrg if (cursors->cursors[0] == None) 4447914d74bSmrg { 4457914d74bSmrg XcursorCursorsDestroy (cursors); 4467914d74bSmrg cursors = NULL; 4477914d74bSmrg } 4487914d74bSmrg else 4497914d74bSmrg cursors->ncursor = 1; 4507914d74bSmrg } 4517914d74bSmrg } 4527914d74bSmrg else 4537914d74bSmrg cursors = NULL; 4547914d74bSmrg } 4557914d74bSmrg else 4567914d74bSmrg { 4577914d74bSmrg cursors = XcursorImagesLoadCursors (dpy, images); 4587914d74bSmrg XcursorImagesDestroy (images); 4597914d74bSmrg } 4606b7436aeSmrg returnAddr(cursors); 4617914d74bSmrg} 4627914d74bSmrg 4637914d74bSmrgstatic const char _XcursorStandardNames[] = 4647914d74bSmrg "X_cursor\0" 4657914d74bSmrg "arrow\0" 4667914d74bSmrg "based_arrow_down\0" 4677914d74bSmrg "based_arrow_up\0" 4687914d74bSmrg "boat\0" 4697914d74bSmrg "bogosity\0" 4707914d74bSmrg "bottom_left_corner\0" 4717914d74bSmrg "bottom_right_corner\0" 4727914d74bSmrg "bottom_side\0" 4737914d74bSmrg "bottom_tee\0" 4747914d74bSmrg "box_spiral\0" 4757914d74bSmrg "center_ptr\0" 4767914d74bSmrg "circle\0" 4777914d74bSmrg "clock\0" 4787914d74bSmrg "coffee_mug\0" 4797914d74bSmrg "cross\0" 4807914d74bSmrg "cross_reverse\0" 4817914d74bSmrg "crosshair\0" 4827914d74bSmrg "diamond_cross\0" 4837914d74bSmrg "dot\0" 4847914d74bSmrg "dotbox\0" 4857914d74bSmrg "double_arrow\0" 4867914d74bSmrg "draft_large\0" 4877914d74bSmrg "draft_small\0" 4887914d74bSmrg "draped_box\0" 4897914d74bSmrg "exchange\0" 4907914d74bSmrg "fleur\0" 4917914d74bSmrg "gobbler\0" 4927914d74bSmrg "gumby\0" 4937914d74bSmrg "hand1\0" 4947914d74bSmrg "hand2\0" 4957914d74bSmrg "heart\0" 4967914d74bSmrg "icon\0" 4977914d74bSmrg "iron_cross\0" 4987914d74bSmrg "left_ptr\0" 4997914d74bSmrg "left_side\0" 5007914d74bSmrg "left_tee\0" 5017914d74bSmrg "leftbutton\0" 5027914d74bSmrg "ll_angle\0" 5037914d74bSmrg "lr_angle\0" 5047914d74bSmrg "man\0" 5057914d74bSmrg "middlebutton\0" 5067914d74bSmrg "mouse\0" 5077914d74bSmrg "pencil\0" 5087914d74bSmrg "pirate\0" 5097914d74bSmrg "plus\0" 5107914d74bSmrg "question_arrow\0" 5117914d74bSmrg "right_ptr\0" 5127914d74bSmrg "right_side\0" 5137914d74bSmrg "right_tee\0" 5147914d74bSmrg "rightbutton\0" 5157914d74bSmrg "rtl_logo\0" 5167914d74bSmrg "sailboat\0" 5177914d74bSmrg "sb_down_arrow\0" 5187914d74bSmrg "sb_h_double_arrow\0" 5197914d74bSmrg "sb_left_arrow\0" 5207914d74bSmrg "sb_right_arrow\0" 5217914d74bSmrg "sb_up_arrow\0" 5227914d74bSmrg "sb_v_double_arrow\0" 5237914d74bSmrg "shuttle\0" 5247914d74bSmrg "sizing\0" 5257914d74bSmrg "spider\0" 5267914d74bSmrg "spraycan\0" 5277914d74bSmrg "star\0" 5287914d74bSmrg "target\0" 5297914d74bSmrg "tcross\0" 5307914d74bSmrg "top_left_arrow\0" 5317914d74bSmrg "top_left_corner\0" 5327914d74bSmrg "top_right_corner\0" 5337914d74bSmrg "top_side\0" 5347914d74bSmrg "top_tee\0" 5357914d74bSmrg "trek\0" 5367914d74bSmrg "ul_angle\0" 5377914d74bSmrg "umbrella\0" 5387914d74bSmrg "ur_angle\0" 5397914d74bSmrg "watch\0" 5407914d74bSmrg "xterm"; 5417914d74bSmrg 5427914d74bSmrgstatic const unsigned short _XcursorStandardNameOffsets[] = { 5437914d74bSmrg 0, 9, 15, 32, 47, 52, 61, 80, 100, 112, 123, 134, 145, 152, 158, 5447914d74bSmrg 169, 175, 189, 199, 213, 217, 224, 237, 249, 261, 272, 281, 287, 5457914d74bSmrg 295, 301, 307, 313, 319, 324, 335, 344, 354, 363, 374, 383, 392, 5467914d74bSmrg 396, 409, 415, 422, 429, 434, 449, 459, 470, 480, 492, 501, 510, 5477914d74bSmrg 524, 542, 556, 571, 583, 601, 609, 616, 623, 632, 637, 644, 651, 5487914d74bSmrg 666, 682, 699, 708, 716, 721, 730, 739, 748, 754 5497914d74bSmrg}; 5507914d74bSmrg 5517914d74bSmrg#define NUM_STANDARD_NAMES (sizeof _XcursorStandardNameOffsets / sizeof _XcursorStandardNameOffsets[0]) 5527914d74bSmrg 5537914d74bSmrg#define STANDARD_NAME(id) \ 5547914d74bSmrg _XcursorStandardNames + _XcursorStandardNameOffsets[id] 5557914d74bSmrg 5567914d74bSmrgXcursorImage * 5577914d74bSmrgXcursorShapeLoadImage (unsigned int shape, const char *theme, int size) 5587914d74bSmrg{ 5597914d74bSmrg unsigned int id = shape >> 1; 5606b7436aeSmrg XcursorImage *result = NULL; 5616b7436aeSmrg 5626b7436aeSmrg enterFunc((T_CALLED(XcursorShapeLoadImage) "(%u, \"%s\", %d)\n", 5636b7436aeSmrg shape, NonNull(theme), size)); 5647914d74bSmrg 5657914d74bSmrg if (id < NUM_STANDARD_NAMES) 5666b7436aeSmrg result = XcursorLibraryLoadImage (STANDARD_NAME (id), theme, size); 5676b7436aeSmrg 5686b7436aeSmrg returnAddr(result); 5696b7436aeSmrg} 5706b7436aeSmrg 5716b7436aeSmrgXcursorImages * 5726b7436aeSmrg_XcursorShapeLoadImages (Display *dpy, unsigned int shape) 5736b7436aeSmrg{ 5746b7436aeSmrg unsigned int id = shape >> 1; 5756b7436aeSmrg XcursorImages *result = NULL; 5766b7436aeSmrg 5776b7436aeSmrg enterFunc((T_CALLED(_XcursorShapeLoadImages) "(%p, %u)\n", 5786b7436aeSmrg (void*)dpy, shape)); 5796b7436aeSmrg 5806b7436aeSmrg if (id < NUM_STANDARD_NAMES) 5816b7436aeSmrg result = _XcursorLibraryLoadImages (dpy, STANDARD_NAME (id)); 5826b7436aeSmrg 5836b7436aeSmrg returnAddr(result); 5847914d74bSmrg} 5857914d74bSmrg 5867914d74bSmrgXcursorImages * 5877914d74bSmrgXcursorShapeLoadImages (unsigned int shape, const char *theme, int size) 5887914d74bSmrg{ 5897914d74bSmrg unsigned int id = shape >> 1; 5906b7436aeSmrg XcursorImages *result = NULL; 5916b7436aeSmrg 5926b7436aeSmrg enterFunc((T_CALLED(XcursorShapeLoadImages) "(%u, \"%s\", %d)\n", 5936b7436aeSmrg shape, NonNull(theme), size)); 5947914d74bSmrg 5957914d74bSmrg if (id < NUM_STANDARD_NAMES) 5966b7436aeSmrg result = XcursorLibraryLoadImages (STANDARD_NAME (id), theme, size); 5976b7436aeSmrg 5986b7436aeSmrg returnAddr(result); 5997914d74bSmrg} 6007914d74bSmrg 6017914d74bSmrgCursor 6027914d74bSmrgXcursorShapeLoadCursor (Display *dpy, unsigned int shape) 6037914d74bSmrg{ 6047914d74bSmrg unsigned int id = shape >> 1; 6056b7436aeSmrg Cursor result = None; 6066b7436aeSmrg 6076b7436aeSmrg enterFunc((T_CALLED(XcursorShapeLoadCursor) "(%p, %u)\n", 6086b7436aeSmrg (void*)dpy, shape)); 6097914d74bSmrg 6107914d74bSmrg if (id < NUM_STANDARD_NAMES) 6116b7436aeSmrg result = XcursorLibraryLoadCursor (dpy, STANDARD_NAME (id)); 6126b7436aeSmrg 6136b7436aeSmrg returnLong(result); 6147914d74bSmrg} 6157914d74bSmrg 6167914d74bSmrgXcursorCursors * 6177914d74bSmrgXcursorShapeLoadCursors (Display *dpy, unsigned int shape) 6187914d74bSmrg{ 6197914d74bSmrg unsigned int id = shape >> 1; 6206b7436aeSmrg XcursorCursors *result = NULL; 6216b7436aeSmrg 6226b7436aeSmrg enterFunc((T_CALLED(XcursorShapeLoadCursors) "(%p, %u)\n", 6236b7436aeSmrg (void*)dpy, shape)); 6247914d74bSmrg 6257914d74bSmrg if (id < NUM_STANDARD_NAMES) 6266b7436aeSmrg result = XcursorLibraryLoadCursors (dpy, STANDARD_NAME (id)); 6276b7436aeSmrg 6286b7436aeSmrg returnAddr(result); 6297914d74bSmrg} 6307914d74bSmrg 6317914d74bSmrgint 6327914d74bSmrgXcursorLibraryShape (const char *library) 6337914d74bSmrg{ 6347914d74bSmrg int low, high; 6357914d74bSmrg 6366b7436aeSmrg enterFunc((T_CALLED(XcursorLibraryShape) "(%s)\n", NonNull(library))); 6376b7436aeSmrg 6387914d74bSmrg low = 0; 6397914d74bSmrg high = NUM_STANDARD_NAMES - 1; 6407914d74bSmrg while (low < high - 1) 6417914d74bSmrg { 6424d939ec7Smrg int mid = (low + high) >> 1; 6434d939ec7Smrg int c = strcmp (library, STANDARD_NAME (mid)); 6447914d74bSmrg if (c == 0) 6456b7436aeSmrg returnCode(mid << 1); 6467914d74bSmrg if (c > 0) 6477914d74bSmrg low = mid; 6487914d74bSmrg else 6497914d74bSmrg high = mid; 6507914d74bSmrg } 6517914d74bSmrg while (low <= high) 6527914d74bSmrg { 6537914d74bSmrg if (!strcmp (library, STANDARD_NAME (low))) 6547914d74bSmrg return (low << 1); 6557914d74bSmrg low++; 6567914d74bSmrg } 6576b7436aeSmrg returnCode(-1); 6587914d74bSmrg} 659