2 * Copyright (c) 1998 by The XFree86 Project, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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
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
34 #include <X11/IntrinsicP.h>
35 #include <X11/Xmu/CharSet.h>
36 #include <X11/Xfuncs.h>
37 #include <X11/extensions/shape.h>
52 typedef struct _XawCache {
55 unsigned int num_elems;
58 typedef struct _XawPixmapLoaderInfo {
59 XawPixmapLoader loader;
62 } XawPixmapLoaderInfo;
67 static Bool BitmapLoader(XawParams*, Screen*, Colormap, int,
68 Pixmap*, Pixmap*, Dimension*, Dimension*);
69 static Bool GradientLoader(XawParams*, Screen*, Colormap, int,
70 Pixmap*, Pixmap*, Dimension*, Dimension*);
71 static Bool XPixmapLoader(XawParams*, Screen*, Colormap, int,
72 Pixmap*, Pixmap*, Dimension*, Dimension*);
73 static XawPixmap *_XawFindPixmap(String, Screen*, Colormap, int);
74 static void _XawCachePixmap(XawPixmap*, Screen*, Colormap, int);
75 static int _XawFindPixmapLoaderIndex(String, String);
76 static int qcmp_long(register _Xconst void*, register _Xconst void *);
77 static int bcmp_long(register _Xconst void*, register _Xconst void *);
78 static int qcmp_string(register _Xconst void*, register _Xconst void *);
79 static int bcmp_string(register _Xconst void*, register _Xconst void *);
80 static void GetResourcePixmapPath(Display*);
85 static XawCache xaw_pixmaps;
86 static XawCache x_pixmaps; /* for fast reverse search */
87 static XawPixmapLoaderInfo **loader_info;
88 static Cardinal num_loader_info;
94 XawPixmapsInitialize(void)
96 static Boolean first_time = True;
101 (void)XawAddPixmapLoader(NULL, NULL, BitmapLoader);
102 (void)XawAddPixmapLoader("bitmap", NULL, BitmapLoader);
103 (void)XawAddPixmapLoader("gradient", NULL, GradientLoader);
104 (void)XawAddPixmapLoader("xpm", "xpm", XPixmapLoader);
110 XawParseParamsString(String name)
112 XawParams *xaw_params;
113 char *tok, *str, *type = NULL, *ext = NULL, *params = NULL;
118 xaw_params = (XawParams *)XtMalloc(sizeof(XawParams));
120 str = XtNewString(name);
124 while (tok = strchr(tok, ':'), tok)
126 if (tok == str || tok[-1] != '\\')
128 memmove(&tok[-1], tok, strlen(tok) + 1);
133 if (strchr(str, '?'))
140 type = XtNewString(str);
141 memmove(str, tok, strlen(tok) + 1);
147 while (tok = strchr(tok, '?'), tok)
149 if (tok == str || tok[-1] != '\\')
151 if (tok != str && tok[-1] == '\\')
152 memmove(&tok[-1], tok, strlen(tok) + 1);
164 while (tok = strchr(tok, '.'), tok)
166 if (tok == str || tok[-1] != '\\')
168 if (tok != str && tok[-1] == '\\')
169 memmove(&tok[-1], tok, strlen(tok) + 1);
176 if (strchr(ext, '/'))
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;
192 for (tok = strtok(params, "&"); tok; tok = strtok(NULL, "&"))
194 val = strchr(tok, '=');
200 val = XtNewString(val);
204 arg = XtNewString(tok);
205 xaw_arg = (XawArgVal *)XtMalloc(sizeof(XawArgVal));
207 xaw_arg->value = val;
208 if (!xaw_params->num_args)
210 xaw_params->num_args = 1;
211 xaw_params->args = (XawArgVal **)
212 XtMalloc(sizeof(XawArgVal*));
216 ++xaw_params->num_args;
217 xaw_params->args = (XawArgVal **)
218 XtRealloc((char *)xaw_params->args,
219 sizeof(XawArgVal*) * xaw_params->num_args);
221 xaw_params->args[xaw_params->num_args - 1] = xaw_arg;
225 if (xaw_params->num_args > 1)
226 qsort(xaw_params->args, xaw_params->num_args, sizeof(XtPointer),
235 XawFreeParamsStruct(XawParams *params)
242 for (i = 0; i < params->num_args; i++)
244 XtFree(params->args[i]->name);
245 if (params->args[i]->value)
246 XtFree(params->args[i]->value);
247 XtFree((char *)params->args[i]);
251 XtFree((char *)params->args);
252 XtFree((char *)params);
256 XawFindArgVal(XawParams *params, String name)
263 arg_val = (XawArgVal **)bsearch((void *)name, params->args,
264 params->num_args, sizeof(XtPointer*),
273 XawLoadPixmap(String name, Screen *screen, Colormap colormap, int depth)
277 XawPixmap *xaw_pixmap;
279 Dimension width, height;
280 XawParams *xaw_params;
285 xaw_pixmap = _XawFindPixmap(name, screen, colormap, depth);
290 if ((xaw_params = XawParseParamsString(name)) == NULL)
293 idx = _XawFindPixmapLoaderIndex(xaw_params->type, xaw_params->ext);
298 fprintf(stderr, "(*) Loading pixmap \"%s\": ", name);
301 success = loader_info[idx]->loader(xaw_params, screen, colormap, depth,
302 &pixmap, &mask, &width, &height);
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);
314 XawFreeParamsStruct(xaw_params);
317 fprintf(stderr, "%s", success ? "success\n" : "failed\n");
320 return (success ? xaw_pixmap : NULL);
324 XawAddPixmapLoader(String type, String ext, XawPixmapLoader loader)
326 XawPixmapLoaderInfo *info;
332 i = _XawFindPixmapLoaderIndex(type, ext);
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;
346 if ((info = (XawPixmapLoaderInfo *)XtMalloc(sizeof(XawPixmapLoaderInfo)))
350 info->loader = loader;
351 info->type = type ? XtNewString(type) : NULL;
352 info->ext = ext ? XtNewString(ext) : NULL;
357 loader_info = (XawPixmapLoaderInfo**)
358 XtMalloc(sizeof(XawPixmapLoaderInfo*));
363 loader_info = (XawPixmapLoaderInfo**)
364 XtRealloc((char *)loader_info,
365 sizeof(XawPixmapLoaderInfo) * num_loader_info);
367 loader_info[num_loader_info - 1] = info;
373 _XawFindPixmapLoaderIndex(String type, String ext)
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))
386 return (0); /* try a bitmap */
392 qcmp_x_cache(register _Xconst void *left, register _Xconst void *right)
394 return ((int)((*(XawPixmap **)left)->pixmap) -
395 (int)((*(XawPixmap **)right)->pixmap));
399 bcmp_x_cache(register _Xconst void *pixmap, register _Xconst void *xaw)
401 return (int)((long)pixmap - (long)((*(XawPixmap **)xaw)->pixmap));
405 qcmp_long(register _Xconst void *left, register _Xconst void *right)
407 return ((long)((*(XawCache **)left)->value) -
408 (long)((*(XawCache **)right)->value));
412 qcmp_string(register _Xconst void *left, register _Xconst void *right)
414 return (strcmp((String)((*(XawCache **)left)->value),
415 (String)((*(XawCache **)right)->value)));
419 bcmp_long(register _Xconst void *value, register _Xconst void *cache)
421 return ((long)value - (long)((*(XawCache **)cache)->value));
425 bcmp_string(register _Xconst void *string,
426 register _Xconst void *cache)
428 return (strcmp((String)string, (String)((*(XawCache **)cache)->value)));
432 #define FIND_SCREEN 1
433 #define FIND_COLORMAP 2
436 _XawFindCache(XawCache *xaw,
437 Screen *screen, Colormap colormap, int depth, int flags)
445 cache = (XawCache **)bsearch(screen, xaw->elems,
446 xaw->num_elems, sizeof(XtPointer),
448 if (!cache || !(*cache)->num_elems)
450 if (flags == FIND_SCREEN)
454 cache = (XawCache **)bsearch((void *)colormap, (*cache)->elems,
455 (*cache)->num_elems, sizeof(XtPointer),
457 if (!cache || !(*cache)->num_elems)
459 if (flags == FIND_COLORMAP)
463 cache = (XawCache **)bsearch((void *)(long)depth, (*cache)->elems,
464 (*cache)->num_elems, sizeof(XtPointer),
467 if (!cache || !(*cache)->num_elems)
473 _XawGetCache(XawCache *xaw, Screen *screen, Colormap colormap, int depth)
475 XawCache *s_cache, *c_cache, *d_cache, *cache, *pcache;
477 cache = _XawFindCache(xaw, screen, colormap, depth, FIND_ALL);
481 s_cache = _XawFindCache(xaw,
482 screen, colormap, depth, FIND_SCREEN);
485 pcache = (XawCache *)XtMalloc(sizeof(XawCache));
489 xaw->elems = (XtPointer*)XtMalloc(sizeof(XtPointer));
494 xaw->elems = (XtPointer*)
495 XtRealloc((char *)xaw->elems,
496 sizeof(XtPointer) * xaw->num_elems);
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);
507 c_cache = _XawFindCache(xaw,
508 screen, colormap, depth, FIND_COLORMAP);
511 pcache = (XawCache *)XtMalloc(sizeof(XawCache));
512 if (!s_cache->num_elems)
514 s_cache->num_elems = 1;
515 s_cache->elems = (XtPointer*)XtMalloc(sizeof(XtPointer));
519 ++s_cache->num_elems;
520 s_cache->elems = (XtPointer*)
521 XtRealloc((char *)s_cache->elems,
522 sizeof(XtPointer) * s_cache->num_elems);
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);
534 d_cache = _XawFindCache(xaw,
535 screen, colormap, depth, FIND_DEPTH);
538 pcache = (XawCache *)XtMalloc(sizeof(XawCache));
539 if (!c_cache->num_elems)
541 c_cache->num_elems = 1;
542 c_cache->elems = (XtPointer*)XtMalloc(sizeof(XtPointer));
546 ++c_cache->num_elems;
547 c_cache->elems = (XtPointer*)
548 XtRealloc((char *)c_cache->elems,
549 sizeof(XtPointer) * c_cache->num_elems);
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);
568 _XawFindPixmap(String name, Screen *screen, Colormap colormap, int depth)
573 cache = _XawFindCache(&xaw_pixmaps, screen, colormap, depth, FIND_ALL);
579 pixmap = (XawPixmap **)bsearch((void *)name, cache->elems,
580 cache->num_elems, sizeof(XtPointer),
589 XawPixmapFromXPixmap(Pixmap pixmap,
590 Screen *screen, Colormap colormap, int depth)
593 XawPixmap **x_pixmap;
595 cache = _XawFindCache(&x_pixmaps, screen, colormap, depth, FIND_ALL);
601 x_pixmap = (XawPixmap **)bsearch((void *)pixmap, cache->elems,
602 cache->num_elems, sizeof(XtPointer),
611 _XawCachePixmap(XawPixmap *pixmap,
612 Screen *screen, Colormap colormap, int depth)
614 XawCache *xaw_cache, *x_cache;
616 xaw_cache = _XawGetCache(&xaw_pixmaps, screen, colormap, depth);
617 x_cache = _XawGetCache(&x_pixmaps, screen, colormap, depth);
619 if (!xaw_cache->num_elems)
621 xaw_cache->num_elems = 1;
622 xaw_cache->elems = (XtPointer*)XtMalloc(sizeof(XtPointer));
626 ++xaw_cache->num_elems;
627 xaw_cache->elems = (XtPointer*)XtRealloc((char *)xaw_cache->elems,
629 xaw_cache->num_elems);
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);
638 if (!x_cache->num_elems)
640 x_cache->num_elems = 1;
641 x_cache->elems = (XtPointer*)XtMalloc(sizeof(XtPointer));
645 ++x_cache->num_elems;
646 x_cache->elems = (XtPointer*)XtRealloc((char *)x_cache->elems,
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);
657 #define PROJECT_ROOT "/usr/X11R6"
660 static char *pixmap_path = NULL;
663 GetResourcePixmapPath(Display *display)
666 XrmClass xrm_class[2];
667 XrmRepresentation rep_type;
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";
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")) {
682 char *tok, *buffer = XtNewString(value.addr);
684 for (tok = strtok(buffer, ":"); tok; tok = strtok(NULL, ":")) {
685 int toklen = strlen(tok);
688 pixmap_path = XtRealloc(pixmap_path, length + toklen + 5);
689 strcpy(pixmap_path + length, tok);
691 pixmap_path[length++] = ':';
692 sprintf(pixmap_path + length, "%s/%%N", tok);
693 length += strlen(tok) + 3;
696 pixmap_path = XtRealloc(pixmap_path, length + strlen(default_path) + 2);
698 pixmap_path[length++] = ':';
699 strcpy(pixmap_path + length, default_path);
702 pixmap_path = default_path;
706 BitmapLoader(XawParams *params, Screen *screen, Colormap colormap, int depth,
707 Pixmap *pixmap_return, Pixmap *mask_return,
708 Dimension *width_return, Dimension *height_return)
713 unsigned int width, height;
714 unsigned char *data = NULL;
718 static SubstitutionRec sub[] = {
726 fg = BlackPixelOfScreen(screen);
727 bg = WhitePixelOfScreen(screen);
729 if ((argval = XawFindArgVal(params, "foreground")) != NULL
732 if (XAllocNamedColor(DisplayOfScreen(screen), colormap, argval->value,
738 if ((argval = XawFindArgVal(params, "background")) != NULL
741 if (XAllocNamedColor(DisplayOfScreen(screen), colormap, argval->value,
748 if (params->name[0] != '/' && params->name[0] != '.')
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);
760 filename = params->name;
762 if (XReadBitmapFileData(filename, &width, &height, &data,
763 &hotX, &hotY) == BitmapSuccess)
765 pixmap = XCreatePixmapFromBitmapData(DisplayOfScreen(screen),
766 RootWindowOfScreen(screen),
768 width, height, fg, bg, depth);
771 *pixmap_return = pixmap;
773 *width_return = width;
774 *height_return = height;
779 if (filename != params->name)
788 GradientLoader(XawParams *params, Screen *screen, Colormap colormap, int depth,
789 Pixmap *pixmap_return, Pixmap *mask_return,
790 Dimension *width_return, Dimension *height_return)
792 double ired, igreen, iblue, red, green, blue;
793 XColor start, end, color;
796 double i, inc, x, y, xend, yend;
799 int orientation, dimension, steps;
802 if (XmuCompareISOLatin1(params->name, "vertical") == 0)
803 orientation = VERTICAL;
804 else if (XmuCompareISOLatin1(params->name, "horizontal") == 0)
805 orientation = HORIZONTAL;
809 if ((argval = XawFindArgVal(params, "dimension")) != NULL
812 dimension = atoi(argval->value);
819 if ((argval = XawFindArgVal(params, "steps")) != NULL
822 steps = atoi(argval->value);
829 steps = XawMin(steps, dimension);
832 if ((argval = XawFindArgVal(params, "start")) != NULL)
833 value = argval->value;
834 if (value && !XAllocNamedColor(DisplayOfScreen(screen), colormap, value,
839 start.pixel = WhitePixelOfScreen(screen);
840 XQueryColor(DisplayOfScreen(screen), colormap, &start);
843 if ((argval = XawFindArgVal(params, "end")) != NULL)
844 value = argval->value;
845 if (value && !XAllocNamedColor(DisplayOfScreen(screen), colormap, value,
850 end.pixel = BlackPixelOfScreen(screen);
851 XQueryColor(DisplayOfScreen(screen), colormap, &end);
854 if ((pixmap = XCreatePixmap(DisplayOfScreen(screen),
855 RootWindowOfScreen(screen),
856 orientation == VERTICAL ? 1 : dimension,
857 orientation == VERTICAL ? dimension : 1, depth))
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;
865 red = color.red = start.red;
866 green = color.green = start.green;
867 blue = color.blue = start.blue;
869 inc = (double)dimension / (double)steps;
871 gc = XCreateGC(DisplayOfScreen(screen), pixmap, 0, &values);
874 if (orientation == VERTICAL)
885 color.flags = DoRed | DoGreen | DoBlue;
887 XSetForeground(DisplayOfScreen(screen), gc, start.pixel);
888 for (i = 0.0; i < dimension; i += inc)
890 if ((int)color.red != (int)red || (int)color.green != (int)green
891 || (int)color.blue != (int)blue)
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))
900 XFreePixmap(DisplayOfScreen(screen), pixmap);
903 XSetForeground(DisplayOfScreen(screen), gc, color.pixel);
904 if (orientation == VERTICAL)
912 if (orientation == VERTICAL)
917 XFillRectangle(DisplayOfScreen(screen), pixmap, gc, (int)x, (int)y,
918 (unsigned int)xend, (unsigned int)yend);
920 *pixmap_return = pixmap;
922 *width_return = orientation == VERTICAL ? 1 : dimension;
923 *height_return = orientation == VERTICAL ? dimension : 1;
925 XFreeGC(DisplayOfScreen(screen), gc);
931 XPixmapLoader(XawParams *params, Screen *screen, Colormap colormap, int depth,
932 Pixmap *pixmap_return, Pixmap *mask_return,
933 Dimension *width_return, Dimension *height_return)
935 XpmAttributes xpm_attributes;
937 unsigned int closeness = 4000;
938 static SubstitutionRec sub[] = {
946 if ((argval = XawFindArgVal(params, "closeness")) != NULL
948 closeness = atoi(argval->value);
950 if (params->name[0] != '/' && params->name[0] != '.')
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);
962 filename = params->name;
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)
971 *width_return = xpm_attributes.width;
972 *height_return = xpm_attributes.height;
981 XawReshapeWidget(Widget w, XawPixmap *pixmap)
983 if (!pixmap || pixmap->mask == None)
984 XShapeCombineMask(XtDisplay(w), XtWindow(w), ShapeBounding, 0, 0,
987 XShapeCombineMask(XtDisplay(w), XtWindow(w), ShapeBounding, 0, 0,
988 pixmap->mask, ShapeSet);