Subject: FVWM color limiting

From: Dan Espen <[email-masked]>
Date: Tue, 25 Feb 1997 15:28:29 -0500

This patch causes fvwm to limit the colors used in pixmaps.

I failed  to  keep  the  FvwmPager   mini-icon patch, so   it  doesn't
currently do anything to the colors in the pager.

I've tested  this with my own configurations  on 2 different machines,
and it seems to work surprisingly well.  Assuming this eventually gets
incorporated into fvwm, any feedback would be appreciated.

*** fvwm/fvwm2.man.orig	Tue Jan 14 17:38:43 1997
--- fvwm/fvwm2.man	Thu Feb 20 22:47:10 1997
***************
*** 826,831 ****
--- 826,847 ----
  destroyed.

+ .IP "ColorLimit \fIlimit\fP"
+ Specifies a  limit on the colors  used in pixmaps.  Zero (the default)
+ sets no limit.   This command limits pixmap  colors to a set of colors
+ that  starts out with common  colors.  The current list contains about
+ 40 colors and starts with white, black,  grey, green, blue, red, cyan,
+ yellow, and  magenta.  The command  "ColorLimit 9" would limit pixmaps
+ to these 9 colors.
+ 
+ It makes the most sense to put this command at the front of the
+ .fvwm2rc  file.  This   command should  be   before any  menu
+ definitions that contain mini-icons.
+ 
+ Frame and  title  colors  (including shading  and gradients)  are  not
+ controlled by this command.
+ 
+ 
  .IP "ColormapFocus [FollowsMouse | FollowsFocus]"
  By default, fvwm installs the colormap of the window that the cursor
  is in.  If you use ColormapFocus FollowsFocus, then the installed
*** fvwm/icons.c.orig	Mon Feb 17 16:38:01 1997
--- fvwm/icons.c	Sun Feb 23 14:10:35 1997
***************
*** 593,598 ****
--- 593,600 ----
    XpmAttributes xpm_attributes;
    extern char *PixmapPath;
    char *path = NULL;
+   XpmImage	my_image;
+   int rc;
  
    path = findIconFile(tmp_win->icon_bitmap_file, PixmapPath,R_OK);
    if(path == NULL)return;  
***************
*** 600,621 ****
    XGetWindowAttributes(dpy,Scr.Root,&root_attr);
    xpm_attributes.colormap = root_attr.colormap;
    xpm_attributes.closeness = 40000; /* Allow for "similar" colors */
!   xpm_attributes.valuemask = XpmSize | XpmReturnPixels | XpmColormap | XpmCloseness;
  
!   if(XpmReadFileToPixmap(dpy, Scr.Root, path,
! 			 &tmp_win->iconPixmap, 
! 			 &tmp_win->icon_maskPixmap, 
! 			 &xpm_attributes) == XpmSuccess) 
!     { 
!       tmp_win->icon_p_width = xpm_attributes.width;
!       tmp_win->icon_p_height = xpm_attributes.height;
!       tmp_win->flags |= PIXMAP_OURS;
!       tmp_win->iconDepth = Scr.d_depth;
  #ifdef SHAPE
!       if (ShapesSupported && tmp_win->icon_maskPixmap)
! 	tmp_win->flags |= SHAPED_ICON;
  #endif
-     } 
    free(path);
  #endif /* XPM */
  }
--- 602,633 ----
    XGetWindowAttributes(dpy,Scr.Root,&root_attr);
    xpm_attributes.colormap = root_attr.colormap;
    xpm_attributes.closeness = 40000; /* Allow for "similar" colors */
!   xpm_attributes.valuemask = XpmSize|XpmReturnPixels|XpmColormap|XpmCloseness;
  
!   rc =XpmReadFileToXpmImage(path, &my_image, NULL);
!   if (rc != XpmSuccess) {
!     fvwm_msg(ERR,"GetXPMFile","XpmReadFileToXpmImage failed, pixmap %s, rc %d",
!            path, rc);
!     return;
!   }
!   color_reduce_pixmap(&my_image,Scr.ColorLimit);
!   rc = XpmCreatePixmapFromXpmImage(dpy,Scr.Root, &my_image,
!                                    &tmp_win->iconPixmap, 
!                                    &tmp_win->icon_maskPixmap, 
!                                    &xpm_attributes);
!   if (rc != XpmSuccess) {
!     fvwm_msg(ERR,"GetXPMFile",
!              "XpmCreatePixmapFromXpmImage failed, rc %d\n", rc);
!     return;
!   }
!   tmp_win->icon_p_width = my_image.width;
!   tmp_win->icon_p_height = my_image.height;
!   tmp_win->flags |= PIXMAP_OURS;
!   tmp_win->iconDepth = Scr.d_depth;
  #ifdef SHAPE
!   if (ShapesSupported && tmp_win->icon_maskPixmap)
!     tmp_win->flags |= SHAPED_ICON;
  #endif
    free(path);
  #endif /* XPM */
  }
*** fvwm/builtins.c.orig	Mon Feb 17 16:38:43 1997
--- fvwm/builtins.c	Sun Feb 23 11:20:46 1997
***************
*** 2156,2162 ****
  #else
  				   NULL,
  #endif
! 				   file);
  	    if (bf->u.p == NULL)
  	    {
  		if(verbose)fvwm_msg(ERR,"ReadButtonFace",
--- 2156,2162 ----
  #else
  				   NULL,
  #endif
! 				   file,Scr.ColorLimit);
  	    if (bf->u.p == NULL)
  	    {
  		if(verbose)fvwm_msg(ERR,"ReadButtonFace",
***************
*** 3136,3139 ****
--- 3136,3153 ----
    }
    if (opts) /* should be empty at this point... */
      free(opts);
+ }
+ void SetColorLimit(XEvent *eventp,Window w,FvwmWindow *tmp_win,
+                    unsigned long context, char *action,int* Module)
+ {
+   long val1;
+   int val1_unit,n;
+   
+   n = GetOneArgument(action, &val1, &val1_unit);
+   if(n != 1) {
+     fvwm_msg(ERR,"SetColorLimit","ColorLimit requires 1 argument, found %d",n);
+     return;
+   }
+   
+   Scr.ColorLimit = val1;
  }
*** fvwm/functions.c.orig	Mon Feb 17 16:38:29 1997
--- fvwm/functions.c	Thu Feb 20 22:12:46 1997
***************
*** 57,62 ****
--- 57,63 ----
  #endif
    {"ClickTime",    SetClick,         F_CLICK,               FUNC_NO_WINDOW},
    {"Close",        close_function,   F_CLOSE,               FUNC_NEEDS_WINDOW},
+   {"ColorLimit",   SetColorLimit,    F_COLOR_LIMIT,         FUNC_NO_WINDOW},
    {"ColormapFocus",SetColormapFocus, F_COLORMAP_FOCUS,      FUNC_NO_WINDOW},
    {"CursorMove",   movecursor,       F_MOVECURSOR,          FUNC_NO_WINDOW},
    {"Delete",       delete_function,  F_DELETE,              FUNC_NEEDS_WINDOW},
*** fvwm/misc.h.orig	Mon Feb 17 16:37:48 1997
--- fvwm/misc.h	Sun Feb 23 10:19:23 1997
***************
*** 354,359 ****
--- 354,361 ----
  		unsigned long context, char *action,int *Module);
  void SetColormapFocus(XEvent *eventp,Window w,FvwmWindow *tmp_win,
  		      unsigned long context, char *action,int* Module);
+ void SetColorLimit(XEvent *eventp,Window w,FvwmWindow *tmp_win,
+ 		      unsigned long context, char *action,int* Module);
  FVWM_INLINE void DrawPattern(Window, GC, GC, int, int,int);
  Pixel    GetShadow(Pixel);
  Pixel    GetHilite(Pixel);
*** fvwm/read.c.orig	Sun Feb 23 11:57:06 1997
--- fvwm/read.c	Sun Feb 23 11:57:51 1997
***************
*** 319,324 ****
--- 319,326 ----
  #ifdef XPM
    sprintf(message,"PixmapPath %s\n",PixmapPath);
    SendName(*Module,M_CONFIG_INFO,0,0,0,message);
+   sprintf(message,"ColorLimit %d\n",Scr.ColorLimit);
+   SendName(*Module,M_CONFIG_INFO,0,0,0,message);
  #endif
    sprintf(message,"ClickTime %d\n",Scr.ClickTime);
    SendName(*Module,M_CONFIG_INFO,0,0,0,message);
*** fvwm/screen.h.orig	Mon Feb 17 16:32:18 1997
--- fvwm/screen.h	Thu Feb 20 22:12:43 1997
***************
*** 311,316 ****
--- 311,317 ----
    int OpaqueSize;
    int CurrentDesk;             /* The current desktop number */
    int ColormapFocus;           /* colormap focus style */
+   int ColorLimit;              /* Limit on colors used in pixmaps */
  
    /*
    ** some additional global options which will probably become window
*** fvwm/parse.h.orig	Mon Feb 17 16:38:15 1997
--- fvwm/parse.h	Thu Feb 20 22:12:44 1997
***************
*** 101,106 ****
--- 101,107 ----
  #define F_DESTROY_DECOR         124
  #define F_UPDATE_DECOR          125
  #define F_WINDOW_SHADE          126
+ #define F_COLOR_LIMIT           127
  
  /* Functions for use by modules only! */
  #define F_SEND_WINDOW_LIST     1000
*** fvwm/add_window.c.orig	Mon Feb 24 20:50:54 1997
--- fvwm/add_window.c	Sun Feb 23 13:31:21 1997
***************
*** 519,525 ****
  #else
  					   NULL,
  #endif
! 					   tmp_win->mini_pixmap_file);
        }
        else {
  	tmp_win->mini_icon = NULL;
--- 519,526 ----
  #else
  					   NULL,
  #endif
! 					   tmp_win->mini_pixmap_file,
!                                            Scr.ColorLimit);
        }
        else {
  	tmp_win->mini_icon = NULL;
*** fvwm/menus.c.orig	Mon Jan 20 11:56:11 1997
--- fvwm/menus.c	Tue Feb 25 12:30:02 1997
***************
*** 1145,1153 ****
  
  	  /* Next, check for a color pixmap */
  #ifdef XPM
! 	  pp=CachePicture(dpy,Scr.Root,IconPath,PixmapPath,name);
  #else
! 	  pp=CachePicture(dpy,Scr.Root,IconPath,IconPath,name);
  #endif
  	  if(*txt != '\0')txt++;
  	  while(*txt != '\0')
--- 1145,1153 ----
  
  	  /* Next, check for a color pixmap */
  #ifdef XPM
! 	  pp=CachePicture(dpy,Scr.Root,IconPath,PixmapPath,name,Scr.ColorLimit);
  #else
! 	  pp=CachePicture(dpy,Scr.Root,IconPath,IconPath,name,Scr.ColorLimit);
  #endif
  	  if(*txt != '\0')txt++;
  	  while(*txt != '\0')
*** libs/Picture.c.orig	Mon Feb 17 16:42:00 1997
--- libs/Picture.c	Sun Feb 23 13:55:16 1997
***************
*** 5,10 ****
--- 5,28 ----
   *     You may use this code for any purpose, as long as the original
   *     copyright remains in the source code and all documentation
   ****************************************************************************/
+ /*
+   Changed 02/12/97 by Dan Espen:
+   - added routines to determine color closeness, for color use reduction.
+   Some of the logic comes from pixy2, so the copyright is below.
+   */
+ /*
+  * $Id: pixy.c,v 3.0.1.1 1996/03/20 12:31:49 deejai!martin Exp $
+  * Copyright 1996, Romano Giannetti. No guarantees or warantees or anything
+  * are provided or implied in any way whatsoever. Use this program at your
+  * own risk. Permission to use this program for any purpose is given,
+  * as long as the copyright is kept intact.
+  *
+  * Romano Giannetti - Dipartimento di Ingegneria dell'Informazione
+  *                    via Diotisalvi, 2  PISA
+  * mailto:[email-masked]
+  * http://www.iet.unipi.it/~romano
+  *
+  */

  /****************************************************************************
***************
*** 30,36 ****
  #include <X11/Xutil.h>
  
  #ifdef XPM
! #include <X11/xpm.h>
  #endif
  
  #include "fvwmlib.h"
--- 48,58 ----
  #include <X11/Xutil.h>
  
  #ifdef XPM
! /* static function prototypes */
! static void c100_init_base_table ();    /* prototype */
! static void c200_substitute_color(char **,int); /* prototype */
! static void c300_color_to_rgb(char *, XColor *); /* prototype */
! static double c400_distance(XColor *, XColor *); /* prototype */
  #endif
  
  #include "fvwmlib.h"
***************
*** 38,59 ****
  
  static Picture *PictureList=NULL;
  static Colormap PictureCMap;
  
! 
  void InitPictureCMap(Display *dpy,Window Root)
  {
    XWindowAttributes root_attr;
    XGetWindowAttributes(dpy,Root,&root_attr);
    PictureCMap=root_attr.colormap;
  }

! Picture *LoadPicture(Display *dpy,Window Root,char *path)
  {
    int i,l;
    Picture *p;
  #ifdef XPM
    XpmAttributes xpm_attributes;
  #endif
  
    p=(Picture*)safemalloc(sizeof(Picture));
--- 60,85 ----
  
  static Picture *PictureList=NULL;
  static Colormap PictureCMap;
+ static Display *save_dpy;               /* Save area for display pointer */
  
! /* This routine called during fvwm initialization */
  void InitPictureCMap(Display *dpy,Window Root)
  {
    XWindowAttributes root_attr;
+   save_dpy = dpy;                       /* save for latter */
    XGetWindowAttributes(dpy,Root,&root_attr);
    PictureCMap=root_attr.colormap;
  }

! Picture *LoadPicture(Display *dpy,Window Root,char *path, int color_limit)
  {
    int i,l;
    Picture *p;
  #ifdef XPM
    XpmAttributes xpm_attributes;
+   int rc;
+   XpmImage	my_image;
  #endif
  
    p=(Picture*)safemalloc(sizeof(Picture));
***************
*** 68,81 ****
    xpm_attributes.valuemask=
      XpmSize | XpmReturnPixels | XpmColormap | XpmCloseness;
    
!   if(XpmReadFileToPixmap(dpy,Root,path,&p->picture,&p->mask,&xpm_attributes)
!      == XpmSuccess) 
!     { 
!       p->width = xpm_attributes.width;
!       p->height = xpm_attributes.height;
        p->depth = DefaultDepthOfScreen(DefaultScreenOfDisplay(dpy));
        return p;
      }
  #endif
  
    /* If no XPM support, or XPM loading failed, try bitmap */
--- 94,112 ----
    xpm_attributes.valuemask=
      XpmSize | XpmReturnPixels | XpmColormap | XpmCloseness;
    
!   rc =XpmReadFileToXpmImage(path, &my_image, NULL);
!   if (rc == XpmSuccess) {
!     color_reduce_pixmap(&my_image, color_limit);
!     rc = XpmCreatePixmapFromXpmImage(dpy, Root, &my_image,
!                                      &p->picture,&p->mask,
!                                      &xpm_attributes);
!     if (rc == XpmSuccess) {
!       p->width = my_image.width;
!       p->height = my_image.height;
        p->depth = DefaultDepthOfScreen(DefaultScreenOfDisplay(dpy));
        return p;
      }
+   }
  #endif
  
    /* If no XPM support, or XPM loading failed, try bitmap */
***************
*** 92,98 ****
    return NULL;
  }
  
! 
  Picture *GetPicture(Display *dpy,Window Root,char *IconPath,char *PixmapPath,
  		    char *name)
  {
--- 123,129 ----
    return NULL;
  }
  
! #ifdef NotUsed
  Picture *GetPicture(Display *dpy,Window Root,char *IconPath,char *PixmapPath,
  		    char *name)
  {
***************
*** 100,111 ****
    if(!(path=findIconFile(name,PixmapPath,R_OK)))
      if(!(path=findIconFile(name,IconPath,R_OK)))
        return NULL;
!   return LoadPicture(dpy,Root,path);
  }
  
- 
  Picture *CachePicture(Display *dpy,Window Root,char *IconPath,char *PixmapPath,
! 		    char *name)
  {
    char *path;
    Picture *p=PictureList;
--- 131,142 ----
    if(!(path=findIconFile(name,PixmapPath,R_OK)))
      if(!(path=findIconFile(name,IconPath,R_OK)))
        return NULL;
!   return LoadPicture(dpy,Root,path, color_limit);
  }
+ #endif
  
  Picture *CachePicture(Display *dpy,Window Root,char *IconPath,char *PixmapPath,
! 		    char *name, int color_limit)
  {
    char *path;
    Picture *p=PictureList;
***************
*** 135,141 ****
      }
  
    /* Not previously cached, have to load it ourself. Put it first in list */
!   p=LoadPicture(dpy,Root,path);
    if(p)
      {
        p->next=PictureList;
--- 166,172 ----
      }
  
    /* Not previously cached, have to load it ourself. Put it first in list */
!   p=LoadPicture(dpy,Root,path, color_limit);
    if(p)
      {
        p->next=PictureList;
***************
*** 248,250 ****
--- 279,431 ----
  }

+ #ifdef XPM
+ /* This structure is used to quickly access the RGB values of the colors */
+ /* without repeatedly having to transform them.   */
+ typedef struct {
+   char * c_color;	/* Pointer to the name of the color */
+   XColor rgb_space;                     /* rgb color info */
+ } Color_Info;
+ 
+ /* First thing in base array are colors probably already in the color map
+    because they have familiar names.
+    I pasted them into a xpm and spread them out so that similar colors are
+    spread out.
+    TODO:
+    Find the large gaps and add colors to fill them.
+    Currently contains 41 colors.
+    If reducing from 256, how many colors should be allowed for?
+    */
+ static Color_Info base_array[] = {
+   {"white"},
+   {"black"},
+   {"grey"},
+   {"green"},
+   {"blue"},
+   {"red"},
+   {"cyan"},
+   {"yellow"},
+   {"magenta"},
+   {"DodgerBlue"},
+   {"SteelBlue"},
+   {"chartreuse"},
+   {"wheat"},
+   {"turquoise"},
+   {"CadetBlue"},
+   {"gray87"},
+   {"CornflowerBlue"},
+   {"YellowGreen"},
+   {"NavyBlue"},
+   {"MediumBlue"},
+   {"plum"},
+   {"aquamarine"},
+   {"orchid"},
+   {"ForestGreen"},
+   {"lightyellow"},
+   {"brown"},
+   {"orange"},
+   {"red3"},
+   {"HotPink"},
+   {"LightBlue"},
+   {"gray47"},
+   {"pink"},
+   {"red4"},
+   {"violet"},
+   {"purple"},
+   {"gray63"},
+   {"gray94"},
+   {"plum1"},
+   {"PeachPuff"},
+   {"maroon"},
+   {"lavender"}
+ };
+ 
+ #define NColors (sizeof(base_array) / sizeof(Color_Info))
+ 
+ /* given an xpm, change colors to colors close to the
+    subset above. */
+ void
+ color_reduce_pixmap(XpmImage *image,int color_limit) {
+   int i;
+   XpmColor *color_table_ptr;
+   static char base_init = 'n';
+   if (color_limit > 0) {                /* If colors to be limited */
+     if (base_init == 'n') {             /* if base table not created yet */
+       c100_init_base_table();           /* init the base table */
+       base_init = 'y';                  /* remember that its set now. */
+     }                                   /* end base table init */
+     color_table_ptr = image->colorTable; /* start of xpm color table */
+     for(i=0; i<image->ncolors; i++) {   /* all colors in the xpm */
+       c200_substitute_color(&color_table_ptr->c_color,
+                             color_limit); /* fix each one */
+       color_table_ptr +=1;              /* counter for loop */
+     }                                   /* end all colors in xpm */
+   }                                     /* end colors limited */
+   return;                               /* return, no rc! */
+ }
+ 
+ /* from the color names in the base table, calc rgbs */
+ static void
+ c100_init_base_table () {
+   int i;
+   for (i=0; i<NColors; i++) {           /* change all base colors to numbers */
+     c300_color_to_rgb(base_array[i].c_color, &base_array[i].rgb_space);
+   }
+ }
+ 
+ 
+ /* Replace the color in my_color by the closest matching color
+    from base_table */
+ void c200_substitute_color(char **my_color, int color_limit) {
+   int i, limit, minind;
+   double mindst=1e20;
+   double dst;
+   XColor rgb;          /* place to calc rgb for each color in xpm */
+ 
+   if (!strcasecmp(*my_color,"none")) {
+     return ;                        /* do not substitute the "none" color */
+   }
+ 
+   c300_color_to_rgb(*my_color, &rgb);  /* get rgb for a color in xpm */
+   /* Loop over all base_array colors; find out which one is closest
+      to my_color */
+   minind = 0;                           /* Its going to find something... */
+   limit = NColors;                      /* init to max */
+   if (color_limit < NColors) {          /* can't do more than I have */
+     limit = color_limit;                /* Do reduction using subset */
+   }                                     /* end reducing limit */
+   for(i=0; i < limit; i++) {            /* loop over base array */
+     dst = c400_distance (&rgb, &base_array[i].rgb_space); /* distance */
+     if (dst < mindst ) {              /* less than min and better than last */
+       mindst=dst;                     /* new minimum */
+       minind=i;                       /* save loc of new winner */
+       if (dst <= 100) {               /* if close enough */
+         break;                        /* done */
+       }                               /* end close enough */
+     }                                 /* end new low distance */
+   }                                   /* end all base colors */
+   /* Finally: replace the color string by the newly determined color string */
+   *my_color = base_array[minind].c_color; /* change the color */
+   return;                             /* all done */
+ }
+ 
+ static void c300_color_to_rgb(char *c_color, XColor *rgb_space) {
+   int rc;
+   rc=XParseColor(save_dpy, PictureCMap, c_color, rgb_space);
+   if (rc==0) {
+     fprintf(stderr,"color_to_rgb: can't parse color %s, rc %d\n", c_color, rc);
+     return;
+   } 
+ }
+ 
+ /* A macro for squaring things */
+ #define SQUARE(X) ((X)*(X))
+ /* RGB Color distance sum of square of differences */
+ double c400_distance(XColor *target_ptr, XColor *base_ptr) {
+   register double dst;
+   dst = SQUARE((double)(base_ptr->red   - target_ptr->red  )/655.35)
+     +   SQUARE((double)(base_ptr->green - target_ptr->green)/655.35)
+     +   SQUARE((double)(base_ptr->blue  - target_ptr->blue )/655.35);
+   return dst;
+ }
+ #endif /* XPM */
*** libs/fvwmlib.h.orig	Sun Feb 23 10:12:00 1997
--- libs/fvwmlib.h	Sun Feb 23 13:33:22 1997
***************
*** 73,83 ****
  } Picture;
  
  void InitPictureCMap(Display*,Window);
  Picture *GetPicture(Display*,Window,char *iconpath,char *pixmappath,char*);
! Picture *CachePicture(Display*,Window,char *iconpath,char *pixmappath,char*);
  void DestroyPicture(Display*,Picture*);
  
  char *findIconFile(char *icon, char *pathlist, int type);
  
  /***********************************************************************
   * Wrappers around various X11 routines
--- 73,91 ----
  } Picture;
  
  void InitPictureCMap(Display*,Window);
+ #ifdef NotUsed
  Picture *GetPicture(Display*,Window,char *iconpath,char *pixmappath,char*);
! #endif
! Picture *CachePicture(Display*,Window,char *iconpath,
!                       char *pixmappath,char*,int);
  void DestroyPicture(Display*,Picture*);
  
  char *findIconFile(char *icon, char *pathlist, int type);
+ #ifdef XPM
+ #include <X11/Intrinsic.h>              /* needed for xpm.h */
+ #include <X11/xpm.h>                    /* needed for next prototype */
+ void color_reduce_pixmap(XpmImage *, int);
+ #endif
  
  /***********************************************************************
   * Wrappers around various X11 routines
*** modules/FvwmButtons/FvwmButtons.c.orig	Sun Feb 23 10:21:12 1997
--- modules/FvwmButtons/FvwmButtons.c	Sun Feb 23 15:05:14 1997
***************
*** 133,138 ****
--- 133,139 ----
  
  button_info *UberButton=NULL;
  
+ int save_color_limit;                   /* Color limit, if any */
  /* ------------------------------ Misc functions ----------------------------*/
  
  #ifdef DEBUG
***************
*** 768,774 ****
  **/
  int LoadIconFile(char *s,Picture **p)
  {
!   *p=CachePicture(Dpy,Root,iconPath,pixmapPath,s);
    if(*p)
      return 1;
    return 0;
--- 769,775 ----
  **/
  int LoadIconFile(char *s,Picture **p)
  {
!   *p=CachePicture(Dpy,Root,iconPath,pixmapPath,s, save_color_limit);
    if(*p)
      return 1;
    return 0;
*** modules/FvwmButtons/parse.c.orig	Sun Feb 23 09:52:08 1997
--- modules/FvwmButtons/parse.c	Sun Feb 23 12:03:31 1997
***************
*** 793,798 ****
--- 793,799 ----
    fclose(f);
  }
  
+ extern int save_color_limit;            /* global for xpm color limiting */
  /**
  *** ParseOptions()
  **/
***************
*** 799,808 ****
  void ParseOptions(button_info *ub)
  {
    char *s;
!   char *items[]={"iconpath","pixmappath",NULL,NULL};
  
!   items[2]=mymalloc(strlen(MyName)+2);
!   sprintf(items[2],"*%s",MyName);
  
    GetConfigLine(fd,&s);
    while(s && s[0])
--- 800,810 ----
  void ParseOptions(button_info *ub)
  {
    char *s;
!   char *items[]={"iconpath","pixmappath","colorlimit",NULL,NULL};
!   int rc;
  
!   items[3]=mymalloc(strlen(MyName)+2);
!   sprintf(items[3],"*%s",MyName);
  
    GetConfigLine(fd,&s);
    while(s && s[0])
***************
*** 817,823 ****
  	case 1:
  	  CopyString(&pixmapPath,s);
  	  break;
! 	case 2:
  	  if(s && s[0] && !config_file)
  	    ParseConfigLine(&ub,s);
  	}
--- 819,828 ----
  	case 1:
  	  CopyString(&pixmapPath,s);
  	  break;
! 	case 2:                         /* colorlimit */
!           sscanf(s,"%d",&save_color_limit);
! 	  break;
! 	case 3:
  	  if(s && s[0] && !config_file)
  	    ParseConfigLine(&ub,s);
  	}
*** modules/FvwmIconBox/icons.c.orig	Sun Feb 23 14:03:25 1997
--- modules/FvwmIconBox/icons.c	Mon Feb 24 21:29:48 1997
***************
*** 45,50 ****
--- 45,52 ----
  #include <X11/extensions/shape.h>
  #endif /* SHAPE */
  
+ extern int save_color_limit;
+ 
  #define ICON_EVENTS (ExposureMask |\
  ButtonReleaseMask | ButtonPressMask | EnterWindowMask | LeaveWindowMask)
  
***************
*** 235,240 ****
--- 237,244 ----
    XWindowAttributes root_attr;
    XpmAttributes xpm_attributes;
    char *path = NULL;
+   int rc;
+   XpmImage	my_image;
  
    path = findIconFile(item->icon_file, pixmapPath,R_OK);
    if(path == NULL)return;  
***************
*** 241,257 ****
  
    XGetWindowAttributes(dpy,Root,&root_attr);
    xpm_attributes.colormap = root_attr.colormap;
!   xpm_attributes.closeness = 20000;    /* tight? */
    xpm_attributes.valuemask = XpmSize|XpmReturnPixels|XpmColormap|XpmCloseness;
!   if(XpmReadFileToPixmap(dpy, Root, path,
! 			 &item->iconPixmap,
! 			 &item->icon_maskPixmap, 
! 			 &xpm_attributes) == XpmSuccess) 
!     { 
!       item->icon_w = min(max_icon_width, xpm_attributes.width);
!       item->icon_h = min(max_icon_height, xpm_attributes.height);
!       item->icon_depth = d_depth;
!     } 
    free(path);
  #endif /* XPM */
  }
--- 245,271 ----
  
    XGetWindowAttributes(dpy,Root,&root_attr);
    xpm_attributes.colormap = root_attr.colormap;
!   xpm_attributes.closeness = 40000;    /* same closeness used elsewhere */
    xpm_attributes.valuemask = XpmSize|XpmReturnPixels|XpmColormap|XpmCloseness;
!   rc = XpmReadFileToXpmImage(path, &my_image, NULL);
!   if (rc != XpmSuccess) {
!     fprintf(stderr, "Problem reading pixmap %s, rc %d\n", path, rc);
!     free(path);
!     return;
!   }
!   color_reduce_pixmap(&my_image,save_color_limit);
!   rc = XpmCreatePixmapFromXpmImage(dpy,Root, &my_image,
!                                     &item->iconPixmap,
!                                     &item->icon_maskPixmap, 
!                                     &xpm_attributes);
!   if (rc != XpmSuccess) {
!     fprintf(stderr, "Problem creating pixmap from image, rc %d\n", rc);
!     free(path);
!     return;
!   }
!   item->icon_w = min(max_icon_width, my_image.width);
!   item->icon_h = min(max_icon_height, my_image.height);
!   item->icon_depth = d_depth;
    free(path);
  #endif /* XPM */
  }
***************
*** 340,349 ****
    XWindowAttributes root_attr;
  #ifdef XPM
    XpmAttributes xpm_attributes;
  #endif
    char *path = NULL;
    Pixmap tmp_bitmap, maskPixmap;
!   int x, y, w=0, h=0;
  
    if (IconwinPixmapFile == NULL)
      return False;
--- 354,364 ----
    XWindowAttributes root_attr;
  #ifdef XPM
    XpmAttributes xpm_attributes;
+   XpmImage my_image;
  #endif
    char *path = NULL;
    Pixmap tmp_bitmap, maskPixmap;
!   int x, y, w=0, h=0, rc;
  
    if (IconwinPixmapFile == NULL)
      return False;
***************
*** 368,380 ****
      { 
        XGetWindowAttributes(dpy,Root,&root_attr);
        xpm_attributes.colormap = root_attr.colormap;
!       xpm_attributes.valuemask = XpmSize|XpmReturnPixels|XpmColormap;
!       if (XpmReadFileToPixmap(dpy, Root, path, &IconwinPixmap,
! 			      &maskPixmap, &xpm_attributes) ==
! 	  XpmSuccess){ 
! 	w = xpm_attributes.width;
! 	h = xpm_attributes.height;
        }
        free(path);
      }
  #endif
--- 383,409 ----
      { 
        XGetWindowAttributes(dpy,Root,&root_attr);
        xpm_attributes.colormap = root_attr.colormap;
!       xpm_attributes.closeness = 40000;    /* same closeness used elsewhere */
!       xpm_attributes.valuemask = XpmSize|XpmReturnPixels|XpmColormap|
!         XpmCloseness;
!       rc = XpmReadFileToXpmImage(path, &my_image, NULL);
!       if (rc != XpmSuccess) {
!         fprintf(stderr, "Problem reading pixmap %s, rc %d\n", path, rc);
!         free(path);
!         return False;
        }
+       color_reduce_pixmap(&my_image,save_color_limit);
+       rc = XpmCreatePixmapFromXpmImage(dpy,Root, &my_image,
+                                        &IconwinPixmap,
+                                        &maskPixmap,
+                                        &xpm_attributes);
+       if (rc != XpmSuccess) {
+         fprintf(stderr, "Problem creating pixmap from image, rc %d\n", rc);
+         free(path);
+         return False;
+       }
+       w = my_image.width;
+       h = my_image.height;
        free(path);
      }
  #endif
*** modules/FvwmIconBox/FvwmIconBox.c.orig	Mon Feb 24 20:51:59 1997
--- modules/FvwmIconBox/FvwmIconBox.c	Mon Feb 24 20:54:17 1997
***************
*** 158,163 ****
--- 158,165 ----
  unsigned long local_flags = 0;
  int sortby = UNSORT;
  
+ int save_color_limit;                   /* color limit from config */
+ 
  /************************************************************************
    Main 
    Based on main() from GoodStuff:
***************
*** 208,213 ****
--- 210,216 ----
        fprintf(stderr,"%s: Screen %d is not valid ", MyName, screen);
        exit(1);
      }
+   InitPictureCMap(dpy,Root); /* store the root cmap */
    d_depth = DefaultDepth(dpy, screen);
  
    XSetErrorHandler((XErrorHandler)myErrorHandler);
***************
*** 1579,1584 ****
--- 1582,1590 ----
  	  CopyString(&pixmapPath,&tline[10]);
  	else if (mystrncasecmp(tline,"ClickTime",9)==0)
  	  ClickTime = atoi(&tline[9]);
+ 	else if (mystrncasecmp(tline,"ColorLimit",10)==0) {
+ 	  save_color_limit = atoi(&tline[10]);
+         }
        }
        GetConfigLine(fd,&tline);
      }

--
Dan Espen                                    Phone: (908) 699-5570
[email-masked]
444 Hoes Lane  Room RRC 1C-214
Piscataway, NJ 08854
--
Visit the official FVWM web page at <URL:http://www.hpc.uh.edu/fvwm/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked].

---

From: Dan Espen <[email-masked]>
Date: Wed, 26 Feb 1997 08:50:57 -0500

Thimo Jansen <[email-masked]> writes:
> On 25 Feb 1997, Dan Espen ([email-masked]) wrote:
> > 
> If you would like to try this with the patch mentioned, here it is (hope
> you did not already get it a thousand times). Yep, it was me who posted
> it on the mailinglist, BUT, I did not write it!
> 
> Good luck and have fun. :)

Thanks,  I did.

Since the   Mini-icons in FvwmPager are  copied  from pixmaps that the
color limit patch already limited, no  change to the color limit patch
is needed.

> Thimo Jansen