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