Subject: Colorsets

From: Tim Phipps <[email-masked]>
Date: Tue, 16 Apr 2002 15:13:30 +0100

Hi All,
	Is it time to move the colorset handling from FvwmTheme to fvwm? What I'm 
thinking of is:

*) copy most of modules/FvwmTheme/FvwmTheme.c to fvwm/colorset.c
*) new command Colorset that calls fvwm/colorset.c
*) new command ReadWriteColors to replace *FvwmThemeReadWriteColors
*) a very simple replacement for FvwmTheme that just turns config lines
    into Colorset commands and prints a warning.
*) strip out every color type command from fvwm and all the modules

Advantages:
*) Much less code in the modules for color handling so less bugs
*) Smaller man pages for the modules
*) Initializing colorset 0 to black/white with a stipled pixmap
    background will enable monochrome monitors to have a 3d look and we
    can lose all the "if (Pdepth < 2)" code
*) by default fvwm and the modules won't alloc any color cells

Disadvantages:
*) lots of configs would break but the result would just be that
    everything uses colorset 0 so it would just look a bit boring.

Cheers,
Tim.

--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
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: Mikhael Goikhman <[email-masked]>
Date: Tue, 16 Apr 2002 16:00:12 +0000

On 16 Apr 2002 15:13:30 +0100, Tim Phipps wrote:
> 
> 	Is it time to move the colorset handling from FvwmTheme to fvwm?

Actually moving the FvwmTheme code and replacing it with a pass-through
module was on my todo list, near the top. But if you may do it, fine.
I didn't plan to break any existing configs at this stage though.

> What I'm thinking of is:

We should also add DeleteColorset somewhen to emulate DestroyModuleConfig.

>     everything uses colorset 0 so it would just look a bit boring.

I don't know. I think this is 2 independent tasks.

FvwmTheme may be obsoleted now without anyone noticing, but maybe removing
non colorset color functionality may be done after 2.6.x, i.e. in 2.9.x?

The main problem here is still TitleStyle, ButtonStyle, BorderStyle.

I am not sure about the last 2 advantages, maybe I don't understand it,
but monochrome monitors don't really need to dictate the (ugly) default.

Regards,
Mikhael.

---

From: Tim Phipps <[email-masked]>
Date: Wed, 17 Apr 2002 12:00:49 +0100

>I didn't plan to break any existing configs at this stage though.
OK, I'll do a patch that moves FvwmTheme into fvwm, I'll leave removing 
stuff for later.

>We should also add DeleteColorset somewhen to emulate DestroyModuleConfig.
There are problems with deleting colorsets that modules may be using 
since they share the resources rather than copy them. Would it be 
acceptable for DeleteColorset to reset the colorset to a simple default 
rather than really delete it?

>non colorset color functionality may be done after 2.6.x, i.e. in 2.9.x?
OK, I just thought that now might be a good time since we've just 
changed fvwm2 to fvwm.

>The main problem here is still TitleStyle, ButtonStyle, BorderStyle.
Yes, I don't know what to do about these. I think these things are too 
complex at the moment what with add..style and decors.

>but monochrome monitors don't really need to dictate the (ugly) default.
There are lots of instances of code that only get used on monochrome 
monitors, do a grep for Pdepth and count the number of "if (Pdepth < 
2)"s. If fvwm's default colorset worked well on monochrome monitors we 
could remove all this code.

The other point about not alloc'ing any color cells will only help users 
on PseudoColor displays. It means that fvwm would by default only alloc 
black and white. These are always there on PseudoColor displays so fvwm 
would not reduce the number of color cells available.

Cheers,
Tim.

---

From: Dominik Vogt <[email-masked]>
Date: Wed, 17 Apr 2002 13:30:00 +0200

> rather than really delete it?

What else could be done?  The few bytes of wasted memory for the
structure are irrelevant if the pixmaps are freed.

> OK, I just thought that now might be a good time since we've just 

I'd rather leave the big changes for 3.0.  Maybe we should make
the 2.6 release in about half a year (I mean the release date, not
the feature freeze).

> could remove all this code.

Yes, that would be a big step in the right direction.

Bye

Dominik ^_^  ^_^

-- 
Dominik Vogt, email: [email-masked]
LifeBits Aktiengesellschaft, Albrechtstr. 9, D-72072 Tuebingen
fon: ++49 (0) 7071/7965-0, fax: ++49 (0) 7071/7965-20
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
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: Mikhael Goikhman <[email-masked]>
Date: Wed, 17 Apr 2002 13:02:25 +0000

> could remove all this code.

Of course, this is a good thing, my point is that it may be better.
I don't like to have stippled black-white background on color monitors.

Why not to have one "if (Pdepth < 2)" when defining colorset 0 or any
unused/deleted colorset? The default for normal depths could be as it is
now, 4 colors: black on rgb:be/be/be and its shadow/hilight.

Regards,
Mikhael.

---

From: Dominik Vogt <[email-masked]>
Date: Wed, 17 Apr 2002 16:56:44 +0200

> now, 4 colors: black on rgb:be/be/be and its shadow/hilight.

Good idea.

Bye

Dominik ^_^  ^_^

---

From: Tim Phipps <[email-masked]>
Date: Wed, 17 Apr 2002 17:20:12 +0100

>>now, 4 colors: black on rgb:be/be/be and its shadow/hilight.
OK here's a patch that does the following:

    * Replaces FvwmTheme with a dummy module that just sends the
      Colorset and ReadWriteColors commands to fvwm
    * Adds the new commands Colorset and ReadWriteColors to fvwm
    * Initializes colorsets to black on gray for color screens and black
      on white for mono

There's two files attached as well that need to go in the fvwm 
directory. I haven't updated any man pages, could someone else do this 
please?

Cheers,
Tim.

/* This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#define FVWMTHEME_PRIVATE
#include "libs/Colorset.h"
#undef FVWMTHEME_PRIVATE

void set_readwrite_colors();
void parse_colorset(int n, char *line);
void cleanup_colorsets();
void alloc_colorset(int n);

/* Copyright (C) 2002 the late Joey Shutup.
 *
 * http://www.streetmap.co.uk/streetmap.dll?postcode2map?BS24+9TZ
 *
 * No guarantees or warranties 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.
 */
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
#define FVWMTHEME_PRIVATE

#include "config.h"
#include "libs/fvwmlib.h"
#include "externs.h"
#include "fvwm.h"
#include "cursor.h"
#include "functions.h"
#include "misc.h"
#include "screen.h"
#include "colorset.h"
#include "module_interface.h"
#include "commands.h"
#include "libs/FShape.h"
#include "libs/Picture.h"

extern int nColorsets;  /* in libs/Colorset.c */

/* Globals */
static Bool privateCells = False;	/* set when read/write colors used */
static Bool sharedCells = False;	/* set after a shared color is used */
static char *black = "black";
static char *white = "white";
static char *gray = "gray";

/* When fvwm destroys pixmaps it puts them on a list and only destroys them
 * after some period of inactivity. This is necessary because changing colorset
 * options rapidly may result in a module redrawing itself due to the first
 * change while the second change is happening. If the module renders something
 * with the colorset affected by the second change there is a chance it may
 * reference pixmaps that FvwmTheme has destroyed, bad things would happen */
struct junklist {
  struct junklist *prev;
  Pixmap pixmap;
};
static struct junklist *junk = NULL;
static Bool cleanup_scheduled = False;
static void add_to_junk(Pixmap pixmap)
{
  struct junklist *oldjunk = junk;

  junk = (struct junklist *)safemalloc(sizeof(struct junklist));
  junk->prev = oldjunk;
  junk->pixmap = pixmap;
  if (!cleanup_scheduled) {
    CMD_Schedule(NULL, NULL, 0, NULL, 0, "3000 CleanupColorsets", NULL);
    cleanup_scheduled = True;
  }
}
void cleanup_colorsets()
{
  struct junklist *oldjunk = junk;

  while (junk)
  {
    XFreePixmap(dpy, junk->pixmap);
    oldjunk = junk;
    junk = junk->prev;
    free(oldjunk);
  }
  cleanup_scheduled = False;
}

static void MyXParseColor(
  char *spec, XColor *exact_def_return)
{
  if (!XParseColor(dpy, Pcmap, spec, exact_def_return))
  {
    fvwm_msg(ERR, "MyXParseColor", "can't parse color \"%s\"",
             (spec) ? spec : "");
    exact_def_return->red = 0;
    exact_def_return->green = 0;
    exact_def_return->blue = 0;
    exact_def_return->flags |= DoRed | DoGreen | DoBlue;
  }

  return;
}

void CMD_ReadWriteColors(F_CMD_ARGS) {
  static char *name = "ReadWriteColors";

  if (sharedCells)
    fvwm_msg(ERR, name, "%s must come first, already allocated shared pixels", name);
  else if (Pvisual->class != PseudoColor)
    fvwm_msg(ERR, name, "%s only works with PseudoColor visuals", name);
  else
    privateCells = True;
}

static char *get_simple_color(
  char *string, char **color, colorset_struct *cs, int supplied_color,
  int special_flag, char *special_string)
{
  char *rest;

  if (*color)
  {
    free(*color);
    *color = NULL;
  }
  rest = GetNextToken(string, color);
  if (*color)
  {
    if (special_string && StrEquals(*color, special_string))
    {
      free(*color);
      *color = NULL;
      cs->color_flags |= special_flag;
      cs->color_flags &= ~supplied_color;
    }
    else
    {
      cs->color_flags |= supplied_color;
      cs->color_flags &= ~special_flag;
    }
  }
  else
    cs->color_flags &= ~(supplied_color | special_flag);

  return rest;
}

static void SafeDestroyPicture(Display *dpy, Picture *picture)
{
  /* have to subvert destroy picture so that it doesn't free pixmaps,
   * these are added to the junk list to be cleaned up after a timeout */
  if (picture->count < 2)
  {
    if (picture->picture)
    {
      add_to_junk(picture->picture);
      picture->picture = None;
    }
    if (picture->mask)
    {
      add_to_junk(picture->mask);
      picture->mask = None;
    }
  }
  /* all that this will now do is free the colors and the name */
  DestroyPicture(dpy, picture);
}

static void free_colorset_background(colorset_struct *cs)
{
  if (cs->picture) {
    SafeDestroyPicture(dpy, cs->picture);
    cs->picture = None;
    cs->pixmap = None;
  }
  if (cs->pixmap && cs->pixmap != ParentRelative)
  {
    add_to_junk(cs->pixmap);
  }
  cs->pixmap = None;
  if (cs->mask)
  {
    add_to_junk(cs->mask);
    cs->mask = None;
  }
  if (cs->pixels && cs->nalloc_pixels)
  {
    XFreeColors(dpy, Pcmap, cs->pixels, cs->nalloc_pixels, 0);
    free(cs->pixels);
    cs->pixels = NULL;
    cs->nalloc_pixels = 0;
  }
}

static char *csetopts[] =
{
  "Foreground",
  "Fore",
  "fg",

  "Background",
  "Back",
  "bg",

  "Hilight",
  "Hilite",
  "hi",

  "Shadow",
  "Shade",
  "sh",

  /* these strings are used inside the cases in the switch below! */
  "Pixmap",
  "TiledPixmap",
  "AspectPixmap",

  /* these strings are used inside the cases in the switch below! */
  "Shape",
  "TiledShape",
  "AspectShape",

  /* switch off pixmaps and gradients */
  "Plain",
  /* switch off shape */
  "NoShape",

  /* Make the background transparent, it copies the root window background */
  "Transparent",

  NULL
};

/* translate a colorset spec into a colorset structure */
void parse_colorset(int n, char *line)
{
  int i;
  int w;
  int h;
  colorset_struct *cs;
  char *token;
  char *optstring;
  char *args;
  char *option;
  char type;
  char *fg = NULL;
  char *bg = NULL;
  char *hi = NULL;
  char *sh = NULL;
  Bool do_remove_shape;
  Bool have_pixels_changed = False;
  Bool has_fg_changed = False;
  Bool has_bg_changed = False;
  Bool has_sh_changed = False;
  Bool has_hi_changed = False;
  Bool has_pixmap_changed = False;
  Bool has_shape_changed = False;
  XColor color;
  XGCValues xgcv;
  static char *name = "parse_colorset";
  Window win = Scr.SizeWindow;
  static GC gc = None;

  /* make sure it exists and has sensible contents */
  if (nColorsets <= n) {
    Colorset =
      (colorset_struct *)saferealloc((char *)Colorset,
				     (n + 1) * sizeof(colorset_struct));
    memset(&Colorset[nColorsets], 0,
	   (n + 1 - nColorsets) * sizeof(colorset_struct));
  }

  /* initialize new colorsets to black on gray */
  while (nColorsets <= n)
  {
    colorset_struct *ncs = &Colorset[nColorsets];
    have_pixels_changed = True;
    if (privateCells &&
	/* grab four writeable cells */
	XAllocColorCells(dpy, Pcmap, False, NULL, 0, &(ncs->fg), 4)) {
      XColor *colorp;

      /* set the fg color */
      MyXParseColor(black, &color);
      color.pixel = ncs->fg;
      XStoreColor(dpy, Pcmap, &color);
      /* set the bg */
      MyXParseColor(gray, &color);
      color.pixel = ncs->bg;
      XStoreColor(dpy, Pcmap, &color);
      /* calculate and set the hilite */
      colorp = GetHiliteColor(ncs->bg);
      colorp->pixel = ncs->hilite;
      XStoreColor(dpy, Pcmap, colorp);
      /* calculate and set the shadow */
      colorp = GetShadowColor(ncs->bg);
      colorp->pixel = ncs->shadow;
      XStoreColor(dpy, Pcmap, colorp);
    } else {
      /* grab four shareable colors */
      if (Pdepth < 2) {
	/* monochrome monitors get black on white */
	/* FIXME: add a gray pixmap background */
	Colorset[nColorsets].fg = GetColor(black);
	Colorset[nColorsets].bg = GetColor(white);
	Colorset[nColorsets].hilite = GetColor(white);
	Colorset[nColorsets].shadow = GetColor(black);
      } else {
	Colorset[nColorsets].fg = GetColor(black);
	Colorset[nColorsets].bg = GetColor(gray);
	Colorset[nColorsets].hilite = GetHilite(Colorset[nColorsets].bg);
	Colorset[nColorsets].shadow = GetShadow(Colorset[nColorsets].bg);
      }
      /* set flags for fg contrast, bg average in case just a pixmap is given */
      Colorset[nColorsets].color_flags = FG_CONTRAST | BG_AVERAGE;
    }
    nColorsets++;
  }

  cs = &Colorset[n];
  if (gc == None)
  {
    gc = fvwmlib_XCreateGC(dpy, win, 0, &xgcv);
  }

  /* ---------- Parse the options ---------- */
  while (line && *line)
  {
    /* Read next option specification (delimited by a comma or \0). */
    line = GetQuotedString(line, &optstring, ",", NULL, NULL, NULL);
    if (!optstring)
      break;
    args = GetNextToken(optstring, &option);
    if (!option)
    {
      free(optstring);
      break;
    }

    do_remove_shape = False;
    switch((i = GetTokenIndex(option, csetopts, 0, NULL)))
    {
    case 0: /* Foreground */
    case 1: /* Fore */
    case 2: /* fg */
      get_simple_color(args, &fg, cs, FG_SUPPLIED, FG_CONTRAST, "contrast");
      has_fg_changed = True;
      break;
    case 3: /* Background */
    case 4: /* Back */
    case 5: /* bg */
      get_simple_color(args, &bg, cs, BG_SUPPLIED, BG_AVERAGE, "average");
      has_bg_changed = True;
      break;
    case 6: /* Hilight */
    case 7: /* Hilite */
    case 8: /* hi */
      get_simple_color(args, &hi, cs, HI_SUPPLIED, 0, NULL);
      has_hi_changed = True;
      break;
    case 9: /* Shadow */
    case 10: /* Shade */
    case 11: /* sh */
      get_simple_color(args, &sh, cs, SH_SUPPLIED, 0, NULL);
      has_sh_changed = True;
      break;
    case 12: /* TiledPixmap */
    case 13: /* Pixmap */
    case 14: /* AspectPixmap */
      has_pixmap_changed = True;
      free_colorset_background(cs);
      /* set the flags */
      if (csetopts[i][0] == 'T')
	cs->pixmap_type = PIXMAP_TILED;
      else if (csetopts[i][0] == 'A')
	cs->pixmap_type = PIXMAP_STRETCH_ASPECT;
      else
	cs->pixmap_type = PIXMAP_STRETCH;

      /* read filename */
      token = PeekToken(args, &args);
      if (!token)
	break;
      /* load the file using the color reduction routines in Picture.c */
      cs->picture = CachePicture(dpy, win, NULL, token, Scr.ColorLimit);
      if (!cs->picture)
      {
	fvwm_msg(ERR, name, "can't load picture %s", token);
	break;
      }
      /* don't try to be smart with bitmaps */
      if (cs->picture->depth != Pdepth)
      {
	fvwm_msg(ERR, name, "bitmaps not supported");
	SafeDestroyPicture(dpy, cs->picture);
	cs->picture = None;
	break;
      }
      /* copy the picture pixmap into the public colorset structure */
      cs->width = cs->picture->width;
      cs->height = cs->picture->height;
      cs->pixmap = cs->picture->picture;

      if (cs->pixmap)
      {
	if (cs->picture->mask != None)
	{
	  /* make an inverted copy of the mask */
	  cs->mask = XCreatePixmap(dpy, win, cs->width, cs->height, 1);
	  if (cs->mask)
	  {
	    XCopyArea(dpy, cs->picture->mask, cs->mask, Scr.MonoGC, 0, 0,
		      cs->width, cs->height, 0, 0);
	    /* Invert the mask. We use it to draw the background. */
	    XSetFunction(dpy, Scr.MonoGC, GXinvert);
	    XFillRectangle(dpy, cs->mask, Scr.MonoGC, 0, 0,
			   cs->width, cs->height);
	    XSetFunction(dpy, Scr.MonoGC, GXcopy);
	  }
	}
      }
      break;
    case 15: /* Shape */
    case 16: /* TiledShape */
    case 17: /* AspectShape */
      if (FHaveShapeExtension)
      {
	/* read filename */
	token = PeekToken(args, &args);
	has_shape_changed = True;
	if (cs->shape_mask)
	{
	  add_to_junk(cs->shape_mask);
	  cs->shape_mask = None;
	}
	if (do_remove_shape == True)
	  break;
	/* set the flags */
	if (csetopts[i][0] == 'T')
	  cs->shape_type = SHAPE_TILED;
	else if (csetopts[i][0] == 'A')
	  cs->shape_type = SHAPE_STRETCH_ASPECT;
	else
	  cs->shape_type = SHAPE_STRETCH;

	/* try to load the shape mask */
	if (token)
	{
	  Picture *picture;

	  /* load the shape mask */
	  picture = CachePicture(dpy, win, NULL, token, Scr.ColorLimit);
	  if (!picture)
	    fvwm_msg(ERR, name, "can't load picture %s", token);
	  else if (picture->depth != 1 && picture->mask == None)
	  {
	    fvwm_msg(ERR, name, "shape pixmap must be of depth 1");
	    SafeDestroyPicture(dpy, picture);
	  }
	  else
	  {
	    Pixmap mask;

	    /* okay, we have what we want */
	    if (picture->mask != None)
	      mask = picture->mask;
	    else
	      mask = picture->picture;
	    cs->shape_width = picture->width;
	    cs->shape_height = picture->height;

	    if (mask != None)
	    {
	      cs->shape_mask = XCreatePixmap(
		dpy, mask, picture->width, picture->height, 1);
	      if (cs->shape_mask != None)
	      {
		XCopyPlane(dpy, mask, cs->shape_mask, Scr.MonoGC, 0, 0,
			   picture->width, picture->height, 0, 0, 1);
	      }
	    }
	  }
	  if (picture)
	  {
	    SafeDestroyPicture(dpy, picture);
	    picture = None;
	  }
	}
      }
      else
      {
	cs->shape_mask = None;
      }
      break;
    case 18: /* Plain */
      has_pixmap_changed = True;
      free_colorset_background(cs);
      break;
    case 19: /* NoShape */
      has_shape_changed = True;
      if (cs->shape_mask)
      {
	add_to_junk(cs->shape_mask);
	cs->shape_mask = None;
      }
      break;
    case 20: /* Transparent */
      /* this is only allowable when the root depth == fvwm visual depth
       * otherwise bad match errors happen, it may be even more restrictive
       * but my tests (on exceed 6.2) show that only == depth is necessary */
      if (Pdepth != DefaultDepth(dpy, (DefaultScreen(dpy))))
      {
	fvwm_msg(ERR, name, "can't do Transparent when root_depth!=fvwm_depth");
	break;
      }
      has_pixmap_changed = True;
      free_colorset_background(cs);
      cs->pixmap = ParentRelative;
      cs->pixmap_type = PIXMAP_STRETCH;
      break;
    default:
      /* test for ?Gradient */
      if (option[0] && StrEquals(&option[1], "Gradient"))
      {
	type = toupper(option[0]);
	if (!IsGradientTypeSupported(type))
	  break;
	has_pixmap_changed = True;
	free_colorset_background(cs);
	/* create a pixmap of the gradient type */
	cs->pixmap = CreateGradientPixmapFromString(dpy, win, gc, type, args,
						    &w, &h, &cs->pixels,
						    &cs->nalloc_pixels);
	cs->width = w;
	cs->height = h;
	if (type == V_GRADIENT)
	  cs->pixmap_type = PIXMAP_STRETCH_Y;
	else if (type == H_GRADIENT)
	  cs->pixmap_type = PIXMAP_STRETCH_X;
	else
	  cs->pixmap_type = PIXMAP_STRETCH;
      }
      else
      {
	fvwm_msg(WARN, name, "bad colorset pixmap specifier %s %s",
		 option, line);
      }
      break;
    } /* switch */

    if (option)
    {
      free(option);
      option = NULL;
    }
    free(optstring);
    optstring = NULL;
  } /* while (line && *line) */

  /*
   * ---------- change the background colour ----------
   */
  if (has_bg_changed || has_pixmap_changed)
  {
    Bool do_set_default_background = False;

    if ((cs->color_flags & BG_AVERAGE) && cs->pixmap != None &&
        cs->pixmap != ParentRelative)
    {
      /* calculate average background color */
      XColor *colors;
      XImage *image;
      XImage *mask_image = None;
      unsigned int i, j, k = 0;
      unsigned long red = 0, blue = 0, green = 0;

      /* create an array to store all the pixmap colors in */
      colors = (XColor *)safemalloc(cs->width * cs->height * sizeof(XColor));
      /* get the pixmap and mask into an image */
      image = XGetImage(dpy, cs->pixmap, 0, 0, cs->width, cs->height,
			AllPlanes, ZPixmap);
      if (cs->mask != None)
	mask_image = XGetImage(dpy, cs->mask, 0, 0, cs->width, cs->height,
			       AllPlanes, ZPixmap);
      /* only fetch the pixels that are not masked out */
      for (i = 0; i < cs->width; i++)
	for (j = 0; j < cs->height; j++)
	  if ((cs->mask == None) || (XGetPixel(mask_image, i, j) == 0))
	    colors[k++].pixel = XGetPixel(image, i, j);

      XDestroyImage(image);
      if (mask_image != None)
	XDestroyImage(mask_image);
      if (k == 0)
      {
	do_set_default_background = True;
      }
      else
      {
	/* look them all up, XQueryColors() can't handle more than 256 */
	for (i = 0; i < k; i += 256)
	  XQueryColors(dpy, Pcmap, &colors[i], min(k - i, 256));
	/* calculate average, ignore overflow: .red is short, red is long */
	for (i = 0; i < k; i++) {
	  red += colors[i].red;
	  green += colors[i].green;
	  blue += colors[i].blue;
	}
	free(colors);
	/* get it */
	color.red = red / k;
	color.green = green / k;
	color.blue = blue / k;
	if (privateCells) {
	  color.pixel = cs->bg;
	  XStoreColor(dpy, Pcmap, &color);
	} else {
	  Pixel old_bg = cs->bg;

	  XFreeColors(dpy, Pcmap, &cs->bg, 1, 0);
	  XAllocColor(dpy, Pcmap, &color);
	  cs->bg = color.pixel;
	  if (old_bg != cs->bg)
	    have_pixels_changed = True;
	}
      }
    } /* average */
    else if ((cs->color_flags & BG_SUPPLIED) && bg != NULL)
    {
      /* user specified colour */
      if (privateCells) {
	unsigned short red, green, blue;

	MyXParseColor(bg, &color);
	red = color.red;
	green = color.green;
	blue = color.blue;
	color.pixel = cs->bg;
	XStoreColor(dpy, Pcmap, &color);
      } else {
	Pixel old_bg = cs->bg;

	XFreeColors(dpy, Pcmap, &cs->bg, 1, 0);
	cs->bg = GetColor(bg);
	if (old_bg != cs->bg)
	  have_pixels_changed = True;
      }
    } /* user specified */
    else if ((bg == NULL && has_bg_changed) ||
             ((cs->color_flags & BG_AVERAGE) && cs->pixmap == ParentRelative))
    {
      /* default */
      do_set_default_background = True;
    } /* default */
    if (do_set_default_background)
    {
      if (privateCells) {
        MyXParseColor(white, &color);
        color.pixel = cs->bg;
        XStoreColor(dpy, Pcmap, &color);
      } else {
	Pixel old_bg = cs->bg;

	XFreeColors(dpy, Pcmap, &cs->bg, 1, 0);
	cs->bg = GetColor(white);
	if (old_bg != cs->bg)
	  have_pixels_changed = True;
      }
    }
    has_bg_changed = True;
  } /* has_bg_changed */

  /*
   * ---------- change the foreground colour ----------
   */
  if (has_fg_changed || (has_bg_changed && (cs->color_flags & FG_CONTRAST)))
  {
    has_fg_changed = 1;
    if (cs->color_flags & FG_CONTRAST)
    {
      /* calculate contrasting foreground color */
      color.pixel = cs->bg;
      XQueryColor(dpy, Pcmap, &color);
      color.red = (color.red > 32767) ? 0 : 65535;
      color.green = (color.green > 32767) ? 0 : 65535;
      color.blue = (color.blue > 32767) ? 0 : 65535;
      if (privateCells) {
	color.pixel = cs->fg;
	XStoreColor(dpy, Pcmap, &color);
      } else {
	Pixel old_fg = cs->fg;

	XFreeColors(dpy, Pcmap, &cs->fg, 1, 0);
	XAllocColor(dpy, Pcmap, &color);
	cs->fg = color.pixel;
	if (old_fg != cs->fg)
	  have_pixels_changed = True;
      }
    } /* contrast */
    else if ((cs->color_flags & FG_SUPPLIED) && fg != NULL)
    {
      /* user specified colour */
      if (privateCells) {
	MyXParseColor(fg, &color);
	color.pixel = cs->fg;
	XStoreColor(dpy, Pcmap, &color);
      } else {
	Pixel old_fg = cs->fg;

	XFreeColors(dpy, Pcmap, &cs->fg, 1, 0);
	cs->fg = GetColor(fg);
	if (old_fg != cs->fg)
	  have_pixels_changed = True;
      }
    } /* user specified */
    else if (fg == NULL)
    {
      /* default */
      if (privateCells) {
        /* query it */
        MyXParseColor(black, &color);
        color.pixel = cs->fg;
        XStoreColor(dpy, Pcmap, &color);
      } else {
	Pixel old_fg = cs->fg;

	XFreeColors(dpy, Pcmap, &cs->fg, 1, 0);
	cs->fg = GetColor(black);
	if (old_fg != cs->fg)
	  have_pixels_changed = True;
      }
    }
  } /* has_fg_changed */

  /*
   * ---------- change the hilight colour ----------
   */
  if (has_hi_changed || has_bg_changed)
  {
    has_hi_changed = 1;
    if ((cs->color_flags & HI_SUPPLIED) && hi != NULL)
    {
      /* user specified colour */
      if (privateCells) {
	MyXParseColor(hi, &color);
	color.pixel = cs->hilite;
	XStoreColor(dpy, Pcmap, &color);
      } else {
	Pixel old_hilite = cs->hilite;

	XFreeColors(dpy, Pcmap, &cs->hilite, 1, 0);
	cs->hilite = GetColor(hi);
	if (old_hilite != cs->hilite)
	  have_pixels_changed = True;
      }
    } /* user specified */
    else if (hi == NULL)
    {
      if (privateCells) {
	XColor *colorp;

	colorp = GetHiliteColor(cs->bg);
	colorp->pixel = cs->hilite;
	XStoreColor(dpy, Pcmap, colorp);
      } else {
	Pixel old_hilite = cs->hilite;

	XFreeColors(dpy, Pcmap, &cs->hilite, 1, 0);
	cs->hilite = GetHilite(cs->bg);
	if (old_hilite != cs->hilite)
	  have_pixels_changed = True;
      }
    }
  } /* has_hi_changed */

  /*
   * ---------- change the shadow colour ----------
   */
  if (has_sh_changed || has_bg_changed)
  {
    has_sh_changed = 1;
    if ((cs->color_flags & SH_SUPPLIED) && sh != NULL)
    {
      /* user specified colour */
      if (privateCells) {
	MyXParseColor(sh, &color);
	color.pixel = cs->shadow;
	XStoreColor(dpy, Pcmap, &color);
      } else {
	Pixel old_shadow = cs->shadow;

	XFreeColors(dpy, Pcmap, &cs->shadow, 1, 0);
	cs->shadow = GetColor(sh);
	if (old_shadow != cs->shadow)
	  have_pixels_changed = True;
      }
    } /* user specified */
    else if (sh == NULL)
    {
      if (privateCells) {
	XColor *colorp;

	colorp = GetShadowColor(cs->bg);
	colorp->pixel = cs->shadow;
	XStoreColor(dpy, Pcmap, colorp);
      } else {
	Pixel old_shadow = cs->shadow;

	XFreeColors(dpy, Pcmap, &cs->shadow, 1, 0);
	cs->shadow = GetShadow(cs->bg);
	if (old_shadow != cs->shadow)
	  have_pixels_changed = True;
      }
    }
  } /* has_sh_changed */

  /*
   * ---------- change the masked out parts of the background pixmap ----------
   */
  if ((cs->mask != None) && (has_pixmap_changed || has_bg_changed))
  {
    /* Now that we know the background colour we can update the pixmap
     * background. */
    XSetForeground(dpy, gc, cs->bg);
    XSetClipMask(dpy, gc, cs->mask);
    XFillRectangle(dpy, cs->pixmap, gc, 0, 0, cs->width, cs->height);
    XSetClipMask(dpy, gc, None);
    has_pixmap_changed = True;
  } /* has_pixmap_changed */

  /*
   * ---------- send new colorset to fvwm and clean up ----------
   */
  /* make sure the server has this to avoid races */
  XSync(dpy, False);

  /* inform modules of the change */
  if (have_pixels_changed || has_pixmap_changed || has_shape_changed)
    BroadcastColorset(n);

  if (fg)
    free(fg);
  if (bg)
    free(bg);
  if (hi)
    free(hi);
  if (sh)
    free(sh);

  /* if privateCells are not being used and XAllocColor has been used
   * we are stuck in sharedCells behaviour forever */
  /* have_pixels_changed will be set if a new colorset has been made */
  if (!privateCells && have_pixels_changed)
    sharedCells = True;
}

/*****************************************************************************
 * alloc_colorset() grows the size of the Colorset array to include set n
 * Colorset_struct *Colorset will be altered
 * returns the address of the member
 *****************************************************************************/
void alloc_colorset(int n)
{
  /* do nothing if it already exists */
  if (n < nColorsets)
    return;

  /* increment n to get the required array size, get a new array */
  Colorset = (colorset_struct *)saferealloc((char *)Colorset,
                                            ++n * sizeof(colorset_struct));

  /* zero out the new members */
  memset(&Colorset[nColorsets], 0, (n - nColorsets) * sizeof(colorset_struct));

  /* copy colorset 0 pixels into new members so that if undefined ones are
   * referenced at least they don't give black on black */
  if (n > 1)
  {
    for ( ; nColorsets < n; nColorsets++)
    {
      Colorset[nColorsets].fg = Colorset[0].fg;
      Colorset[nColorsets].bg = Colorset[0].bg;
      Colorset[nColorsets].hilite = Colorset[0].hilite;
      Colorset[nColorsets].shadow = Colorset[0].shadow;
    }
  }

  nColorsets = n;
}
Index: ChangeLog
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/ChangeLog,v
retrieving revision 1.137
diff -u -r1.137 ChangeLog
--- ChangeLog	2002/04/16 07:10:22	1.137
+++ ChangeLog	2002/04/17 16:04:43
@@ -1,3 +1,7 @@
+2002-04016  Hippo
+
+	* fvwm/*.[ch]: Moved FvwmTheme functionality into fvwm
+
 2002-04-15  Dominik Vogt  <[email-masked]>
 
 	* libs/Bindings.c (CheckBinding):
Index: fvwm/ConfigFvwmDefaults
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/ConfigFvwmDefaults,v
retrieving revision 1.8
diff -u -r1.8 ConfigFvwmDefaults
--- fvwm/ConfigFvwmDefaults	2002/03/20 14:07:02	1.8
+++ fvwm/ConfigFvwmDefaults	2002/04/16 22:48:45
@@ -6,12 +6,12 @@
 #  Created on 03/21/99 by DanEspen (dje):
 #  - FvwmDefaults file.  Contains fvwm defaults, and enough to help out
 #  the new user with no configuration file.
-#  This picks up from where the builtin table in fvwm.c SetUpRCDefaults ends.
+#  This picks up from where the builtin table in fvwm.c SetRCDefaults ends.
 
 # Set at least 2 root keys to bring up the builtin menu:
 Silent Key Help R A Popup MenuFvwmRoot
 Key F1 R A Popup MenuFvwmRoot
-# Ctrl-Alt-Escape for aboring Wait pause and ModuleSynchronous command
+# Ctrl-Alt-Escape for aborting Wait pause and ModuleSynchronous command
 Key Escape A MC EscapeFunc
 
 # Needed by the builtin WindowList command, this should match the manpage.
Index: fvwm/Makefile.am
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/Makefile.am,v
retrieving revision 1.17
diff -u -r1.17 Makefile.am
--- fvwm/Makefile.am	2002/04/16 07:10:23	1.17
+++ fvwm/Makefile.am	2002/04/17 13:09:04
@@ -16,7 +16,8 @@
 	gnome.h icccm2.h icons.h menuitem.h menus.h menustyle.h menudim.h \
 	misc.h modconf.h module_interface.h move_resize.h placement.h \
 	read.h repeat.h schedule.h screen.h session.h stack.h style.h \
-	update.h virtual.h window_flags.h windowlist.h frame.h menus.c \
+	update.h virtual.h window_flags.h windowlist.h frame.h colorset.h \
+	menus.c colorset.c \
 	style.c borders.c move_resize.c builtins.c events.c add_window.c \
 	module_interface.c icons.c stack.c functions.c virtual.c session.c \
 	fvwm.c placement.c focus.c read.c misc.c conditional.c colormaps.c \
Index: fvwm/borders.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/borders.c,v
retrieving revision 1.28
diff -u -r1.28 borders.c
--- fvwm/borders.c	2002/04/02 08:59:39	1.28
+++ fvwm/borders.c	2002/04/17 14:10:10
@@ -48,7 +48,7 @@
 #include "builtins.h"
 #include "icons.h"
 #include "module_interface.h"
-#include "libs/Colorset.h"
+#include "colorset.h"
 #include "add_window.h"
 #include "frame.h"
 
Index: fvwm/builtins.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/builtins.c,v
retrieving revision 1.37
diff -u -r1.37 builtins.c
--- fvwm/builtins.c	2002/04/08 10:43:29	1.37
+++ fvwm/builtins.c	2002/04/17 14:47:36
@@ -40,7 +40,7 @@
 #include "libs/Picture.h"
 #include "fvwm.h"
 #include "externs.h"
-#include "libs/Colorset.h"
+#include "colorset.h"
 #include "bindings.h"
 #include "misc.h"
 #include "cursor.h"
@@ -2226,18 +2226,17 @@
 
 void CMD_Colorset(F_CMD_ARGS)
 {
-	int n = -1, ret;
+	int n;
 	char *token;
 
-	token = PeekToken(action, NULL);
-	if (token == NULL)
+	if (GetIntegerArguments(action, &token, &n, 1) != 1)
 		return;
-	ret = sscanf(token, "%x", &n);
-
-	if ((ret == 0) || (n < 0))
+	if (n < 0)
+		return;
+	if (token == NULL)
 		return;
 
-	LoadColorset(action);
+	parse_colorset(n, token);
 	BroadcastColorset(n);
 
 	if (n == Scr.DefaultColorset)
@@ -2252,6 +2251,11 @@
 	return;
 }
 
+void CMD_CleanupColorsets(F_CMD_ARGS)
+{
+	cleanup_colorsets();
+}
+
 void CMD_PropertyChange(F_CMD_ARGS)
 {
 	char string[256] = "\0";
@@ -2290,7 +2294,7 @@
 	Scr.DefaultColorset = cset;
 	if (Scr.DefaultColorset < 0)
 		Scr.DefaultColorset = -1;
-	AllocColorset(Scr.DefaultColorset);
+	alloc_colorset(Scr.DefaultColorset);
 	Scr.flags.do_need_window_update = 1;
 	Scr.flags.has_default_color_changed = 1;
 
Index: fvwm/commands.h
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/commands.h,v
retrieving revision 1.12
diff -u -r1.12 commands.h
--- fvwm/commands.h	2002/04/12 11:43:16	1.12
+++ fvwm/commands.h	2002/04/17 15:41:56
@@ -39,6 +39,7 @@
 void CMD_ChangeDecor(F_CMD_ARGS);
 #endif /* USEDECOR */
 void CMD_ChangeMenuStyle(F_CMD_ARGS);
+void CMD_CleanupColorsets(F_CMD_ARGS);
 void CMD_ClickTime(F_CMD_ARGS);
 void CMD_Close(F_CMD_ARGS);
 void CMD_ColorLimit(F_CMD_ARGS);
@@ -135,6 +136,7 @@
 void CMD_Raise(F_CMD_ARGS);
 void CMD_RaiseLower(F_CMD_ARGS);
 void CMD_Read(F_CMD_ARGS);
+void CMD_ReadWriteColors(F_CMD_ARGS);
 void CMD_Recapture(F_CMD_ARGS);
 void CMD_RecaptureWindow(F_CMD_ARGS);
 void CMD_Refresh(F_CMD_ARGS);
Index: fvwm/events.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/events.c,v
retrieving revision 1.52
diff -u -r1.52 events.c
--- fvwm/events.c	2002/04/15 08:25:56	1.52
+++ fvwm/events.c	2002/04/17 14:10:34
@@ -71,7 +71,7 @@
 #include "screen.h"
 #include "defaults.h"
 #include "events.h"
-#include "libs/Colorset.h"
+#include "colorset.h"
 #include "fvwmsignal.h"
 #include "module_interface.h"
 #include "session.h"
Index: fvwm/functions.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/functions.c,v
retrieving revision 1.28
diff -u -r1.28 functions.c
--- fvwm/functions.c	2002/04/12 11:43:16	1.28
+++ fvwm/functions.c	2002/04/17 15:41:03
@@ -51,7 +51,7 @@
 #include "repeat.h"
 #include "read.h"
 #include "virtual.h"
-#include "libs/Colorset.h"
+#include "colorset.h"
 #include "ewmh.h"
 #include "schedule.h"
 
@@ -121,6 +121,7 @@
   CMD_ENTRY("changedecor", CMD_ChangeDecor, F_CHANGE_DECOR, FUNC_NEEDS_WINDOW),
 #endif /* USEDECOR */
   CMD_ENTRY("changemenustyle", CMD_ChangeMenuStyle, F_CHANGE_MENUSTYLE, 0),
+  CMD_ENTRY("cleanupcolorsets", CMD_CleanupColorsets, F_NOP, 0),
   CMD_ENTRY("clicktime", CMD_ClickTime, F_CLICK, 0),
   CMD_ENTRY("close", CMD_Close, F_CLOSE, FUNC_NEEDS_WINDOW),
   CMD_ENTRY("colorlimit", CMD_ColorLimit, F_COLOR_LIMIT, 0),
@@ -221,6 +222,7 @@
   CMD_ENTRY("raise", CMD_Raise, F_RAISE, FUNC_NEEDS_WINDOW),
   CMD_ENTRY("raiselower", CMD_RaiseLower, F_RAISELOWER, FUNC_NEEDS_WINDOW),
   CMD_ENTRY("read", CMD_Read, F_READ, 0),
+  CMD_ENTRY("readwritecolors", CMD_ReadWriteColors, F_NOP, 0),
   CMD_ENTRY("recapture", CMD_Recapture, F_RECAPTURE, 0),
   CMD_ENTRY("recapturewindow", CMD_RecaptureWindow, F_RECAPTURE_WINDOW, 0),
   CMD_ENTRY("refresh", CMD_Refresh, F_REFRESH, 0),
@@ -406,7 +408,7 @@
       return 0;
     if (cs < 0)
       return 0;
-    AllocColorset(cs);
+    alloc_colorset(cs);
     switch (i)
     {
     case 0:
Index: fvwm/fvwm.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/fvwm.c,v
retrieving revision 1.29
diff -u -r1.29 fvwm.c
--- fvwm/fvwm.c	2002/04/12 11:43:17	1.29
+++ fvwm/fvwm.c	2002/04/17 14:14:15
@@ -54,7 +54,7 @@
 #include "builtins.h"
 #include "menus.h"
 #include "module_interface.h"
-#include "libs/Colorset.h"
+#include "colorset.h"
 #include "icccm2.h"
 #include "gnome.h"
 #include "ewmh.h"
@@ -1390,7 +1390,7 @@
   Scr.DefaultIcon = NULL;
 
   Scr.DefaultColorset = -1;
-  AllocColorset(0);
+  alloc_colorset(0);
   /* set up colorset 0 so that if FvwmTheme fails to start any modules
    * using colorsets don't appear black on black */
   Colorset[0].fg = Scr.StdFore = GetColor(DEFAULT_FORE_COLOR);
Index: fvwm/icons.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/icons.c,v
retrieving revision 1.42
diff -u -r1.42 icons.c
--- fvwm/icons.c	2002/04/08 10:43:31	1.42
+++ fvwm/icons.c	2002/04/17 14:12:18
@@ -57,7 +57,7 @@
 #include "virtual.h"
 #include "decorations.h"
 #include "module_interface.h"
-#include "libs/Colorset.h"
+#include "colorset.h"
 #include "libs/FImageLoader.h"
 #include "gnome.h"
 #include "ewmh.h"
Index: fvwm/menucmd.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/menucmd.c,v
retrieving revision 1.3
diff -u -r1.3 menucmd.c
--- fvwm/menucmd.c	2002/03/26 14:36:49	1.3
+++ fvwm/menucmd.c	2002/04/17 14:12:23
@@ -50,7 +50,7 @@
 #include "colors.h"
 #include "colormaps.h"
 #include "decorations.h"
-#include "libs/Colorset.h"
+#include "colorset.h"
 #include "defaults.h"
 #include "libs/FScreen.h"
 #include "libs/Flocale.h"
Index: fvwm/menus.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/menus.c,v
retrieving revision 1.32
diff -u -r1.32 menus.c
--- fvwm/menus.c	2002/04/08 10:43:31	1.32
+++ fvwm/menus.c	2002/04/17 14:12:29
@@ -49,7 +49,7 @@
 #include "colors.h"
 #include "colormaps.h"
 #include "decorations.h"
-#include "libs/Colorset.h"
+#include "colorset.h"
 #include "defaults.h"
 #include "libs/FScreen.h"
 #include "libs/Flocale.h"
Index: fvwm/menustyle.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/menustyle.c,v
retrieving revision 1.4
diff -u -r1.4 menustyle.c
--- fvwm/menustyle.c	2002/04/08 10:43:31	1.4
+++ fvwm/menustyle.c	2002/04/17 14:14:20
@@ -42,7 +42,7 @@
 #include "colors.h"
 #include "colormaps.h"
 #include "decorations.h"
-#include "libs/Colorset.h"
+#include "colorset.h"
 #include "defaults.h"
 #include "libs/FScreen.h"
 #include "libs/Flocale.h"
@@ -1229,7 +1229,7 @@
 			{
 				ST_HAS_MENU_CSET(tmpms) = 1;
 				ST_CSET_MENU(tmpms) = *val;
-				AllocColorset(*val);
+				alloc_colorset(*val);
 			}
 			has_gc_changed = True;
 			break;
@@ -1243,7 +1243,7 @@
 			{
 				ST_HAS_ACTIVE_CSET(tmpms) = 1;
 				ST_CSET_ACTIVE(tmpms) = *val;
-				AllocColorset(*val);
+				alloc_colorset(*val);
 			}
 			has_gc_changed = True;
 			break;
@@ -1258,7 +1258,7 @@
 			{
 				ST_HAS_GREYED_CSET(tmpms) = 1;
 				ST_CSET_GREYED(tmpms) = *val;
-				AllocColorset(*val);
+				alloc_colorset(*val);
 			}
 			has_gc_changed = True;
 			break;
Index: fvwm/modconf.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/modconf.c,v
retrieving revision 1.11
diff -u -r1.11 modconf.c
--- fvwm/modconf.c	2002/04/08 10:43:31	1.11
+++ fvwm/modconf.c	2002/04/17 14:12:43
@@ -52,7 +52,7 @@
 #include "misc.h"
 #include "screen.h"
 #include "module_interface.h"
-#include "libs/Colorset.h"
+#include "colorset.h"
 #include "libs/FScreen.h"
 
 extern int nColorsets;	/* in libs/Colorset.c */
Index: fvwm/module_interface.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/module_interface.c,v
retrieving revision 1.24
diff -u -r1.24 module_interface.c
--- fvwm/module_interface.c	2002/03/26 14:36:49	1.24
+++ fvwm/module_interface.c	2002/04/17 14:16:46
@@ -38,7 +38,6 @@
 #endif
 
 #include "libs/fvwmlib.h"
-#include "libs/Colorset.h"
 #include "libs/FScreen.h"
 #include "libs/Module.h"
 #include "libs/queue.h"
@@ -50,6 +49,7 @@
 #include "bindings.h"
 #include "misc.h"
 #include "screen.h"
+#include "colorset.h"
 #include "module_interface.h"
 #include "read.h"
 #include "events.h"
Index: fvwm/move_resize.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/move_resize.c,v
retrieving revision 1.39
diff -u -r1.39 move_resize.c
--- fvwm/move_resize.c	2002/04/08 10:43:31	1.39
+++ fvwm/move_resize.c	2002/04/17 14:16:06
@@ -32,7 +32,6 @@
 #include <stdio.h>
 
 #include "libs/fvwmlib.h"
-#include "libs/Colorset.h"
 #include "libs/FScreen.h"
 #include "libs/Flocale.h"
 #include <libs/gravity.h>
@@ -44,6 +43,7 @@
 #include "bindings.h"
 #include "misc.h"
 #include "screen.h"
+#include "colorset.h"
 #include "defaults.h"
 #include "move_resize.h"
 #include "module_interface.h"
Index: fvwm/schedule.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/schedule.c,v
retrieving revision 1.3
diff -u -r1.3 schedule.c
--- fvwm/schedule.c	2002/03/18 12:47:12	1.3
+++ fvwm/schedule.c	2002/04/17 14:13:00
@@ -21,7 +21,7 @@
 #include "libs/queue.h"
 #include "fvwm.h"
 #include "externs.h"
-#include "libs/Colorset.h"
+#include "colorset.h"
 #include "bindings.h"
 #include "misc.h"
 #include "cursor.h"
Index: fvwm/style.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/style.c,v
retrieving revision 1.27
diff -u -r1.27 style.c
--- fvwm/style.c	2002/04/09 11:38:01	1.27
+++ fvwm/style.c	2002/04/17 14:14:24
@@ -41,7 +41,7 @@
 #include "defaults.h"
 #include "update.h"
 #include "style.h"
-#include "libs/Colorset.h"
+#include "colorset.h"
 #include "ewmh.h"
 #include "gnome.h"
 #include "icons.h"
@@ -991,7 +991,7 @@
           *val = -1;
 	  GetIntegerArguments(rest, NULL, val, 1);
 	  SSET_BORDER_COLORSET(*ptmpstyle, *val);
-	  AllocColorset(*val);
+	  alloc_colorset(*val);
 	  ptmpstyle->flags.use_border_colorset = (*val >= 0);
 	  ptmpstyle->flag_mask.use_border_colorset = 1;
 	  ptmpstyle->change_mask.use_border_colorset = 1;
@@ -1056,7 +1056,7 @@
 	  if (*val < 0)
 	    *val = -1;
 	  SSET_COLORSET(*ptmpstyle, *val);
-	  AllocColorset(*val);
+	  alloc_colorset(*val);
 	  ptmpstyle->flags.use_colorset = (*val >= 0);
 	  ptmpstyle->flag_mask.use_colorset = 1;
 	  ptmpstyle->change_mask.use_colorset = 1;
@@ -1505,7 +1505,7 @@
           *val = -1;
 	  GetIntegerArguments(rest, NULL, val, 1);
 	  SSET_COLORSET_HI(*ptmpstyle, *val);
-	  AllocColorset(*val);
+	  alloc_colorset(*val);
 	  ptmpstyle->flags.use_colorset_hi = (*val >= 0);
 	  ptmpstyle->flag_mask.use_colorset_hi = 1;
 	  ptmpstyle->change_mask.use_colorset_hi = 1;
@@ -1516,7 +1516,7 @@
           *val = -1;
 	  GetIntegerArguments(rest, NULL, val, 1);
 	  SSET_BORDER_COLORSET_HI(*ptmpstyle, *val);
-	  AllocColorset(*val);
+	  alloc_colorset(*val);
 	  ptmpstyle->flags.use_border_colorset_hi = (*val >= 0);
 	  ptmpstyle->flag_mask.use_border_colorset_hi = 1;
 	  ptmpstyle->change_mask.use_border_colorset_hi = 1;
Index: fvwm/update.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/update.c,v
retrieving revision 1.27
diff -u -r1.27 update.c
--- fvwm/update.c	2002/03/26 14:36:50	1.27
+++ fvwm/update.c	2002/04/17 14:13:10
@@ -32,7 +32,7 @@
 #include "update.h"
 #include "style.h"
 #include "builtins.h"
-#include "libs/Colorset.h"
+#include "colorset.h"
 #include "borders.h"
 #include "frame.h"
 #include "gnome.h"
@@ -459,8 +459,6 @@
 	{
 		if (Scr.Hilite != NULL && t == Scr.Hilite)
 		{
-			fprintf(stderr, "fc broadcast 0x%08x '%s'\n",
-				(int)Scr.Hilite, Scr.Hilite->name.name);
 			BroadcastPacket(
 				M_FOCUS_CHANGE, 5, FW_W(Scr.Hilite),
 				FW_W_FRAME(Scr.Hilite), 0,
Index: modules/ChangeLog
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/modules/ChangeLog,v
retrieving revision 1.86
diff -u -r1.86 ChangeLog
--- modules/ChangeLog	2002/04/16 07:10:24	1.86
+++ modules/ChangeLog	2002/04/17 16:06:40
@@ -1,3 +1,8 @@
+2002-04-16  Hippo
+
+	* FvwmTheme/FvwmTheme.c: FvwmTheme printf a warning and 
+	  and sends the command back to fvwm
+
 2002-04-15  Dominik Vogt  <[email-masked]>
 
 	* FvwmIconMan/readconfig.h:
Index: modules/FvwmTheme/FvwmTheme.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/modules/FvwmTheme/FvwmTheme.c,v
retrieving revision 1.4
diff -u -r1.4 FvwmTheme.c
--- modules/FvwmTheme/FvwmTheme.c	2002/04/08 10:43:43	1.4
+++ modules/FvwmTheme/FvwmTheme.c	2002/04/17 15:37:48
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999 Joey Shutup.
+/* Copyright (C) 2002 the late Joey Shutup.
  *
  * http://www.streetmap.co.uk/streetmap.dll?postcode2map?BS24+9TZ
  *
@@ -21,85 +21,37 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-#define FVWMTHEME_PRIVATE
-
 #include "config.h"
 
 #include <stdio.h>
 #include <signal.h>
 
-#include <X11/Xlib.h>
-#include <X11/Xproto.h>
-#include <X11/Intrinsic.h>
-
 #include "libs/fvwmlib.h"
-#include "libs/FShape.h"
 #include "libs/Module.h"
-#include "libs/InitPicture.h"
-#include "libs/Picture.h"
-#include "libs/Colorset.h"
 #include "libs/fvwmsignal.h"
 
 /* Globals */
-static Display *dpy;
-static Window win;			/* need a window to create pixmaps */
-static GC gc;				/* ditto */
 static char *name;
 static int namelen;
-static int color_limit = 0;
 static int fd[2];			/* communication pipes */
-static Bool privateCells = False;	/* set when read/write colors used */
-static Bool sharedCells = False;	/* set after a shared color is used */
-static char *black = "black";
-static char *gray = "gray";
 
 /* forward declarations */
 static RETSIGTYPE signal_handler(int signal);
 static void set_signals(void);
-static int error_handler(Display *dpy, XErrorEvent *e);
 static void parse_config(void);
 static void parse_config_line(char *line);
 static void parse_message_line(char *line);
 static void main_loop(void) __attribute__((__noreturn__));
 static void parse_colorset(char *line);
-static void add_to_junk(Pixmap pixmap);
-static void feng_shui();
 
-/* When FvemTheme destroys pixmaps it puts them on a list and only destoys them
- * after some period of inactivity. This is necessary because changing colorset
- * options rapidly may result in a module redrawing itself due to the first
- * change whie the second change is happening. If the module renders something
- * with the colorset affected by the second change there is a chance it may
- * reference pixmaps that FvwmTheme has destroyed */
-struct junklist {
-  struct junklist *prev;
-  Pixmap pixmap;
-};
-static struct junklist *junk = NULL;
-
-void MyXParseColor(
-  Display *display, Colormap colormap, char *spec, XColor *exact_def_return)
-{
-  if (!XParseColor(display, colormap, spec, exact_def_return))
-  {
-    fprintf(stderr,"%s: can't parse color \"%s\"\n", name, (spec) ? spec : "");
-    exact_def_return->red = 0;
-    exact_def_return->green = 0;
-    exact_def_return->blue = 0;
-    exact_def_return->flags |= DoRed | DoGreen | DoBlue;
-  }
-
-  return;
-}
-
 int main(int argc, char **argv)
 {
-  XSetWindowAttributes xswa;
-  XGCValues xgcv;
-
   name = GetFileNameFromPath(argv[0]);
   namelen = strlen(name);
 
+  fprintf(stderr,
+          "%s is obsolete, see the Colorset section of the fvwm(1) man page\n",
+          name);
   set_signals();
 
   /* try to make sure it is fvwm that spawned this module */
@@ -112,52 +64,12 @@
   fd[0] = atoi(argv[1]);
   fd[1] = atoi(argv[2]);
 
-  /* open the display and initialize the picture library */
-  dpy = XOpenDisplay(NULL);
-  if (!dpy) {
-    fprintf(stderr,"%s: can't open display %s", name, XDisplayName(NULL));
-    exit (1);
-  }
-  InitPictureCMap(dpy);
-
-  /* This module allocates resouces that othe rmodules may rely on.
-   * Set the closedown mode so that the pixmaps and colors are not freed
-   * by the server if this module dies
-   */
-  XSetCloseDownMode(dpy, RetainTemporary);
-
-  /* create a window to work in */
-  xswa.background_pixmap = None;
-  xswa.border_pixel = 0;
-  xswa.colormap = Pcmap;
-  win = XCreateWindow(dpy, RootWindow(dpy, DefaultScreen(dpy)), -2, -2, 2, 2,
-		      0, Pdepth, InputOutput, Pvisual,
-		      CWBackPixmap | CWBorderPixel | CWColormap, &xswa);
-
-  /* create a GC */
-  gc = fvwmlib_XCreateGC(dpy, win, 0, &xgcv);
-
-  /* die horribly if either win or gc could not be created */
-  XSync(dpy, False);
-
-  /* install a non-fatal error handler */
-  XSetErrorHandler(error_handler);
-
   /* get the initial configuration options */
   parse_config();
 
   /* tell fvwm we're running */
   SendFinishedStartupNotification(fd);
 
-  /* garbage collect */
-  alloca(0);
-
-  /* just in case any previous FvwmTheme has died and left pixmaps dangling.
-   * This might be overkill but any other method must ensure that fvwm doesn't
-   * get killed (it can be the owner of the pixels in colorset 0)
-   */
-  XKillClient(dpy, AllTemporary);
-
   /* sit around waiting for something to do */
   main_loop();
 }
@@ -167,12 +79,9 @@
   FvwmPacket *packet;
   fd_set_size_t fd_width;
   fd_set in_fdset;
-  struct timeval delay;
 
   fd_width = fd[1] + 1;
   FD_ZERO(&in_fdset);
-  delay.tv_sec = 5;
-  delay.tv_usec = 0;
 
   while (True) {
     /* garbage collect */
@@ -180,18 +89,12 @@
 
     FD_SET(fd[1], &in_fdset);
     /* wait for an instruction from fvwm or a timeout */
-    if (fvwmSelect(fd_width, &in_fdset, NULL, NULL, junk ? &delay : NULL) < 0)
+    if (fvwmSelect(fd_width, &in_fdset, NULL, NULL, NULL) < 0)
     {
       fprintf(stderr, "%s: select error!\n", name);
       exit(-1);
     }
 
-    if (!FD_ISSET(fd[1], &in_fdset))
-    { /* have a timeout, tidy up */
-      feng_shui();
-      continue;
-    }
-
     packet = ReadFvwmPacket(fd[1]);
     if (!packet)
       exit(0);
@@ -229,781 +132,22 @@
   switch(GetTokenIndex(line, config_options, -1, &rest))
   {
   case 0: /* ImagePath */
-    SetImagePath(rest);
     break;
   case 1: /* ColorLimit */
-    sscanf(rest, "%d", &color_limit);
     break;
   case 2: /* *FvwmThemColorset */
     parse_colorset(rest);
     break;
   case 3: /* *FvwmThemeReadWriteColors */
-    if (sharedCells)
-      fprintf(stderr, "%s: must come first, already allocated shared pixels\n",
-	      config_options[3]);
-    else if (Pvisual->class != PseudoColor)
-      fprintf(stderr, "%s: only works with PseudoColor visuals\n",
-	      config_options[3]);
-    else
-      privateCells = True;
-  }
-}
-
-static char *get_simple_color(
-  char *string, char **color, colorset_struct *cs, int supplied_color,
-  int special_flag, char *special_string)
-{
-  char *rest;
-
-  if (*color)
-  {
-    free(*color);
-    *color = NULL;
-  }
-  rest = GetNextToken(string, color);
-  if (*color)
-  {
-    if (special_string && StrEquals(*color, special_string))
-    {
-      free(*color);
-      *color = NULL;
-      cs->color_flags |= special_flag;
-      cs->color_flags &= ~supplied_color;
-    }
-    else
-    {
-      cs->color_flags |= supplied_color;
-      cs->color_flags &= ~special_flag;
-    }
-  }
-  else
-    cs->color_flags &= ~(supplied_color | special_flag);
-
-  return rest;
-}
-
-static void SafeDestroyPicture(Display *dpy, Picture *picture)
-{
-    /* have to subvert destroy picture so that it doesn't free pixmaps
-     * these are added to the junk list to be cleaned up after a timeout */
-    if (picture->count < 2)
-    {
-      if (picture->picture)
-      {
-        add_to_junk(picture->picture);
-        picture->picture = None;
-      }
-      if (picture->mask)
-      {
-        add_to_junk(picture->mask);
-        picture->mask = None;
-      }
-    }
-    /* all that this will now do is free the colors and the name */
-    DestroyPicture(dpy, picture);
-}
-
-static void free_colorset_background(colorset_struct *cs)
-{
-  if (cs->picture) {
-    if (cs->picture->picture != cs->pixmap)
-      fprintf(stderr, "FvwmTheme warning: cs->picture != cs->pixmap\n");
-    SafeDestroyPicture(dpy, cs->picture);
-    cs->picture = None;
-    cs->pixmap = None;
-  }
-  if (cs->pixmap && cs->pixmap != ParentRelative)
-  {
-    add_to_junk(cs->pixmap);
-  }
-  cs->pixmap = None;
-  if (cs->mask)
-  {
-    add_to_junk(cs->mask);
-    cs->mask = None;
-  }
-  if (cs->pixels && cs->nalloc_pixels)
-  {
-    XFreeColors(dpy, Pcmap, cs->pixels, cs->nalloc_pixels, 0);
-    free(cs->pixels);
-    cs->pixels = NULL;
-    cs->nalloc_pixels = 0;
+    SendText(fd, "ReadWriteColors", 0);
+    break;
   }
 }
 
-static char *csetopts[] =
-{
-  "Foreground",
-  "Fore",
-  "fg",
-
-  "Background",
-  "Back",
-  "bg",
-
-  "Hilight",
-  "Hilite",
-  "hi",
-
-  "Shadow",
-  "Shade",
-  "sh",
-
-  /* these strings are used inside the cases in the switch below! */
-  "Pixmap",
-  "TiledPixmap",
-  "AspectPixmap",
-
-  /* these strings are used inside the cases in the switch below! */
-  "Shape",
-  "TiledShape",
-  "AspectShape",
-
-  /* switch off pixmaps and gradients */
-  "Plain",
-  /* switch off shape */
-  "NoShape",
-
-  /* Make the background transparent, it copies the root window background */
-  "Transparent",
-
-  NULL
-};
-
 /* translate a colorset spec into a colorset structure */
 static void parse_colorset(char *line)
 {
-  int n;
-  int i;
-  int w;
-  int h;
-  colorset_struct *cs;
-  char *token;
-  char *optstring;
-  char *args;
-  char *option;
-  char type;
-  char *fg = NULL;
-  char *bg = NULL;
-  char *hi = NULL;
-  char *sh = NULL;
-  Bool do_remove_shape;
-  Bool have_pixels_changed = False;
-  Bool has_fg_changed = False;
-  Bool has_bg_changed = False;
-  Bool has_sh_changed = False;
-  Bool has_hi_changed = False;
-  Bool has_pixmap_changed = False;
-  Bool has_shape_changed = False;
-  XColor color;
-  XGCValues xgcv;
-  static GC mono_gc = None;
-  static int nColorsets = 0;
-
-  /* find out which colorset */
-  if (GetIntegerArguments(line, &line, &n, 1) != 1)
-    return;
-  if (n < 0)
-  {
-    fprintf(stderr, "%s: colorset number must be zero or positive\n", name);
-    return;
-  }
-
-  /* make sure it exists and has sensible contents */
-  if (nColorsets <= n) {
-    Colorset =
-      (colorset_struct *)saferealloc((char *)Colorset,
-				     (n + 1) * sizeof(colorset_struct));
-    memset(&Colorset[nColorsets], 0,
-	   (n + 1 - nColorsets) * sizeof(colorset_struct));
-  }
-
-  /* initialize new colorsets to black on gray */
-  while (nColorsets <= n)
-  {
-    colorset_struct *ncs = &Colorset[nColorsets];
-    have_pixels_changed = True;
-    if (privateCells &&
-	/* grab four writeable cells */
-	XAllocColorCells(dpy, Pcmap, False, NULL, 0, &(ncs->fg), 4)) {
-      XColor *colorp;
-
-      /* set the fg color */
-      MyXParseColor(dpy, Pcmap, black, &color);
-      color.pixel = ncs->fg;
-      XStoreColor(dpy, Pcmap, &color);
-      /* set the bg */
-      MyXParseColor(dpy, Pcmap, gray, &color);
-      color.pixel = ncs->bg;
-      XStoreColor(dpy, Pcmap, &color);
-      /* calculate and set the hilite */
-      colorp = GetHiliteColor(ncs->bg);
-      colorp->pixel = ncs->hilite;
-      XStoreColor(dpy, Pcmap, colorp);
-      /* calculate and set the shadow */
-      colorp = GetShadowColor(ncs->bg);
-      colorp->pixel = ncs->shadow;
-      XStoreColor(dpy, Pcmap, colorp);
-    } else {
-      /* grab four shareable colors */
-      Colorset[nColorsets].fg = GetColor(black);
-      Colorset[nColorsets].bg = GetColor(gray);
-      Colorset[nColorsets].hilite = GetHilite(Colorset[nColorsets].bg);
-      Colorset[nColorsets].shadow = GetShadow(Colorset[nColorsets].bg);
-      /* set flags for fg contrast, bg average in case just a pixmap is given */
-      Colorset[nColorsets].color_flags = FG_CONTRAST | BG_AVERAGE;
-    }
-    nColorsets++;
-  }
-
-  cs = &Colorset[n];
-
-  /* ---------- Parse the options ---------- */
-  while (line && *line)
-  {
-    /* Read next option specification (delimited by a comma or \0). */
-    line = GetQuotedString(line, &optstring, ",", NULL, NULL, NULL);
-    if (!optstring)
-      break;
-    args = GetNextToken(optstring, &option);
-    if (!option)
-    {
-      free(optstring);
-      break;
-    }
-
-    do_remove_shape = False;
-    switch((i = GetTokenIndex(option, csetopts, 0, NULL)))
-    {
-    case 0: /* Foreground */
-    case 1: /* Fore */
-    case 2: /* fg */
-      get_simple_color(args, &fg, cs, FG_SUPPLIED, FG_CONTRAST, "contrast");
-      has_fg_changed = True;
-      break;
-    case 3: /* Background */
-    case 4: /* Back */
-    case 5: /* bg */
-      get_simple_color(args, &bg, cs, BG_SUPPLIED, BG_AVERAGE, "average");
-      has_bg_changed = True;
-      break;
-    case 6: /* Hilight */
-    case 7: /* Hilite */
-    case 8: /* hi */
-      get_simple_color(args, &hi, cs, HI_SUPPLIED, 0, NULL);
-      has_hi_changed = True;
-      break;
-    case 9: /* Shadow */
-    case 10: /* Shade */
-    case 11: /* sh */
-      get_simple_color(args, &sh, cs, SH_SUPPLIED, 0, NULL);
-      has_sh_changed = True;
-      break;
-    case 12: /* TiledPixmap */
-    case 13: /* Pixmap */
-    case 14: /* AspectPixmap */
-      has_pixmap_changed = True;
-      free_colorset_background(cs);
-      /* set the flags */
-      if (csetopts[i][0] == 'T')
-	cs->pixmap_type = PIXMAP_TILED;
-      else if (csetopts[i][0] == 'A')
-	cs->pixmap_type = PIXMAP_STRETCH_ASPECT;
-      else
-	cs->pixmap_type = PIXMAP_STRETCH;
-
-      /* read filename */
-      token = PeekToken(args, &args);
-      if (!token)
-	break;
-      /* load the file using the color reduction routines in Picture.c */
-      cs->picture = CachePicture(dpy, win, NULL, token, color_limit);
-      if (!cs->picture)
-      {
-	fprintf(stderr, "%s: can't load picture %s\n", name, token);
-	break;
-      }
-      /* don't try to be smart with bitmaps */
-      if (cs->picture->depth != Pdepth)
-      {
-	fprintf(stderr, "%s: bitmaps not supported\n", name);
-	SafeDestroyPicture(dpy, cs->picture);
-	cs->picture = None;
-	break;
-      }
-      /* copy the picture pixmap into the public colorset structure */
-      cs->width = cs->picture->width;
-      cs->height = cs->picture->height;
-      cs->pixmap = cs->picture->picture;
-
-      if (cs->pixmap)
-      {
-	if (cs->picture->mask != None)
-	{
-	  /* make an inverted copy of the mask */
-	  cs->mask = XCreatePixmap(dpy, win, cs->width, cs->height, 1);
-	  if (cs->mask)
-	  {
-	    if (mono_gc == None)
-	    {
-	      xgcv.foreground = 1;
-	      xgcv.background = 0;
-	      /* create a gc for 1 bit depth */
-	      mono_gc = fvwmlib_XCreateGC(
-		dpy, cs->mask, GCForeground | GCBackground, &xgcv);
-	    }
-	    XCopyArea(dpy, cs->picture->mask, cs->mask, mono_gc, 0, 0,
-		      cs->width, cs->height, 0, 0);
-	    /* Invert the mask. We use it to draw the background. */
-	    XSetFunction(dpy, mono_gc, GXinvert);
-	    XFillRectangle(dpy, cs->mask, mono_gc, 0, 0, cs->width, cs->height);
-	    XSetFunction(dpy, mono_gc, GXcopy);
-	  }
-	}
-      }
-      break;
-    case 15: /* Shape */
-    case 16: /* TiledShape */
-    case 17: /* AspectShape */
-      if (FHaveShapeExtension)
-      {
-	/* read filename */
-	token = PeekToken(args, &args);
-	has_shape_changed = True;
-	if (cs->shape_mask)
-	{
-	  add_to_junk(cs->shape_mask);
-	  cs->shape_mask = None;
-	}
-	if (do_remove_shape == True)
-	  break;
-	/* set the flags */
-	if (csetopts[i][0] == 'T')
-	  cs->shape_type = SHAPE_TILED;
-	else if (csetopts[i][0] == 'A')
-	  cs->shape_type = SHAPE_STRETCH_ASPECT;
-	else
-	  cs->shape_type = SHAPE_STRETCH;
-
-	/* try to load the shape mask */
-	if (token)
-	{
-	  Picture *picture;
-
-	  /* load the shape mask */
-	  picture = CachePicture(dpy, win, NULL, token, color_limit);
-	  if (!picture)
-	    fprintf(stderr, "%s: can't load picture %s\n", name, token);
-	  else if (picture->depth != 1 && picture->mask == None)
-	  {
-	    fprintf(stderr, "%s: shape pixmap must be of depth 1\n", name);
-	    SafeDestroyPicture(dpy, picture);
-	  }
-	  else
-	  {
-	    Pixmap mask;
-
-	    /* okay, we have what we want */
-	    if (picture->mask != None)
-	      mask = picture->mask;
-	    else
-	      mask = picture->picture;
-	    cs->shape_width = picture->width;
-	    cs->shape_height = picture->height;
-
-	    if (mask != None)
-	    {
-	      cs->shape_mask = XCreatePixmap(
-		dpy, mask, picture->width, picture->height, 1);
-	      if (cs->shape_mask != None)
-	      {
-		if (mono_gc == None)
-		{
-		  xgcv.foreground = 1;
-		  xgcv.background = 0;
-		  /* create a gc for 1 bit depth */
-		  mono_gc = fvwmlib_XCreateGC(
-		    dpy, picture->mask, GCForeground|GCBackground, &xgcv);
-		}
-		XCopyPlane(dpy, mask, cs->shape_mask, mono_gc, 0, 0,
-			   picture->width, picture->height, 0, 0, 1);
-	      }
-	    }
-	  }
-	  if (picture)
-	  {
-	    SafeDestroyPicture(dpy, picture);
-	    picture = None;
-	  }
-	}
-      }
-      else
-      {
-	cs->shape_mask = None;
-      }
-      break;
-    case 18: /* Plain */
-      has_pixmap_changed = True;
-      free_colorset_background(cs);
-      break;
-    case 19: /* NoShape */
-      has_shape_changed = True;
-      if (cs->shape_mask)
-      {
-	add_to_junk(cs->shape_mask);
-	cs->shape_mask = None;
-      }
-      break;
-    case 20: /* Transparent */
-      /* this is only allowable when the root depth == fvwm visual depth
-       * otherwise bad match errors happen, it may be even more restrictive
-       * but my tests (on exceed 6.2) show that only == depth is necessary */
-      if (Pdepth != DefaultDepth(dpy, (DefaultScreen(dpy))))
-      {
-	fprintf(stderr,
-		"%s: can't do Transparent when root_depth != fvwm_depth\n",
-		name);
-	break;
-      }
-      has_pixmap_changed = True;
-      free_colorset_background(cs);
-      cs->pixmap = ParentRelative;
-      cs->pixmap_type = PIXMAP_STRETCH;
-      break;
-    default:
-      /* test for ?Gradient */
-      if (option[0] && StrEquals(&option[1], "Gradient"))
-      {
-	type = toupper(option[0]);
-	if (!IsGradientTypeSupported(type))
-	  break;
-	has_pixmap_changed = True;
-	free_colorset_background(cs);
-	/* create a pixmap of the gradient type */
-	cs->pixmap = CreateGradientPixmapFromString(dpy, win, gc, type, args,
-						    &w, &h, &cs->pixels,
-						    &cs->nalloc_pixels);
-	cs->width = w;
-	cs->height = h;
-	if (type == V_GRADIENT)
-	  cs->pixmap_type = PIXMAP_STRETCH_Y;
-	else if (type == H_GRADIENT)
-	  cs->pixmap_type = PIXMAP_STRETCH_X;
-	else
-	  cs->pixmap_type = PIXMAP_STRETCH;
-      }
-      else
-      {
-	fprintf(stderr, "%s: bad colorset pixmap specifier %s %s\n", name,
-		option, line);
-      }
-      break;
-    } /* switch */
-
-    if (option)
-    {
-      free(option);
-      option = NULL;
-    }
-    free(optstring);
-    optstring = NULL;
-  } /* while (line && *line) */
-
-  /*
-   * ---------- change the background colour ----------
-   */
-  if (has_bg_changed || has_pixmap_changed)
-  {
-    Bool do_set_default_background = False;
-
-    if ((cs->color_flags & BG_AVERAGE) && cs->pixmap != None &&
-        cs->pixmap != ParentRelative)
-    {
-      /* calculate average background color */
-      XColor *colors;
-      XImage *image;
-      XImage *mask_image = None;
-      unsigned int i, j, k = 0;
-      unsigned long red = 0, blue = 0, green = 0;
-
-      /* create an array to store all the pixmap colors in */
-      colors = (XColor *)safemalloc(cs->width * cs->height * sizeof(XColor));
-      /* get the pixmap and mask into an image */
-      image = XGetImage(dpy, cs->pixmap, 0, 0, cs->width, cs->height,
-			AllPlanes, ZPixmap);
-      if (cs->mask != None)
-	mask_image = XGetImage(dpy, cs->mask, 0, 0, cs->width, cs->height,
-			       AllPlanes, ZPixmap);
-      /* only fetch the pixels that are not masked out */
-      for (i = 0; i < cs->width; i++)
-	for (j = 0; j < cs->height; j++)
-	  if ((cs->mask == None) || (XGetPixel(mask_image, i, j) == 0))
-	    colors[k++].pixel = XGetPixel(image, i, j);
-
-      XDestroyImage(image);
-      if (mask_image != None)
-	XDestroyImage(mask_image);
-      if (k == 0)
-      {
-	do_set_default_background = True;
-      }
-      else
-      {
-	/* look them all up, XQueryColors() can't handle more than 256 */
-	for (i = 0; i < k; i += 256)
-	  XQueryColors(dpy, Pcmap, &colors[i], min(k - i, 256));
-	/* calculate average, ignore overflow: .red is short, red is long */
-	for (i = 0; i < k; i++) {
-	  red += colors[i].red;
-	  green += colors[i].green;
-	  blue += colors[i].blue;
-	}
-	free(colors);
-	/* get it */
-	color.red = red / k;
-	color.green = green / k;
-	color.blue = blue / k;
-	if (privateCells) {
-	  color.pixel = cs->bg;
-	  XStoreColor(dpy, Pcmap, &color);
-	} else {
-	  Pixel old_bg = cs->bg;
-
-	  XFreeColors(dpy, Pcmap, &cs->bg, 1, 0);
-	  XAllocColor(dpy, Pcmap, &color);
-	  cs->bg = color.pixel;
-	  if (old_bg != cs->bg)
-	    have_pixels_changed = True;
-	}
-      }
-    } /* average */
-    else if ((cs->color_flags & BG_SUPPLIED) && bg != NULL)
-    {
-      /* user specified colour */
-      if (privateCells) {
-	unsigned short red, green, blue;
-
-	MyXParseColor(dpy, Pcmap, bg, &color);
-	red = color.red;
-	green = color.green;
-	blue = color.blue;
-	color.pixel = cs->bg;
-	XStoreColor(dpy, Pcmap, &color);
-      } else {
-	Pixel old_bg = cs->bg;
-
-	XFreeColors(dpy, Pcmap, &cs->bg, 1, 0);
-	cs->bg = GetColor(bg);
-	if (old_bg != cs->bg)
-	  have_pixels_changed = True;
-      }
-    } /* user specified */
-    else if ((bg == NULL && has_bg_changed) ||
-             ((cs->color_flags & BG_AVERAGE) && cs->pixmap == ParentRelative))
-    {
-      /* default */
-      do_set_default_background = True;
-    } /* default */
-    if (do_set_default_background)
-    {
-      if (privateCells) {
-        MyXParseColor(dpy, Pcmap, gray, &color);
-        color.pixel = cs->bg;
-        XStoreColor(dpy, Pcmap, &color);
-      } else {
-	Pixel old_bg = cs->bg;
-
-	XFreeColors(dpy, Pcmap, &cs->bg, 1, 0);
-	cs->bg = GetColor(gray);
-	if (old_bg != cs->bg)
-	  have_pixels_changed = True;
-      }
-    }
-    has_bg_changed = True;
-  } /* has_bg_changed */
-
-  /*
-   * ---------- change the foreground colour ----------
-   */
-  if (has_fg_changed || (has_bg_changed && (cs->color_flags & FG_CONTRAST)))
-  {
-    has_fg_changed = 1;
-    if (cs->color_flags & FG_CONTRAST)
-    {
-      /* calculate contrasting foreground color */
-      color.pixel = cs->bg;
-      XQueryColor(dpy, Pcmap, &color);
-      color.red = (color.red > 32767) ? 0 : 65535;
-      color.green = (color.green > 32767) ? 0 : 65535;
-      color.blue = (color.blue > 32767) ? 0 : 65535;
-      if (privateCells) {
-	color.pixel = cs->fg;
-	XStoreColor(dpy, Pcmap, &color);
-      } else {
-	Pixel old_fg = cs->fg;
-
-	XFreeColors(dpy, Pcmap, &cs->fg, 1, 0);
-	XAllocColor(dpy, Pcmap, &color);
-	cs->fg = color.pixel;
-	if (old_fg != cs->fg)
-	  have_pixels_changed = True;
-      }
-    } /* contrast */
-    else if ((cs->color_flags & FG_SUPPLIED) && fg != NULL)
-    {
-      /* user specified colour */
-      if (privateCells) {
-	MyXParseColor(dpy, Pcmap, fg, &color);
-	color.pixel = cs->fg;
-	XStoreColor(dpy, Pcmap, &color);
-      } else {
-	Pixel old_fg = cs->fg;
-
-	XFreeColors(dpy, Pcmap, &cs->fg, 1, 0);
-	cs->fg = GetColor(fg);
-	if (old_fg != cs->fg)
-	  have_pixels_changed = True;
-      }
-    } /* user specified */
-    else if (fg == NULL)
-    {
-      /* default */
-      if (privateCells) {
-        /* query it */
-        MyXParseColor(dpy, Pcmap, black, &color);
-        color.pixel = cs->fg;
-        XStoreColor(dpy, Pcmap, &color);
-      } else {
-	Pixel old_fg = cs->fg;
-
-	XFreeColors(dpy, Pcmap, &cs->fg, 1, 0);
-	cs->fg = GetColor(black);
-	if (old_fg != cs->fg)
-	  have_pixels_changed = True;
-      }
-    }
-  } /* has_fg_changed */
-
-  /*
-   * ---------- change the hilight colour ----------
-   */
-  if (has_hi_changed || has_bg_changed)
-  {
-    has_hi_changed = 1;
-    if ((cs->color_flags & HI_SUPPLIED) && hi != NULL)
-    {
-      /* user specified colour */
-      if (privateCells) {
-	MyXParseColor(dpy, Pcmap, hi, &color);
-	color.pixel = cs->hilite;
-	XStoreColor(dpy, Pcmap, &color);
-      } else {
-	Pixel old_hilite = cs->hilite;
-
-	XFreeColors(dpy, Pcmap, &cs->hilite, 1, 0);
-	cs->hilite = GetColor(hi);
-	if (old_hilite != cs->hilite)
-	  have_pixels_changed = True;
-      }
-    } /* user specified */
-    else if (hi == NULL)
-    {
-      if (privateCells) {
-	XColor *colorp;
-
-	colorp = GetHiliteColor(cs->bg);
-	colorp->pixel = cs->hilite;
-	XStoreColor(dpy, Pcmap, colorp);
-      } else {
-	Pixel old_hilite = cs->hilite;
-
-	XFreeColors(dpy, Pcmap, &cs->hilite, 1, 0);
-	cs->hilite = GetHilite(cs->bg);
-	if (old_hilite != cs->hilite)
-	  have_pixels_changed = True;
-      }
-    }
-  } /* has_hi_changed */
-
-  /*
-   * ---------- change the shadow colour ----------
-   */
-  if (has_sh_changed || has_bg_changed)
-  {
-    has_sh_changed = 1;
-    if ((cs->color_flags & SH_SUPPLIED) && sh != NULL)
-    {
-      /* user specified colour */
-      if (privateCells) {
-	MyXParseColor(dpy, Pcmap, sh, &color);
-	color.pixel = cs->shadow;
-	XStoreColor(dpy, Pcmap, &color);
-      } else {
-	Pixel old_shadow = cs->shadow;
-
-	XFreeColors(dpy, Pcmap, &cs->shadow, 1, 0);
-	cs->shadow = GetColor(sh);
-	if (old_shadow != cs->shadow)
-	  have_pixels_changed = True;
-      }
-    } /* user specified */
-    else if (sh == NULL)
-    {
-      if (privateCells) {
-	XColor *colorp;
-
-	colorp = GetShadowColor(cs->bg);
-	colorp->pixel = cs->shadow;
-	XStoreColor(dpy, Pcmap, colorp);
-      } else {
-	Pixel old_shadow = cs->shadow;
-
-	XFreeColors(dpy, Pcmap, &cs->shadow, 1, 0);
-	cs->shadow = GetShadow(cs->bg);
-	if (old_shadow != cs->shadow)
-	  have_pixels_changed = True;
-      }
-    }
-  } /* has_sh_changed */
-
-  /*
-   * ---------- change the masked out parts of the background pixmap ----------
-   */
-  if ((cs->mask != None) && (has_pixmap_changed || has_bg_changed))
-  {
-    /* Now that we know the background colour we can update the pixmap
-     * background. */
-    XSetForeground(dpy, gc, cs->bg);
-    XSetClipMask(dpy, gc, cs->mask);
-    XFillRectangle(dpy, cs->pixmap, gc, 0, 0, cs->width, cs->height);
-    XSetClipMask(dpy, gc, None);
-    has_pixmap_changed = True;
-  } /* has_pixmap_changed */
-
-  /*
-   * ---------- send new colorset to fvwm and clean up ----------
-   */
-  /* make sure the server has this to avoid races */
-  XSync(dpy, False);
-
-  /* inform fvwm of the change */
-  if (have_pixels_changed || has_pixmap_changed || has_shape_changed)
-    SendText(fd, DumpColorset(n, &Colorset[n]), 0);
-
-  if (fg)
-    free(fg);
-  if (bg)
-    free(bg);
-  if (hi)
-    free(hi);
-  if (sh)
-    free(sh);
-
-  /* if privateCells are not being used and XAllocColor has been used
-   * we are stuck in sharedCells behaviour forever */
-  /* have_pixels_changed will be set if a new colorset has been made */
-  if (!privateCells && have_pixels_changed)
-    sharedCells = True;
+  SendText(fd, CatString2("Colorset ", line), 0);
 }
 
 /* SendToModule options */
@@ -1048,21 +192,6 @@
   SetSyncMask(fd, M_CONFIG_INFO | M_STRING);
 }
 
-static int error_handler(Display *d, XErrorEvent *e)
-{
-  /* Since GetColor() doesn't return a status it is possible that FvwmTheme
-   * will try to free a color that it hasn't XAlloc()'d. Allow this error */
-  if (e->error_code == BadAccess && e->request_code == X_FreeColors)
-  {
-    fprintf(stderr, "%s: couldn't free a pixel, may have run out of colors\n",
-	    name);
-    return 0;
-  }
-  /* All other errors cause diagnostic output and stop execution */
-  PrintXErrorAndCoredump(d, e, name);
-  return 0;
-}
-
 static void set_signals(void) {
 #ifdef HAVE_SIGACTION
   struct sigaction  sigact;
@@ -1106,27 +235,4 @@
 static RETSIGTYPE signal_handler(int signal) {
   fprintf(stderr, "%s quiting on signal %d\n", name, signal);
   exit(signal);
-}
-
-static void add_to_junk(Pixmap pixmap)
-{
-  struct junklist *oldjunk = junk;
-
-  junk = (struct junklist *)safemalloc(sizeof(struct junklist));
-  junk->prev = oldjunk;
-  junk->pixmap = pixmap;
-}
-
-static void feng_shui()
-{
-  struct junklist *oldjunk = junk;
-
-  while (junk)
-  {
-    XFreePixmap(dpy, junk->pixmap);
-    oldjunk = junk;
-    junk = junk->prev;
-    free(oldjunk);
-  }
-  XFlush(dpy);
 }

---

From: Mikhael Goikhman <[email-masked]>
Date: Wed, 17 Apr 2002 17:09:22 +0000

On 17 Apr 2002 17:20:12 +0100, Tim Phipps wrote:
> directory.

Ok, I will apply this patch, but will replace FVWMTHEME_PRIVATE with
FVWM_COLORSET_PRIVATE and use the TAB-based indentation for new files.

> I haven't updated any man pages, could someone else do this please?

I will do this later. First I should document perllib and FvwmPerl.

Regards,
Mikhael.

---

From: Mikhael Goikhman <[email-masked]>
Date: Wed, 17 Apr 2002 23:15:38 +0000

> FVWM_COLORSET_PRIVATE and use the TAB-based indentation for new files.

Everything seems to work ok, except for this problem.

Gradients when Colorset is defined for the first time look a bit like
transparent, but when defined more and more produce random colors and
there is an error message:

[FVWM][FvwmErrorHandler]: <<ERROR>> *** internal error ***
[FVWM][FvwmErrorHandler]: <<ERROR>> Request 56, Error 13, EventType: 0
[FVWM][FvwmErrorHandler]: <<ERROR>> *** internal error ***
[FVWM][FvwmErrorHandler]: <<ERROR>> Request 72, Error 13, EventType: 0

(EventType may be 19.)

Tim, can you please take a look at this?

Regards,
Mikhael.

---

From: Tim Phipps <[email-masked]>
Date: Thu, 18 Apr 2002 15:13:59 +0100

>[FVWM][FvwmErrorHandler]: <<ERROR>> Request 72, Error 13, EventType: 0
I think these are being caused by parse_colorset() using a GC that has 
not been created. I just assumed that Scr.MonoGC would be OK. Here's a 
patch that makes parse_colorset() create it's own mono GC. It also 
includes a debug message that you should see excatly once
Index: fvwm/colorset.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/colorset.c,v
retrieving revision 1.1
diff -u -r1.1 colorset.c
--- fvwm/colorset.c	2002/04/18 12:18:58	1.1
+++ fvwm/colorset.c	2002/04/18 14:08:49
@@ -273,7 +273,7 @@
 	XGCValues xgcv;
 	static char *name = "parse_colorset";
 	Window win = Scr.SizeWindow;
-	static GC gc = None;
+	static GC gc = None, monoGC = None;
 
 	/* make sure it exists and has sensible contents */
 	if (nColorsets <= n) {
@@ -343,7 +343,9 @@
 	cs = &Colorset[n];
 	if (gc == None)
 	{
+		fvwm_msg(DBG, name, "Creating GCs");
 		gc = fvwmlib_XCreateGC(dpy, win, 0, &xgcv);
+		monoGC = fvwmlib_XCreateGC(dpy, Scr.ScratchMonoPixmap,0, &xgcv);
 	}
 
 	/* ---------- Parse the options ---------- */
@@ -444,18 +446,18 @@
 					{
 						XCopyArea(
 							dpy, cs->picture->mask,
-							cs->mask, Scr.MonoGC,
+							cs->mask, monoGC,
 							0, 0,
 							cs->width, cs->height,
 							0, 0);
 						/* Invert the mask. We use it to draw the background. */
 						XSetFunction(
-							dpy, Scr.MonoGC, GXinvert);
+							dpy, monoGC, GXinvert);
 						XFillRectangle(
 							dpy, cs->mask,
-							Scr.MonoGC, 0, 0,
+							monoGC, 0, 0,
 							cs->width, cs->height);
-						XSetFunction(dpy, Scr.MonoGC, GXcopy);
+						XSetFunction(dpy, monoGC, GXcopy);
 					}
 				}
 			}
@@ -520,7 +522,7 @@
 								dpy, mask, picture->width, picture->height, 1);
 							if (cs->shape_mask != None)
 							{
-								XCopyPlane(dpy, mask, cs->shape_mask, Scr.MonoGC, 0, 0,
+								XCopyPlane(dpy, mask, cs->shape_mask, monoGC, 0, 0,
 								 picture->width, picture->height, 0, 0, 1);
 							}
 						}

---

From: Tim Phipps <[email-masked]>
Date: Thu, 18 Apr 2002 18:21:38 +0100

>Tim, can you please take a look at this?
There is a problem with ReadWriteColors on a PseudoColor display, 
attached is a patch. I could not get the above errors to appear and I 
get no errors unless I run out of colors. Even then things work OK.

I'll try to get mono to have a pixmap tomorrow.

Cheers,
Tim.

Index: configure.in
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/configure.in,v
retrieving revision 1.2
diff -u -r1.2 configure.in
--- configure.in	2002/04/18 12:18:57	1.2
+++ configure.in	2002/04/18 12:20:03
@@ -73,7 +73,7 @@
 
 dnl added -Wall for gcc, what about for others?
 if test "x$GCC" = "xyes"; then
-  CFLAGS="$CFLAGS -Wall"
+  CFLAGS="$CFLAGS -Wall -Wno-implicit-int"
 fi
 
 dnl Help finding POSIX functions on some systems
Index: fvwm/colorset.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/colorset.c,v
retrieving revision 1.2
diff -u -r1.2 colorset.c
--- fvwm/colorset.c	2002/04/18 14:37:56	1.2
+++ fvwm/colorset.c	2002/04/18 17:15:08
@@ -275,6 +275,13 @@
 	Window win = Scr.SizeWindow;
 	static GC gc = None, monoGC = None;
 
+	/* initialize statucs */
+	if (gc == None)
+	{
+		gc = fvwmlib_XCreateGC(dpy, win, 0, &xgcv);
+		monoGC = fvwmlib_XCreateGC(dpy, Scr.ScratchMonoPixmap,0, &xgcv);
+	}
+
 	/* make sure it exists and has sensible contents */
 	if (nColorsets <= n) {
 		Colorset = (colorset_struct *)saferealloc(
@@ -288,6 +295,7 @@
 	while (nColorsets <= n)
 	{
 		colorset_struct *ncs = &Colorset[nColorsets];
+
 		have_pixels_changed = True;
 		if (privateCells && XAllocColorCells(
 			/* grab four writeable cells */
@@ -317,36 +325,27 @@
 			/* grab four shareable colors */
 			if (Pdepth < 2) {
 				/* monochrome monitors get black on white */
-				/* FIXME: add a gray pixmap background */
-				Colorset[nColorsets].fg = GetColor(black);
-				Colorset[nColorsets].bg = GetColor(white);
-				Colorset[nColorsets].hilite = GetColor(white);
-				Colorset[nColorsets].shadow = GetColor(black);
+				/* FIXME: with a gray pixmap background */
+				ncs->fg = GetColor(black);
+				ncs->bg = GetColor(white);
+				ncs->hilite = GetColor(white);
+				ncs->shadow = GetColor(black);
 			}
 			else
 			{
-				Colorset[nColorsets].fg = GetColor(black);
-				Colorset[nColorsets].bg = GetColor(gray);
-				Colorset[nColorsets].hilite =
-					GetHilite(Colorset[nColorsets].bg);
-				Colorset[nColorsets].shadow =
-					GetShadow(Colorset[nColorsets].bg);
+				ncs->fg = GetColor(black);
+				ncs->bg = GetColor(gray);
+				ncs->hilite = GetHilite(ncs->bg);
+				ncs->shadow = GetShadow(ncs->bg);
 			}
 			/* set flags for fg contrast, bg average */
 			/* in case just a pixmap is given */
-			Colorset[nColorsets].color_flags =
-				FG_CONTRAST | BG_AVERAGE;
+			ncs->color_flags = FG_CONTRAST | BG_AVERAGE;
 		}
 		nColorsets++;
 	}
 
 	cs = &Colorset[n];
-	if (gc == None)
-	{
-		fvwm_msg(DBG, name, "Creating GCs");
-		gc = fvwmlib_XCreateGC(dpy, win, 0, &xgcv);
-		monoGC = fvwmlib_XCreateGC(dpy, Scr.ScratchMonoPixmap,0, &xgcv);
-	}
 
 	/* ---------- Parse the options ---------- */
 	while (line && *line)
@@ -951,30 +950,10 @@
 	/* do nothing if it already exists */
 	if (n < nColorsets)
 		return;
-
-	/* increment n to get the required array size, get a new array */
-	Colorset = (colorset_struct *)saferealloc(
-		(char *)Colorset, ++n * sizeof(colorset_struct));
-
-	/* zero out the new members */
-	memset(
-		&Colorset[nColorsets], 0,
-		(n - nColorsets) * sizeof(colorset_struct));
-
-	/* copy colorset 0 pixels into new members so that if undefined ones are
-	 * referenced at least they don't give black on black */
-	if (n > 1)
-	{
-		for ( ; nColorsets < n; nColorsets++)
-		{
-			Colorset[nColorsets].fg = Colorset[0].fg;
-			Colorset[nColorsets].bg = Colorset[0].bg;
-			Colorset[nColorsets].hilite = Colorset[0].hilite;
-			Colorset[nColorsets].shadow = Colorset[0].shadow;
-		}
-	}
 
-	nColorsets = n;
+	/* parse_colorset resizes the array if necessary
+	   so just use it to get a sensible default */
+	parse_colorset(n, "");
 }
 
 /* ---------------------------- builtin commands ---------------------------- */
Index: fvwm/fvwm.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/fvwm.c,v
retrieving revision 1.2
diff -u -r1.2 fvwm.c
--- fvwm/fvwm.c	2002/04/18 12:18:58	1.2
+++ fvwm/fvwm.c	2002/04/18 16:50:57
@@ -758,6 +758,10 @@
 #define startFuncName "StartFunction"
   const char *initFuncName;
 
+  /* make sure colorset 0 exists in case modules get started that use colorsets
+     and the startup files/commands have not created any */
+  alloc_colorset(0);
+
   CaptureAllWindows(False);
   /* Turn off the SM stuff after the initial capture so that new windows will
    * not be matched by accident. */
@@ -1390,13 +1394,7 @@
   Scr.DefaultIcon = NULL;
 
   Scr.DefaultColorset = -1;
-  alloc_colorset(0);
-  /* set up colorset 0 so that if FvwmTheme fails to start any modules
-   * using colorsets don't appear black on black */
-  Colorset[0].fg = Scr.StdFore = GetColor(DEFAULT_FORE_COLOR);
-  Colorset[0].bg = Scr.StdBack = GetColor(DEFAULT_BACK_COLOR);
-  Colorset[0].hilite = Scr.StdHilite = GetHilite(Scr.StdBack);
-  Colorset[0].shadow = Scr.StdShadow = GetShadow(Scr.StdBack);
+
   Scr.StdGC = 0;
   Scr.StdReliefGC = 0;
   Scr.StdShadowGC = 0;
Index: modules/FvwmScript/Scripts/FvwmScript-Colorset
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/modules/FvwmScript/Scripts/FvwmScript-Colorset,v
retrieving revision 1.1
diff -u -r1.1 FvwmScript-Colorset
--- modules/FvwmScript/Scripts/FvwmScript-Colorset	2002/04/18 10:47:52	1.1
+++ modules/FvwmScript/Scripts/FvwmScript-Colorset	2002/04/18 11:09:02
@@ -2,7 +2,7 @@
 # I can't believe how big this is
 # I haven't got the energy to implement a Save button
 # Just goes to show that command lines are better
-# Don't switch on Dynamic update unless using *FvwmThemeReadWriteColors
+# Don't switch on Dynamic update unless using ReadWriteColors
 WindowTitle	{Colorset Editor}
 WindowSize	380 290
 Colorset 0
@@ -13,7 +13,7 @@
   Set $Cset = 0
   Set $OldCset = 0
   Set $Color = (GetBack 1)
-  Do {SendToModule FvwmTheme Colorset } $Cset { Pixmap, Background #} $Color {, Foreground Contrast}
+  Do {Colorset } $Cset { Pixmap, Background #} $Color {, Foreground Contrast}
   # Sliders are initially hidden
   HideWidget 1
   HideWidget 2
@@ -183,10 +183,10 @@
    End
   Else
    Begin
-    # I think ther might be a bug in FvwmTheme that resets a colrset to a copy of 0
+    # I think there might be a bug in Colorset that resets a colorset to a copy of 0
     # if {pixmap} is used to select a plain background
     Set $Color = (GetBack 1)
-    Do {SendToModule FvwmTheme Colorset } $Cset { Pixmap, Background #} $Color {, Foreground Contrast}
+    Do {Colorset } $Cset { Pixmap, Background #} $Color {, Foreground Contrast}
     Set $OldCset = $Cset
    End
  End
@@ -239,7 +239,7 @@
   Set $Color = $Color {/} (NumToHex (GetValue 2) 2)
   Set $Color = $Color {/} (NumToHex (GetValue 3) 2)
   # pick the current colorset
-  Set $Command = {SendToModule FvwmTheme Colorset } $Cset
+  Set $Command = {Colorset } $Cset
   # pick the type to set
   If (GetValue 10) == 1 Then
    Set $Command = $Command { Foreground } $Color

---

From: Mikhael Goikhman <[email-masked]>
Date: Thu, 18 Apr 2002 20:07:49 +0000

> includes a debug message that you should see excatly once

Unfortunately this patch does not change anything for me, so I suppose
it should not be applied.

I can't reproduce this problem with any simple config, including the
original Dominik's one. However, the problem is fully reproducible
using fvwm-themes.

I even got core dump when changed one Plain colorset to gradient.
This happens when I change colorset 10 in colors@migo to this:

  Colorset 10 DGradient 100 2 yellow 1 green 1 navy

But I can't get a core dump trace (I don't know why it is empty).

I tried to debug this problem, but something strange happens.
The depth (8, 16, 24) does not matter. Simple configs seem to work ok.

Please someone confirm or deny these 2 problems with fvwm-themes:

  1) gradients do not work (they produce 4 error lines above)
  2) core dump when changing one line in colors@migo

Regards,
Mikhael.

---

From: Mikhael Goikhman <[email-masked]>
Date: Thu, 18 Apr 2002 20:41:12 +0000

On 18 Apr 2002 18:21:38 +0100, Tim Phipps wrote:
> attached is a patch.

Ok, I am applying both patches, you will decide whether the first one is
needed. I leave a debug message for now.

Regards,
Mikhael.

---

From: Jason Kibblewhite <[email-masked]>
Date: Thu, 18 Apr 2002 19:39:38 -0700

>   2) core dump when changing one line in colors@migo

I still don't use fvwm-themes but I can confirm core dumps at least a
few times.  However only if the config file contains the gradients, if I
use FvwmConsole to dump in the colorsets I get same errors, and the
gradients are changed, but they are not really gradients, more random
color masks.  Also works the same if I use *FvwmTheme: Colorset.

---

From: Tim Phipps <[email-masked]>
Date: Fri, 19 Apr 2002 16:23:59 +0100

>color masks.  Also works the same if I use *FvwmTheme: Colorset.
Another patch that fixes my problems. It was due to running out of 
colors on 8bit while having ReadWriteColors turned on.

This patch also initializes monochrome pixmaps to have a gray 
background. It does three types for colorsets 0, 1 & 2 and then repeats 
for any more. These pixmaps correspond to the ones fvwm uses by default 
in mono for normal, focused and sticky windows. If modules are to use 
them the colorsets the modules use must be referred to by fvwm before 
the module starts e.g. put "Colorset 2" in the StartFunction before the 
modules are started.

This probably won't fix your problems, if it doesn't you should be able 
to get a core dump by starting fvwm with the -debug flag to get 
synchronous behaviour and then putting "abort();" in the error handler 
routine (fvwm.c line 1762).

Hope this helps,
Tim.

Index: libs/Colorset.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/libs/Colorset.c,v
retrieving revision 1.1
diff -u -r1.1 Colorset.c
--- libs/Colorset.c	2002/04/18 10:47:18	1.1
+++ libs/Colorset.c	2002/04/19 13:56:35
@@ -50,21 +50,15 @@
   Colorset = (colorset_struct *)saferealloc((char *)Colorset,
 					    ++n * sizeof(colorset_struct));
 
-  /* zero out the new members */
-  memset(&Colorset[nColorsets], 0, (n - nColorsets) * sizeof(colorset_struct));
-
-  /* copy colorset 0 pixels into new members so that if undefined ones are
-   * referenced at least they don't give black on black */
-  if (n > 1)
-  {
+  /* zero out colorset 0
+     it's always defined so will be filled in during module startup */
+  if (n == 0)
+    memset(&Colorset[nColorsets], 0, (n - nColorsets) * sizeof(colorset_struct));
+  else
+    /* copy colorset 0 into new members so that if undefined ones are
+     * referenced at least they don't give black on black */
     for ( ; nColorsets < n; nColorsets++)
-    {
-      Colorset[nColorsets].fg = Colorset[0].fg;
-      Colorset[nColorsets].bg = Colorset[0].bg;
-      Colorset[nColorsets].hilite = Colorset[0].hilite;
-      Colorset[nColorsets].shadow = Colorset[0].shadow;
-    }
-  }
+      memcpy(&Colorset[nColorsets], Colorset, sizeof(colorset_struct));
 
   nColorsets = n;
 }
Index: fvwm/colorset.c
===================================================================
RCS file: /u/phippst/share/cvsroot/fvwm/fvwm/colorset.c,v
retrieving revision 1.3
diff -u -r1.3 colorset.c
--- fvwm/colorset.c	2002/04/19 10:27:23	1.3
+++ fvwm/colorset.c	2002/04/19 15:07:53
@@ -275,7 +275,7 @@
 	Window win = Scr.SizeWindow;
 	static GC gc = None, monoGC = None;
 
-	/* initialize statucs */
+	/* initialize statics */
 	if (gc == None)
 	{
 		gc = fvwmlib_XCreateGC(dpy, win, 0, &xgcv);
@@ -283,67 +283,7 @@
 	}
 
 	/* make sure it exists and has sensible contents */
-	if (nColorsets <= n) {
-		Colorset = (colorset_struct *)saferealloc(
-			(char *)Colorset, (n + 1) * sizeof(colorset_struct));
-		memset(
-			&Colorset[nColorsets], 0,
-			(n + 1 - nColorsets) * sizeof(colorset_struct));
-	}
-
-	/* initialize new colorsets to black on gray */
-	while (nColorsets <= n)
-	{
-		colorset_struct *ncs = &Colorset[nColorsets];
-
-		have_pixels_changed = True;
-		if (privateCells && XAllocColorCells(
-			/* grab four writeable cells */
-			dpy, Pcmap, False, NULL, 0, &(ncs->fg), 4))
-		{
-			XColor *colorp;
-
-			/* set the fg color */
-			MyXParseColor(black, &color);
-			color.pixel = ncs->fg;
-			XStoreColor(dpy, Pcmap, &color);
-			/* set the bg */
-			MyXParseColor(gray, &color);
-			color.pixel = ncs->bg;
-			XStoreColor(dpy, Pcmap, &color);
-			/* calculate and set the hilite */
-			colorp = GetHiliteColor(ncs->bg);
-			colorp->pixel = ncs->hilite;
-			XStoreColor(dpy, Pcmap, colorp);
-			/* calculate and set the shadow */
-			colorp = GetShadowColor(ncs->bg);
-			colorp->pixel = ncs->shadow;
-			XStoreColor(dpy, Pcmap, colorp);
-		}
-		else
-		{
-			/* grab four shareable colors */
-			if (Pdepth < 2) {
-				/* monochrome monitors get black on white */
-				/* FIXME: with a gray pixmap background */
-				ncs->fg = GetColor(black);
-				ncs->bg = GetColor(white);
-				ncs->hilite = GetColor(white);
-				ncs->shadow = GetColor(black);
-			}
-			else
-			{
-				ncs->fg = GetColor(black);
-				ncs->bg = GetColor(gray);
-				ncs->hilite = GetHilite(ncs->bg);
-				ncs->shadow = GetShadow(ncs->bg);
-			}
-			/* set flags for fg contrast, bg average */
-			/* in case just a pixmap is given */
-			ncs->color_flags = FG_CONTRAST | BG_AVERAGE;
-		}
-		nColorsets++;
-	}
+	alloc_colorset(n);
 
 	cs = &Colorset[n];
 
@@ -936,12 +876,6 @@
 		free(hi);
 	if (sh)
 		free(sh);
-
 
 /*****************************************************************************
@@ -954,10 +888,81 @@
 	/* do nothing if it already exists */
 	if (n < nColorsets)
 		return;
+	else {
+		Colorset = (colorset_struct *)saferealloc(
+			(char *)Colorset, (n + 1) * sizeof(colorset_struct));
+		memset(
+			&Colorset[nColorsets], 0,
+			(n + 1 - nColorsets) * sizeof(colorset_struct));
+	}
 
-	/* parse_colorset resizes the array if necessary
-	 * so just use it to get a sensible default */
-	parse_colorset(n, "");
+	/* initialize new colorsets to black on gray */
+	while (nColorsets <= n)
+	{
+		colorset_struct *ncs = &Colorset[nColorsets];
+
+		/* try to allocate private colormap entries if required */
+		if (privateCells && XAllocColorCells(
+			/* grab four writeable cells */
+			dpy, Pcmap, False, NULL, 0, &(ncs->fg), 4))
+		{
+			XColor color;
+			XColor *colorp;
+
+			/* set the fg color */
+			MyXParseColor(black, &color);
+			color.pixel = ncs->fg;
+			XStoreColor(dpy, Pcmap, &color);
+			/* set the bg */
+			MyXParseColor(gray, &color);
+			color.pixel = ncs->bg;
+			XStoreColor(dpy, Pcmap, &color);
+			/* calculate and set the hilite */
+			colorp = GetHiliteColor(ncs->bg);
+			colorp->pixel = ncs->hilite;
+			XStoreColor(dpy, Pcmap, colorp);
+			/* calculate and set the shadow */
+			colorp = GetShadowColor(ncs->bg);
+			colorp->pixel = ncs->shadow;
+			XStoreColor(dpy, Pcmap, colorp);
+		}
+		/* otherwise allocate shared ones and turn off private flag */
+		else
+		{
+			sharedCells = True;
+			privateCells = False;
+			/* grab four shareable colors */
+			if (Pdepth < 2) {
+				char g_bits[] = {0x0a, 0x05, 0x0a, 0x05,
+						 0x08, 0x02, 0x08, 0x02,
+						 0x01, 0x02, 0x04, 0x08};
+				/* monochrome monitors get black on white */
+				/* with a gray pixmap background */
+				ncs->fg = GetColor(black);
+				ncs->bg = GetColor(white);
+				ncs->hilite = GetColor(white);
+				ncs->shadow = GetColor(black);
+				ncs->pixmap = XCreatePixmapFromBitmapData(dpy,
+					Scr.NoFocusWin,
+					&g_bits[4 * (nColorsets % 3)], 4, 4,
+					BlackPixel(dpy, Scr.screen),
+					WhitePixel(dpy, Scr.screen), Pdepth);
+				ncs->width = 4;
+				ncs->height = 4;
+			}
+			else
+			{
+				ncs->fg = GetColor(black);
+				ncs->bg = GetColor(gray);
+				ncs->hilite = GetHilite(ncs->bg);
+				ncs->shadow = GetShadow(ncs->bg);
+			}
+			/* set flags for fg contrast, bg average */
+			/* in case just a pixmap is given */
+			ncs->color_flags = FG_CONTRAST | BG_AVERAGE;
+		}
+		nColorsets++;
+	}
 }

---

From: Mikhael Goikhman <[email-masked]>
Date: Sat, 20 Apr 2002 16:08:38 +0000

> routine (fvwm.c line 1762).

I upgraded my gcc and gdb and now I get non-empty stack traces.
So I may send any stack trace.

But I think you may reproduce this error

using this minimal config (fvwm -f colorset-bug):

  ModuleSynchronous FvwmTheme
  *FvwmTheme: Colorset 1 fg black, bg gray50, VGradient 30 gray40 gray60

You may switch these lines - the same result.

Now, if you remove a comma after "black" or remove fg and bg parts
altogether you get core dump. I think this is because image is NULL in
line 586 of colorset.c.

Regards,
Mikhael.

---

From: Mikhael Goikhman <[email-masked]>
Date: Mon, 22 Apr 2002 14:22:37 +0000

> altogether you get core dump. I think this is because image is NULL in

After the latest Olivier commits, these problems are solved.
Gradients now fully work with fvwm-themes.

I would like to know what was the problem and when it was introduced?

Regards,
Mikhael.

---

From: Olivier Chapuis <[email-masked]>
Date: Mon, 22 Apr 2002 16:36:35 +0200

> I would like to know what was the problem and when it was introduced?

Form the ChangeLog:

* fvwm/colorset.c (parse_colorset):
Use the Scr.NoFocusWin as main window in the place of the Scr.SizeWindow,
this fix a lot of X errors in my machine.

I do not think the use of the SizeWindow was correct, it causes problem
when you create the static gc in parse_colorset. If you take a look
at the code the SizeWindow is created after the config file is read.
Also, since a long times it is the  Scr.NoFocusWin which is used for
loading FvwmPicture, so I used the Scr.NoFocusWin (which is created
as soon as possible with the good parameters) and I saw no more
FvwmErrorHandler error ... so I think the change is good :o)

Olivier

---

From: Tim Phipps <[email-masked]>
Date: Tue, 23 Apr 2002 09:05:15 +0100

>at the code the SizeWindow is created after the config file is read.
Sorry, that was my fault. My fvwmrc defines the colorsets as part of the 
start function so I couldn't see the problem.

>FvwmErrorHandler error ... so I think the change is good :o)
Me too. Does this mean the mono gc in colorsets.c isn't needed? If not 
it could use Scr.MonoGC.

Is there anyone out there with a monochrome monitor that can test it?

Cheers,
Tim.

---

From: Dominik Vogt <[email-masked]>
Date: Tue, 23 Apr 2002 11:54:10 +0200

> Is there anyone out there with a monochrome monitor that can test it?

You can run XNest in monochrome mode.  The X server has to support
a monochrome visual though.  Currently, I can't get it running
again.

  Xnest -full -sync -depth 1 :1

Bye

Dominik ^_^  ^_^

---

From: Olivier Chapuis <[email-masked]>
Date: Wed, 24 Apr 2002 06:15:18 +0200

> Me too. Does this mean the mono gc in colorsets.c isn't needed? If not 

Yes, I think it safe to use Scr.MonoGC for the mono gc. I will do
the change soon with adding XBM support to colorset.
 
Olivier

PS: my curent available connection to the web is random (I am
in holidays)

---

From: Dominik Vogt <[email-masked]>
Date: Wed, 24 Apr 2002 13:23:22 +0200

> the change soon with adding XBM support to colorset.

Just remember that the Scr.MonoGC is supposed to have some members
(like tiling/stippling) set to specific values.  If these are
changed, the original values have to be restored after use.

Bye

Dominik ^_^  ^_^