library.c revision 4d939ec7
17914d74bSmrg/* 27914d74bSmrg * Copyright © 2002 Keith Packard 37914d74bSmrg * 47914d74bSmrg * Permission to use, copy, modify, distribute, and sell this software and its 57914d74bSmrg * documentation for any purpose is hereby granted without fee, provided that 67914d74bSmrg * the above copyright notice appear in all copies and that both that 77914d74bSmrg * copyright notice and this permission notice appear in supporting 87914d74bSmrg * documentation, and that the name of Keith Packard not be used in 97914d74bSmrg * advertising or publicity pertaining to distribution of the software without 107914d74bSmrg * specific, written prior permission. Keith Packard makes no 117914d74bSmrg * representations about the suitability of this software for any purpose. It 127914d74bSmrg * is provided "as is" without express or implied warranty. 137914d74bSmrg * 147914d74bSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 157914d74bSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 167914d74bSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 177914d74bSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 187914d74bSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 197914d74bSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 207914d74bSmrg * PERFORMANCE OF THIS SOFTWARE. 217914d74bSmrg */ 227914d74bSmrg 237914d74bSmrg#include "xcursorint.h" 247914d74bSmrg#include <stdlib.h> 257914d74bSmrg#include <string.h> 267914d74bSmrg 277914d74bSmrg#ifndef ICONDIR 287914d74bSmrg#define ICONDIR "/usr/X11R6/lib/X11/icons" 297914d74bSmrg#endif 307914d74bSmrg 317914d74bSmrg#ifndef XCURSORPATH 32cdce750aSmrg#define XCURSORPATH "~/.local/share/icons:~/.icons:/usr/share/icons:/usr/share/pixmaps:"ICONDIR 337914d74bSmrg#endif 347914d74bSmrg 354d939ec7Smrgtypedef struct XcursorInherit { 364d939ec7Smrg char *line; 374d939ec7Smrg const char *theme; 384d939ec7Smrg} XcursorInherit; 394d939ec7Smrg 407914d74bSmrgconst char * 417914d74bSmrgXcursorLibraryPath (void) 427914d74bSmrg{ 437914d74bSmrg static const char *path; 447914d74bSmrg 457914d74bSmrg if (!path) 467914d74bSmrg { 477914d74bSmrg path = getenv ("XCURSOR_PATH"); 487914d74bSmrg if (!path) 497914d74bSmrg path = XCURSORPATH; 507914d74bSmrg } 517914d74bSmrg return path; 527914d74bSmrg} 537914d74bSmrg 547914d74bSmrgstatic void 557914d74bSmrg_XcursorAddPathElt (char *path, const char *elt, int len) 567914d74bSmrg{ 579d0ccd10Smrg size_t pathlen = strlen (path); 58e6d5e4e0Smrg 597914d74bSmrg /* append / if the path doesn't currently have one */ 607914d74bSmrg if (path[0] == '\0' || path[pathlen - 1] != '/') 617914d74bSmrg { 627914d74bSmrg strcat (path, "/"); 637914d74bSmrg pathlen++; 647914d74bSmrg } 657914d74bSmrg if (len == -1) 664d939ec7Smrg len = (int) strlen (elt); 677914d74bSmrg /* strip leading slashes */ 687914d74bSmrg while (len && elt[0] == '/') 697914d74bSmrg { 707914d74bSmrg elt++; 717914d74bSmrg len--; 727914d74bSmrg } 734d939ec7Smrg strncpy (path + pathlen, elt, (size_t) len); 744d939ec7Smrg path[pathlen + (size_t) len] = '\0'; 757914d74bSmrg} 767914d74bSmrg 777914d74bSmrgstatic char * 787914d74bSmrg_XcursorBuildThemeDir (const char *dir, const char *theme) 797914d74bSmrg{ 807914d74bSmrg const char *colon; 817914d74bSmrg const char *tcolon; 827914d74bSmrg char *full; 837914d74bSmrg char *home; 847914d74bSmrg int dirlen; 857914d74bSmrg int homelen; 867914d74bSmrg int themelen; 877914d74bSmrg int len; 887914d74bSmrg 897914d74bSmrg if (!dir || !theme) 904d939ec7Smrg return NULL; 91e6d5e4e0Smrg 927914d74bSmrg colon = strchr (dir, ':'); 937914d74bSmrg if (!colon) 947914d74bSmrg colon = dir + strlen (dir); 95e6d5e4e0Smrg 964d939ec7Smrg dirlen = (int) (colon - dir); 977914d74bSmrg 987914d74bSmrg tcolon = strchr (theme, ':'); 997914d74bSmrg if (!tcolon) 1007914d74bSmrg tcolon = theme + strlen (theme); 1017914d74bSmrg 1024d939ec7Smrg themelen = (int) (tcolon - theme); 103e6d5e4e0Smrg 1047914d74bSmrg home = NULL; 1057914d74bSmrg homelen = 0; 1067914d74bSmrg if (*dir == '~') 1077914d74bSmrg { 1087914d74bSmrg home = getenv ("HOME"); 1097914d74bSmrg if (!home) 1107914d74bSmrg return NULL; 1114d939ec7Smrg homelen = (int) strlen (home); 1127914d74bSmrg dir++; 1137914d74bSmrg dirlen--; 1147914d74bSmrg } 1157914d74bSmrg 1167914d74bSmrg /* 1177914d74bSmrg * add space for any needed directory separators, one per component, 1187914d74bSmrg * and one for the trailing null 1197914d74bSmrg */ 1207914d74bSmrg len = 1 + homelen + 1 + dirlen + 1 + themelen + 1; 121e6d5e4e0Smrg 1224d939ec7Smrg full = malloc ((size_t)len); 1237914d74bSmrg if (!full) 1247914d74bSmrg return NULL; 1257914d74bSmrg full[0] = '\0'; 1267914d74bSmrg 1277914d74bSmrg if (home) 1287914d74bSmrg _XcursorAddPathElt (full, home, -1); 1297914d74bSmrg _XcursorAddPathElt (full, dir, dirlen); 1307914d74bSmrg _XcursorAddPathElt (full, theme, themelen); 1317914d74bSmrg return full; 1327914d74bSmrg} 1337914d74bSmrg 1347914d74bSmrgstatic char * 1357914d74bSmrg_XcursorBuildFullname (const char *dir, const char *subdir, const char *file) 1367914d74bSmrg{ 1377914d74bSmrg char *full; 1387914d74bSmrg 1397914d74bSmrg if (!dir || !subdir || !file) 1404d939ec7Smrg return NULL; 1417914d74bSmrg 1427914d74bSmrg full = malloc (strlen (dir) + 1 + strlen (subdir) + 1 + strlen (file) + 1); 1437914d74bSmrg if (!full) 1447914d74bSmrg return NULL; 1457914d74bSmrg full[0] = '\0'; 1467914d74bSmrg _XcursorAddPathElt (full, dir, -1); 1477914d74bSmrg _XcursorAddPathElt (full, subdir, -1); 1487914d74bSmrg _XcursorAddPathElt (full, file, -1); 1497914d74bSmrg return full; 1507914d74bSmrg} 1517914d74bSmrg 1527914d74bSmrgstatic const char * 1537914d74bSmrg_XcursorNextPath (const char *path) 1547914d74bSmrg{ 1557914d74bSmrg char *colon = strchr (path, ':'); 1567914d74bSmrg 1577914d74bSmrg if (!colon) 1587914d74bSmrg return NULL; 1597914d74bSmrg return colon + 1; 1607914d74bSmrg} 1617914d74bSmrg 1627914d74bSmrg#define XcursorWhite(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') 1637914d74bSmrg#define XcursorSep(c) ((c) == ';' || (c) == ',') 1647914d74bSmrg 1657914d74bSmrgstatic char * 1667914d74bSmrg_XcursorThemeInherits (const char *full) 1677914d74bSmrg{ 1687914d74bSmrg char line[8192]; 1697914d74bSmrg char *result = NULL; 1707914d74bSmrg FILE *f; 1717914d74bSmrg 1727914d74bSmrg if (!full) 1734d939ec7Smrg return NULL; 1747914d74bSmrg 1757914d74bSmrg f = fopen (full, "r"); 1767914d74bSmrg if (f) 1777914d74bSmrg { 1787914d74bSmrg while (fgets (line, sizeof (line), f)) 1797914d74bSmrg { 1807914d74bSmrg if (!strncmp (line, "Inherits", 8)) 1817914d74bSmrg { 1827914d74bSmrg char *l = line + 8; 1837914d74bSmrg while (*l == ' ') l++; 1847914d74bSmrg if (*l != '=') continue; 1857914d74bSmrg l++; 1867914d74bSmrg while (*l == ' ') l++; 1879d0ccd10Smrg result = malloc (strlen (l) + 1); 1887914d74bSmrg if (result) 1897914d74bSmrg { 1904d939ec7Smrg char *r = result; 191e6d5e4e0Smrg while (*l) 1927914d74bSmrg { 1937914d74bSmrg while (XcursorSep(*l) || XcursorWhite (*l)) l++; 1947914d74bSmrg if (!*l) 1957914d74bSmrg break; 1967914d74bSmrg if (r != result) 1977914d74bSmrg *r++ = ':'; 198e6d5e4e0Smrg while (*l && !XcursorWhite(*l) && 1997914d74bSmrg !XcursorSep(*l)) 2007914d74bSmrg *r++ = *l++; 2017914d74bSmrg } 2027914d74bSmrg *r++ = '\0'; 2037914d74bSmrg } 2047914d74bSmrg break; 2057914d74bSmrg } 2067914d74bSmrg } 2077914d74bSmrg fclose (f); 2087914d74bSmrg } 2097914d74bSmrg return result; 2107914d74bSmrg} 2117914d74bSmrg 2127914d74bSmrg#define XCURSOR_SCAN_CORE ((FILE *) 1) 2134d939ec7Smrg#define MAX_INHERITS_DEPTH 32 2147914d74bSmrg 2157914d74bSmrgstatic FILE * 2167914d74bSmrgXcursorScanTheme (const char *theme, const char *name) 2177914d74bSmrg{ 2184d939ec7Smrg FILE *f = NULL; 2194d939ec7Smrg char *full; 2204d939ec7Smrg char *dir; 2214d939ec7Smrg const char *path; 2224d939ec7Smrg XcursorInherit inherits[MAX_INHERITS_DEPTH + 1]; 2234d939ec7Smrg int d; 2247914d74bSmrg 2257914d74bSmrg if (!theme || !name) 2264d939ec7Smrg return NULL; 2277914d74bSmrg 2287914d74bSmrg /* 2297914d74bSmrg * XCURSOR_CORE_THEME is a magic name; cursors from the core set 2307914d74bSmrg * are never found in any directory. Instead, a magic value is 2317914d74bSmrg * returned which truncates any search so that overlying functions 2327914d74bSmrg * can switch to equivalent core cursors 2337914d74bSmrg */ 2347914d74bSmrg if (!strcmp (theme, XCURSOR_CORE_THEME) && XcursorLibraryShape (name) >= 0) 2357914d74bSmrg return XCURSOR_SCAN_CORE; 2364d939ec7Smrg 2374d939ec7Smrg memset (inherits, 0, sizeof (inherits)); 2384d939ec7Smrg 2394d939ec7Smrg d = 0; 2404d939ec7Smrg inherits[d].theme = theme; 2414d939ec7Smrg 2424d939ec7Smrg while (f == NULL && d >= 0 && inherits[d].theme != NULL) 2437914d74bSmrg { 2444d939ec7Smrg /* 2454d939ec7Smrg * Scan this theme 2464d939ec7Smrg */ 2474d939ec7Smrg for (path = XcursorLibraryPath (); 2484d939ec7Smrg path && f == NULL; 2494d939ec7Smrg path = _XcursorNextPath (path)) 2507914d74bSmrg { 2514d939ec7Smrg dir = _XcursorBuildThemeDir (path, inherits[d].theme); 2524d939ec7Smrg if (dir) 2537914d74bSmrg { 2544d939ec7Smrg full = _XcursorBuildFullname (dir, "cursors", name); 2557914d74bSmrg if (full) 2567914d74bSmrg { 2574d939ec7Smrg f = fopen (full, "r"); 2587914d74bSmrg free (full); 2597914d74bSmrg } 2604d939ec7Smrg if (!f && inherits[d + 1].line == NULL) 2614d939ec7Smrg { 2624d939ec7Smrg if (d + 1 >= MAX_INHERITS_DEPTH) 2634d939ec7Smrg { 2644d939ec7Smrg free (dir); 2654d939ec7Smrg goto finish; 2664d939ec7Smrg } 2674d939ec7Smrg full = _XcursorBuildFullname (dir, "", "index.theme"); 2684d939ec7Smrg if (full) 2694d939ec7Smrg { 2704d939ec7Smrg inherits[d + 1].line = _XcursorThemeInherits (full); 2714d939ec7Smrg inherits[d + 1].theme = inherits[d + 1].line; 2724d939ec7Smrg free (full); 2734d939ec7Smrg } 2744d939ec7Smrg } 2754d939ec7Smrg free (dir); 2767914d74bSmrg } 2777914d74bSmrg } 2784d939ec7Smrg 2794d939ec7Smrg d++; 2804d939ec7Smrg while (d > 0 && inherits[d].theme == NULL) 2814d939ec7Smrg { 2824d939ec7Smrg free (inherits[d].line); 2834d939ec7Smrg inherits[d].line = NULL; 2844d939ec7Smrg 2854d939ec7Smrg if (--d == 0) 2864d939ec7Smrg inherits[d].theme = NULL; 2874d939ec7Smrg else 2884d939ec7Smrg inherits[d].theme = _XcursorNextPath (inherits[d].theme); 2894d939ec7Smrg } 2904d939ec7Smrg 2914d939ec7Smrg /* 2924d939ec7Smrg * Detect and break self reference loop early on. 2934d939ec7Smrg */ 2944d939ec7Smrg if (inherits[d].theme != NULL && strcmp (inherits[d].theme, theme) == 0) 2954d939ec7Smrg break; 2967914d74bSmrg } 2974d939ec7Smrg 2984d939ec7Smrgfinish: 2994d939ec7Smrg for (d = 1; d <= MAX_INHERITS_DEPTH; d++) 3004d939ec7Smrg free (inherits[d].line); 3014d939ec7Smrg 3027914d74bSmrg return f; 3037914d74bSmrg} 3047914d74bSmrg 3057914d74bSmrgXcursorImage * 3067914d74bSmrgXcursorLibraryLoadImage (const char *file, const char *theme, int size) 3077914d74bSmrg{ 3087914d74bSmrg FILE *f = NULL; 3097914d74bSmrg XcursorImage *image = NULL; 3107914d74bSmrg 3117914d74bSmrg if (!file) 3124d939ec7Smrg return NULL; 3137914d74bSmrg 3147914d74bSmrg if (theme) 3157914d74bSmrg f = XcursorScanTheme (theme, file); 3167914d74bSmrg if (!f) 3177914d74bSmrg f = XcursorScanTheme ("default", file); 3184d939ec7Smrg if (f != NULL && f != XCURSOR_SCAN_CORE) 3197914d74bSmrg { 3207914d74bSmrg image = XcursorFileLoadImage (f, size); 3217914d74bSmrg fclose (f); 3227914d74bSmrg } 3237914d74bSmrg return image; 3247914d74bSmrg} 3257914d74bSmrg 3267914d74bSmrgXcursorImages * 3277914d74bSmrgXcursorLibraryLoadImages (const char *file, const char *theme, int size) 3287914d74bSmrg{ 3297914d74bSmrg FILE *f = NULL; 3307914d74bSmrg XcursorImages *images = NULL; 3317914d74bSmrg 3327914d74bSmrg if (!file) 3334d939ec7Smrg return NULL; 3347914d74bSmrg 3357914d74bSmrg if (theme) 3367914d74bSmrg f = XcursorScanTheme (theme, file); 3377914d74bSmrg if (!f) 3387914d74bSmrg f = XcursorScanTheme ("default", file); 3394d939ec7Smrg if (f != NULL && f != XCURSOR_SCAN_CORE) 3407914d74bSmrg { 3417914d74bSmrg images = XcursorFileLoadImages (f, size); 3427914d74bSmrg if (images) 3437914d74bSmrg XcursorImagesSetName (images, file); 3447914d74bSmrg fclose (f); 3457914d74bSmrg } 3467914d74bSmrg return images; 3477914d74bSmrg} 3487914d74bSmrg 3497914d74bSmrgCursor 3507914d74bSmrgXcursorLibraryLoadCursor (Display *dpy, const char *file) 3517914d74bSmrg{ 3527914d74bSmrg int size = XcursorGetDefaultSize (dpy); 3537914d74bSmrg char *theme = XcursorGetTheme (dpy); 3547914d74bSmrg XcursorImages *images = XcursorLibraryLoadImages (file, theme, size); 3557914d74bSmrg Cursor cursor; 3567914d74bSmrg 3577914d74bSmrg if (!file) 3584d939ec7Smrg return 0; 359e6d5e4e0Smrg 3607914d74bSmrg if (!images) 3617914d74bSmrg { 3627914d74bSmrg int id = XcursorLibraryShape (file); 3637914d74bSmrg 3647914d74bSmrg if (id >= 0) 3654d939ec7Smrg return _XcursorCreateFontCursor (dpy, (unsigned) id); 3667914d74bSmrg else 3677914d74bSmrg return 0; 3687914d74bSmrg } 3697914d74bSmrg cursor = XcursorImagesLoadCursor (dpy, images); 3707914d74bSmrg XcursorImagesDestroy (images); 3717914d74bSmrg#if defined HAVE_XFIXES && XFIXES_MAJOR >= 2 3727914d74bSmrg XFixesSetCursorName (dpy, cursor, file); 3737914d74bSmrg#endif 3747914d74bSmrg return cursor; 3757914d74bSmrg} 3767914d74bSmrg 3777914d74bSmrgXcursorCursors * 3787914d74bSmrgXcursorLibraryLoadCursors (Display *dpy, const char *file) 3797914d74bSmrg{ 3807914d74bSmrg int size = XcursorGetDefaultSize (dpy); 3817914d74bSmrg char *theme = XcursorGetTheme (dpy); 3827914d74bSmrg XcursorImages *images = XcursorLibraryLoadImages (file, theme, size); 3837914d74bSmrg XcursorCursors *cursors; 384e6d5e4e0Smrg 3857914d74bSmrg if (!file) 3864d939ec7Smrg return NULL; 387e6d5e4e0Smrg 3887914d74bSmrg if (!images) 3897914d74bSmrg { 3907914d74bSmrg int id = XcursorLibraryShape (file); 3917914d74bSmrg 3927914d74bSmrg if (id >= 0) 3937914d74bSmrg { 3947914d74bSmrg cursors = XcursorCursorsCreate (dpy, 1); 3957914d74bSmrg if (cursors) 3967914d74bSmrg { 3974d939ec7Smrg cursors->cursors[0] = _XcursorCreateFontCursor (dpy, (unsigned) id); 3987914d74bSmrg if (cursors->cursors[0] == None) 3997914d74bSmrg { 4007914d74bSmrg XcursorCursorsDestroy (cursors); 4017914d74bSmrg cursors = NULL; 4027914d74bSmrg } 4037914d74bSmrg else 4047914d74bSmrg cursors->ncursor = 1; 4057914d74bSmrg } 4067914d74bSmrg } 4077914d74bSmrg else 4087914d74bSmrg cursors = NULL; 4097914d74bSmrg } 4107914d74bSmrg else 4117914d74bSmrg { 4127914d74bSmrg cursors = XcursorImagesLoadCursors (dpy, images); 4137914d74bSmrg XcursorImagesDestroy (images); 4147914d74bSmrg } 4157914d74bSmrg return cursors; 4167914d74bSmrg} 4177914d74bSmrg 4187914d74bSmrgstatic const char _XcursorStandardNames[] = 4197914d74bSmrg "X_cursor\0" 4207914d74bSmrg "arrow\0" 4217914d74bSmrg "based_arrow_down\0" 4227914d74bSmrg "based_arrow_up\0" 4237914d74bSmrg "boat\0" 4247914d74bSmrg "bogosity\0" 4257914d74bSmrg "bottom_left_corner\0" 4267914d74bSmrg "bottom_right_corner\0" 4277914d74bSmrg "bottom_side\0" 4287914d74bSmrg "bottom_tee\0" 4297914d74bSmrg "box_spiral\0" 4307914d74bSmrg "center_ptr\0" 4317914d74bSmrg "circle\0" 4327914d74bSmrg "clock\0" 4337914d74bSmrg "coffee_mug\0" 4347914d74bSmrg "cross\0" 4357914d74bSmrg "cross_reverse\0" 4367914d74bSmrg "crosshair\0" 4377914d74bSmrg "diamond_cross\0" 4387914d74bSmrg "dot\0" 4397914d74bSmrg "dotbox\0" 4407914d74bSmrg "double_arrow\0" 4417914d74bSmrg "draft_large\0" 4427914d74bSmrg "draft_small\0" 4437914d74bSmrg "draped_box\0" 4447914d74bSmrg "exchange\0" 4457914d74bSmrg "fleur\0" 4467914d74bSmrg "gobbler\0" 4477914d74bSmrg "gumby\0" 4487914d74bSmrg "hand1\0" 4497914d74bSmrg "hand2\0" 4507914d74bSmrg "heart\0" 4517914d74bSmrg "icon\0" 4527914d74bSmrg "iron_cross\0" 4537914d74bSmrg "left_ptr\0" 4547914d74bSmrg "left_side\0" 4557914d74bSmrg "left_tee\0" 4567914d74bSmrg "leftbutton\0" 4577914d74bSmrg "ll_angle\0" 4587914d74bSmrg "lr_angle\0" 4597914d74bSmrg "man\0" 4607914d74bSmrg "middlebutton\0" 4617914d74bSmrg "mouse\0" 4627914d74bSmrg "pencil\0" 4637914d74bSmrg "pirate\0" 4647914d74bSmrg "plus\0" 4657914d74bSmrg "question_arrow\0" 4667914d74bSmrg "right_ptr\0" 4677914d74bSmrg "right_side\0" 4687914d74bSmrg "right_tee\0" 4697914d74bSmrg "rightbutton\0" 4707914d74bSmrg "rtl_logo\0" 4717914d74bSmrg "sailboat\0" 4727914d74bSmrg "sb_down_arrow\0" 4737914d74bSmrg "sb_h_double_arrow\0" 4747914d74bSmrg "sb_left_arrow\0" 4757914d74bSmrg "sb_right_arrow\0" 4767914d74bSmrg "sb_up_arrow\0" 4777914d74bSmrg "sb_v_double_arrow\0" 4787914d74bSmrg "shuttle\0" 4797914d74bSmrg "sizing\0" 4807914d74bSmrg "spider\0" 4817914d74bSmrg "spraycan\0" 4827914d74bSmrg "star\0" 4837914d74bSmrg "target\0" 4847914d74bSmrg "tcross\0" 4857914d74bSmrg "top_left_arrow\0" 4867914d74bSmrg "top_left_corner\0" 4877914d74bSmrg "top_right_corner\0" 4887914d74bSmrg "top_side\0" 4897914d74bSmrg "top_tee\0" 4907914d74bSmrg "trek\0" 4917914d74bSmrg "ul_angle\0" 4927914d74bSmrg "umbrella\0" 4937914d74bSmrg "ur_angle\0" 4947914d74bSmrg "watch\0" 4957914d74bSmrg "xterm"; 4967914d74bSmrg 4977914d74bSmrgstatic const unsigned short _XcursorStandardNameOffsets[] = { 4987914d74bSmrg 0, 9, 15, 32, 47, 52, 61, 80, 100, 112, 123, 134, 145, 152, 158, 4997914d74bSmrg 169, 175, 189, 199, 213, 217, 224, 237, 249, 261, 272, 281, 287, 5007914d74bSmrg 295, 301, 307, 313, 319, 324, 335, 344, 354, 363, 374, 383, 392, 5017914d74bSmrg 396, 409, 415, 422, 429, 434, 449, 459, 470, 480, 492, 501, 510, 5027914d74bSmrg 524, 542, 556, 571, 583, 601, 609, 616, 623, 632, 637, 644, 651, 5037914d74bSmrg 666, 682, 699, 708, 716, 721, 730, 739, 748, 754 5047914d74bSmrg}; 5057914d74bSmrg 5067914d74bSmrg#define NUM_STANDARD_NAMES (sizeof _XcursorStandardNameOffsets / sizeof _XcursorStandardNameOffsets[0]) 5077914d74bSmrg 5087914d74bSmrg#define STANDARD_NAME(id) \ 5097914d74bSmrg _XcursorStandardNames + _XcursorStandardNameOffsets[id] 5107914d74bSmrg 5117914d74bSmrgXcursorImage * 5127914d74bSmrgXcursorShapeLoadImage (unsigned int shape, const char *theme, int size) 5137914d74bSmrg{ 5147914d74bSmrg unsigned int id = shape >> 1; 5157914d74bSmrg 5167914d74bSmrg if (id < NUM_STANDARD_NAMES) 5177914d74bSmrg return XcursorLibraryLoadImage (STANDARD_NAME (id), theme, size); 5187914d74bSmrg else 5197914d74bSmrg return NULL; 5207914d74bSmrg} 5217914d74bSmrg 5227914d74bSmrgXcursorImages * 5237914d74bSmrgXcursorShapeLoadImages (unsigned int shape, const char *theme, int size) 5247914d74bSmrg{ 5257914d74bSmrg unsigned int id = shape >> 1; 5267914d74bSmrg 5277914d74bSmrg if (id < NUM_STANDARD_NAMES) 5287914d74bSmrg return XcursorLibraryLoadImages (STANDARD_NAME (id), theme, size); 5297914d74bSmrg else 5307914d74bSmrg return NULL; 5317914d74bSmrg} 5327914d74bSmrg 5337914d74bSmrgCursor 5347914d74bSmrgXcursorShapeLoadCursor (Display *dpy, unsigned int shape) 5357914d74bSmrg{ 5367914d74bSmrg unsigned int id = shape >> 1; 5377914d74bSmrg 5387914d74bSmrg if (id < NUM_STANDARD_NAMES) 5397914d74bSmrg return XcursorLibraryLoadCursor (dpy, STANDARD_NAME (id)); 5407914d74bSmrg else 5417914d74bSmrg return 0; 5427914d74bSmrg} 5437914d74bSmrg 5447914d74bSmrgXcursorCursors * 5457914d74bSmrgXcursorShapeLoadCursors (Display *dpy, unsigned int shape) 5467914d74bSmrg{ 5477914d74bSmrg unsigned int id = shape >> 1; 5487914d74bSmrg 5497914d74bSmrg if (id < NUM_STANDARD_NAMES) 5507914d74bSmrg return XcursorLibraryLoadCursors (dpy, STANDARD_NAME (id)); 5517914d74bSmrg else 5527914d74bSmrg return NULL; 5537914d74bSmrg} 5547914d74bSmrg 5557914d74bSmrgint 5567914d74bSmrgXcursorLibraryShape (const char *library) 5577914d74bSmrg{ 5587914d74bSmrg int low, high; 5597914d74bSmrg 5607914d74bSmrg low = 0; 5617914d74bSmrg high = NUM_STANDARD_NAMES - 1; 5627914d74bSmrg while (low < high - 1) 5637914d74bSmrg { 5644d939ec7Smrg int mid = (low + high) >> 1; 5654d939ec7Smrg int c = strcmp (library, STANDARD_NAME (mid)); 5667914d74bSmrg if (c == 0) 5677914d74bSmrg return (mid << 1); 5687914d74bSmrg if (c > 0) 5697914d74bSmrg low = mid; 5707914d74bSmrg else 5717914d74bSmrg high = mid; 5727914d74bSmrg } 5737914d74bSmrg while (low <= high) 5747914d74bSmrg { 5757914d74bSmrg if (!strcmp (library, STANDARD_NAME (low))) 5767914d74bSmrg return (low << 1); 5777914d74bSmrg low++; 5787914d74bSmrg } 5797914d74bSmrg return -1; 5807914d74bSmrg} 581