Pixmap.c revision 5ec34c4c
1/*
2 * Copyright (c) 1998 by The XFree86 Project, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the XFree86 Project shall
23 * not be used in advertising or otherwise to promote the sale, use or other
24 * dealings in this Software without prior written authorization from the
25 * XFree86 Project.
26 */
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include <string.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <X11/IntrinsicP.h>
35#include <X11/Xmu/CharSet.h>
36#include <X11/Xfuncs.h>
37#include <X11/extensions/shape.h>
38#ifndef OLDXAW
39#include <X11/xpm.h>
40#endif
41#include "Private.h"
42
43
44#ifndef OLDXAW
45
46/*
47 * Types
48 */
49typedef struct _XawCache {
50  long value;
51  XtPointer *elems;
52  unsigned int num_elems;
53} XawCache;
54
55typedef struct _XawPixmapLoaderInfo {
56  XawPixmapLoader loader;
57  String type;
58  String ext;
59} XawPixmapLoaderInfo;
60
61/*
62 * Private Methods
63 */
64static Bool BitmapLoader(XawParams*, Screen*, Colormap, int,
65			    Pixmap*, Pixmap*, Dimension*, Dimension*);
66static Bool GradientLoader(XawParams*, Screen*, Colormap, int,
67			      Pixmap*, Pixmap*, Dimension*, Dimension*);
68static Bool XPixmapLoader(XawParams*, Screen*, Colormap, int,
69			  Pixmap*, Pixmap*, Dimension*, Dimension*);
70static XawPixmap *_XawFindPixmap(String, Screen*, Colormap, int);
71static void _XawCachePixmap(XawPixmap*, Screen*, Colormap, int);
72static int _XawFindPixmapLoaderIndex(String, String);
73static int qcmp_long(register _Xconst void*, register _Xconst void *);
74static int bcmp_long(register _Xconst void*, register _Xconst void *);
75static int qcmp_string(register _Xconst void*, register _Xconst void *);
76static int bcmp_string(register _Xconst void*, register _Xconst void *);
77static void GetResourcePixmapPath(Display*);
78
79/*
80 * Initialization
81 */
82static XawCache xaw_pixmaps;
83static XawCache x_pixmaps;   /* for fast reverse search */
84static XawPixmapLoaderInfo **loader_info;
85static Cardinal num_loader_info;
86
87/*
88 * Implementation
89 */
90Bool
91XawPixmapsInitialize(void)
92{
93  static Boolean first_time = True;
94
95  if (!first_time)
96    return (False);
97
98  (void)XawAddPixmapLoader(NULL, NULL, BitmapLoader);
99  (void)XawAddPixmapLoader("bitmap", NULL, BitmapLoader);
100  (void)XawAddPixmapLoader("gradient", NULL, GradientLoader);
101  (void)XawAddPixmapLoader("xpm", "xpm", XPixmapLoader);
102
103  return (True);
104}
105
106XawParams *
107XawParseParamsString(String name)
108{
109  XawParams *xaw_params;
110  char *tok, *str, *type = NULL, *ext = NULL, *params = NULL;
111
112  if (!name)
113    return (NULL);
114
115  xaw_params = (XawParams *)XtMalloc(sizeof(XawParams));
116
117  str = XtNewString(name);
118
119  /* Find type */
120  tok = str;
121  while (tok = strchr(tok, ':'), tok)
122    {
123      if (tok == str || tok[-1] != '\\')
124	break;
125      memmove(&tok[-1], tok, strlen(tok) + 1);
126    }
127  if (tok)
128    {
129      *tok = '\0';
130      if (strchr(str, '?'))
131	{
132	  *tok = ':';
133	}
134      else
135	{
136	  ++tok;
137	  type = XtNewString(str);
138	  memmove(str, tok, strlen(tok) + 1);
139	}
140    }
141
142  /* Find params */
143  tok = str;
144  while (tok = strchr(tok, '?'), tok)
145    {
146      if (tok == str || tok[-1] != '\\')
147	params = tok;
148      if (tok != str && tok[-1] == '\\')
149	memmove(&tok[-1], tok, strlen(tok) + 1);
150      else
151	break;
152    }
153  if (params)
154    {
155      *params = '\0';
156      ++params;
157    }
158
159  /* Find ext */
160  tok = str;
161  while (tok = strchr(tok, '.'), tok)
162    {
163      if (tok == str || tok[-1] != '\\')
164	ext = tok;
165      if (tok != str && tok[-1] == '\\')
166	memmove(&tok[-1], tok, strlen(tok) + 1);
167      else
168	break;
169    }
170  if (ext)
171    {
172      ++ext;
173      if (strchr(ext, '/'))
174	ext = NULL;
175    }
176
177  xaw_params->name = XtNewString(str);
178  xaw_params->type = type;
179  xaw_params->ext = ext ? XtNewString(ext) : ext;
180  xaw_params->args = NULL;
181  xaw_params->num_args = 0;
182
183  /* Parse params */
184  if (params)
185    {
186      char *arg, *val;
187      XawArgVal *xaw_arg;
188
189      for (tok = strtok(params, "&"); tok; tok = strtok(NULL, "&"))
190	{
191	  val = strchr(tok, '=');
192	  if (val)
193	    {
194	      *val = '\0';
195	      ++val;
196	      if (*val != '\0')
197		val = XtNewString(val);
198	      else
199		val = NULL;
200	    }
201	  arg = XtNewString(tok);
202	  xaw_arg = (XawArgVal *)XtMalloc(sizeof(XawArgVal));
203	  xaw_arg->name = arg;
204	  xaw_arg->value = val;
205	  if (!xaw_params->num_args)
206	    {
207	      xaw_params->num_args = 1;
208	      xaw_params->args = (XawArgVal **)
209		XtMalloc(sizeof(XawArgVal*));
210	    }
211	  else
212	    {
213	      ++xaw_params->num_args;
214	      xaw_params->args = (XawArgVal **)
215		XtRealloc((char *)xaw_params->args,
216			  (Cardinal)(sizeof(XawArgVal*) * (size_t)xaw_params->num_args));
217	    }
218	  xaw_params->args[xaw_params->num_args - 1] = xaw_arg;
219	}
220    }
221
222  if (xaw_params->num_args > 1)
223    qsort(xaw_params->args, xaw_params->num_args, sizeof(XtPointer),
224	  qcmp_string);
225
226  XtFree(str);
227
228  return (xaw_params);
229}
230
231void
232XawFreeParamsStruct(XawParams *params)
233{
234  unsigned int i;
235
236  if (!params)
237    return;
238
239  for (i = 0; i < params->num_args; i++)
240    {
241      XtFree((char *)params->args[i]->name);
242      if (params->args[i]->value)
243	XtFree((char *)params->args[i]->value);
244      XtFree((char *)params->args[i]);
245    }
246
247  if (params->args)
248    XtFree((char *)params->args);
249  XtFree((char *)params);
250}
251
252XawArgVal *
253XawFindArgVal(XawParams *params, String name)
254{
255  XawArgVal **arg_val;
256
257  if (!params->args)
258    return (NULL);
259
260  arg_val = (XawArgVal **)bsearch((void *)name, params->args,
261				  params->num_args, sizeof(XtPointer*),
262				  bcmp_string);
263  if (!arg_val)
264    return (NULL);
265
266  return (*arg_val);
267}
268
269XawPixmap *
270XawLoadPixmap(String name, Screen *screen, Colormap colormap, int depth)
271{
272  int idx;
273  Bool success;
274  XawPixmap *xaw_pixmap;
275  Pixmap pixmap, mask;
276  Dimension width, height;
277  XawParams *xaw_params;
278
279  if (!name)
280    return (NULL);
281
282  xaw_pixmap = _XawFindPixmap(name, screen, colormap, depth);
283
284  if (xaw_pixmap)
285    return (xaw_pixmap);
286
287  if ((xaw_params = XawParseParamsString(name)) == NULL)
288    return (NULL);
289
290  idx = _XawFindPixmapLoaderIndex(xaw_params->type, xaw_params->ext);
291  if (idx < 0)
292    return (NULL);
293
294#ifdef DIAGNOSTIC
295  fprintf(stderr, "(*) Loading pixmap \"%s\": ", name);
296#endif
297
298  success = loader_info[idx]->loader(xaw_params, screen, colormap, depth,
299				       &pixmap, &mask, &width, &height);
300  if (success)
301    {
302      xaw_pixmap = (XawPixmap *)XtMalloc(sizeof(XawPixmap));
303      xaw_pixmap->name = XtNewString(name);
304      xaw_pixmap->pixmap = pixmap;
305      xaw_pixmap->mask = mask;
306      xaw_pixmap->width = width;
307      xaw_pixmap->height = height;
308      _XawCachePixmap(xaw_pixmap, screen, colormap, depth);
309    }
310
311  XawFreeParamsStruct(xaw_params);
312
313#ifdef DIAGNOSTIC
314  fprintf(stderr, "%s", success ? "success\n" : "failed\n");
315#endif
316
317  return (success ? xaw_pixmap : NULL);
318}
319
320Bool
321XawAddPixmapLoader(String type, String ext, XawPixmapLoader loader)
322{
323  XawPixmapLoaderInfo *info;
324  int i;
325
326  if (!loader)
327    return (False);
328
329  i = _XawFindPixmapLoaderIndex(type, ext);
330
331  if (i >= 0)
332    {
333      loader_info[i]->loader = loader;
334      if (loader_info[i]->type)
335	XtFree((char *)loader_info[i]->type);
336      if (loader_info[i]->ext)
337	XtFree((char *)loader_info[i]->ext);
338      loader_info[i]->type = type ? XtNewString(type) : NULL;
339      loader_info[i]->ext = ext ? XtNewString(ext) : NULL;
340      return (True);
341    }
342
343  if ((info = (XawPixmapLoaderInfo *)XtMalloc(sizeof(XawPixmapLoaderInfo)))
344      == NULL)
345    return (False);
346
347  info->loader = loader;
348  info->type = type ? XtNewString(type) : NULL;
349  info->ext = ext ? XtNewString(ext) : NULL;
350
351  if (!loader_info)
352    {
353      num_loader_info = 1;
354      loader_info = (XawPixmapLoaderInfo**)
355	XtMalloc(sizeof(XawPixmapLoaderInfo*));
356    }
357  else
358    {
359      ++num_loader_info;
360      loader_info = (XawPixmapLoaderInfo**)
361	XtRealloc((char *)loader_info,
362		  (Cardinal)(sizeof(XawPixmapLoaderInfo) * (size_t)num_loader_info));
363    }
364  loader_info[num_loader_info - 1] = info;
365
366  return (True);
367}
368
369static int
370_XawFindPixmapLoaderIndex(String type, String ext)
371{
372  Cardinal i;
373
374  if (!loader_info)
375    return (-1);
376
377  for (i = 0; i < num_loader_info; i++)
378    if ((type && loader_info[i]->type && strcmp(type, loader_info[i]->type) == 0)
379	|| (ext && loader_info[i]->ext && strcmp(ext, loader_info[i]->ext) == 0))
380      return ((int)i);
381
382  if (!type)
383    return (0);	/* try a bitmap */
384
385  return (-1);
386}
387
388static int
389qcmp_x_cache(register _Xconst void *left, register _Xconst void *right)
390{
391  return ((int)((*(XawPixmap **)left)->pixmap) -
392	  (int)((*(XawPixmap **)right)->pixmap));
393}
394
395static int
396bcmp_x_cache(register _Xconst void *pixmap, register _Xconst void *xaw)
397{
398  return (int)((long)pixmap - (long)((*(XawPixmap **)xaw)->pixmap));
399}
400
401static int
402qcmp_long(register _Xconst void *left, register _Xconst void *right)
403{
404  return (int)((long)((*(XawCache **)left)->value) -
405	       (long)((*(XawCache **)right)->value));
406}
407
408static int
409qcmp_string(register _Xconst void *left, register _Xconst void *right)
410{
411  return (strcmp((String)((*(XawCache **)left)->value),
412		 (String)((*(XawCache **)right)->value)));
413}
414
415static int
416bcmp_long(register _Xconst void *value, register _Xconst void *cache)
417{
418  return (int)((long)value - (long)((*(XawCache **)cache)->value));
419}
420
421static int
422bcmp_string(register _Xconst void *string,
423	    register _Xconst void *cache)
424{
425  return (strcmp((String)string, (String)((*(XawCache **)cache)->value)));
426}
427
428#define FIND_ALL      0
429#define FIND_SCREEN   1
430#define FIND_COLORMAP 2
431#define FIND_DEPTH    3
432static XawCache *
433_XawFindCache(XawCache *xaw,
434	      Screen *screen, Colormap colormap, int depth, int flags)
435{
436  XawCache **cache;
437
438  if (!xaw->num_elems)
439    return (NULL);
440
441  /* Screen */
442  cache = (XawCache **)bsearch(screen, xaw->elems,
443			       xaw->num_elems, sizeof(XtPointer),
444			       bcmp_long);
445  if (!cache || !(*cache)->num_elems)
446    return (NULL);
447  if (flags == FIND_SCREEN)
448    return (*cache);
449
450  /* Colormap */
451  cache = (XawCache **)bsearch((void *)colormap, (*cache)->elems,
452			       (*cache)->num_elems, sizeof(XtPointer),
453			       bcmp_long);
454  if (!cache || !(*cache)->num_elems)
455    return (NULL);
456  if (flags == FIND_COLORMAP)
457    return (*cache);
458
459  /* Depth */
460  cache = (XawCache **)bsearch((void *)(long)depth, (*cache)->elems,
461			       (*cache)->num_elems, sizeof(XtPointer),
462			       bcmp_long);
463
464  if (!cache || !(*cache)->num_elems)
465    return (NULL);
466  return (*cache);
467}
468
469static XawCache *
470_XawGetCache(XawCache *xaw, Screen *screen, Colormap colormap, int depth)
471{
472  XawCache *s_cache, *c_cache, *d_cache, *cache, *pcache;
473
474  cache = _XawFindCache(xaw, screen, colormap, depth, FIND_ALL);
475
476  if (!cache)
477    {
478      s_cache = _XawFindCache(xaw,
479			      screen, colormap, depth, FIND_SCREEN);
480      if (!s_cache)
481	{
482	  pcache = (XawCache *)XtMalloc(sizeof(XawCache));
483	  if (!xaw->num_elems)
484	    {
485	      xaw->num_elems = 1;
486	      xaw->elems = (XtPointer*)XtMalloc(sizeof(XtPointer));
487	    }
488	  else
489	    {
490	      ++xaw->num_elems;
491	      xaw->elems = (XtPointer*)
492		XtRealloc((char *)xaw->elems,
493			  (Cardinal)(sizeof(XtPointer) * (size_t)xaw->num_elems));
494	    }
495	  pcache->value = (long)screen;
496	  pcache->elems = NULL;
497	  pcache->num_elems = 0;
498	  xaw->elems[xaw->num_elems - 1] = (XtPointer)pcache;
499	  s_cache = (XawCache *)xaw->elems[xaw->num_elems - 1];
500	  if (xaw->num_elems > 1)
501	    qsort(xaw->elems, xaw->num_elems, sizeof(XtPointer), qcmp_long);
502	}
503
504      c_cache = _XawFindCache(xaw,
505			      screen, colormap, depth, FIND_COLORMAP);
506      if (!c_cache)
507	{
508	  pcache = (XawCache *)XtMalloc(sizeof(XawCache));
509	  if (!s_cache->num_elems)
510	    {
511	      s_cache->num_elems = 1;
512	      s_cache->elems = (XtPointer*)XtMalloc(sizeof(XtPointer));
513	    }
514	  else
515	    {
516	      ++s_cache->num_elems;
517	      s_cache->elems = (XtPointer*)
518		XtRealloc((char *)s_cache->elems,
519			  (Cardinal)(sizeof(XtPointer) * s_cache->num_elems));
520	    }
521	  pcache->value = (long)colormap;
522	  pcache->elems = NULL;
523	  pcache->num_elems = 0;
524	  s_cache->elems[s_cache->num_elems - 1] = (XtPointer)pcache;
525	  c_cache = (XawCache *)s_cache->elems[s_cache->num_elems - 1];
526	  if (s_cache->num_elems > 1)
527	    qsort(s_cache->elems, s_cache->num_elems,
528		  sizeof(XtPointer), qcmp_long);
529	}
530
531      d_cache = _XawFindCache(xaw,
532			      screen, colormap, depth, FIND_DEPTH);
533      if (!d_cache)
534	{
535	  pcache = (XawCache *)XtMalloc(sizeof(XawCache));
536	  if (!c_cache->num_elems)
537	    {
538	      c_cache->num_elems = 1;
539	      c_cache->elems = (XtPointer*)XtMalloc(sizeof(XtPointer));
540	    }
541	  else
542	    {
543	      ++c_cache->num_elems;
544	      c_cache->elems = (XtPointer*)
545		XtRealloc((char *)c_cache->elems,
546			  (Cardinal)(sizeof(XtPointer) * c_cache->num_elems));
547	    }
548	  pcache->value = (long)depth;
549	  pcache->elems = NULL;
550	  pcache->num_elems = 0;
551	  c_cache->elems[c_cache->num_elems - 1] = (XtPointer)pcache;
552	  d_cache = (XawCache *)c_cache->elems[c_cache->num_elems - 1];
553	  if (c_cache->num_elems > 1)
554	    qsort(c_cache->elems, c_cache->num_elems,
555		  sizeof(XtPointer), qcmp_long);
556	}
557
558      cache = d_cache;
559    }
560
561  return (cache);
562}
563
564static XawPixmap *
565_XawFindPixmap(String name, Screen *screen, Colormap colormap, int depth)
566{
567  XawCache *cache;
568  XawPixmap **pixmap;
569
570  cache = _XawFindCache(&xaw_pixmaps, screen, colormap, depth, FIND_ALL);
571
572  if (!cache)
573    return (NULL);
574
575  /* Name */
576  pixmap = (XawPixmap **)bsearch((void *)name, cache->elems,
577				 cache->num_elems, sizeof(XtPointer),
578				 bcmp_string);
579  if (!pixmap)
580    return (NULL);
581
582  return (*pixmap);
583}
584
585XawPixmap *
586XawPixmapFromXPixmap(Pixmap pixmap,
587		     Screen *screen, Colormap colormap, int depth)
588{
589  XawCache *cache;
590  XawPixmap **x_pixmap;
591
592  cache = _XawFindCache(&x_pixmaps, screen, colormap, depth, FIND_ALL);
593
594  if (!cache)
595    return (NULL);
596
597  /* Pixmap */
598  x_pixmap = (XawPixmap **)bsearch((void *)pixmap, cache->elems,
599				   cache->num_elems, sizeof(XtPointer),
600				   bcmp_x_cache);
601  if (!x_pixmap)
602    return (NULL);
603
604  return (*x_pixmap);
605}
606
607static void
608_XawCachePixmap(XawPixmap *pixmap,
609		Screen *screen, Colormap colormap, int depth)
610{
611  XawCache *xaw_cache, *x_cache;
612
613  xaw_cache = _XawGetCache(&xaw_pixmaps, screen, colormap, depth);
614  x_cache = _XawGetCache(&x_pixmaps, screen, colormap, depth);
615
616  if (!xaw_cache->num_elems)
617    {
618      xaw_cache->num_elems = 1;
619      xaw_cache->elems = (XtPointer*)XtMalloc(sizeof(XtPointer));
620    }
621  else
622    {
623      ++xaw_cache->num_elems;
624      xaw_cache->elems = (XtPointer*)XtRealloc((char *)xaw_cache->elems,
625					       (Cardinal)(sizeof(XtPointer) *
626							  xaw_cache->num_elems));
627    }
628
629  xaw_cache->elems[xaw_cache->num_elems - 1] = (XtPointer)pixmap;
630  if (xaw_cache->num_elems > 1)
631    qsort(xaw_cache->elems, xaw_cache->num_elems,
632	  sizeof(XtPointer), qcmp_string);
633
634
635  if (!x_cache->num_elems)
636    {
637      x_cache->num_elems = 1;
638      x_cache->elems = (XtPointer*)XtMalloc(sizeof(XtPointer));
639    }
640  else
641    {
642      ++x_cache->num_elems;
643      x_cache->elems = (XtPointer*)XtRealloc((char *)x_cache->elems,
644					     (Cardinal)(sizeof(XtPointer) *
645							x_cache->num_elems));
646    }
647
648  x_cache->elems[x_cache->num_elems - 1] = (XtPointer)pixmap;
649  if (x_cache->num_elems > 1)
650    qsort(x_cache->elems, x_cache->num_elems, sizeof(XtPointer), qcmp_x_cache);
651}
652
653#ifndef PROJECT_ROOT
654#define PROJECT_ROOT	"/usr/X11R6"
655#endif
656
657static char *pixmap_path = NULL;
658
659static void
660GetResourcePixmapPath(Display *display)
661{
662    XrmName xrm_name[2];
663    XrmClass xrm_class[2];
664    XrmRepresentation rep_type;
665    XrmValue value;
666    static char *default_path =
667	"%H/%T/%N:%P/include/X11/%T/%N:/usr/X11R6/include/X11/%T/%N:/usr/include/X11/%T/%N:%N";
668
669    xrm_name[0] = XrmPermStringToQuark("pixmapFilePath");
670    xrm_name[1] = NULLQUARK;
671    xrm_class[0] = XrmPermStringToQuark("PixmapFilePath");
672    xrm_class[1] = NULLQUARK;
673    if (!XrmGetDatabase(display))
674	(void) XGetDefault(display, "", "");
675    if (XrmQGetResource(XrmGetDatabase(display), xrm_name, xrm_class,
676			&rep_type, &value) &&
677			rep_type == XrmPermStringToQuark("String")) {
678	int length = 0;
679	char *tok, *buffer = XtNewString(value.addr);
680
681	for (tok = strtok(buffer, ":"); tok; tok = strtok(NULL, ":")) {
682	    int toklen = (int)strlen(tok);
683
684	    if (toklen) {
685		pixmap_path = XtRealloc(pixmap_path, (Cardinal)(length + toklen + 5));
686		strcpy(pixmap_path + length, tok);
687		if (length)
688		    pixmap_path[length++] = ':';
689		sprintf(pixmap_path + length, "%s/%%N", tok);
690		length = (length + (int)strlen(tok) + 3);
691	    }
692	}
693	pixmap_path = XtRealloc(pixmap_path, (Cardinal)((size_t)length + strlen(default_path) + 2));
694	if (length)
695	    pixmap_path[length++] = ':';
696	strcpy(pixmap_path + length, default_path);
697    }
698    else
699	pixmap_path = default_path;
700}
701
702static Bool
703BitmapLoader(XawParams *params, Screen *screen, Colormap colormap, int depth,
704	     Pixmap *pixmap_return, Pixmap *mask_return,
705	     Dimension *width_return, Dimension *height_return)
706{
707  Pixel fg, bg;
708  XColor color, exact;
709  Pixmap pixmap;
710  unsigned int width, height;
711  unsigned char *data = NULL;
712  int hotX, hotY;
713  XawArgVal *argval;
714  Bool retval = False;
715  static SubstitutionRec sub[] = {
716    {'H',   NULL},
717    {'N',   NULL},
718    {'T',   "bitmaps"},
719    {'P',   PROJECT_ROOT},
720  };
721  char *filename;
722
723  fg = BlackPixelOfScreen(screen);
724  bg = WhitePixelOfScreen(screen);
725
726  if ((argval = XawFindArgVal(params, "foreground")) != NULL
727      && argval->value)
728    {
729      if (XAllocNamedColor(DisplayOfScreen(screen), colormap, argval->value,
730			   &color, &exact))
731	fg = color.pixel;
732      else
733	return (False);
734    }
735  if ((argval = XawFindArgVal(params, "background")) != NULL
736      && argval->value)
737    {
738      if (XAllocNamedColor(DisplayOfScreen(screen), colormap, argval->value,
739			   &color, &exact))
740	bg = color.pixel;
741      else
742	return (False);
743    }
744
745  if (params->name[0] != '/' && params->name[0] != '.')
746    {
747      if (!sub[0].substitution)
748	sub[0].substitution = getenv("HOME");
749      sub[1].substitution = params->name;
750      if (pixmap_path == NULL)
751	GetResourcePixmapPath(DisplayOfScreen(screen));
752      filename = XtFindFile(pixmap_path, sub, XtNumber(sub), NULL);
753      if (!filename)
754	return (FALSE);
755    }
756  else
757    filename = params->name;
758
759  if (XReadBitmapFileData(filename, &width, &height, &data,
760			  &hotX, &hotY) == BitmapSuccess)
761    {
762      pixmap = XCreatePixmapFromBitmapData(DisplayOfScreen(screen),
763					   RootWindowOfScreen(screen),
764					   (char *)data,
765					   width, height, fg, bg, (unsigned)depth);
766      if (data)
767	XFree(data);
768      *pixmap_return = pixmap;
769      *mask_return = None;
770      *width_return = (Dimension)width;
771      *height_return = (Dimension)height;
772
773      retval = True;
774    }
775
776  if (filename != params->name)
777    XtFree(filename);
778
779  return (retval);
780}
781
782#define VERTICAL   1
783#define HORIZONTAL 2
784static Bool
785GradientLoader(XawParams *params, Screen *screen, Colormap colormap, int depth,
786	       Pixmap *pixmap_return, Pixmap *mask_return,
787	       Dimension *width_return, Dimension *height_return)
788{
789  double ired, igreen, iblue, red, green, blue;
790  XColor start, end, color;
791  XGCValues values;
792  GC gc;
793  double i, inc, x, y, xend, yend;
794  Pixmap pixmap;
795  XawArgVal *argval;
796  int orientation, dimension, steps;
797  char *value;
798
799  if (XmuCompareISOLatin1(params->name, "vertical") == 0)
800    orientation = VERTICAL;
801  else if (XmuCompareISOLatin1(params->name, "horizontal") == 0)
802    orientation = HORIZONTAL;
803  else
804    return (False);
805
806  if ((argval = XawFindArgVal(params, "dimension")) != NULL
807      && argval->value)
808    {
809      dimension = atoi(argval->value);
810      if (dimension <= 0)
811	return (False);
812    }
813  else
814    dimension = 50;
815
816  if ((argval = XawFindArgVal(params, "steps")) != NULL
817      && argval->value)
818    {
819      steps = atoi(argval->value);
820      if (steps <= 0)
821	return (False);
822    }
823  else
824      steps = dimension;
825
826  steps = XawMin(steps, dimension);
827
828  value = NULL;
829  if ((argval = XawFindArgVal(params, "start")) != NULL)
830    value = argval->value;
831  if (value && !XAllocNamedColor(DisplayOfScreen(screen), colormap, value,
832			    &start, &color))
833    return (False);
834  else if (!value)
835    {
836      start.pixel = WhitePixelOfScreen(screen);
837      XQueryColor(DisplayOfScreen(screen), colormap, &start);
838    }
839  value = NULL;
840  if ((argval = XawFindArgVal(params, "end")) != NULL)
841    value = argval->value;
842  if (value && !XAllocNamedColor(DisplayOfScreen(screen), colormap, value,
843			    &end, &color))
844    return (False);
845  else if (!value)
846    {
847      end.pixel = BlackPixelOfScreen(screen);
848      XQueryColor(DisplayOfScreen(screen), colormap, &end);
849    }
850
851  if ((pixmap = XCreatePixmap(DisplayOfScreen(screen),
852			      RootWindowOfScreen(screen),
853			      (unsigned)(orientation == VERTICAL ? 1 : dimension),
854			      (unsigned)(orientation == VERTICAL ? dimension : 1), (unsigned)depth))
855      == 0)
856    return (False);
857
858  ired   = (double)(end.red   - start.red)   / (double)steps;
859  igreen = (double)(end.green - start.green) / (double)steps;
860  iblue  = (double)(end.blue  - start.blue)  / (double)steps;
861
862  red   = color.red   = start.red;
863  green = color.green = start.green;
864  blue  = color.blue  = start.blue;
865
866  inc = (double)dimension / (double)steps;
867
868  gc = XCreateGC(DisplayOfScreen(screen), pixmap, 0, &values);
869
870  x = y = 0.0;
871  if (orientation == VERTICAL)
872    {
873      xend = 1;
874      yend = 0;
875    }
876  else
877    {
878      xend = 0;
879      yend = 1;
880    }
881
882  color.flags = DoRed | DoGreen | DoBlue;
883
884  XSetForeground(DisplayOfScreen(screen), gc, start.pixel);
885  for (i = 0.0; i < dimension; i += inc)
886    {
887      if ((int)color.red != (int)red || (int)color.green != (int)green
888	  || (int)color.blue != (int)blue)
889	{
890	  XFillRectangle(DisplayOfScreen(screen), pixmap, gc, (int)x, (int)y,
891			 (unsigned int)xend, (unsigned int)yend);
892	  color.red   = (unsigned short)red;
893	  color.green = (unsigned short)green;
894	  color.blue  = (unsigned short)blue;
895	  if (!XAllocColor(DisplayOfScreen(screen), colormap, &color))
896	    {
897	      XFreePixmap(DisplayOfScreen(screen), pixmap);
898	      return (False);
899	    }
900	  XSetForeground(DisplayOfScreen(screen), gc, color.pixel);
901	  if (orientation == VERTICAL)
902	    y = yend;
903	  else
904	    x = xend;
905	}
906      red   += ired;
907      green += igreen;
908      blue  += iblue;
909      if (orientation == VERTICAL)
910	yend += inc;
911      else
912	xend += inc;
913    }
914  XFillRectangle(DisplayOfScreen(screen), pixmap, gc, (int)x, (int)y,
915		 (unsigned int)xend, (unsigned int)yend);
916
917  *pixmap_return = pixmap;
918  *mask_return = None;
919  *width_return = (Dimension)(orientation == VERTICAL ? 1 : dimension);
920  *height_return = (Dimension)(orientation == VERTICAL ? dimension : 1);
921
922  XFreeGC(DisplayOfScreen(screen), gc);
923
924  return (True);
925}
926
927static Bool
928XPixmapLoader(XawParams *params, Screen *screen, Colormap colormap, int depth _X_UNUSED,
929	      Pixmap *pixmap_return, Pixmap *mask_return,
930	      Dimension *width_return, Dimension *height_return)
931{
932  XpmAttributes xpm_attributes;
933  XawArgVal *argval;
934  unsigned int closeness = 4000;
935  static SubstitutionRec sub[] = {
936    {'H',   NULL},
937    {'N',   NULL},
938    {'T',   "pixmaps"},
939    {'P',   PROJECT_ROOT},
940  };
941  const char *filename;
942
943  if ((argval = XawFindArgVal(params, "closeness")) != NULL
944      && argval->value)
945    closeness = (unsigned)atoi(argval->value);
946
947  if (params->name[0] != '/' && params->name[0] != '.')
948    {
949      if (!sub[0].substitution)
950	sub[0].substitution = getenv("HOME");
951      sub[1].substitution = params->name;
952      if (pixmap_path == NULL)
953	GetResourcePixmapPath(DisplayOfScreen(screen));
954      filename = XtFindFile(pixmap_path, sub, XtNumber(sub), NULL);
955      if (!filename)
956	return (False);
957    }
958  else
959    filename = params->name;
960
961  xpm_attributes.colormap = colormap;
962  xpm_attributes.closeness = closeness;
963  xpm_attributes.valuemask = XpmSize | XpmColormap | XpmCloseness;
964  if (XpmReadFileToPixmap(DisplayOfScreen(screen),
965			  RootWindowOfScreen(screen), filename, pixmap_return,
966			  mask_return, &xpm_attributes) == XpmSuccess)
967    {
968      *width_return = (Dimension)xpm_attributes.width;
969      *height_return = (Dimension)xpm_attributes.height;
970
971      return (True);
972    }
973
974  return (False);
975}
976
977void
978XawReshapeWidget(Widget w, XawPixmap *pixmap)
979{
980  if (!pixmap || pixmap->mask == None)
981    XShapeCombineMask(XtDisplay(w), XtWindow(w), ShapeBounding, 0, 0,
982		      None, ShapeSet);
983  else
984    XShapeCombineMask(XtDisplay(w), XtWindow(w), ShapeBounding, 0, 0,
985		      pixmap->mask, ShapeSet);
986}
987
988#endif /* OLDXAW */
989