1/* 2 3Copyright 1987, 1988, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25*/ 26 27/*********************************************************** 28 29Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. 30 31 All Rights Reserved 32 33Permission to use, copy, modify, and distribute this software and its 34documentation for any purpose and without fee is hereby granted, 35provided that the above copyright notice appear in all copies and that 36both that copyright notice and this permission notice appear in 37supporting documentation, and that the name of Digital not be 38used in advertising or publicity pertaining to distribution of the 39software without specific, written prior permission. 40 41DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 42ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 43DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 44ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 45WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 46ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 47SOFTWARE. 48 49******************************************************************/ 50 51#ifdef HAVE_CONFIG_H 52#include <config.h> 53#endif 54#include <X11/Intrinsic.h> 55#include <X11/StringDefs.h> 56#include <X11/Xmu/Converters.h> 57#include <X11/Xmu/Drawing.h> 58#include <X11/Xmu/CurUtil.h> 59#include <X11/Xmu/CharSet.h> 60 61#include <stdlib.h> 62 63#ifdef _POSIX_SOURCE 64#include <limits.h> 65#else 66#define _POSIX_SOURCE 67#include <limits.h> 68#undef _POSIX_SOURCE 69#endif 70 71#ifndef PATH_MAX 72#ifdef WIN32 73#define PATH_MAX 512 74#else 75#include <sys/param.h> 76#endif 77#ifndef PATH_MAX 78#ifdef MAXPATHLEN 79#define PATH_MAX MAXPATHLEN 80#else 81#define PATH_MAX 1024 82#endif 83#endif 84#endif /* PATH_MAX */ 85 86/* Kludge source to avoid encountering broken shared library linkers 87 which insist on resolving references unused by the application, 88 and broken object file formats that don't correctly distinguish 89 references to procedures from references to data. 90 */ 91#if defined(SVR4) 92#define XMU_KLUDGE 93#endif 94 95/* 96 * XmuConvertStringToCursor: 97 * 98 * allows String to specify a standard cursor name (from cursorfont.h), a 99 * font name and glyph index of the form "FONT fontname index [[font] index]", 100 * or a bitmap file name (absolute, or relative to the global resource 101 * bitmapFilePath, class BitmapFilePath). If the resource is not 102 * defined, the default value is the build symbol BITMAPDIR. 103 * 104 * shares lots of code with XmuCvtStringToPixmap, but unfortunately 105 * can't use it as the hotspot info is lost. 106 * 107 * To use, include the following in your ClassInitialize procedure: 108 109static XtConvertArgRec screenConvertArg[] = { 110 {XtBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.screen), 111 sizeof(Screen *)} 112}; 113 114 XtAddConverter(XtRString, XtRCursor, XmuCvtStringToCursor, 115 screenConvertArg, XtNumber(screenConvertArg)); 116 * 117 */ 118 119#define done(address, type) \ 120 { (*toVal).size = sizeof(type); (*toVal).addr = (XPointer) address; } 121 122#define FONTSPECIFIER "FONT " 123 124/*ARGSUSED*/ 125void 126XmuCvtStringToCursor(XrmValuePtr args, Cardinal *num_args, 127 XrmValuePtr fromVal, XrmValuePtr toVal) 128{ 129 static Cursor cursor; /* static for cvt magic */ 130 char *name = (char *)fromVal->addr; 131 Screen *screen; 132 register int i; 133 char maskname[PATH_MAX]; 134 Pixmap source, mask = 0; 135 /* XXX - make fg/bg resources */ 136 static XColor bgColor = {0, 0xffff, 0xffff, 0xffff, 0, 0}; 137 static XColor fgColor = {0, 0, 0, 0, 0, 0}; 138 int xhot, yhot; 139 int len; 140 141 142 if (*num_args != 1) 143 XtErrorMsg("wrongParameters","cvtStringToCursor","XtToolkitError", 144 "String to cursor conversion needs screen argument", 145 (String *)NULL, (Cardinal *)NULL); 146 147 if (XmuCompareISOLatin1(name, "None") == 0) 148 { 149 cursor = None; 150 done(&cursor, Cursor); 151 return; 152 } 153 154 screen = *((Screen **) args[0].addr); 155 156 if (0 == strncmp(FONTSPECIFIER, name, strlen(FONTSPECIFIER))) { 157 char source_name[PATH_MAX], mask_name[PATH_MAX]; 158 int source_char, mask_char, fields = 0; 159 Font source_font, mask_font; 160 XrmValue fromString, toFont; 161 XrmValue cvtArg; 162 Boolean success; 163 Display *dpy = DisplayOfScreen(screen); 164 char *strspec = NULL; 165 int strspeclen; 166#ifdef XMU_KLUDGE 167 Cardinal num; 168#endif 169 170 strspeclen = strlen("FONT %s %d %s %d") + 21; 171 strspec = XtMalloc(strspeclen); 172 if (strspec != NULL) { 173 snprintf(strspec, strspeclen, "FONT %%%lds %%d %%%lds %%d", 174 (unsigned long)sizeof(source_name) - 1, 175 (unsigned long)sizeof(mask_name) - 1); 176 fields = sscanf(name, strspec, 177 source_name, &source_char, 178 mask_name, &mask_char); 179 XtFree(strspec); 180 } 181 if (fields < 2) { 182 XtStringConversionWarning(name, XtRCursor); 183 return; 184 } 185 186 fromString.addr = source_name; 187 fromString.size = strlen(source_name) + 1; 188 toFont.addr = (XPointer) &source_font; 189 toFont.size = sizeof(Font); 190 cvtArg.addr = (XPointer) &dpy; 191 cvtArg.size = sizeof(Display *); 192 /* XXX using display of screen argument as message display */ 193#ifdef XMU_KLUDGE 194 /* XXX Sacrifice caching */ 195 num = 1; 196 success = XtCvtStringToFont(dpy, &cvtArg, &num, &fromString, &toFont, 197 NULL); 198#else 199 success = XtCallConverter(dpy, XtCvtStringToFont, &cvtArg, 200 (Cardinal)1, &fromString, &toFont, NULL); 201#endif 202 if (!success) { 203 XtStringConversionWarning(name, XtRCursor); 204 return; 205 } 206 207 switch (fields) { 208 case 2: /* defaulted mask font & char */ 209 mask_font = source_font; 210 mask_char = source_char; 211 break; 212 213 case 3: /* defaulted mask font */ 214 mask_font = source_font; 215 mask_char = atoi(mask_name); 216 break; 217 218 case 4: /* specified mask font & char */ 219 fromString.addr = mask_name; 220 fromString.size = strlen(mask_name) + 1; 221 toFont.addr = (XPointer) &mask_font; 222 toFont.size = sizeof(Font); 223 /* XXX using display of screen argument as message display */ 224#ifdef XMU_KLUDGE 225 /* XXX Sacrifice caching */ 226 num = 1; 227 success = XtCvtStringToFont(dpy, &cvtArg, &num, &fromString, 228 &toFont, NULL); 229#else 230 success = XtCallConverter(dpy, XtCvtStringToFont, &cvtArg, 231 (Cardinal)1, &fromString, &toFont, NULL); 232#endif 233 if (!success) { 234 XtStringConversionWarning(name, XtRCursor); 235 return; 236 } 237 } 238 239 cursor = XCreateGlyphCursor( DisplayOfScreen(screen), source_font, 240 mask_font, source_char, mask_char, 241 &fgColor, &bgColor ); 242 done(&cursor, Cursor); 243 return; 244 } 245 246 i = XmuCursorNameToIndex (name); 247 if (i != -1) { 248 cursor = XCreateFontCursor (DisplayOfScreen(screen), i); 249 done(&cursor, Cursor); 250 return; 251 } 252 253 if ((source = XmuLocateBitmapFile (screen, name, 254 maskname, (sizeof maskname) - 4, 255 NULL, NULL, &xhot, &yhot)) == None) { 256 XtStringConversionWarning (name, XtRCursor); 257 cursor = None; 258 done(&cursor, Cursor); 259 return; 260 } 261 len = strlen (maskname); 262 for (i = 0; i < 2; i++) { 263 strcpy (maskname + len, i == 0 ? "Mask" : "msk"); 264 if ((mask = XmuLocateBitmapFile (screen, maskname, NULL, 0, 265 NULL, NULL, NULL, NULL)) != None) 266 break; 267 } 268 269 cursor = XCreatePixmapCursor( DisplayOfScreen(screen), source, mask, 270 &fgColor, &bgColor, xhot, yhot ); 271 XFreePixmap( DisplayOfScreen(screen), source ); 272 if (mask != None) XFreePixmap( DisplayOfScreen(screen), mask ); 273 274 done(&cursor, Cursor); 275} 276 277#define new_done(type, value) \ 278 { \ 279 if (toVal->addr != NULL) { \ 280 if (toVal->size < sizeof(type)) { \ 281 toVal->size = sizeof(type); \ 282 return False; \ 283 } \ 284 *(type*)(toVal->addr) = (value); \ 285 } \ 286 else { \ 287 static type static_val; \ 288 static_val = (value); \ 289 toVal->addr = (XPointer)&static_val; \ 290 } \ 291 toVal->size = sizeof(type); \ 292 return True; \ 293 } 294 295/* Function Name: XmuCvtStringToColorCursor 296 * Description: Converts a string into a colored cursor. 297 * Arguments: dpy 298 * args - an argument list (see below). 299 * num_args - number of elements in the argument list. 300 * fromVal - value to convert from. 301 * toVal - value to convert to. 302 * data 303 * Returns: True or False 304 */ 305 306/*ARGSUSED*/ 307Boolean 308XmuCvtStringToColorCursor(Display *dpy, XrmValuePtr args, Cardinal *num_args, 309 XrmValuePtr fromVal, XrmValuePtr toVal, 310 XtPointer *converter_data) 311{ 312 Cursor cursor; 313 Screen *screen; 314 Pixel fg, bg; 315 Colormap c_map; 316 XColor colors[2]; 317 Cardinal number; 318 XrmValue ret_val; 319 320 if (*num_args != 4) { 321 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 322 "wrongParameters","cvtStringToColorCursor","XmuError", 323 "String to color cursor conversion needs four arguments", 324 (String *)NULL, (Cardinal *)NULL); 325 return False; 326 } 327 328 screen = *((Screen **) args[0].addr); 329 fg = *((Pixel *) args[1].addr); 330 bg = *((Pixel *) args[2].addr); 331 c_map = *((Colormap *) args[3].addr); 332 333 number = 1; 334 XmuCvtStringToCursor(args, &number, fromVal, &ret_val); 335 336 cursor = *((Cursor *) ret_val.addr); 337 338 if (cursor == None || (fg == BlackPixelOfScreen(screen) 339 && bg == WhitePixelOfScreen(screen))) 340 new_done(Cursor, cursor); 341 342 colors[0].pixel = fg; 343 colors[1].pixel = bg; 344 345 XQueryColors (dpy, c_map, colors, 2); 346 XRecolorCursor(dpy, cursor, colors, colors + 1); 347 new_done(Cursor, cursor); 348} 349 350 351 352