/* Copyright (C) 1992 by Gustaf Neumann, Stefan Nusser

 *      Wirtschaftsuniversitaet Wien, 
 *      Abteilung fuer Wirtschaftsinformatik
 *      Augasse 2-6, 
 *      A-1090 Vienna, Austria
 *      neumann@wu-wien.ac.at, nusser@wu-wien.ac.at

 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appears in all copies and that both that
 * copyright notice and this permission notice appear in all supporting
 * documentation.  This software is provided "as is" without expressed or
 * implied warranty.

 * Creation: Sun Jun  5 18:42:18 GMT 1994 on mohegan
 * Author: genc
 * Version: 0.96999999999999997335


 */
#define HTML_C
#include <wafe.h>
#ifdef HTML

#include <errno.h>
#include <HTML.h>
#define hTMLWidgetClass htmlWidgetClass
#ifndef X_NOT_STDC_ENV
#include <stdlib.h>
#else
char *malloc(), *realloc(), *calloc();
#endif

/* 
 * ******* begin required file <gifread.inc> *******
 */
/* make emcas happy -*-C-*-  make emacs happy */

/* +-------------------------------------------------------------------+ */
/* | Copyright 1990  - 1994, David Koblas. (koblas@netcom.com)         | */
/* |   Permission to use, copy, modify, and distribute this software   | */
/* |   and its documentation for any purpose and without fee is hereby | */
/* |   granted, provided that the above copyright notice appear in all | */
/* |   copies and that both that copyright notice and this permission  | */
/* |   notice appear in supporting documentation.  This software is    | */
/* |   provided "as is" without express or implied warranty.           | */
/* +-------------------------------------------------------------------+ */


#define	MAXCOLORMAPSIZE		256

#define	TRUE	1
#define	FALSE	0

#define CM_RED		0
#define CM_GREEN	1
#define CM_BLUE		2

#define	MAX_LWZ_BITS		12

#define INTERLACE		0x40
#define LOCALCOLORMAP	0x80
#define BitSet(byte, bit)	(((byte) & (bit)) == (bit))

#define	ReadOK(file,buffer,len)	(fread(buffer, len, 1, file) != 0)

#define LM_to_uint(a,b)			(((b)<<8)|(a))

struct {
	unsigned int	Width;
	unsigned int	Height;
	unsigned char	ColorMap[3][MAXCOLORMAPSIZE];
	unsigned int	BitPixel;
	unsigned int	ColorResolution;
	unsigned int	Background;
	unsigned int	AspectRatio;
	/*
	**
	*/
	int             xGrayScale;
} GifScreen;

static struct {
	int	transparent;
	int	delayTime;
	int	inputFlag;
	int	disposal;
} Gif89 = { -1, -1, -1, 0 };

static int	verbose = FALSE;
static int	showComment = FALSE;


static int ReadColorMap(FILE *, int, unsigned char [3][MAXCOLORMAPSIZE], int *);
static int DoExtension(FILE *, int);
static int GetDataBlock(FILE *, unsigned char *);
static unsigned char *ReadImage(FILE *, int, int, XColor *, int,
                unsigned char[3][MAXCOLORMAPSIZE], int, int, int);
/*
unsigned char *ReadGIF ARGS(( FILE	*fd, int imageNumber, int *bg ));
static int ReadColorMap ARGS(( FILE *fd, int number, unsigned char buffer[3][MAXCOLORMAPSIZE] ));
static int DoExtension ARGS(( FILE *fd, int label ));
static int GetDataBlock ARGS(( FILE *fd, unsigned char  *buf ));
static int GetCode ARGS(( FILE *fd, int code_size, int flag ));
static int LWZReadByte ARGS(( FILE *fd, int flag, int input_code_size ));
static unsigned char *ReadImage ARGS(( FILE *fd, int len, int height, unsigned char cmap[3][MAXCOLORMAPSIZE], int interlace, int ignore ));
*/

/*
static int ReadColorMap();
static int DoExtension();
static int GetDataBlock();
static int GetCode();
static int LWZReadByte();
static unsigned char *ReadImage();
*/

unsigned char *
ReadGIF(fd, w, h, colrs, bg)
FILE	*fd;
int *w, *h;
XColor *colrs;
int *bg;
{
	unsigned char	buf[16];
	unsigned char	c;
	unsigned char	localColorMap[3][MAXCOLORMAPSIZE];
	int             grayScale;
	int		useGlobalColormap;
	int		bitPixel;
	int		imageCount = 0;
	char		version[4];
	int		imageNumber = 1;
	unsigned char   *image = NULL;
	int		i;

	verbose = FALSE;
	showComment = FALSE;

	/*
	 * Initialize GIF89 extensions
	 */
	Gif89.transparent = -1;
	Gif89.delayTime = -1;
	Gif89.inputFlag = -1;
        Gif89.disposal = 0;

	if (! ReadOK(fd,buf,6))
	{
#if 0
		fprintf(stderr, "error reading magic number\n");
#endif
		return(NULL);
	}

	if (strncmp((char *)buf,"GIF",3) != 0)
	{
#if 0
		if (verbose)
			fprintf(stderr, "not a GIF file\n");
#endif
		return(NULL);
	}

	strncpy(version, (char *)buf + 3, 3);
	version[3] = '\0';

	if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0))
	{
#if 0
		fprintf(stderr, "bad version number, not '87a' or '89a'\n");
#endif
		return(NULL);
	}

	if (! ReadOK(fd,buf,7))
	{
#if 0
		fprintf(stderr, "failed to read screen descriptor\n");
#endif
		return(NULL);
	}

	GifScreen.Width           = LM_to_uint(buf[0],buf[1]);
	GifScreen.Height          = LM_to_uint(buf[2],buf[3]);
	GifScreen.BitPixel        = 2<<(buf[4]&0x07);
	GifScreen.ColorResolution = (((buf[4]&0x70)>>3)+1);
	GifScreen.Background      = buf[5];
	GifScreen.AspectRatio     = buf[6];

	if (BitSet(buf[4], LOCALCOLORMAP)) {	/* Global Colormap */
		int scale = 65536/MAXCOLORMAPSIZE;

		if (ReadColorMap(fd,GifScreen.BitPixel,GifScreen.ColorMap,
			&GifScreen.xGrayScale))
		{
#if 0 
			fprintf(stderr, "error reading global colormap\n");
#endif
			return(NULL);
		}
		for (i=0; i < GifScreen.BitPixel; i++)
		{

			colrs[i].red = GifScreen.ColorMap[0][i] * scale;
			colrs[i].green = GifScreen.ColorMap[1][i] * scale;
			colrs[i].blue = GifScreen.ColorMap[2][i] * scale;
			colrs[i].pixel = i;
			colrs[i].flags = DoRed|DoGreen|DoBlue;
		}
		for (i = GifScreen.BitPixel; i<MAXCOLORMAPSIZE; i++)
		{
			colrs[i].red = 0;
			colrs[i].green = 0;
			colrs[i].blue = 0;
			colrs[i].pixel = i;
			colrs[i].flags = DoRed|DoGreen|DoBlue;
		}
	}

	if (GifScreen.AspectRatio != 0 && GifScreen.AspectRatio != 49) {
		float	r;
		r = ( (float) GifScreen.AspectRatio + 15.0 ) / 64.0;
#if 0
		fprintf(stderr, "Warning:  non-square pixels!\n");
#endif
	}

	while (image == NULL) {
		if (! ReadOK(fd,&c,1))
		{
#if 0
			fprintf(stderr, "EOF / read error on image data\n");
#endif
			return(NULL);
		}

		if (c == ';') {		/* GIF terminator */
			if (imageCount < imageNumber)
			{
#if 0
				fprintf(stderr, "No images found in file\n");
#endif
				return(NULL);
			}
			break;
		}

		if (c == '!') { 	/* Extension */
			if (! ReadOK(fd,&c,1))
			{
#if 0
				fprintf(stderr, "EOF / read error on extention function code\n");
#endif
				return(NULL);
			}
			DoExtension(fd, c);
			continue;
		}

		if (c != ',') {		/* Not a valid start character */
#if 0
			fprintf(stderr, "bogus character 0x%02x, ignoring\n",
				(int)c);
#endif
			continue;
		}

		++imageCount;

		if (! ReadOK(fd,buf,9))
		{
#if 0
			fprintf(stderr,"couldn't read left/top/width/height\n");
#endif
			return(NULL);
		}

		useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);

		bitPixel = 1<<((buf[8]&0x07)+1);

		/*
		 * We only want to set width and height for the imageNumber
		 * we are requesting.
		 */
		if (imageCount == imageNumber)
		{
			*w = LM_to_uint(buf[4],buf[5]);
			*h = LM_to_uint(buf[6],buf[7]);
		}
		if (! useGlobalColormap) {
			if (ReadColorMap(fd,bitPixel,localColorMap,&grayScale))
			{
#if 0
				fprintf(stderr, "error reading local colormap\n");
#endif
				return(NULL);
			}

			/*
			 * We only want to set the data for the
			 * imageNumber we are requesting.
			 */
			if (imageCount == imageNumber)
			{
			    image = ReadImage(fd, LM_to_uint(buf[4],buf[5]),
			          LM_to_uint(buf[6],buf[7]), colrs,
			          bitPixel, localColorMap, grayScale,
			          BitSet(buf[8], INTERLACE),
			          imageCount != imageNumber);
			}
			else
			{
			    unsigned char *tdata;
			
			    tdata = ReadImage(fd, LM_to_uint(buf[4],buf[5]),
			          LM_to_uint(buf[6],buf[7]), colrs,
			          bitPixel, localColorMap, grayScale,
			          BitSet(buf[8], INTERLACE),
			          imageCount != imageNumber);
			}
		} else {
			/*
			 * We only want to set the data for the
			 * imageNumber we are requesting.
			 */
			if (imageCount == imageNumber)
                        {
			    image = ReadImage(fd, LM_to_uint(buf[4],buf[5]),
			          LM_to_uint(buf[6],buf[7]), colrs,
			          GifScreen.BitPixel, GifScreen.ColorMap,
			          GifScreen.xGrayScale,
			          BitSet(buf[8], INTERLACE),
			          imageCount != imageNumber);
                        }
			else
                        {
			    unsigned char *tdata;
			
			    tdata = ReadImage(fd, LM_to_uint(buf[4],buf[5]),
			          LM_to_uint(buf[6],buf[7]), colrs,
			          GifScreen.BitPixel, GifScreen.ColorMap,
			          GifScreen.xGrayScale,
			          BitSet(buf[8], INTERLACE),
			          imageCount != imageNumber);
                        }
                }
  
        }
	*bg = Gif89.transparent;

	return(image);
}

static int
ReadColorMap(fd,number,buffer,gray)
FILE		*fd;
int		number;
unsigned char	buffer[3][MAXCOLORMAPSIZE];
int		*gray;
{
	int		i;
	unsigned char	rgb[3];
	int		flag;

	flag = TRUE;

	for (i = 0; i < number; ++i) {
		if (! ReadOK(fd, rgb, sizeof(rgb)))
		{
#if 0
			fprintf(stderr, "bad colormap\n");
#endif
			return(TRUE);
		}

		buffer[CM_RED][i] = rgb[0] ;
		buffer[CM_GREEN][i] = rgb[1] ;
		buffer[CM_BLUE][i] = rgb[2] ;

		flag &= (rgb[0] == rgb[1] && rgb[1] == rgb[2]);
	}

	*gray = flag;

	return FALSE;
}

static int
DoExtension(fd, label)
FILE	*fd;
int	label;
{
	static char	buf[256];
	char		*str;

	switch (label) {
	case 0x01:		/* Plain Text Extension */
		str = "Plain Text Extension";
#ifdef notdef
		if (GetDataBlock(fd, (unsigned char*) buf) <= 0)
			;

		lpos   = LM_to_uint(buf[0], buf[1]);
		tpos   = LM_to_uint(buf[2], buf[3]);
		width  = LM_to_uint(buf[4], buf[5]);
		height = LM_to_uint(buf[6], buf[7]);
		cellw  = buf[8];
		cellh  = buf[9];
		foreground = buf[10];
		background = buf[11];

		while (GetDataBlock(fd, (unsigned char*) buf) > 0) {
			PPM_ASSIGN(image[ypos][xpos],
					cmap[CM_RED][v],
					cmap[CM_GREEN][v],
					cmap[CM_BLUE][v]);
			++index;
		}

		return FALSE;
#else
		break;
#endif
	case 0xff:		/* Application Extension */
		str = "Application Extension";
		break;
	case 0xfe:		/* Comment Extension */
		str = "Comment Extension";
		while (GetDataBlock(fd, (unsigned char*) buf) > 0) {
			if (showComment)
			{
#if 0
				fprintf(stderr, "gif comment: %s\n", buf);
#endif
			}
		}
		return FALSE;
	case 0xf9:		/* Graphic Control Extension */
		str = "Graphic Control Extension";
		(void) GetDataBlock(fd, (unsigned char*) buf);
		Gif89.disposal    = (buf[0] >> 2) & 0x7;
		Gif89.inputFlag   = (buf[0] >> 1) & 0x1;
		Gif89.delayTime   = LM_to_uint(buf[1],buf[2]);
		if ((buf[0] & 0x1) != 0)
			Gif89.transparent = (int)((unsigned char)buf[3]);

		while (GetDataBlock(fd, (unsigned char*) buf) > 0)
			;
		return FALSE;
	default:
		str = buf;
		sprintf(buf, "UNKNOWN (0x%02x)", label);
		break;
	}

	/* fprintf(stderr, "got a '%s' extension\n", str); */

	while (GetDataBlock(fd, (unsigned char*) buf) > 0)
		;

	return FALSE;
}

static int	ZeroDataBlock = FALSE;

static int
GetDataBlock(fd, buf)
FILE		*fd;
unsigned char 	*buf;
{
	unsigned char	count;

	count = 0;
	if (! ReadOK(fd, &count, 1)) {
#if 0
		fprintf(stderr, "error in getting DataBlock size\n");
#endif
		return -1;
	}

	ZeroDataBlock = count == 0;

	if ((count != 0) && (! ReadOK(fd, buf, count))) {
#if 0
		fprintf(stderr, "error in reading DataBlock\n");
#endif
		return -1;
	}

	return((int)count);
}


/*
**  Pulled out of nextCode
*/
static  int             curbit, lastbit, get_done, last_byte;
static  int             return_clear;
/*
**  Out of nextLWZ
*/
static int      stack[(1<<(MAX_LWZ_BITS))*2], *sp;
static int      code_size, set_code_size;
static int      max_code, max_code_size;
static int      clear_code, end_code;

static void initLWZ(input_code_size)
int input_code_size;
{
	set_code_size = input_code_size;
	code_size     = set_code_size + 1;
	clear_code    = 1 << set_code_size ;
	end_code      = clear_code + 1;
	max_code_size = 2 * clear_code;
	max_code      = clear_code + 2;
	
	curbit = lastbit = 0;
	last_byte = 2;
	get_done = FALSE;
	
	return_clear = TRUE;

	sp = stack;
}
  
static int nextCode(fd, code_size)
FILE *fd;
int code_size;
{
        static unsigned char    buf[280];
	static int maskTbl[16] = {
		0x0000, 0x0001, 0x0003, 0x0007,
		0x000f, 0x001f, 0x003f, 0x007f,
		0x00ff, 0x01ff, 0x03ff, 0x07ff,
		0x0fff, 0x1fff, 0x3fff, 0x7fff,
	};
	int                     i, j, ret, end;
		
	if (return_clear) {
		return_clear = FALSE;
		return clear_code;
	}
		
	end = curbit + code_size;
  
	if (end >= lastbit) {
		int     count;
  
		if (get_done) {
                        if (curbit >= lastbit)
                        {
#if 0
		                ERROR("ran off the end of my bits" );
#endif
                        }
                        return -1;
		}
		buf[0] = buf[last_byte-2];
		buf[1] = buf[last_byte-1];

		if ((count = GetDataBlock(fd, &buf[2])) == 0)
			get_done = TRUE;

		last_byte = 2 + count;
		curbit = (curbit - lastbit) + 16;
		lastbit = (2+count)*8 ;

		end = curbit + code_size;
	}

	j = end / 8;
	i = curbit / 8;
	
	if (i == j)
	        ret = (int)buf[i];
	else if (i + 1 == j)
	        ret = (int)buf[i] | ((int)buf[i+1] << 8);
	else
	        ret = (int)buf[i] | ((int)buf[i+1] << 8) | ((int)buf[i+2] << 16);
	
	ret = (ret >> (curbit % 8)) & maskTbl[code_size];

	curbit += code_size;

	return ret;
}

#define readLWZ(fd) ((sp > stack) ? *--sp : nextLWZ(fd))

static int nextLWZ(fd)
FILE	*fd;
{
	static int       table[2][(1<< MAX_LWZ_BITS)];
	static int       firstcode, oldcode;
	int		code, incode;
	register int	i;

	while ((code = nextCode(fd, code_size)) >= 0) {
		if (code == clear_code) {

			 /* corrupt GIFs can make this happen */
			if (clear_code >= (1<<MAX_LWZ_BITS))
			{
				return -2;
			}

			for (i = 0; i < clear_code; ++i) {
				table[0][i] = 0;
				table[1][i] = i;
		}
		for (; i < (1<<MAX_LWZ_BITS); ++i)
			table[0][i] = table[1][i] = 0;
		code_size = set_code_size+1;
		max_code_size = 2*clear_code;
		max_code = clear_code+2;
		sp = stack;
		do {
			firstcode = oldcode = nextCode(fd, code_size);
		} while (firstcode == clear_code);

		 return firstcode;
	}
	if (code == end_code) {
			int		count;
			unsigned char	buf[260];

			if (ZeroDataBlock)
				return -2;

			while ((count = GetDataBlock(fd, buf)) > 0)
				;

			if (count != 0)
			{
#if 0
				INFO_MSG(("missing EOD in data stream (common occurence)"));
#endif
			}
			return -2;
		}

		incode = code;

		if (code >= max_code) {
			*sp++ = firstcode;
			code = oldcode;
		}

		while (code >= clear_code) {
			*sp++ = table[1][code];
			if (code == table[0][code])
			{
#if 0
				ERROR("circular table entry BIG ERROR");
#endif
				return(code);
			}
			if ((int)sp >= ((int)stack + sizeof(stack)))
			{
#if 0
				ERROR("circular table STACK OVERFLOW!");
#endif
			 return(code);
			}
			code = table[0][code];
		}

		*sp++ = firstcode = table[1][code];

		if ((code = max_code) <(1<<MAX_LWZ_BITS)) {
			table[0][code] = oldcode;
			table[1][code] = firstcode;
			++max_code;
			if ((max_code >= max_code_size) &&
				(max_code_size < (1<<MAX_LWZ_BITS))) {
				max_code_size *= 2;
				++code_size;
			}
		}

		oldcode = incode;

		if (sp > stack)
			return *--sp;
	}
	return code;
}


static unsigned char *
ReadImage(fd, len, height, colrs, cmapSize, cmap, gray, interlace, ignore)
FILE	*fd;
int	len, height;
XColor	*colrs;
int	cmapSize;
unsigned char	cmap[3][MAXCOLORMAPSIZE];
int	gray;
int	interlace, ignore;
{
	unsigned char	*dp, c;	
	int		v;
	int		xpos = 0, ypos = 0;
	unsigned char   *image;

	/*
	**  Initialize the Compression routines
	*/
	if (! ReadOK(fd,&c,1))
	{
#if 0
		fprintf(stderr, "EOF / read error on image data\n");
#endif
		return(NULL);
	}

	initLWZ(c);

	/*
	**  If this is an "uninteresting picture" ignore it.
	*/
	if (ignore) {
#if 0
		if (verbose)
			fprintf(stderr, "skipping image...\n" );
#endif
		while (readLWZ(fd) >= 0)
			;
		return(NULL);
	}

	image = (unsigned char *)calloc(len * height, sizeof(char));
	if (image == NULL)
	{
#if 0
		fprintf(stderr, "Cannot allocate space for image data\n");
#endif
		return(NULL);
	}

	for (v = 0; v < MAXCOLORMAPSIZE; v++) {
		colrs[v].red = colrs[v].green = colrs[v].blue = 0;
		colrs[v].pixel = v;
		colrs[v].flags = DoRed|DoGreen|DoBlue;
	}
	for (v = 0; v < cmapSize; v++) {
		colrs[v].red   = cmap[CM_RED][v]   * 0x101;
		colrs[v].green = cmap[CM_GREEN][v] * 0x101;
		colrs[v].blue  = cmap[CM_BLUE][v]  * 0x101;
	}

#if 0
	if (verbose)
		fprintf(stderr, "reading %d by %d%s GIF image\n",
			len, height, interlace ? " interlaced" : "" );
#endif

	 if (interlace) {
		int     i;
		int     pass = 0, step = 8;

		for (i = 0; i < height; i++) {
			if (ypos < height)
			{
				dp = &image[len * ypos];
				for (xpos = 0; xpos < len; xpos++) {
					if ((v = readLWZ(fd)) < 0)
						goto fini;

					*dp++ = v;
				}
			}
			if ((ypos += step) >= height) {
				if (pass++ > 0)
					step /= 2;
				ypos = step / 2;
			}
		}
	} else {
		dp = image;
		for (ypos = 0; ypos < height; ypos++) {
			for (xpos = 0; xpos < len; xpos++) {
				if ((v = readLWZ(fd)) < 0)
					goto fini;

				*dp++ = v;
			}
		}
	}

fini:
	if (readLWZ(fd)>=0)
	{
#if 0
		INFO_MSG(("too much input data, ignoring extra..."));
#endif
	}

	return(image);
}


/* 
 * ******* end required file <gifread.inc> *******
 */
/* 
 * ******* begin required file <xpmread.inc> *******
 */
#include <xpm.h>

#ifndef _XtIntrinsic_h
# include <xpmP.h>
#else
# define TRANSPARENT_COLOR "None" /* this must be a string! */
# define NKEYS 5
#endif

unsigned char *ReadXpm3Pixmap(view,fp, filename, w, h, colrs, bg)
Widget view;
FILE *fp;
char *filename;
int *w, *h;
XColor *colrs;
int *bg;
{
	XpmAttributes attributes;
	XpmInfo info;
	XpmImage image;
	int ErrorStatus;
	XColor tmpcolr;
	int i, size;
	char *colorName;
	unsigned char *pix_data;
	unsigned char *bptr;
	unsigned int *pixels;
        /*extern Widget view;*/

	attributes.valuemask = XpmReturnPixels | XpmColorTable;

	ErrorStatus = XpmReadFileToXpmImage(filename, &image, &info);
	if (ErrorStatus != XpmSuccess)
	{
	        *w = 0;
	        *h = 0;
		return(NULL);
	}

	*w = (int)image.width;
	*h = (int)image.height;
	size = (*w) * (*h);

	for (i=0; i<image.ncolors; i++)
	{
		colorName = image.colorTable[i].c_color;
		/*
		fprintf(stderr,
			"colorstring=<%s> string=<%s> c_color=<%s>\n",
			image.colorTable[i].symbolic,
			image.colorTable[i].string,
			image.colorTable[i].c_color
			);
		*/
		if (strcmp(colorName, TRANSPARENT_COLOR) == 0)
		{
			unsigned long bg_pixel;

			/* First, go fetch the background pixel. */
			XtVaGetValues (view, XtNbackground, &bg_pixel, NULL);

			/* Now, load up tmpcolr. */
			tmpcolr.pixel = bg_pixel;

			/* Now query for the full color info. */
			XQueryColor (XtDisplay (view), 
				DefaultColormap (XtDisplay (view),
				DefaultScreen (XtDisplay (view))),
			       &tmpcolr);
			*bg = i;
		}
		else
		{
		  Display *dsp = XtDisplay(view);
			XParseColor(dsp,
				DefaultColormap(dsp, DefaultScreen(dsp)),
				colorName, &tmpcolr);
		}
		colrs[i].red = tmpcolr.red;
		colrs[i].green = tmpcolr.green;
		colrs[i].blue = tmpcolr.blue;
		colrs[i].pixel = i;
		colrs[i].flags = DoRed|DoGreen|DoBlue;
	}
	for (i=image.ncolors; i<256; i++)
	{
		colrs[i].red = 0;
		colrs[i].green = 0;
		colrs[i].blue = 0;
		colrs[i].pixel = i;
		colrs[i].flags = DoRed|DoGreen|DoBlue;
	}

	pixels = image.data;
	pix_data = (unsigned char *)malloc(size);
        if (pix_data == NULL)
        {
                fprintf(stderr, "Not enough memory for data.\n");
		XpmFreeXpmImage(&image);
		XpmFreeXpmInfo(&info);
                return((unsigned char *)NULL);
        }
	bptr = pix_data;
        for (i=0; i<size; i++)
        {
		int pix;
 
		pix = (int)*pixels;
                if (pix > (256 - 1))
                        pix = 0;
		*bptr++ = (unsigned char)pix;
                pixels++;
        }
	XpmFreeXpmImage(&image);
	XpmFreeXpmInfo(&info);

        return(pix_data);
}

#ifdef MOSAIC
#ifndef _XtIntrinsic_h
#include <xpmP.h>
#else
typedef struct {
    unsigned int type;
    union {
        FILE *file;
        char **data;
    }     stream;
    char *cptr;
    unsigned int line;
    int CommentLength;
    char Comment[BUFSIZ];
    char *Bcmt, *Ecmt, Bos, Eos;
    int format;                 /* 1 if XPM1, 0 otherwise */
}      xpmData;
#endif

unsigned char *ProcessXpm3Data(wid, xpmdata, w, h, colrs, bg)
Widget wid;
char **xpmdata;
int *w, *h;
XColor *colrs;
int *bg;
{
	xpmData mdata;
	XpmAttributes attributes;
	int ErrorStatus;
	XColor tmpcolr;
	int i, size;
	char *colorName;
	unsigned char *pix_data;
	unsigned char *bptr;
	unsigned int *pixels;
	XpmImage image;
	XpmInfo info;

	attributes.valuemask = XpmReturnPixels | XpmColorTable;

	xpmOpenArray(xpmdata, &mdata);
	xpmInitXpmImage(&image);
	xpmInitXpmInfo(&info);

	ErrorStatus = xpmParseData(&mdata, &image, &info);
	if (ErrorStatus != XpmSuccess)
	{
	        *w = 0;
	        *h = 0;
		XpmFreeXpmImage(&image);
		XpmFreeXpmInfo(&info);
		xpmDataClose(&mdata);
		return(NULL);
	}

	*w = (int)image.width;
	*h = (int)image.height;
	size = (*w) * (*h);

	for (i=0; i<image.ncolors; i++)
	{
		colorName = image.colorTable[i].c_color;
		if (strcmp(colorName, TRANSPARENT_COLOR) == 0)
		{
			unsigned long bg_pixel;

			/* First, go fetch the pixel. */
			XtVaGetValues (wid, XtNbackground, &bg_pixel, NULL);

			/* Now, load up tmpcolr. */
			tmpcolr.pixel = bg_pixel;

			/* Now query for the full color info. */
			XQueryColor (XtDisplay (wid), 
				DefaultColormap (XtDisplay (wid),
				DefaultScreen (XtDisplay (wid))),
			       &tmpcolr);
			*bg = i;
		}
		else
		{
			XParseColor(XtDisplay (wid),
				DefaultColormap(XtDisplay (wid),
				DefaultScreen(XtDisplay (wid))),
				colorName, &tmpcolr);
		}
		colrs[i].red = tmpcolr.red;
		colrs[i].green = tmpcolr.green;
		colrs[i].blue = tmpcolr.blue;
		colrs[i].pixel = i;
		colrs[i].flags = DoRed|DoGreen|DoBlue;
	}
	for (i=image.ncolors; i<256; i++)
	{
		colrs[i].red = 0;
		colrs[i].green = 0;
		colrs[i].blue = 0;
		colrs[i].pixel = i;
		colrs[i].flags = DoRed|DoGreen|DoBlue;
	}

	pixels = image.data;
	pix_data = (unsigned char *)malloc(size);
        if (pix_data == NULL)
        {
                fprintf(stderr, "Not enough memory for data.\n");
		XpmFreeXpmImage(&image);
		XpmFreeXpmInfo(&info);
		xpmDataClose(&mdata);
                return((unsigned char *)NULL);
        }
	bptr = pix_data;
        for (i=0; i<size; i++)
        {
		int pix;

		pix = (int)*pixels;
                if (pix > (256 - 1))
                        pix = 0;
		*bptr++ = (unsigned char)pix;
                pixels++;
        }

	XpmFreeXpmImage(&image);
	XpmFreeXpmInfo(&info);
	xpmDataClose(&mdata);

#ifdef TIMING
X_GETTIMEOFDAY(&Tv);
fprintf(stderr, "ReadXpm3Pixmap exit (%d.%d)\n", Tv.tv_sec, Tv.tv_usec);
#endif
        return(pix_data);
}

#endif


/* 
 * ******* end required file <xpmread.inc> *******
 */
 XrmQuark qimageList;
/* 
 * ******* begin required file <html.inc> *******
 */
/* make emcas happy -*-C-*-  make emacs happy */
#undef IMAGECACHETRACE
/* 
   Copyright for the image resolving functions as well as for all of
   the html widget is the following (With kind permission of Mark
   Andreessen from the NCSA). We use the contents of img.c and picread.c:
 */

/****************************************************************************
 * NCSA Mosaic for the X Window System                                      *
 * Software Development Group                                               *
 * National Center for Supercomputing Applications                          *
 * University of Illinois at Urbana-Champaign                               *
 * 605 E. Springfield, Champaign IL 61820                                   *
 * mosaic@ncsa.uiuc.edu                                                     *
 *                                                                          *
 * Copyright (C) 1993, Board of Trustees of the University of Illinois      *
 *                                                                          *
 * NCSA Mosaic software, both binary and source (hereafter, Software) is    *
 * copyrighted by The Board of Trustees of the University of Illinois       *
 * (UI), and ownership remains with the UI.                                 *
 *                                                                          *
 * The UI grants you (hereafter, Licensee) a license to use the Software    *
 * for academic, research and internal business purposes only, without a    *
 * fee.  Licensee may distribute the binary and source code (if released)   *
 * to third parties provided that the copyright notice and this statement   *
 * appears on all copies and that no charge is associated with such         *
 * copies.                                                                  *
 *                                                                          *
 * Licensee may make derivative works.  However, if Licensee distributes    *
 * any derivative work based on or derived from the Software, then          *
 * Licensee will (1) notify NCSA regarding its distribution of the          *
 * derivative work, and (2) clearly notify users that such derivative       *
 * work is a modified version and not the original NCSA Mosaic              *
 * distributed by the UI.                                                   *
 *                                                                          *
 * Any Licensee wishing to make commercial use of the Software should       *
 * contact the UI, c/o NCSA, to negotiate an appropriate license for such   *
 * commercial use.  Commercial use includes (1) integration of all or       *
 * part of the source code into a product for sale or license by or on      *
 * behalf of Licensee to third parties, or (2) distribution of the binary   *
 * code or source code to third parties that need it to utilize a           *
 * commercial product sold or licensed by or on behalf of Licensee.         *
 *                                                                          *
 * UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR   *
 * ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED          *
 * WARRANTY.  THE UI SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY THE    *
 * USERS OF THIS SOFTWARE.                                                  *
 *                                                                          *
 * By using or copying this Software, Licensee agrees to abide by the       *
 * copyright law and all other applicable laws of the U.S. including, but   *
 * not limited to, export control laws, and the terms of this license.      *
 * UI shall have the right to terminate this license immediately by         *
 * written notice upon Licensee's breach of, or non-compliance with, any    *
 * of its terms.  Licensee may be held legally responsible for any          *
 * copyright infringement that is caused or encouraged by Licensee's        *
 * failure to abide by the terms of this license.                           *
 *                                                                          *
 * Comments and questions are welcome and can be sent to                    *
 * mosaic-x@ncsa.uiuc.edu.                                                  *
 ****************************************************************************/

#define HIGHWATERIMAGESIZE 300000

#include <values.h>
#include <HTMLP.h>
#include <ctype.h>

typedef struct ele_rec  HTMLElementRecord;

#define DEF_BLACK       BlackPixel(dsp, DefaultScreen(dsp))
#define DEF_WHITE       WhitePixel(dsp, DefaultScreen(dsp))
/*#define	MAX_LINE	81*/
#define	MAX_LINE	256
#define NO_VISUAL       200


unsigned long fg_pixel, bg_pixel;
XColor fg_color, bg_color;

char nibMask[8] = {
	1, 2, 4, 8, 16, 32, 64, 128
};


/* Caching Mechanism is a must, since Conversion Procedure is called
   for each resize (and we use opaqueResize ....)
   
 */

typedef struct _imgDataRec
    {
    XrmQuark              qFilename;
    int                   count;
    ImageInfo             *imgData;    
    long                  size;
    struct _imgDataRec    *next;
    } imgDataRec, *imgDataRecPtr;

typedef struct _htmlImgCache 
    {
    imgDataRecPtr         dataRec;
    struct _htmlImgCache  *next;
    } htmlImgCacheStruct, *htmlImgCachePtr;

imgDataRecPtr     imgList  = NULL;



#ifdef IMAGECACHETRACE
void
printWidgetInfo(text,w,ptr)
char   *text;
Widget w;
htmlImgCachePtr ptr;
    {
    fprintf(stderr, "----%s(%p)--%s--WidgetInfo Ptr: %p------------\n", 
	    XtName(w), w, text, ptr);
    
    while(ptr)
	{
	fprintf(stderr, "   Data %p contains filename %s, count %d (next %p)\n",
		ptr, XrmQuarkToString(ptr->dataRec->qFilename),
		ptr->dataRec->count, ptr->next);
	ptr=ptr->next;
	}
    }

void
printCacheInfo(text)
char *text;
    {
    imgDataRecPtr ptr = imgList;
    
    fprintf(stderr, "****%s*****CacheInfo ImgList: %p------------\n", text, ptr);

    while(ptr)
	{
	fprintf(stderr, "   Data %p contains filename %s, count %d (next %p)\n",
		ptr, XrmQuarkToString(ptr->qFilename),
		ptr->count, ptr->next);
	ptr=ptr->next;
	}
    }
#endif


/* Add imgData to global list and return address.
 * Does NOT check wether imgData is allready in the list 
 */

static imgDataRecPtr 
htmlAddImgData(qFilename, imgData)
XrmQuark   qFilename;
ImageInfo  *imgData;
    {
    imgDataRecPtr    ptr;

    DBUG_ENTER("htmlAddImgData");

    ptr = (imgDataRecPtr)XtMalloc(sizeof(imgDataRec));
    ptr->next = imgList;
    ptr->qFilename = qFilename;
    ptr->count = 0;
    ptr->imgData = imgData;
    ptr->size = imgData->num_colors * 3 * sizeof(int) + 
	        imgData->width * imgData->height;
    imgList = ptr;

#ifdef IMAGECACHETRACE
    printCacheInfo("Nach AddImgData");
#endif
    DBUG_RETURN(ptr);
    } 


/* actually free colors and image data */

static void
free_image_data (img)
ImageInfo *img;
    {
    if (!img)
	return;

    if (img->reds)
      {
	free (img->reds);
	img->reds = NULL;
      }
    if (img->greens)
      {
	free (img->greens);
	img->greens = NULL;
      }
    if (img->blues)
      {
	free (img->blues);
	img->blues = NULL;
      }
    if (img->image_data)
      {
	free (img->image_data);
	img->image_data = NULL;
      }

    return;
    }


/* 
 * Search all available imgData Structures for
 * matching entry, return NULL if not found, the data 
 * structure otherwise.
 */



static imgDataRecPtr
htmlLocateImgInfo(qFilename)
XrmQuark   qFilename;
    {
    imgDataRecPtr    ptr, *reference;
    long             memUsed;

    DBUG_ENTER("htmlLocateImgInfo");

#ifdef IMAGECACHETRACE
    printCacheInfo("Vor Locate");
    fprintf(stderr,"   looking for %s\n",XrmQuarkToString(qFilename));
#endif

    for (ptr = imgList, memUsed = 0; 
	 ((ptr != NULL) && (ptr->qFilename != qFilename));
	 ptr = ptr->next)
	memUsed += ptr->size;

    if (ptr)
	DBUG_RETURN(ptr);

    /* fprintf(stderr,"memused=%ld\n",memUsed); */

    if (memUsed > HIGHWATERIMAGESIZE)
	{
	for (reference = &imgList, ptr = imgList; 
	     ptr != NULL; 
	     reference = &ptr)
	    {
	    if (ptr->count == 0)
		{
		/*
		fprintf(stderr,"freeing ptr=%p, name=%s, count=%d\n",
			ptr,XrmQuarkToString(ptr->qFilename),ptr->count);
		*/

		free_image_data(ptr->imgData);
		memUsed -= ptr->size;

		*reference = ptr->next;
		XtFree((char*)ptr);
		/* fprintf(stderr,"after XtFree, memUsed=%d\n",memUsed); */
		ptr = *reference;
		}
	    else
		ptr = ptr->next;
	    }
	}
#ifdef IMAGECACHETRACE
    printCacheInfo("Nach Loesch");
#endif
    DBUG_RETURN(NULL);
    }

/* This function is called by the MM* routines and frees 
 * the reference list of a widget. The imageInfo is NOT freed, we'll
 * only decrement the counter;
 */

void
wafeHTMLfreeImageData(ptr)
char *ptr;
    {
    htmlImgCachePtr iPtr = (htmlImgCachePtr) ptr;
    htmlImgCachePtr nextPtr;

    DBUG_ENTER("wafeHTMLfreeImageData");

    while (iPtr != NULL)
	{
	nextPtr = iPtr->next;
	iPtr->dataRec->count--;
	XtFree((char *)iPtr);
	iPtr = nextPtr;
	}
    DBUG_VOID_RETURN;
    }




/*
 * Add a new ref to a widget's image-list if not yet there
 */

static void
htmlAddRefToWidget(w, qFilename, dataPtr)
Widget          w;
XrmQuark        qFilename;
imgDataRecPtr   dataPtr;
    {
    MMattribListPtr     *al = wafeMMgetAttribList(w,True);
    htmlImgCachePtr     imgCachePtr = (htmlImgCachePtr)wafeMMgetValue(al, qimageList);
    htmlImgCachePtr     iPtr;
    
    DBUG_ENTER("htmlAddRefToWidgetCache");

#ifdef IMAGECACHETRACE    
    printWidgetInfo("Beginn:", w, imgCachePtr);
#endif

    if (!imgCachePtr) 
	{  /* First image ref for this widget */
	imgCachePtr = (htmlImgCachePtr) XtMalloc(sizeof(htmlImgCacheStruct));
	imgCachePtr->next = NULL;
	dataPtr->count++;
/*
 	fprintf(stderr, "Ptr: %p; Incrementing count for %s to %d\n",
		imgCachePtr,
		XrmQuarkToString(qFilename), dataPtr->count);
*/
	imgCachePtr->dataRec = dataPtr;
	wafeMMreplace(al, qimageList, (char *) imgCachePtr, wafeHTMLfreeImageData);
	}
    else
	{ /* scan existing image refs */

	for (iPtr = imgCachePtr;
	     ((iPtr->next != NULL) && (iPtr->dataRec->qFilename != qFilename));
	     iPtr = iPtr->next);
	
	if (iPtr->dataRec->qFilename != qFilename)
	    { /* first display of this image for widget: add image ref */
	    iPtr->next = (htmlImgCachePtr) XtMalloc(sizeof(htmlImgCacheStruct));
	    iPtr = iPtr->next;
	    dataPtr->count++;
/*
	    fprintf(stderr, "New href: Incrementing count for %s to %d\n", 
		    XrmQuarkToString(qFilename), dataPtr->count);
*/

	    iPtr->dataRec = dataPtr;
	    iPtr->next = NULL;
	    }
	}

#ifdef IMAGECACHETRACE    
    printWidgetInfo("End: ", w, imgCachePtr);
#endif
    
    DBUG_VOID_RETURN;
    }
    

/* this function is essentially from NCSA Mosaic */

static unsigned char *
ReadXpmPixmap(view, fp, datafile, w, h, colrs, Colors, CharsPP)
Widget view;
FILE *fp;
char *datafile;
int *w, *h;
XColor *colrs;
int Colors, CharsPP;
{
	unsigned char *pixels;
	char **Color_Vals;
	XColor tmpcolr;
	int i, j, k;
	int found;
	char line[BUFSIZ], name_and_type[MAX_LINE];
	unsigned char *dataP;
	unsigned char *bitp;
	int tchar;
	char *t;
	char *t2;
	Display *dsp = XtDisplay(view);

	if (Colors == 0)
	{
		/* fprintf(stderr, "Can't find Colors.\n"); */
		return((unsigned char *)NULL);
	}
	if (*w == 0)
	{
		/* fprintf(stderr, "Can't read image.\n"); */
		return((unsigned char *)NULL);
	}
	if (*h == 0)
	{
		/* fprintf(stderr, "Can't read image.\n"); */
		return((unsigned char *)NULL);
	}

	Color_Vals = (char **)XtMalloc(sizeof(char *) * Colors);
	for (i=0; i<Colors; i++)
	{
		tchar = getc(fp);
		while ((tchar != '"')&&(tchar != EOF))
		{
			tchar = getc(fp);
		}
		Color_Vals[i] = (char *)XtMalloc(sizeof(char) * (CharsPP + 1));
		j = 0;
		tchar = getc(fp);
		while ((tchar != '"')&&(tchar != EOF)&&(j < CharsPP))
		{
			Color_Vals[i][j] = (char)tchar;
			tchar = getc(fp);
			j++;
		}
		Color_Vals[i][j] = '\0';
		if (tchar != '"')
		{
			tchar = getc(fp);
			while ((tchar != '"')&&(tchar != EOF))
			{
				tchar = getc(fp);
			}
		}
		tchar = getc(fp);
		while ((tchar != '"')&&(tchar != EOF))
		{
			tchar = getc(fp);
		}
		j = 0;
		tchar = getc(fp);
		while ((tchar != '"')&&(tchar != EOF))
		{
			line[j] = (char)tchar;
			tchar = getc(fp);
			j++;
		}
		line[j] = '\0';
		XParseColor(dsp, DefaultColormap(dsp, DefaultScreen(dsp)),
			line, &tmpcolr);
		colrs[i].red = tmpcolr.red;
		colrs[i].green = tmpcolr.green;
		colrs[i].blue = tmpcolr.blue;
		colrs[i].pixel = i;
		colrs[i].flags = DoRed|DoGreen|DoBlue;
	}
	for (i=Colors; i<256; i++)
	{
		colrs[i].red = 0;
		colrs[i].green = 0;
		colrs[i].blue = 0;
		colrs[i].pixel = i;
		colrs[i].flags = DoRed|DoGreen|DoBlue;
	}
	tchar = getc(fp);
	while ((tchar != ';')&&(tchar != EOF))
	{
		tchar = getc(fp);
	}

	for ( ; ; )
	{
		if (!(fgets(line, MAX_LINE, fp)))
		{
			fprintf(stderr, "Can't find Pixels\n");
			return((unsigned char *)NULL);
		}
		else if (sscanf(line,"static char * %s = {",name_and_type) == 1)
		{
			if ((t = strrchr(name_and_type, '_')) == NULL)
			{
				t = name_and_type;
			}
			else
			{
				t++;
			}
			if ((t2 = strchr(name_and_type, '[')) != NULL)
			{
				*t2 = '\0';
			}
			if (!strcmp("pixels", t))
			{
				break;
			}
		}
	}
	pixels = (unsigned char *)XtMalloc((*w) * (*h));
	if (pixels == NULL)
	{
		fprintf(stderr, "Not enough memory for data.\n");
		return((unsigned char *)NULL);
	}

	line[0] = '\0';
	t = line;
	dataP = pixels;
	tchar = getc(fp);
	while ((tchar != '"')&&(tchar != EOF))
	{
		tchar = getc(fp);
	}
	tchar = getc(fp);
	for (j=0; j<(*h); j++)
	{
		for (i=0; i<(*w); i++)
		{
			k = 0;
			while ((tchar != '"')&&(tchar != EOF)&&(k < CharsPP))
			{
				line[k] = (char)tchar;
				tchar = getc(fp);
				k++;
			}
			if ((k == 0)&&(tchar == '"'))
			{
				tchar = getc(fp);
				while ((tchar != '"')&&(tchar != EOF))
				{
					tchar = getc(fp);
				}
				k = 0;
				tchar = getc(fp);
				while ((tchar != '"')&&(tchar != EOF)&&
					(k < CharsPP))
				{
					line[k] = (char)tchar;
					tchar = getc(fp);
					k++;
				}
			}
			line[k] = '\0';
			found = 0;
			for (k=0; k<Colors; k++)
			{
				if (strncmp(Color_Vals[k], line, CharsPP) == 0)
				{
					*dataP++ = (unsigned char)k;
					found = 1;
					break;
				}
			}
			if (found == 0)
			{
				fprintf(stderr, "Invalid Pixel (%2s) in file %s\n", line, datafile);
				*dataP++ = (unsigned char)0;
			}
		}
	}

	bitp = pixels;
	for (i=0; i<((*w) * (*h)); i++)
	{
		if ((int)*bitp > (256 - 1))
			*bitp = (unsigned char)0;
		bitp++;
	}

	for (i=0; i<Colors; i++)
	{
		XtFree((char *)Color_Vals[i]);
	}
	XtFree((char *)Color_Vals);
	return(pixels);
}

/* This function is essentially from NCSA Mosaic */

static unsigned char *
ReadXbmBitmap(view, fp, datafile, w, h, colrs)
Widget view;
FILE *fp;
char *datafile;
int *w, *h;
XColor *colrs;
{
	char line[MAX_LINE], name_and_type[MAX_LINE];
	char *t;
	char *t2;
	unsigned char *ptr, *dataP;
	int bytes_per_line, version10p, raster_length, padding;
	int i, bytes, temp, value;
	int Ncolors, charspp, xpmformat;
        static unsigned long fg_pixel, bg_pixel;
        static int done_fetch_colors = 0;
        extern XColor fg_color, bg_color;
	int blackbit;
	int whitebit;

        if (!done_fetch_colors)
	    {
             /* First, go fetch the pixels. */
#ifndef MOTIF11	    
	    XtVaGetValues (view, 
			   XtNforeground, &fg_pixel,
			   XtNbackground, &bg_pixel, 
			   NULL);
#else
	    XtVaGetValues (view, 
			   XtNbackground, &bg_pixel, 
			   NULL);
	    XtVaGetValues (XtParent(view),
			   XtNforeground, &fg_pixel,
			   NULL);
#endif
             
	    /* Now, load up fg_color and bg_color. */
	    fg_color.pixel = fg_pixel;
	    bg_color.pixel = bg_pixel;
	    
	    /* Now query for the full color info. */
	    XQueryColor(XtDisplay (view), 
			DefaultColormap (XtDisplay (view),
					 DefaultScreen (XtDisplay (view))),
			&fg_color);
             XQueryColor(XtDisplay (view), 
			 DefaultColormap (XtDisplay (view),
					  DefaultScreen (XtDisplay (view))),
			 &bg_color);
 
	    done_fetch_colors = 1;

#ifdef MORETHAN256COLORS
            /*
             * For a TrueColor visual, we can't use the pixel value as
             * the color index because it is > 255.  Arbitrarily assign
             * 0 to foreground, and 1 to background.
             */
            if ((Vclass == TrueColor) ||(Vclass == DirectColor))
		{
                fg_color.pixel = 0;
		bg_color.pixel = 1;
                }
#endif
	    }

 /*
	if (Rdata.reverse_inlined_bitmap_colors)
	    {
	    blackbit = bg_color.pixel;
	    whitebit = fg_color.pixel;
	    }
	else
*/
	    {
	    blackbit = fg_color.pixel;
	    whitebit = bg_color.pixel;
	    }

	/*
	 * Error out here on visuals we can't handle so we won't core dump
	 * later.
	
	if (((blackbit > 255)||(whitebit > 255))&&(Vclass != TrueColor))
	  {
		fprintf(stderr, "Error:  cannot deal with default colormap that is deeper than 8, and not TrueColor\n");
                fprintf(stderr, "        If you actually have such a system, please notify mosaic-x@ncsa.uiuc.edu.\n");
                fprintf(stderr, "        We thank you for your support.\n");
		exit(1);
	  }
*/
/*        if (Rdata.reverse_inlined_bitmap_colors)
          {
            colrs[blackbit].red = bg_color.red;
            colrs[blackbit].green = bg_color.green;
            colrs[blackbit].blue = bg_color.blue;
            colrs[blackbit].pixel = bg_color.pixel;
            colrs[blackbit].flags = DoRed|DoGreen|DoBlue;
            
            colrs[whitebit].red = fg_color.red;
            colrs[whitebit].green = fg_color.green;
            colrs[whitebit].blue = fg_color.blue;
            colrs[whitebit].pixel = fg_color.pixel;
            colrs[whitebit].flags = DoRed|DoGreen|DoBlue;
          }
        else
          { */
            colrs[blackbit].red = fg_color.red;
            colrs[blackbit].green = fg_color.green;
            colrs[blackbit].blue = fg_color.blue;
            colrs[blackbit].pixel = fg_color.pixel;
            colrs[blackbit].flags = DoRed|DoGreen|DoBlue;
            
            colrs[whitebit].red = bg_color.red;
            colrs[whitebit].green = bg_color.green;
            colrs[whitebit].blue = bg_color.blue;
            colrs[whitebit].pixel = bg_color.pixel;
            colrs[whitebit].flags = DoRed|DoGreen|DoBlue;

	*w = 0;
	*h = 0;
	Ncolors = 0;
	charspp = 0;
	xpmformat = 0;
	for ( ; ; )
	{
		if (!(fgets(line, MAX_LINE, fp)))
			break;
		if (strlen(line) == (MAX_LINE - 1))
		{
#ifdef DEBUG
			fprintf(stderr, "Line too long.\n");
#endif
			return((unsigned char *)NULL);
		}
		if (sscanf(line, "#define %s %d", name_and_type, &value) == 2)
		{
			if (!(t = strrchr(name_and_type, '_')))
				t = name_and_type;
			else
				t++;
			if (!strcmp("width", t))
				*w= value;
			if (!strcmp("height", t))
				*h= value;
			if (!strcmp("ncolors", t))
				Ncolors = value;
			if (!strcmp("pixel", t))
				charspp = value;
			continue;
		}
		if (sscanf(line, "static short %s = {", name_and_type) == 1)
		{
			version10p = 1;
			break;
		}
		else if 
		  (sscanf(line,"static char * %s = {",name_and_type) == 1 || 
		   sscanf(line,"static unsigned char * %s = {",name_and_type) == 1 )
		{
			xpmformat = 1;
			if (!(t = strrchr(name_and_type, '_')))
				t = name_and_type;
			else
				t++;
			if ((t2 = strchr(name_and_type, '[')) != NULL)
				*t2 = '\0';
			if (!strcmp("mono", t))
				continue;
			else
				break;
		}
		else if 
		  (sscanf(line, "static char %s = {", name_and_type) == 1 ||
		   sscanf(line, "static unsigned char %s = {", name_and_type) == 1)
		{
			version10p = 0;
			break;
		}
		else
			continue;
	}
	if (xpmformat)
	{
		dataP = ReadXpmPixmap(view, fp, datafile, w, h, colrs, Ncolors, charspp);
		return(dataP);
	}
	if (*w == 0)
	{
		/* fprintf(stderr, "Can't read image.\n"); */
		return((unsigned char *)NULL);
	}
	if (*h == 0)
	{
		/* fprintf(stderr, "Can't read image.\n"); */
		return((unsigned char *)NULL);
	}
	padding = 0;
	if (((*w % 16) >= 1)&&((*w % 16) <= 8)&&version10p)
	{
		padding = 1;
	}
	bytes_per_line = ((*w + 7) / 8) + padding;
	raster_length =  bytes_per_line * *h;
	dataP = (unsigned char *)XtMalloc((*w) * (*h));
	if (dataP == NULL)
	{
		fprintf(stderr, "Not enough memory.\n");
		return((unsigned char *)NULL);
	}
	ptr = dataP;
	if (version10p)
	{
		int cnt = 0;
		int lim = (bytes_per_line - padding) * 8;
		for (bytes = 0; bytes < raster_length; bytes += 2)
		{
			if (fscanf(fp, " 0x%x%*[,}]%*[ \r\n]", &value) != 1)
			{
				fprintf(stderr, "Error scanning bits item.\n");
				return((unsigned char *)NULL);
			}
			temp = value;
			value = temp & 0xff;
			for (i = 0; i < 8; i++)
			{
				if (cnt < (*w))
				{
					if (value & nibMask[i])
						*ptr++ = blackbit;
					else
						*ptr++ = whitebit;
				}
				if (++cnt >= lim)
					cnt = 0;
			}
			if ((!padding)||((bytes+2) % bytes_per_line))
			{
				value = temp >> 8;
				for (i = 0; i < 8; i++)
				{
					if (cnt < (*w))
					{
						if (value & nibMask[i])
							*ptr++ = blackbit;
						else
							*ptr++ = whitebit;
					}
					if (++cnt >= lim)
						cnt = 0;
				}
			}
		}
	}
	else
	{
		int cnt = 0;
		int lim = bytes_per_line * 8;
		for (bytes = 0; bytes < raster_length; bytes++)
		{
			if (fscanf(fp, " 0x%x%*[,}]%*[ \r\n]", &value) != 1)
			{
				fprintf(stderr, "Error scanning bits item.\n");
				return((unsigned char *)NULL);
			}
			for (i = 0; i < 8; i++)
			{
				if (cnt < (*w))
				{
					if (value & nibMask[i])
						*ptr++ = blackbit;
					else
						*ptr++ = whitebit;
				}
				if (++cnt >= lim)
					cnt = 0;
			}
		}
	}
	return(dataP);
}

static unsigned char *
ReadBitmap(html, datafile, w, h, colrs, bg)
Widget html;
char *datafile;
int *w, *h;
XColor *colrs;
int *bg;
{
	unsigned char *bit_data;
	FILE *fp;

	*bg = -1;

        fp = fopen(datafile, "r");
	if (fp != NULL)
	{
	/* First, go fetch foreground and background colors */
	XtVaGetValues (html, XtNforeground, &fg_pixel,
		       XtNbackground, &bg_pixel, NULL);

	/* Now, load up fg_color and bg_color. */
	fg_color.pixel = fg_pixel;
	bg_color.pixel = bg_pixel;
            
	/* Now query for the full color info. */
	XQueryColor 
	    (XtDisplay (html), 
	     DefaultColormap (XtDisplay (html),
			      DefaultScreen (XtDisplay (html))),
	                      &fg_color);

	XQueryColor 
	    (XtDisplay (html), 
	     DefaultColormap (XtDisplay (html),
			      DefaultScreen (XtDisplay (html))),
	                      &bg_color);

	bit_data = ReadGIF(fp, w, h, colrs);
	if (bit_data != NULL)
	    {
	    if (fp != stdin) fclose(fp);
	    return(bit_data);
	    }
	rewind(fp);

	bit_data = ReadXbmBitmap(html,fp, datafile, w, h, colrs);
	if (bit_data != NULL)
	    {
	    if (fp != stdin) fclose(fp);
	    return(bit_data);
	    }
	rewind(fp);
	
	bit_data = ReadXpm3Pixmap(html,fp, datafile, w, h, colrs, bg);
	if (bit_data != NULL)
	    {
	    if (fp != stdin) fclose(fp);
	    return(bit_data);
	    }
	}
	if (fp != stdin) fclose(fp);
	return((unsigned char *)NULL);
}

/* Image resolution function. in wide parts from NCSA Mosaic, cache is ours */
static ImageInfo *
Resolve (w, src, noload)
Widget w;
char *src;
int noload;
{
  int i, cnt;
  unsigned char *data;
  unsigned char *bg_map;
  unsigned char *bgptr;
  unsigned char *ptr;
  int width, height;
  int widthbyheight = 0;
  int Used[256];
  XColor colrs[256];
  ImageInfo *img_data;
  int bg, bg_red, bg_green, bg_blue;
#ifdef MORETHAN256COLORS
  extern int Vclass;
#endif
  XrmQuark   qFilename;
  char    *origSrc = src;
  imgDataRecPtr  dataPtr;

  DBUG_ENTER("Resolve");

  if (!src)
    DBUG_RETURN(NULL);

  /*
   * If we allready have this imgInfo in cache => just update the widget's 
   * image list and increment the reference counter....
   */ 

  qFilename = XrmStringToQuark(src);
  if ((dataPtr = htmlLocateImgInfo(qFilename)) != NULL)
	{
	htmlAddRefToWidget(w, qFilename, dataPtr);
	DBUG_RETURN(dataPtr->imgData);
	}

  DBUG_PRINT("html", ("img source=<%s>, filesearchpath=<%s>", 
		      origSrc,wafeFileSearchPath));
  src = XtResolvePathname(XtDisplay(w), "bitmaps", origSrc, "", 
			  wafeFileSearchPath, NULL, 0, NULL);

  if (src == NULL)
        DBUG_RETURN(NULL);

  DBUG_PRINT("html", ("img resolved: <%s>", src));

  /* If we don't have the image cached and noload is high,
     then just return NULL to avoid doing a network load. */
  /* Also return if interrupted is high. */
  if (noload /*|| interrupted*/)
    {
      XtFree (src);
      DBUG_RETURN(NULL);
    }

  /*
   * No transparent background by default
   */
  bg = -1;
  bg_map = NULL;
    {
      /* We have to load the image. */
      
      data = ReadBitmap(w, src, &width, &height, colrs, &bg);
      XtFree (src);
      /* if we have a transparent background, prepare for it */
      if ((bg >= 0)&&(data != NULL))
      {
        bg_red = colrs[bg].red;
        bg_green = colrs[bg].green;
        bg_blue = colrs[bg].blue;
        bg_map = (unsigned char *)malloc(width * height);
      }
      
      if (data == NULL)
            DBUG_RETURN(NULL);
      
      img_data = (ImageInfo *)malloc(sizeof(ImageInfo));
      img_data->width = width;
      img_data->height = height;
      img_data->image_data = data;
      img_data->image = (Pixmap)NULL;
      /* Bandaid for bug afflicting Eric's code, apparently. */
      img_data->internal = 0;
    }

  widthbyheight = img_data->width * img_data->height;

  /* Fill out used array. */
  for (i=0; i < 256; i++)
    {
      Used[i] = 0;
    }
  cnt = 1;
  bgptr = bg_map;
  ptr = img_data->image_data;
  for (i=0; i < widthbyheight; i++)
    {
      if (Used[(int)*ptr] == 0)
        {
          Used[(int)*ptr] = cnt;
          cnt++;
        }
      if (bg >= 0)
        {
                if (*ptr == bg)
                {
                        *bgptr = (unsigned char)1;
                }
                else
                {
                        *bgptr = (unsigned char)0;
                }
                bgptr++;
        }
      ptr++;
    }
  cnt--;
#ifdef MORETHAN256COLORS  
  /*
   * If the image has too many colors, apply a median cut algorithm to
   * reduce the color usage, and then reprocess it.
   * Don't cut colors for direct mapped visuals like TrueColor.
   */
  if ((cnt > Rdata.colors_per_inlined_image)&&(Vclass != TrueColor))
    {
      MedianCut(img_data->image_data, &img_data->width, 
                &img_data->height, colrs, cnt, 
                Rdata.colors_per_inlined_image);
      
      for (i=0; i < 256; i++)
        Used[i] = 0;
      cnt = 1;
      ptr = img_data->image_data;
      for (i=0; i < widthbyheight; i++)
        {
          if (Used[(int)*ptr] == 0)
            {
              Used[(int)*ptr] = cnt;
              cnt++;
            }
          ptr++;
        }
      cnt--;

      /* if we had a transparent bg, MedianCut used it.  Get a new one */
      if (bg >= 0)
      {
        cnt++;
        bg = 256;
      }
    }
#endif

  img_data->num_colors = cnt;
    {
      img_data->reds = (int *)malloc(sizeof(int) * cnt);
      img_data->greens = (int *)malloc(sizeof(int) * cnt);
      img_data->blues = (int *)malloc(sizeof(int) * cnt);
    }

  for (i=0; i < 256; i++)
    {
      int indx;
      
      if (Used[i] != 0)
        {
          indx = Used[i] - 1;
          img_data->reds[indx] = colrs[i].red;
          img_data->greens[indx] = colrs[i].green;
          img_data->blues[indx] = colrs[i].blue;
          /* squeegee in the background color */
          if ((bg >= 0)&&(i == bg))
          {
                img_data->reds[indx] = bg_red;
                img_data->greens[indx] = bg_green;
                img_data->blues[indx] = bg_blue;
          }
        }
    }
#ifdef MORETHAN256COLORS  
    /* if MedianCut ate our background, add the new one now. */
    if (bg == 256)
    {
        img_data->reds[cnt - 1] = bg_red;
        img_data->greens[cnt - 1] = bg_green;
        img_data->blues[cnt - 1] = bg_blue;
    }
#endif
  bgptr = bg_map;
  ptr = img_data->image_data;
  for (i=0; i < widthbyheight; i++)
    {
      *ptr = (unsigned char)(Used[(int)*ptr] - 1);
      /* if MedianCut ate the background, enforce it here */
      if (bg == 256)
      {
        if ((int)*bgptr == 1)
        {
                *ptr = (unsigned char)(cnt - 1);
        }
        bgptr++;
      }
      ptr++;
    }

  /* free the background map if we have one */
  if (bg_map != NULL)
  {
    free(bg_map);
  }
  
  dataPtr = htmlAddImgData(qFilename, img_data);
  htmlAddRefToWidget(w, qFilename, dataPtr);  

  DBUG_RETURN(img_data);
}


static int
visitedTestHandler(w, href)
Widget w;
char   *href;
    {
    extern char *wafeHandlers[];
    DBUG_ENTER("visitedTestHandler");

    if(wafeHandlers[HTMLVISITED])
	{
	int result;

	Tcl_SetVar(wafeInterpreter, "HTMLWIDGET", XtName(w), TCL_GLOBAL_ONLY);
	Tcl_SetVar(wafeInterpreter, "HTMLHREF", href, TCL_GLOBAL_ONLY);
	(void) wafeEval(wafeInterpreter, wafeHandlers[HTMLVISITED], "HTMLVISITED");
	
	if (sscanf(wafeInterpreter->result, "%d", &result) != 1)
	    {
	    fprintf(stderr, 
	    "HTMLVISITED Handler Warning: Procedure should return 0 or 1, assuming 0\n");
	    result = 0;
	    }
	DBUG_RETURN(result);
	}
    else
	{
/*	fprintf(stderr, "No handler registered...\n");*/
	DBUG_RETURN(0);
	}
    
    }



static Widget
crtHtmlWidget(father, name, args, numArgs)
Widget   father;
char     *name;
ArgList  args;
Cardinal numArgs;
    {
    Widget newWidget;
    Arg    arg[2];

    /* registering resolveImageFunction before user can use a picture */
    XtSetArg(arg[0], WbNresolveImageFunction, Resolve);
    XtSetArg(arg[1], WbNpreviouslyVisitedTestFunction, visitedTestHandler);

    newWidget = XtCreateWidget(name, htmlWidgetClass, father, arg, 2);

    XtSetValues(newWidget, args, numArgs);
    return(newWidget);
    }


/*
 * Convenience function to return the position of the element
 * based on the element id passed in.
 * Function returns the page number and fills in x,y pixel values.
 * If there is no such element, 0,0 of page 1 is returned.
 */
static Boolean
#ifdef _NO_PROTO
HTMLIdToElement(w, element_id, returnRec)
	Widget w;
	int element_id;
        HTMLElementRecord ** returnRec;
#else
HTMLIdToElement(Widget w, int element_id, HTMLElementRecord ** returnRec)
#endif
    {
    HTMLWidget hw = (HTMLWidget)w;
    struct ele_rec *start;
    struct ele_rec *eptr;
    
    eptr = NULL;
    start = hw->html.formatted_elements;
	
    while (start != NULL)
	{
	fprintf(stderr,"HTMLIdToElement: comparing %d with %d\n", 
		start->ele_id, element_id);
	if (start->ele_id == element_id)
	    {
	    *returnRec = start;
	    return True;
	    }
	start = start->next;
	}
    return False;
    }

static void
#ifdef _NO_PROTO
HTMLsetElementBg(w, element_id, colorString)
	Widget w;
	int element_id;
        char * colorString;
#else
HTMLsetElementBg(Widget w, int element_id, char * colorString)
#endif
    { 
    HTMLElementRecord *returnRec;    
    Boolean validId = HTMLIdToElement(w, element_id, &returnRec);
    fprintf(stderr,"HTMLsetElementBg: id: %d is a validId = %d\n", element_id,
	    (int) validId);
    
    if (validId)
	{
	XrmValue input,output;

	input.addr = colorString;
	input.size = strlen(colorString)+1;
	output.addr =  NULL;

	XtConvert(w, "String", &input, "Pixel", &output);
	if (output.addr)
	    {
	    fprintf(stderr,"background pixel was %p\n", (XtPointer)returnRec->bg);
	    returnRec->bg = *(Pixel *) output.addr;
	    fprintf(stderr,"background pixel is  %p\n", (XtPointer)returnRec->bg);
	    RefreshTextRange(w,returnRec,returnRec);
	    }
	}
    }


static String
hTMLGetHRefs(w) 
Widget w;
    {
    int num;
    char **p = HTMLGetHRefs((w),&num);
    fprintf(stderr, "returned from get hrefs, num=%d\n",num);
    return Tcl_Merge(num,p);
    }



/* 
 * ******* end required file <html.inc> *******
 */
#include <HTML.h>
/* 
 * String
 * HTMLGetText
 * 	in: HTMLWidget     # HTML Widget
 * 	in: int            # Pretty Code 0-2
 */

static int 
cmd_HTMLGetText(clientData, comInterpreter, argc, argv)
ClientData    clientData;
Tcl_Interp   *comInterpreter;
int           argc;
char        **argv;
     {
     Widget localVar1;
     int localVar2;
     String returnVar;

     DBUG_ENTER("HTMLGetText");  

     if (argc != 3) 
	 {
	 wafeArgcError("HTMLGetText","",2,argc);
	 DBUG_RETURN (TCL_ERROR);
         }

     if (!(localVar1 =  name2WidgetOfClass(argv[1],hTMLWidgetClass,"HTML")))
          {
          wafeConvError("HTMLGetText","1",argv[1],"HTMLWidget");
          DBUG_RETURN (TCL_ERROR);
          }

     if (!(sscanf(argv[2], "%d", &localVar2)))
          {
          wafeConvError("HTMLGetText","2",argv[2],"int");
          DBUG_RETURN (TCL_ERROR);
          }

     returnVar = HTMLGetText(localVar1,localVar2);

     
     Tcl_SetResult(comInterpreter, returnVar, TCL_VOLATILE);

     DBUG_RETURN (TCL_OK);
     }     


/* 
 * String
 * HTMLGetTextAndSelection
 * 	in: HTMLWidget    # HTML Widget
 * 	out: String       # Selection starts
 * 	out: String       # Selcetion ends
 * 	out: String       # Insertion Points
 */

static int 
cmd_HTMLGetTextAndSelection(clientData, comInterpreter, argc, argv)
ClientData    clientData;
Tcl_Interp   *comInterpreter;
int           argc;
char        **argv;
     {
     Widget localVar1;
     String localVar2;
     String localVar3;
     String localVar4;
     String returnVar;
     char conversionBuffer[100];

     DBUG_ENTER("HTMLGetTextAndSelection");  

     if (argc != 5) 
	 {
	 wafeArgcError("HTMLGetTextAndSelection","",4,argc);
	 DBUG_RETURN (TCL_ERROR);
         }

     if (!(localVar1 =  name2WidgetOfClass(argv[1],hTMLWidgetClass,"HTML")))
          {
          wafeConvError("HTMLGetTextAndSelection","1",argv[1],"HTMLWidget");
          DBUG_RETURN (TCL_ERROR);
          }

     returnVar = HTMLGetTextAndSelection(localVar1,&localVar2,&localVar3,&localVar4);

     
     Tcl_SetVar(wafeInterpreter, argv[2], localVar2, 0);

     
     Tcl_SetVar(wafeInterpreter, argv[3], localVar3, 0);

     
     Tcl_SetVar(wafeInterpreter, argv[4], localVar4, 0);

     
     Tcl_SetResult(comInterpreter, returnVar, TCL_VOLATILE);

     DBUG_RETURN (TCL_OK);
     }     


/* 
 * String 
 * hTMLGetHRefs vulgo HTMLGetHRefs
 * 	in: HTMLWidget    # HTML Widget
 */

static int 
cmd_HTMLGetHRefs(clientData, comInterpreter, argc, argv)
ClientData    clientData;
Tcl_Interp   *comInterpreter;
int           argc;
char        **argv;
     {
     Widget localVar1;
     String returnVar;

     DBUG_ENTER("HTMLGetHRefs");  

     if (argc != 2) 
	 {
	 wafeArgcError("HTMLGetHRefs","",1,argc);
	 DBUG_RETURN (TCL_ERROR);
         }

     if (!(localVar1 =  name2WidgetOfClass(argv[1],hTMLWidgetClass,"HTML")))
          {
          wafeConvError("HTMLGetHRefs","1",argv[1],"HTMLWidget");
          DBUG_RETURN (TCL_ERROR);
          }

     returnVar = hTMLGetHRefs(localVar1);

     
     Tcl_SetResult(comInterpreter, returnVar, TCL_VOLATILE);

     DBUG_RETURN (TCL_OK);
     }     


/* 
 * int
 * HTMLPositionToId
 * 	in: HTMLWidget    # HTML Widget
 * 	in: int           # x Coordinate
 * 	in: int           # y Coordinate
 */

static int 
cmd_HTMLPositionToId(clientData, comInterpreter, argc, argv)
ClientData    clientData;
Tcl_Interp   *comInterpreter;
int           argc;
char        **argv;
     {
     Widget localVar1;
     int localVar2;
     int localVar3;
     int returnVar;
     char conversionBuffer[100];

     DBUG_ENTER("HTMLPositionToId");  

     if (argc != 4) 
	 {
	 wafeArgcError("HTMLPositionToId","",3,argc);
	 DBUG_RETURN (TCL_ERROR);
         }

     if (!(localVar1 =  name2WidgetOfClass(argv[1],hTMLWidgetClass,"HTML")))
          {
          wafeConvError("HTMLPositionToId","1",argv[1],"HTMLWidget");
          DBUG_RETURN (TCL_ERROR);
          }

     if (!(sscanf(argv[2], "%d", &localVar2)))
          {
          wafeConvError("HTMLPositionToId","2",argv[2],"int");
          DBUG_RETURN (TCL_ERROR);
          }

     if (!(sscanf(argv[3], "%d", &localVar3)))
          {
          wafeConvError("HTMLPositionToId","3",argv[3],"int");
          DBUG_RETURN (TCL_ERROR);
          }

     returnVar = HTMLPositionToId(localVar1,localVar2,localVar3);

     sprintf(conversionBuffer, "%d", returnVar);
     Tcl_SetResult(comInterpreter, conversionBuffer, TCL_VOLATILE);

     DBUG_RETURN (TCL_OK);
     }     


/* 
 * int 
 * HTMLIdToPosition
 * 	in: HTMLWidget     # HTML Widget
 * 	in: int	           # Element ID
 * 	out: int           # x Coordinate
 * 	out: int           # y Coordinate
 */

static int 
cmd_HTMLIdToPosition(clientData, comInterpreter, argc, argv)
ClientData    clientData;
Tcl_Interp   *comInterpreter;
int           argc;
char        **argv;
     {
     Widget localVar1;
     int localVar2;
     int localVar3;
     int localVar4;
     int returnVar;
     char conversionBuffer[100];

     DBUG_ENTER("HTMLIdToPosition");  

     if (argc != 5) 
	 {
	 wafeArgcError("HTMLIdToPosition","",4,argc);
	 DBUG_RETURN (TCL_ERROR);
         }

     if (!(localVar1 =  name2WidgetOfClass(argv[1],hTMLWidgetClass,"HTML")))
          {
          wafeConvError("HTMLIdToPosition","1",argv[1],"HTMLWidget");
          DBUG_RETURN (TCL_ERROR);
          }

     if (!(sscanf(argv[2], "%d", &localVar2)))
          {
          wafeConvError("HTMLIdToPosition","2",argv[2],"int");
          DBUG_RETURN (TCL_ERROR);
          }

     returnVar = HTMLIdToPosition(localVar1,localVar2,&localVar3,&localVar4);

     sprintf(conversionBuffer, "%d", localVar3);
     Tcl_SetVar(wafeInterpreter, argv[3], conversionBuffer, 0);

     sprintf(conversionBuffer, "%d", localVar4);
     Tcl_SetVar(wafeInterpreter, argv[4], conversionBuffer, 0);

     sprintf(conversionBuffer, "%d", returnVar);
     Tcl_SetResult(comInterpreter, conversionBuffer, TCL_VOLATILE);

     DBUG_RETURN (TCL_OK);
     }     


/* 
 * int 
 * HTMLAnchorToPosition
 * 	in: HTMLWidget     # HTML Widget
 * 	in: String         # Anchor's name
 * 	out: int           # x Coordinate
 * 	out: int           # y Coordinate
 */

static int 
cmd_HTMLAnchorToPosition(clientData, comInterpreter, argc, argv)
ClientData    clientData;
Tcl_Interp   *comInterpreter;
int           argc;
char        **argv;
     {
     Widget localVar1;
     int localVar3;
     int localVar4;
     int returnVar;
     char conversionBuffer[100];

     DBUG_ENTER("HTMLAnchorToPosition");  

     if (argc != 5) 
	 {
	 wafeArgcError("HTMLAnchorToPosition","",4,argc);
	 DBUG_RETURN (TCL_ERROR);
         }

     if (!(localVar1 =  name2WidgetOfClass(argv[1],hTMLWidgetClass,"HTML")))
          {
          wafeConvError("HTMLAnchorToPosition","1",argv[1],"HTMLWidget");
          DBUG_RETURN (TCL_ERROR);
          }

    /* no need to assign  << localVar2 = argv[2] >>  */ 

     returnVar = HTMLAnchorToPosition(localVar1,argv[2],&localVar3,&localVar4);

     sprintf(conversionBuffer, "%d", localVar3);
     Tcl_SetVar(wafeInterpreter, argv[3], conversionBuffer, 0);

     sprintf(conversionBuffer, "%d", localVar4);
     Tcl_SetVar(wafeInterpreter, argv[4], conversionBuffer, 0);

     sprintf(conversionBuffer, "%d", returnVar);
     Tcl_SetResult(comInterpreter, conversionBuffer, TCL_VOLATILE);

     DBUG_RETURN (TCL_OK);
     }     


/* 
 * void
 * HTMLClearSelection
 * 	in: HTMLWidget     # HTML Widget
 */

static int 
cmd_HTMLClearSelection(clientData, comInterpreter, argc, argv)
ClientData    clientData;
Tcl_Interp   *comInterpreter;
int           argc;
char        **argv;
     {
     Widget localVar1;

     DBUG_ENTER("HTMLClearSelection");  

     if (argc != 2) 
	 {
	 wafeArgcError("HTMLClearSelection","",1,argc);
	 DBUG_RETURN (TCL_ERROR);
         }

     if (!(localVar1 =  name2WidgetOfClass(argv[1],hTMLWidgetClass,"HTML")))
          {
          wafeConvError("HTMLClearSelection","1",argv[1],"HTMLWidget");
          DBUG_RETURN (TCL_ERROR);
          }

     HTMLClearSelection(localVar1);

     DBUG_RETURN (TCL_OK);
     }     


/* 
 * void 
 * HTMLSetSelection
 * 	in: HTMLWidget         # HTML Widget
 * 	in: ElementRef         # start
 * 	in: ElementRef	       # end
 */

static int 
cmd_HTMLSetSelection(clientData, comInterpreter, argc, argv)
ClientData    clientData;
Tcl_Interp   *comInterpreter;
int           argc;
char        **argv;
     {
     Widget localVar1;
     ElementRef localVar2;
     ElementRef localVar3;

     DBUG_ENTER("HTMLSetSelection");  

     if (argc != 4) 
	 {
	 wafeArgcError("HTMLSetSelection","",3,argc);
	 DBUG_RETURN (TCL_ERROR);
         }

     if (!(localVar1 =  name2WidgetOfClass(argv[1],hTMLWidgetClass,"HTML")))
          {
          wafeConvError("HTMLSetSelection","1",argv[1],"HTMLWidget");
          DBUG_RETURN (TCL_ERROR);
          }

     { char *charp;
         if (!(charp=Tcl_GetVar2(wafeInterpreter,argv[2],"id", 0)))
               {
               wafeNoVarCompError("HTMLSetSelection",argv[2],"id");
               DBUG_RETURN (TCL_ERROR);
               }
         if (!(sscanf(charp, "%d", &localVar2.id)))
              {
              wafeConvError("HTMLSetSelection","2.id",charp,"int");
              DBUG_RETURN (TCL_ERROR);
              }

         if (!(charp=Tcl_GetVar2(wafeInterpreter,argv[2],"pos", 0)))
               {
               wafeNoVarCompError("HTMLSetSelection",argv[2],"pos");
               DBUG_RETURN (TCL_ERROR);
               }
         if (!(sscanf(charp, "%d", &localVar2.pos)))
              {
              wafeConvError("HTMLSetSelection","2.pos",charp,"int");
              DBUG_RETURN (TCL_ERROR);
              }

     }

     { char *charp;
         if (!(charp=Tcl_GetVar2(wafeInterpreter,argv[3],"id", 0)))
               {
               wafeNoVarCompError("HTMLSetSelection",argv[3],"id");
               DBUG_RETURN (TCL_ERROR);
               }
         if (!(sscanf(charp, "%d", &localVar3.id)))
              {
              wafeConvError("HTMLSetSelection","3.id",charp,"int");
              DBUG_RETURN (TCL_ERROR);
              }

         if (!(charp=Tcl_GetVar2(wafeInterpreter,argv[3],"pos", 0)))
               {
               wafeNoVarCompError("HTMLSetSelection",argv[3],"pos");
               DBUG_RETURN (TCL_ERROR);
               }
         if (!(sscanf(charp, "%d", &localVar3.pos)))
              {
              wafeConvError("HTMLSetSelection","3.pos",charp,"int");
              DBUG_RETURN (TCL_ERROR);
              }

     }

     HTMLSetSelection(localVar1,&localVar2,&localVar3);

     DBUG_RETURN (TCL_OK);
     }     


/* 
 * void 
 * HTMLSetText	
 * 	in: HTMLWidget         # HTML Widget
 * 	in: String             # Text
 * 	in: String	       # Header Text
 * 	in: String	       # Footer Text
 * 	in: int		       # element_id
 * 	in: String	       # target_anchor
 * 	const: NULL
 */

static int 
cmd_HTMLSetText(clientData, comInterpreter, argc, argv)
ClientData    clientData;
Tcl_Interp   *comInterpreter;
int           argc;
char        **argv;
     {
     Widget localVar1;
     int localVar5;

     DBUG_ENTER("HTMLSetText");  

     if (argc != 7) 
	 {
	 wafeArgcError("HTMLSetText","",6,argc);
	 DBUG_RETURN (TCL_ERROR);
         }

     if (!(localVar1 =  name2WidgetOfClass(argv[1],hTMLWidgetClass,"HTML")))
          {
          wafeConvError("HTMLSetText","1",argv[1],"HTMLWidget");
          DBUG_RETURN (TCL_ERROR);
          }

    /* no need to assign  << localVar2 = argv[2] >>  */ 

    /* no need to assign  << localVar3 = argv[3] >>  */ 

    /* no need to assign  << localVar4 = argv[4] >>  */ 

     if (!(sscanf(argv[5], "%d", &localVar5)))
          {
          wafeConvError("HTMLSetText","5",argv[5],"int");
          DBUG_RETURN (TCL_ERROR);
          }

    /* no need to assign  << localVar6 = argv[6] >>  */ 

     HTMLSetText(localVar1,argv[2],argv[3],argv[4],localVar5,argv[6],NULL);

     DBUG_RETURN (TCL_OK);
     }     


#define searchtext(w, s, instart, outstart, outend, back, sens) HTMLSearchText(w, s, instart, outend, back, sens); (*outstart).id = (*instart).id; (*outstart).pos = (*instart).pos;

/* 
 * int 
 * searchtext vulgo HTMLSearchText
 * 	in: HTMLWidget         # HTML Widget
 * 	in: String             # Pattern
 * 	in: ElementRef         # Start
 * 	out: ElementRef        # Result: Start
 * 	out: ElementRef        # Result: End
 * 	in: int		       # Backward
 * 	in: int		       # Case Sensitive
 */

static int 
cmd_HTMLSearchText(clientData, comInterpreter, argc, argv)
ClientData    clientData;
Tcl_Interp   *comInterpreter;
int           argc;
char        **argv;
     {
     Widget localVar1;
     ElementRef localVar3;
     ElementRef localVar4;
     ElementRef localVar5;
     int localVar6;
     int localVar7;
     int returnVar;
     char conversionBuffer[100];

     DBUG_ENTER("HTMLSearchText");  

     if (argc != 8) 
	 {
	 wafeArgcError("HTMLSearchText","",7,argc);
	 DBUG_RETURN (TCL_ERROR);
         }

     if (!(localVar1 =  name2WidgetOfClass(argv[1],hTMLWidgetClass,"HTML")))
          {
          wafeConvError("HTMLSearchText","1",argv[1],"HTMLWidget");
          DBUG_RETURN (TCL_ERROR);
          }

    /* no need to assign  << localVar2 = argv[2] >>  */ 

     { char *charp;
         if (!(charp=Tcl_GetVar2(wafeInterpreter,argv[3],"id", 0)))
               {
               wafeNoVarCompError("HTMLSearchText",argv[3],"id");
               DBUG_RETURN (TCL_ERROR);
               }
         if (!(sscanf(charp, "%d", &localVar3.id)))
              {
              wafeConvError("HTMLSearchText","3.id",charp,"int");
              DBUG_RETURN (TCL_ERROR);
              }

         if (!(charp=Tcl_GetVar2(wafeInterpreter,argv[3],"pos", 0)))
               {
               wafeNoVarCompError("HTMLSearchText",argv[3],"pos");
               DBUG_RETURN (TCL_ERROR);
               }
         if (!(sscanf(charp, "%d", &localVar3.pos)))
              {
              wafeConvError("HTMLSearchText","3.pos",charp,"int");
              DBUG_RETURN (TCL_ERROR);
              }

     }

     if (!(sscanf(argv[6], "%d", &localVar6)))
          {
          wafeConvError("HTMLSearchText","6",argv[6],"int");
          DBUG_RETURN (TCL_ERROR);
          }

     if (!(sscanf(argv[7], "%d", &localVar7)))
          {
          wafeConvError("HTMLSearchText","7",argv[7],"int");
          DBUG_RETURN (TCL_ERROR);
          }

     returnVar = searchtext(localVar1,argv[2],&localVar3,&localVar4,&localVar5,localVar6,localVar7);

          sprintf(conversionBuffer, "%d", localVar4.id);
     Tcl_SetVar2(wafeInterpreter,argv[4],"id", conversionBuffer,0);
     sprintf(conversionBuffer, "%d", localVar4.pos);
     Tcl_SetVar2(wafeInterpreter,argv[4],"pos", conversionBuffer,0);


          sprintf(conversionBuffer, "%d", localVar5.id);
     Tcl_SetVar2(wafeInterpreter,argv[5],"id", conversionBuffer,0);
     sprintf(conversionBuffer, "%d", localVar5.pos);
     Tcl_SetVar2(wafeInterpreter,argv[5],"pos", conversionBuffer,0);


     sprintf(conversionBuffer, "%d", returnVar);
     Tcl_SetResult(comInterpreter, conversionBuffer, TCL_VOLATILE);

     DBUG_RETURN (TCL_OK);
     }     


/* 
 * void
 * HTMLGotoId
 * 	in: HTMLWidget		# HTML Widget
 * 	in: int 		# Element ID
 */

static int 
cmd_HTMLGotoId(clientData, comInterpreter, argc, argv)
ClientData    clientData;
Tcl_Interp   *comInterpreter;
int           argc;
char        **argv;
     {
     Widget localVar1;
     int localVar2;

     DBUG_ENTER("HTMLGotoId");  

     if (argc != 3) 
	 {
	 wafeArgcError("HTMLGotoId","",2,argc);
	 DBUG_RETURN (TCL_ERROR);
         }

     if (!(localVar1 =  name2WidgetOfClass(argv[1],hTMLWidgetClass,"HTML")))
          {
          wafeConvError("HTMLGotoId","1",argv[1],"HTMLWidget");
          DBUG_RETURN (TCL_ERROR);
          }

     if (!(sscanf(argv[2], "%d", &localVar2)))
          {
          wafeConvError("HTMLGotoId","2",argv[2],"int");
          DBUG_RETURN (TCL_ERROR);
          }

     HTMLGotoId(localVar1,localVar2);

     DBUG_RETURN (TCL_OK);
     }     


/* 
 * int
 * HTMLAnchorToId
 * 	in: HTMLWidget		# HTML Widget
 * 	in: String		# Anchor string
 */

static int 
cmd_HTMLAnchorToId(clientData, comInterpreter, argc, argv)
ClientData    clientData;
Tcl_Interp   *comInterpreter;
int           argc;
char        **argv;
     {
     Widget localVar1;
     int returnVar;
     char conversionBuffer[100];

     DBUG_ENTER("HTMLAnchorToId");  

     if (argc != 3) 
	 {
	 wafeArgcError("HTMLAnchorToId","",2,argc);
	 DBUG_RETURN (TCL_ERROR);
         }

     if (!(localVar1 =  name2WidgetOfClass(argv[1],hTMLWidgetClass,"HTML")))
          {
          wafeConvError("HTMLAnchorToId","1",argv[1],"HTMLWidget");
          DBUG_RETURN (TCL_ERROR);
          }

    /* no need to assign  << localVar2 = argv[2] >>  */ 

     returnVar = HTMLAnchorToId(localVar1,argv[2]);

     sprintf(conversionBuffer, "%d", returnVar);
     Tcl_SetResult(comInterpreter, conversionBuffer, TCL_VOLATILE);

     DBUG_RETURN (TCL_OK);
     }     


/* 
 * Boolean
 * HTMLIdToElement
 * 	in: HTMLWidget		# HTML Widget
 * 	in: int	       		# Element ID
 * 	out: HTMLElementRecord* # Element Record
 */

static int 
cmd_HTMLIdToElement(clientData, comInterpreter, argc, argv)
ClientData    clientData;
Tcl_Interp   *comInterpreter;
int           argc;
char        **argv;
     {
     Widget localVar1;
     int localVar2;
     HTMLElementRecord* localVar3;
     Boolean returnVar;
     char conversionBuffer[100];

     DBUG_ENTER("HTMLIdToElement");  

     if (argc != 4) 
	 {
	 wafeArgcError("HTMLIdToElement","",3,argc);
	 DBUG_RETURN (TCL_ERROR);
         }

     if (!(localVar1 =  name2WidgetOfClass(argv[1],hTMLWidgetClass,"HTML")))
          {
          wafeConvError("HTMLIdToElement","1",argv[1],"HTMLWidget");
          DBUG_RETURN (TCL_ERROR);
          }

     if (!(sscanf(argv[2], "%d", &localVar2)))
          {
          wafeConvError("HTMLIdToElement","2",argv[2],"int");
          DBUG_RETURN (TCL_ERROR);
          }

     returnVar = HTMLIdToElement(localVar1,localVar2,&localVar3);

          
     Tcl_SetVar2(wafeInterpreter,argv[3],"anchorName", localVar3->anchorName,0);
     
     Tcl_SetVar2(wafeInterpreter,argv[3],"anchorHRef", localVar3->anchorHRef,0);
     
     Tcl_SetVar2(wafeInterpreter,argv[3],"edata", localVar3->edata,0);


          if (returnVar == 0) 
          strcpy(conversionBuffer, "false");
     else
     if (returnVar == 1) 
          strcpy(conversionBuffer, "true");


     Tcl_SetResult(comInterpreter, conversionBuffer, TCL_VOLATILE);

     DBUG_RETURN (TCL_OK);
     }     


/* 
 * void
 * HTMLsetElementBg
 * 	in: HTMLWidget 		# HTML Widget
 * 	in: int	       		# Element ID
 * 	in: String              # backgroundColor
 */

static int 
cmd_HTMLsetElementBg(clientData, comInterpreter, argc, argv)
ClientData    clientData;
Tcl_Interp   *comInterpreter;
int           argc;
char        **argv;
     {
     Widget localVar1;
     int localVar2;

     DBUG_ENTER("HTMLsetElementBg");  

     if (argc != 4) 
	 {
	 wafeArgcError("HTMLsetElementBg","",3,argc);
	 DBUG_RETURN (TCL_ERROR);
         }

     if (!(localVar1 =  name2WidgetOfClass(argv[1],hTMLWidgetClass,"HTML")))
          {
          wafeConvError("HTMLsetElementBg","1",argv[1],"HTMLWidget");
          DBUG_RETURN (TCL_ERROR);
          }

     if (!(sscanf(argv[2], "%d", &localVar2)))
          {
          wafeConvError("HTMLsetElementBg","2",argv[2],"int");
          DBUG_RETURN (TCL_ERROR);
          }

    /* no need to assign  << localVar3 = argv[3] >>  */ 

     HTMLsetElementBg(localVar1,localVar2,argv[3]);

     DBUG_RETURN (TCL_OK);
     }     


/* 
 * void 
 * HTMLRetestAnchors
 * 	in: HTMLWidget		# HTML Widget
 * 	const: NULL

 */

static int 
cmd_HTMLRetestAnchors(clientData, comInterpreter, argc, argv)
ClientData    clientData;
Tcl_Interp   *comInterpreter;
int           argc;
char        **argv;
     {
     Widget localVar1;

     DBUG_ENTER("HTMLRetestAnchors");  

     if (argc != 2) 
	 {
	 wafeArgcError("HTMLRetestAnchors","",1,argc);
	 DBUG_RETURN (TCL_ERROR);
         }

     if (!(localVar1 =  name2WidgetOfClass(argv[1],hTMLWidgetClass,"HTML")))
          {
          wafeConvError("HTMLRetestAnchors","1",argv[1],"HTMLWidget");
          DBUG_RETURN (TCL_ERROR);
          }

     HTMLRetestAnchors(localVar1,NULL);

     DBUG_RETURN (TCL_OK);
     }     


#else
#endif

void
wafeInitialize_htmlGen()
{
#ifdef HTML
 wafeCreateWidgetCommand("HTML",htmlWidgetClass,crtHtmlWidget,False);
#ifdef HTML
 Tcl_SetVar(wafeInterpreter,"PACKAGES","HTML",TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
#endif
 qimageList = WafePermStringToQuark("imageList");
 Tcl_CreateCommand(wafeInterpreter, "HTMLGetText", cmd_HTMLGetText, NULL, NULL);
 Tcl_CreateCommand(wafeInterpreter, "HTMLGetTextAndSelection", cmd_HTMLGetTextAndSelection, NULL, NULL);
 Tcl_CreateCommand(wafeInterpreter, "HTMLGetHRefs", cmd_HTMLGetHRefs, NULL, NULL);
 Tcl_CreateCommand(wafeInterpreter, "HTMLPositionToId", cmd_HTMLPositionToId, NULL, NULL);
 Tcl_CreateCommand(wafeInterpreter, "HTMLIdToPosition", cmd_HTMLIdToPosition, NULL, NULL);
 Tcl_CreateCommand(wafeInterpreter, "HTMLAnchorToPosition", cmd_HTMLAnchorToPosition, NULL, NULL);
 Tcl_CreateCommand(wafeInterpreter, "HTMLClearSelection", cmd_HTMLClearSelection, NULL, NULL);
 Tcl_CreateCommand(wafeInterpreter, "HTMLSetSelection", cmd_HTMLSetSelection, NULL, NULL);
 Tcl_CreateCommand(wafeInterpreter, "HTMLSetText", cmd_HTMLSetText, NULL, NULL);
 Tcl_CreateCommand(wafeInterpreter, "HTMLSearchText", cmd_HTMLSearchText, NULL, NULL);
 Tcl_CreateCommand(wafeInterpreter, "HTMLGotoId", cmd_HTMLGotoId, NULL, NULL);
 Tcl_CreateCommand(wafeInterpreter, "HTMLAnchorToId", cmd_HTMLAnchorToId, NULL, NULL);
 Tcl_CreateCommand(wafeInterpreter, "HTMLIdToElement", cmd_HTMLIdToElement, NULL, NULL);
 Tcl_CreateCommand(wafeInterpreter, "HTMLsetElementBg", cmd_HTMLsetElementBg, NULL, NULL);
 Tcl_CreateCommand(wafeInterpreter, "HTMLRetestAnchors", cmd_HTMLRetestAnchors, NULL, NULL);

#else
#endif
}
