library.c revision 9d0ccd10
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 327914d74bSmrg#define XCURSORPATH "~/.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)) 2637914d74bSmrg f = XcursorScanTheme (i, name); 2647914d74bSmrg if (inherits != NULL) 2657914d74bSmrg free (inherits); 2667914d74bSmrg return f; 2677914d74bSmrg} 2687914d74bSmrg 2697914d74bSmrgXcursorImage * 2707914d74bSmrgXcursorLibraryLoadImage (const char *file, const char *theme, int size) 2717914d74bSmrg{ 2727914d74bSmrg FILE *f = NULL; 2737914d74bSmrg XcursorImage *image = NULL; 2747914d74bSmrg 2757914d74bSmrg if (!file) 2767914d74bSmrg return NULL; 2777914d74bSmrg 2787914d74bSmrg if (theme) 2797914d74bSmrg f = XcursorScanTheme (theme, file); 2807914d74bSmrg if (!f) 2817914d74bSmrg f = XcursorScanTheme ("default", file); 2827914d74bSmrg if (f == XCURSOR_SCAN_CORE) 2837914d74bSmrg return NULL; 2847914d74bSmrg if (f) 2857914d74bSmrg { 2867914d74bSmrg image = XcursorFileLoadImage (f, size); 2877914d74bSmrg fclose (f); 2887914d74bSmrg } 2897914d74bSmrg return image; 2907914d74bSmrg} 2917914d74bSmrg 2927914d74bSmrgXcursorImages * 2937914d74bSmrgXcursorLibraryLoadImages (const char *file, const char *theme, int size) 2947914d74bSmrg{ 2957914d74bSmrg FILE *f = NULL; 2967914d74bSmrg XcursorImages *images = NULL; 2977914d74bSmrg 2987914d74bSmrg if (!file) 2997914d74bSmrg return NULL; 3007914d74bSmrg 3017914d74bSmrg if (theme) 3027914d74bSmrg f = XcursorScanTheme (theme, file); 3037914d74bSmrg if (!f) 3047914d74bSmrg f = XcursorScanTheme ("default", file); 3057914d74bSmrg if (f == XCURSOR_SCAN_CORE) 3067914d74bSmrg return NULL; 3077914d74bSmrg if (f) 3087914d74bSmrg { 3097914d74bSmrg images = XcursorFileLoadImages (f, size); 3107914d74bSmrg if (images) 3117914d74bSmrg XcursorImagesSetName (images, file); 3127914d74bSmrg fclose (f); 3137914d74bSmrg } 3147914d74bSmrg return images; 3157914d74bSmrg} 3167914d74bSmrg 3177914d74bSmrgCursor 3187914d74bSmrgXcursorLibraryLoadCursor (Display *dpy, const char *file) 3197914d74bSmrg{ 3207914d74bSmrg int size = XcursorGetDefaultSize (dpy); 3217914d74bSmrg char *theme = XcursorGetTheme (dpy); 3227914d74bSmrg XcursorImages *images = XcursorLibraryLoadImages (file, theme, size); 3237914d74bSmrg Cursor cursor; 3247914d74bSmrg 3257914d74bSmrg if (!file) 3267914d74bSmrg return 0; 327e6d5e4e0Smrg 3287914d74bSmrg if (!images) 3297914d74bSmrg { 3307914d74bSmrg int id = XcursorLibraryShape (file); 3317914d74bSmrg 3327914d74bSmrg if (id >= 0) 3337914d74bSmrg return _XcursorCreateFontCursor (dpy, id); 3347914d74bSmrg else 3357914d74bSmrg return 0; 3367914d74bSmrg } 3377914d74bSmrg cursor = XcursorImagesLoadCursor (dpy, images); 3387914d74bSmrg XcursorImagesDestroy (images); 3397914d74bSmrg#if defined HAVE_XFIXES && XFIXES_MAJOR >= 2 3407914d74bSmrg XFixesSetCursorName (dpy, cursor, file); 3417914d74bSmrg#endif 3427914d74bSmrg return cursor; 3437914d74bSmrg} 3447914d74bSmrg 3457914d74bSmrgXcursorCursors * 3467914d74bSmrgXcursorLibraryLoadCursors (Display *dpy, const char *file) 3477914d74bSmrg{ 3487914d74bSmrg int size = XcursorGetDefaultSize (dpy); 3497914d74bSmrg char *theme = XcursorGetTheme (dpy); 3507914d74bSmrg XcursorImages *images = XcursorLibraryLoadImages (file, theme, size); 3517914d74bSmrg XcursorCursors *cursors; 352e6d5e4e0Smrg 3537914d74bSmrg if (!file) 3547914d74bSmrg return NULL; 355e6d5e4e0Smrg 3567914d74bSmrg if (!images) 3577914d74bSmrg { 3587914d74bSmrg int id = XcursorLibraryShape (file); 3597914d74bSmrg 3607914d74bSmrg if (id >= 0) 3617914d74bSmrg { 3627914d74bSmrg cursors = XcursorCursorsCreate (dpy, 1); 3637914d74bSmrg if (cursors) 3647914d74bSmrg { 3657914d74bSmrg cursors->cursors[0] = _XcursorCreateFontCursor (dpy, id); 3667914d74bSmrg if (cursors->cursors[0] == None) 3677914d74bSmrg { 3687914d74bSmrg XcursorCursorsDestroy (cursors); 3697914d74bSmrg cursors = NULL; 3707914d74bSmrg } 3717914d74bSmrg else 3727914d74bSmrg cursors->ncursor = 1; 3737914d74bSmrg } 3747914d74bSmrg } 3757914d74bSmrg else 3767914d74bSmrg cursors = NULL; 3777914d74bSmrg } 3787914d74bSmrg else 3797914d74bSmrg { 3807914d74bSmrg cursors = XcursorImagesLoadCursors (dpy, images); 3817914d74bSmrg XcursorImagesDestroy (images); 3827914d74bSmrg } 3837914d74bSmrg return cursors; 3847914d74bSmrg} 3857914d74bSmrg 3867914d74bSmrgstatic const char _XcursorStandardNames[] = 3877914d74bSmrg "X_cursor\0" 3887914d74bSmrg "arrow\0" 3897914d74bSmrg "based_arrow_down\0" 3907914d74bSmrg "based_arrow_up\0" 3917914d74bSmrg "boat\0" 3927914d74bSmrg "bogosity\0" 3937914d74bSmrg "bottom_left_corner\0" 3947914d74bSmrg "bottom_right_corner\0" 3957914d74bSmrg "bottom_side\0" 3967914d74bSmrg "bottom_tee\0" 3977914d74bSmrg "box_spiral\0" 3987914d74bSmrg "center_ptr\0" 3997914d74bSmrg "circle\0" 4007914d74bSmrg "clock\0" 4017914d74bSmrg "coffee_mug\0" 4027914d74bSmrg "cross\0" 4037914d74bSmrg "cross_reverse\0" 4047914d74bSmrg "crosshair\0" 4057914d74bSmrg "diamond_cross\0" 4067914d74bSmrg "dot\0" 4077914d74bSmrg "dotbox\0" 4087914d74bSmrg "double_arrow\0" 4097914d74bSmrg "draft_large\0" 4107914d74bSmrg "draft_small\0" 4117914d74bSmrg "draped_box\0" 4127914d74bSmrg "exchange\0" 4137914d74bSmrg "fleur\0" 4147914d74bSmrg "gobbler\0" 4157914d74bSmrg "gumby\0" 4167914d74bSmrg "hand1\0" 4177914d74bSmrg "hand2\0" 4187914d74bSmrg "heart\0" 4197914d74bSmrg "icon\0" 4207914d74bSmrg "iron_cross\0" 4217914d74bSmrg "left_ptr\0" 4227914d74bSmrg "left_side\0" 4237914d74bSmrg "left_tee\0" 4247914d74bSmrg "leftbutton\0" 4257914d74bSmrg "ll_angle\0" 4267914d74bSmrg "lr_angle\0" 4277914d74bSmrg "man\0" 4287914d74bSmrg "middlebutton\0" 4297914d74bSmrg "mouse\0" 4307914d74bSmrg "pencil\0" 4317914d74bSmrg "pirate\0" 4327914d74bSmrg "plus\0" 4337914d74bSmrg "question_arrow\0" 4347914d74bSmrg "right_ptr\0" 4357914d74bSmrg "right_side\0" 4367914d74bSmrg "right_tee\0" 4377914d74bSmrg "rightbutton\0" 4387914d74bSmrg "rtl_logo\0" 4397914d74bSmrg "sailboat\0" 4407914d74bSmrg "sb_down_arrow\0" 4417914d74bSmrg "sb_h_double_arrow\0" 4427914d74bSmrg "sb_left_arrow\0" 4437914d74bSmrg "sb_right_arrow\0" 4447914d74bSmrg "sb_up_arrow\0" 4457914d74bSmrg "sb_v_double_arrow\0" 4467914d74bSmrg "shuttle\0" 4477914d74bSmrg "sizing\0" 4487914d74bSmrg "spider\0" 4497914d74bSmrg "spraycan\0" 4507914d74bSmrg "star\0" 4517914d74bSmrg "target\0" 4527914d74bSmrg "tcross\0" 4537914d74bSmrg "top_left_arrow\0" 4547914d74bSmrg "top_left_corner\0" 4557914d74bSmrg "top_right_corner\0" 4567914d74bSmrg "top_side\0" 4577914d74bSmrg "top_tee\0" 4587914d74bSmrg "trek\0" 4597914d74bSmrg "ul_angle\0" 4607914d74bSmrg "umbrella\0" 4617914d74bSmrg "ur_angle\0" 4627914d74bSmrg "watch\0" 4637914d74bSmrg "xterm"; 4647914d74bSmrg 4657914d74bSmrgstatic const unsigned short _XcursorStandardNameOffsets[] = { 4667914d74bSmrg 0, 9, 15, 32, 47, 52, 61, 80, 100, 112, 123, 134, 145, 152, 158, 4677914d74bSmrg 169, 175, 189, 199, 213, 217, 224, 237, 249, 261, 272, 281, 287, 4687914d74bSmrg 295, 301, 307, 313, 319, 324, 335, 344, 354, 363, 374, 383, 392, 4697914d74bSmrg 396, 409, 415, 422, 429, 434, 449, 459, 470, 480, 492, 501, 510, 4707914d74bSmrg 524, 542, 556, 571, 583, 601, 609, 616, 623, 632, 637, 644, 651, 4717914d74bSmrg 666, 682, 699, 708, 716, 721, 730, 739, 748, 754 4727914d74bSmrg}; 4737914d74bSmrg 4747914d74bSmrg#define NUM_STANDARD_NAMES (sizeof _XcursorStandardNameOffsets / sizeof _XcursorStandardNameOffsets[0]) 4757914d74bSmrg 4767914d74bSmrg#define STANDARD_NAME(id) \ 4777914d74bSmrg _XcursorStandardNames + _XcursorStandardNameOffsets[id] 4787914d74bSmrg 4797914d74bSmrgXcursorImage * 4807914d74bSmrgXcursorShapeLoadImage (unsigned int shape, const char *theme, int size) 4817914d74bSmrg{ 4827914d74bSmrg unsigned int id = shape >> 1; 4837914d74bSmrg 4847914d74bSmrg if (id < NUM_STANDARD_NAMES) 4857914d74bSmrg return XcursorLibraryLoadImage (STANDARD_NAME (id), theme, size); 4867914d74bSmrg else 4877914d74bSmrg return NULL; 4887914d74bSmrg} 4897914d74bSmrg 4907914d74bSmrgXcursorImages * 4917914d74bSmrgXcursorShapeLoadImages (unsigned int shape, const char *theme, int size) 4927914d74bSmrg{ 4937914d74bSmrg unsigned int id = shape >> 1; 4947914d74bSmrg 4957914d74bSmrg if (id < NUM_STANDARD_NAMES) 4967914d74bSmrg return XcursorLibraryLoadImages (STANDARD_NAME (id), theme, size); 4977914d74bSmrg else 4987914d74bSmrg return NULL; 4997914d74bSmrg} 5007914d74bSmrg 5017914d74bSmrgCursor 5027914d74bSmrgXcursorShapeLoadCursor (Display *dpy, unsigned int shape) 5037914d74bSmrg{ 5047914d74bSmrg unsigned int id = shape >> 1; 5057914d74bSmrg 5067914d74bSmrg if (id < NUM_STANDARD_NAMES) 5077914d74bSmrg return XcursorLibraryLoadCursor (dpy, STANDARD_NAME (id)); 5087914d74bSmrg else 5097914d74bSmrg return 0; 5107914d74bSmrg} 5117914d74bSmrg 5127914d74bSmrgXcursorCursors * 5137914d74bSmrgXcursorShapeLoadCursors (Display *dpy, unsigned int shape) 5147914d74bSmrg{ 5157914d74bSmrg unsigned int id = shape >> 1; 5167914d74bSmrg 5177914d74bSmrg if (id < NUM_STANDARD_NAMES) 5187914d74bSmrg return XcursorLibraryLoadCursors (dpy, STANDARD_NAME (id)); 5197914d74bSmrg else 5207914d74bSmrg return NULL; 5217914d74bSmrg} 5227914d74bSmrg 5237914d74bSmrgint 5247914d74bSmrgXcursorLibraryShape (const char *library) 5257914d74bSmrg{ 5267914d74bSmrg int low, high; 5277914d74bSmrg int mid; 5287914d74bSmrg int c; 5297914d74bSmrg 5307914d74bSmrg low = 0; 5317914d74bSmrg high = NUM_STANDARD_NAMES - 1; 5327914d74bSmrg while (low < high - 1) 5337914d74bSmrg { 5347914d74bSmrg mid = (low + high) >> 1; 5357914d74bSmrg c = strcmp (library, STANDARD_NAME (mid)); 5367914d74bSmrg if (c == 0) 5377914d74bSmrg return (mid << 1); 5387914d74bSmrg if (c > 0) 5397914d74bSmrg low = mid; 5407914d74bSmrg else 5417914d74bSmrg high = mid; 5427914d74bSmrg } 5437914d74bSmrg while (low <= high) 5447914d74bSmrg { 5457914d74bSmrg if (!strcmp (library, STANDARD_NAME (low))) 5467914d74bSmrg return (low << 1); 5477914d74bSmrg low++; 5487914d74bSmrg } 5497914d74bSmrg return -1; 5507914d74bSmrg} 551