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