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