library.c revision cdce750a
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 357914d74bSmrgconst char * 367914d74bSmrgXcursorLibraryPath (void) 377914d74bSmrg{ 387914d74bSmrg static const char *path; 397914d74bSmrg 407914d74bSmrg if (!path) 417914d74bSmrg { 427914d74bSmrg path = getenv ("XCURSOR_PATH"); 437914d74bSmrg if (!path) 447914d74bSmrg path = XCURSORPATH; 457914d74bSmrg } 467914d74bSmrg return path; 477914d74bSmrg} 487914d74bSmrg 497914d74bSmrgstatic void 507914d74bSmrg_XcursorAddPathElt (char *path, const char *elt, int len) 517914d74bSmrg{ 529d0ccd10Smrg size_t pathlen = strlen (path); 53e6d5e4e0Smrg 547914d74bSmrg /* append / if the path doesn't currently have one */ 557914d74bSmrg if (path[0] == '\0' || path[pathlen - 1] != '/') 567914d74bSmrg { 577914d74bSmrg strcat (path, "/"); 587914d74bSmrg pathlen++; 597914d74bSmrg } 607914d74bSmrg if (len == -1) 617914d74bSmrg len = strlen (elt); 627914d74bSmrg /* strip leading slashes */ 637914d74bSmrg while (len && elt[0] == '/') 647914d74bSmrg { 657914d74bSmrg elt++; 667914d74bSmrg len--; 677914d74bSmrg } 687914d74bSmrg strncpy (path + pathlen, elt, len); 697914d74bSmrg path[pathlen + len] = '\0'; 707914d74bSmrg} 717914d74bSmrg 727914d74bSmrgstatic char * 737914d74bSmrg_XcursorBuildThemeDir (const char *dir, const char *theme) 747914d74bSmrg{ 757914d74bSmrg const char *colon; 767914d74bSmrg const char *tcolon; 777914d74bSmrg char *full; 787914d74bSmrg char *home; 797914d74bSmrg int dirlen; 807914d74bSmrg int homelen; 817914d74bSmrg int themelen; 827914d74bSmrg int len; 837914d74bSmrg 847914d74bSmrg if (!dir || !theme) 857914d74bSmrg return NULL; 86e6d5e4e0Smrg 877914d74bSmrg colon = strchr (dir, ':'); 887914d74bSmrg if (!colon) 897914d74bSmrg colon = dir + strlen (dir); 90e6d5e4e0Smrg 917914d74bSmrg dirlen = colon - dir; 927914d74bSmrg 937914d74bSmrg tcolon = strchr (theme, ':'); 947914d74bSmrg if (!tcolon) 957914d74bSmrg tcolon = theme + strlen (theme); 967914d74bSmrg 977914d74bSmrg themelen = tcolon - theme; 98e6d5e4e0Smrg 997914d74bSmrg home = NULL; 1007914d74bSmrg homelen = 0; 1017914d74bSmrg if (*dir == '~') 1027914d74bSmrg { 1037914d74bSmrg home = getenv ("HOME"); 1047914d74bSmrg if (!home) 1057914d74bSmrg return NULL; 1067914d74bSmrg homelen = strlen (home); 1077914d74bSmrg dir++; 1087914d74bSmrg dirlen--; 1097914d74bSmrg } 1107914d74bSmrg 1117914d74bSmrg /* 1127914d74bSmrg * add space for any needed directory separators, one per component, 1137914d74bSmrg * and one for the trailing null 1147914d74bSmrg */ 1157914d74bSmrg len = 1 + homelen + 1 + dirlen + 1 + themelen + 1; 116e6d5e4e0Smrg 1177914d74bSmrg full = malloc (len); 1187914d74bSmrg if (!full) 1197914d74bSmrg return NULL; 1207914d74bSmrg full[0] = '\0'; 1217914d74bSmrg 1227914d74bSmrg if (home) 1237914d74bSmrg _XcursorAddPathElt (full, home, -1); 1247914d74bSmrg _XcursorAddPathElt (full, dir, dirlen); 1257914d74bSmrg _XcursorAddPathElt (full, theme, themelen); 1267914d74bSmrg return full; 1277914d74bSmrg} 1287914d74bSmrg 1297914d74bSmrgstatic char * 1307914d74bSmrg_XcursorBuildFullname (const char *dir, const char *subdir, const char *file) 1317914d74bSmrg{ 1327914d74bSmrg char *full; 1337914d74bSmrg 1347914d74bSmrg if (!dir || !subdir || !file) 1357914d74bSmrg return NULL; 1367914d74bSmrg 1377914d74bSmrg full = malloc (strlen (dir) + 1 + strlen (subdir) + 1 + strlen (file) + 1); 1387914d74bSmrg if (!full) 1397914d74bSmrg return NULL; 1407914d74bSmrg full[0] = '\0'; 1417914d74bSmrg _XcursorAddPathElt (full, dir, -1); 1427914d74bSmrg _XcursorAddPathElt (full, subdir, -1); 1437914d74bSmrg _XcursorAddPathElt (full, file, -1); 1447914d74bSmrg return full; 1457914d74bSmrg} 1467914d74bSmrg 1477914d74bSmrgstatic const char * 1487914d74bSmrg_XcursorNextPath (const char *path) 1497914d74bSmrg{ 1507914d74bSmrg char *colon = strchr (path, ':'); 1517914d74bSmrg 1527914d74bSmrg if (!colon) 1537914d74bSmrg return NULL; 1547914d74bSmrg return colon + 1; 1557914d74bSmrg} 1567914d74bSmrg 1577914d74bSmrg#define XcursorWhite(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') 1587914d74bSmrg#define XcursorSep(c) ((c) == ';' || (c) == ',') 1597914d74bSmrg 1607914d74bSmrgstatic char * 1617914d74bSmrg_XcursorThemeInherits (const char *full) 1627914d74bSmrg{ 1637914d74bSmrg char line[8192]; 1647914d74bSmrg char *result = NULL; 1657914d74bSmrg FILE *f; 1667914d74bSmrg 1677914d74bSmrg if (!full) 1687914d74bSmrg return NULL; 1697914d74bSmrg 1707914d74bSmrg f = fopen (full, "r"); 1717914d74bSmrg if (f) 1727914d74bSmrg { 1737914d74bSmrg while (fgets (line, sizeof (line), f)) 1747914d74bSmrg { 1757914d74bSmrg if (!strncmp (line, "Inherits", 8)) 1767914d74bSmrg { 1777914d74bSmrg char *l = line + 8; 1787914d74bSmrg char *r; 1797914d74bSmrg while (*l == ' ') l++; 1807914d74bSmrg if (*l != '=') continue; 1817914d74bSmrg l++; 1827914d74bSmrg while (*l == ' ') l++; 1839d0ccd10Smrg result = malloc (strlen (l) + 1); 1847914d74bSmrg if (result) 1857914d74bSmrg { 1867914d74bSmrg r = result; 187e6d5e4e0Smrg while (*l) 1887914d74bSmrg { 1897914d74bSmrg while (XcursorSep(*l) || XcursorWhite (*l)) l++; 1907914d74bSmrg if (!*l) 1917914d74bSmrg break; 1927914d74bSmrg if (r != result) 1937914d74bSmrg *r++ = ':'; 194e6d5e4e0Smrg while (*l && !XcursorWhite(*l) && 1957914d74bSmrg !XcursorSep(*l)) 1967914d74bSmrg *r++ = *l++; 1977914d74bSmrg } 1987914d74bSmrg *r++ = '\0'; 1997914d74bSmrg } 2007914d74bSmrg break; 2017914d74bSmrg } 2027914d74bSmrg } 2037914d74bSmrg fclose (f); 2047914d74bSmrg } 2057914d74bSmrg return result; 2067914d74bSmrg} 2077914d74bSmrg 2087914d74bSmrg#define XCURSOR_SCAN_CORE ((FILE *) 1) 2097914d74bSmrg 2107914d74bSmrgstatic FILE * 2117914d74bSmrgXcursorScanTheme (const char *theme, const char *name) 2127914d74bSmrg{ 2137914d74bSmrg FILE *f = NULL; 2147914d74bSmrg char *full; 2157914d74bSmrg char *dir; 2167914d74bSmrg const char *path; 2177914d74bSmrg char *inherits = NULL; 2187914d74bSmrg const char *i; 2197914d74bSmrg 2207914d74bSmrg if (!theme || !name) 2217914d74bSmrg return NULL; 2227914d74bSmrg 2237914d74bSmrg /* 2247914d74bSmrg * XCURSOR_CORE_THEME is a magic name; cursors from the core set 2257914d74bSmrg * are never found in any directory. Instead, a magic value is 2267914d74bSmrg * returned which truncates any search so that overlying functions 2277914d74bSmrg * can switch to equivalent core cursors 2287914d74bSmrg */ 2297914d74bSmrg if (!strcmp (theme, XCURSOR_CORE_THEME) && XcursorLibraryShape (name) >= 0) 2307914d74bSmrg return XCURSOR_SCAN_CORE; 2317914d74bSmrg /* 2327914d74bSmrg * Scan this theme 2337914d74bSmrg */ 2347914d74bSmrg for (path = XcursorLibraryPath (); 235e169010aSmrg path && f == NULL; 2367914d74bSmrg path = _XcursorNextPath (path)) 2377914d74bSmrg { 2387914d74bSmrg dir = _XcursorBuildThemeDir (path, theme); 2397914d74bSmrg if (dir) 2407914d74bSmrg { 2417914d74bSmrg full = _XcursorBuildFullname (dir, "cursors", name); 2427914d74bSmrg if (full) 2437914d74bSmrg { 2447914d74bSmrg f = fopen (full, "r"); 2457914d74bSmrg free (full); 2467914d74bSmrg } 2477914d74bSmrg if (!f && !inherits) 2487914d74bSmrg { 2497914d74bSmrg full = _XcursorBuildFullname (dir, "", "index.theme"); 2507914d74bSmrg if (full) 2517914d74bSmrg { 2527914d74bSmrg inherits = _XcursorThemeInherits (full); 2537914d74bSmrg free (full); 2547914d74bSmrg } 2557914d74bSmrg } 2567914d74bSmrg free (dir); 2577914d74bSmrg } 2587914d74bSmrg } 2597914d74bSmrg /* 2607914d74bSmrg * Recurse to scan inherited themes 2617914d74bSmrg */ 262e169010aSmrg for (i = inherits; i && f == NULL; i = _XcursorNextPath (i)) 263cdce750aSmrg { 264cdce750aSmrg if (strcmp(i, theme) != 0) 265cdce750aSmrg f = XcursorScanTheme (i, name); 266cdce750aSmrg else 267cdce750aSmrg printf("Not calling XcursorScanTheme because of circular dependency: %s. %s", i, name); 268cdce750aSmrg } 2697914d74bSmrg if (inherits != NULL) 2707914d74bSmrg free (inherits); 2717914d74bSmrg return f; 2727914d74bSmrg} 2737914d74bSmrg 2747914d74bSmrgXcursorImage * 2757914d74bSmrgXcursorLibraryLoadImage (const char *file, const char *theme, int size) 2767914d74bSmrg{ 2777914d74bSmrg FILE *f = NULL; 2787914d74bSmrg XcursorImage *image = NULL; 2797914d74bSmrg 2807914d74bSmrg if (!file) 2817914d74bSmrg return NULL; 2827914d74bSmrg 2837914d74bSmrg if (theme) 2847914d74bSmrg f = XcursorScanTheme (theme, file); 2857914d74bSmrg if (!f) 2867914d74bSmrg f = XcursorScanTheme ("default", file); 2877914d74bSmrg if (f == XCURSOR_SCAN_CORE) 2887914d74bSmrg return NULL; 2897914d74bSmrg if (f) 2907914d74bSmrg { 2917914d74bSmrg image = XcursorFileLoadImage (f, size); 2927914d74bSmrg fclose (f); 2937914d74bSmrg } 2947914d74bSmrg return image; 2957914d74bSmrg} 2967914d74bSmrg 2977914d74bSmrgXcursorImages * 2987914d74bSmrgXcursorLibraryLoadImages (const char *file, const char *theme, int size) 2997914d74bSmrg{ 3007914d74bSmrg FILE *f = NULL; 3017914d74bSmrg XcursorImages *images = NULL; 3027914d74bSmrg 3037914d74bSmrg if (!file) 3047914d74bSmrg return NULL; 3057914d74bSmrg 3067914d74bSmrg if (theme) 3077914d74bSmrg f = XcursorScanTheme (theme, file); 3087914d74bSmrg if (!f) 3097914d74bSmrg f = XcursorScanTheme ("default", file); 3107914d74bSmrg if (f == XCURSOR_SCAN_CORE) 3117914d74bSmrg return NULL; 3127914d74bSmrg if (f) 3137914d74bSmrg { 3147914d74bSmrg images = XcursorFileLoadImages (f, size); 3157914d74bSmrg if (images) 3167914d74bSmrg XcursorImagesSetName (images, file); 3177914d74bSmrg fclose (f); 3187914d74bSmrg } 3197914d74bSmrg return images; 3207914d74bSmrg} 3217914d74bSmrg 3227914d74bSmrgCursor 3237914d74bSmrgXcursorLibraryLoadCursor (Display *dpy, const char *file) 3247914d74bSmrg{ 3257914d74bSmrg int size = XcursorGetDefaultSize (dpy); 3267914d74bSmrg char *theme = XcursorGetTheme (dpy); 3277914d74bSmrg XcursorImages *images = XcursorLibraryLoadImages (file, theme, size); 3287914d74bSmrg Cursor cursor; 3297914d74bSmrg 3307914d74bSmrg if (!file) 3317914d74bSmrg return 0; 332e6d5e4e0Smrg 3337914d74bSmrg if (!images) 3347914d74bSmrg { 3357914d74bSmrg int id = XcursorLibraryShape (file); 3367914d74bSmrg 3377914d74bSmrg if (id >= 0) 3387914d74bSmrg return _XcursorCreateFontCursor (dpy, id); 3397914d74bSmrg else 3407914d74bSmrg return 0; 3417914d74bSmrg } 3427914d74bSmrg cursor = XcursorImagesLoadCursor (dpy, images); 3437914d74bSmrg XcursorImagesDestroy (images); 3447914d74bSmrg#if defined HAVE_XFIXES && XFIXES_MAJOR >= 2 3457914d74bSmrg XFixesSetCursorName (dpy, cursor, file); 3467914d74bSmrg#endif 3477914d74bSmrg return cursor; 3487914d74bSmrg} 3497914d74bSmrg 3507914d74bSmrgXcursorCursors * 3517914d74bSmrgXcursorLibraryLoadCursors (Display *dpy, const char *file) 3527914d74bSmrg{ 3537914d74bSmrg int size = XcursorGetDefaultSize (dpy); 3547914d74bSmrg char *theme = XcursorGetTheme (dpy); 3557914d74bSmrg XcursorImages *images = XcursorLibraryLoadImages (file, theme, size); 3567914d74bSmrg XcursorCursors *cursors; 357e6d5e4e0Smrg 3587914d74bSmrg if (!file) 3597914d74bSmrg return NULL; 360e6d5e4e0Smrg 3617914d74bSmrg if (!images) 3627914d74bSmrg { 3637914d74bSmrg int id = XcursorLibraryShape (file); 3647914d74bSmrg 3657914d74bSmrg if (id >= 0) 3667914d74bSmrg { 3677914d74bSmrg cursors = XcursorCursorsCreate (dpy, 1); 3687914d74bSmrg if (cursors) 3697914d74bSmrg { 3707914d74bSmrg cursors->cursors[0] = _XcursorCreateFontCursor (dpy, id); 3717914d74bSmrg if (cursors->cursors[0] == None) 3727914d74bSmrg { 3737914d74bSmrg XcursorCursorsDestroy (cursors); 3747914d74bSmrg cursors = NULL; 3757914d74bSmrg } 3767914d74bSmrg else 3777914d74bSmrg cursors->ncursor = 1; 3787914d74bSmrg } 3797914d74bSmrg } 3807914d74bSmrg else 3817914d74bSmrg cursors = NULL; 3827914d74bSmrg } 3837914d74bSmrg else 3847914d74bSmrg { 3857914d74bSmrg cursors = XcursorImagesLoadCursors (dpy, images); 3867914d74bSmrg XcursorImagesDestroy (images); 3877914d74bSmrg } 3887914d74bSmrg return cursors; 3897914d74bSmrg} 3907914d74bSmrg 3917914d74bSmrgstatic const char _XcursorStandardNames[] = 3927914d74bSmrg "X_cursor\0" 3937914d74bSmrg "arrow\0" 3947914d74bSmrg "based_arrow_down\0" 3957914d74bSmrg "based_arrow_up\0" 3967914d74bSmrg "boat\0" 3977914d74bSmrg "bogosity\0" 3987914d74bSmrg "bottom_left_corner\0" 3997914d74bSmrg "bottom_right_corner\0" 4007914d74bSmrg "bottom_side\0" 4017914d74bSmrg "bottom_tee\0" 4027914d74bSmrg "box_spiral\0" 4037914d74bSmrg "center_ptr\0" 4047914d74bSmrg "circle\0" 4057914d74bSmrg "clock\0" 4067914d74bSmrg "coffee_mug\0" 4077914d74bSmrg "cross\0" 4087914d74bSmrg "cross_reverse\0" 4097914d74bSmrg "crosshair\0" 4107914d74bSmrg "diamond_cross\0" 4117914d74bSmrg "dot\0" 4127914d74bSmrg "dotbox\0" 4137914d74bSmrg "double_arrow\0" 4147914d74bSmrg "draft_large\0" 4157914d74bSmrg "draft_small\0" 4167914d74bSmrg "draped_box\0" 4177914d74bSmrg "exchange\0" 4187914d74bSmrg "fleur\0" 4197914d74bSmrg "gobbler\0" 4207914d74bSmrg "gumby\0" 4217914d74bSmrg "hand1\0" 4227914d74bSmrg "hand2\0" 4237914d74bSmrg "heart\0" 4247914d74bSmrg "icon\0" 4257914d74bSmrg "iron_cross\0" 4267914d74bSmrg "left_ptr\0" 4277914d74bSmrg "left_side\0" 4287914d74bSmrg "left_tee\0" 4297914d74bSmrg "leftbutton\0" 4307914d74bSmrg "ll_angle\0" 4317914d74bSmrg "lr_angle\0" 4327914d74bSmrg "man\0" 4337914d74bSmrg "middlebutton\0" 4347914d74bSmrg "mouse\0" 4357914d74bSmrg "pencil\0" 4367914d74bSmrg "pirate\0" 4377914d74bSmrg "plus\0" 4387914d74bSmrg "question_arrow\0" 4397914d74bSmrg "right_ptr\0" 4407914d74bSmrg "right_side\0" 4417914d74bSmrg "right_tee\0" 4427914d74bSmrg "rightbutton\0" 4437914d74bSmrg "rtl_logo\0" 4447914d74bSmrg "sailboat\0" 4457914d74bSmrg "sb_down_arrow\0" 4467914d74bSmrg "sb_h_double_arrow\0" 4477914d74bSmrg "sb_left_arrow\0" 4487914d74bSmrg "sb_right_arrow\0" 4497914d74bSmrg "sb_up_arrow\0" 4507914d74bSmrg "sb_v_double_arrow\0" 4517914d74bSmrg "shuttle\0" 4527914d74bSmrg "sizing\0" 4537914d74bSmrg "spider\0" 4547914d74bSmrg "spraycan\0" 4557914d74bSmrg "star\0" 4567914d74bSmrg "target\0" 4577914d74bSmrg "tcross\0" 4587914d74bSmrg "top_left_arrow\0" 4597914d74bSmrg "top_left_corner\0" 4607914d74bSmrg "top_right_corner\0" 4617914d74bSmrg "top_side\0" 4627914d74bSmrg "top_tee\0" 4637914d74bSmrg "trek\0" 4647914d74bSmrg "ul_angle\0" 4657914d74bSmrg "umbrella\0" 4667914d74bSmrg "ur_angle\0" 4677914d74bSmrg "watch\0" 4687914d74bSmrg "xterm"; 4697914d74bSmrg 4707914d74bSmrgstatic const unsigned short _XcursorStandardNameOffsets[] = { 4717914d74bSmrg 0, 9, 15, 32, 47, 52, 61, 80, 100, 112, 123, 134, 145, 152, 158, 4727914d74bSmrg 169, 175, 189, 199, 213, 217, 224, 237, 249, 261, 272, 281, 287, 4737914d74bSmrg 295, 301, 307, 313, 319, 324, 335, 344, 354, 363, 374, 383, 392, 4747914d74bSmrg 396, 409, 415, 422, 429, 434, 449, 459, 470, 480, 492, 501, 510, 4757914d74bSmrg 524, 542, 556, 571, 583, 601, 609, 616, 623, 632, 637, 644, 651, 4767914d74bSmrg 666, 682, 699, 708, 716, 721, 730, 739, 748, 754 4777914d74bSmrg}; 4787914d74bSmrg 4797914d74bSmrg#define NUM_STANDARD_NAMES (sizeof _XcursorStandardNameOffsets / sizeof _XcursorStandardNameOffsets[0]) 4807914d74bSmrg 4817914d74bSmrg#define STANDARD_NAME(id) \ 4827914d74bSmrg _XcursorStandardNames + _XcursorStandardNameOffsets[id] 4837914d74bSmrg 4847914d74bSmrgXcursorImage * 4857914d74bSmrgXcursorShapeLoadImage (unsigned int shape, const char *theme, int size) 4867914d74bSmrg{ 4877914d74bSmrg unsigned int id = shape >> 1; 4887914d74bSmrg 4897914d74bSmrg if (id < NUM_STANDARD_NAMES) 4907914d74bSmrg return XcursorLibraryLoadImage (STANDARD_NAME (id), theme, size); 4917914d74bSmrg else 4927914d74bSmrg return NULL; 4937914d74bSmrg} 4947914d74bSmrg 4957914d74bSmrgXcursorImages * 4967914d74bSmrgXcursorShapeLoadImages (unsigned int shape, const char *theme, int size) 4977914d74bSmrg{ 4987914d74bSmrg unsigned int id = shape >> 1; 4997914d74bSmrg 5007914d74bSmrg if (id < NUM_STANDARD_NAMES) 5017914d74bSmrg return XcursorLibraryLoadImages (STANDARD_NAME (id), theme, size); 5027914d74bSmrg else 5037914d74bSmrg return NULL; 5047914d74bSmrg} 5057914d74bSmrg 5067914d74bSmrgCursor 5077914d74bSmrgXcursorShapeLoadCursor (Display *dpy, unsigned int shape) 5087914d74bSmrg{ 5097914d74bSmrg unsigned int id = shape >> 1; 5107914d74bSmrg 5117914d74bSmrg if (id < NUM_STANDARD_NAMES) 5127914d74bSmrg return XcursorLibraryLoadCursor (dpy, STANDARD_NAME (id)); 5137914d74bSmrg else 5147914d74bSmrg return 0; 5157914d74bSmrg} 5167914d74bSmrg 5177914d74bSmrgXcursorCursors * 5187914d74bSmrgXcursorShapeLoadCursors (Display *dpy, unsigned int shape) 5197914d74bSmrg{ 5207914d74bSmrg unsigned int id = shape >> 1; 5217914d74bSmrg 5227914d74bSmrg if (id < NUM_STANDARD_NAMES) 5237914d74bSmrg return XcursorLibraryLoadCursors (dpy, STANDARD_NAME (id)); 5247914d74bSmrg else 5257914d74bSmrg return NULL; 5267914d74bSmrg} 5277914d74bSmrg 5287914d74bSmrgint 5297914d74bSmrgXcursorLibraryShape (const char *library) 5307914d74bSmrg{ 5317914d74bSmrg int low, high; 5327914d74bSmrg int mid; 5337914d74bSmrg int c; 5347914d74bSmrg 5357914d74bSmrg low = 0; 5367914d74bSmrg high = NUM_STANDARD_NAMES - 1; 5377914d74bSmrg while (low < high - 1) 5387914d74bSmrg { 5397914d74bSmrg mid = (low + high) >> 1; 5407914d74bSmrg c = strcmp (library, STANDARD_NAME (mid)); 5417914d74bSmrg if (c == 0) 5427914d74bSmrg return (mid << 1); 5437914d74bSmrg if (c > 0) 5447914d74bSmrg low = mid; 5457914d74bSmrg else 5467914d74bSmrg high = mid; 5477914d74bSmrg } 5487914d74bSmrg while (low <= high) 5497914d74bSmrg { 5507914d74bSmrg if (!strcmp (library, STANDARD_NAME (low))) 5517914d74bSmrg return (low << 1); 5527914d74bSmrg low++; 5537914d74bSmrg } 5547914d74bSmrg return -1; 5557914d74bSmrg} 556