Exemplo n.º 1
0
Arquivo: map.c Projeto: Gilles86/afni
static void
drawSelectionPolygon(XmHTMLWidget html, XmHTMLImage *image, 
	mapArea *area)
{
	ToolkitAbstraction *tka = HTML_ATTR(tka);
	XPoint *points;
	int i, npoints;
	int x = image->owner->x - html->html.scroll_x;
	int y = image->owner->y - html->html.scroll_y;

	npoints = area->ncoords/2;

	points = (XPoint*)calloc(npoints+1, sizeof(XPoint));

	for(i = 0; i < npoints; i++)
	{
		points[i].x = area->coords[i*2] + x;
		points[i].y = area->coords[i*2+1] + y;
	}
	/* last point is same as first point */
	points[npoints].x = points[0].x;
	points[npoints].y = points[0].y;

	tka->SetForeground(tka->dpy, HTML_ATTR(gc), HTML_ATTR(imagemap_fg));
	tka->DrawLines(tka->dpy, tka->win, HTML_ATTR(gc),
		points, npoints+1, tka->coord_mode[GC_COORDMODE_ORIGIN]);
	free(points);
}
Exemplo n.º 2
0
Arquivo: map.c Projeto: Gilles86/afni
static void
drawSelectionRectangle(XmHTMLWidget html, XmHTMLImage *image, 
	mapArea *area)
{
	ToolkitAbstraction *tka = HTML_ATTR(tka);
	int x = image->owner->x - html->html.scroll_x + area->coords[0];
	int y = image->owner->y - html->html.scroll_y + area->coords[1];
	int width = area->coords[2] - area->coords[0];
	int height = area->coords[3] - area->coords[1];

	tka->SetForeground(tka->dpy, HTML_ATTR(gc), HTML_ATTR(imagemap_fg));
	tka->DrawRectangle(tka->dpy, tka->win, HTML_ATTR(gc), x, y, width, height);
}
Exemplo n.º 3
0
Arquivo: map.c Projeto: Gilles86/afni
static void
drawSelectionArc(XmHTMLWidget html, XmHTMLImage *image,
	mapArea *area)
{
	ToolkitAbstraction *tka = HTML_ATTR(tka);
	int x = image->owner->x - html->html.scroll_x + area->coords[0];
	int y = image->owner->y - html->html.scroll_y + area->coords[1];
	int radius = area->coords[2];

	/* upper-left corner of bounding rectangle */
	x -= radius;
	y -= radius;
	
	tka->SetForeground(tka->dpy, HTML_ATTR(gc), HTML_ATTR(imagemap_fg));
	tka->DrawArc(tka->dpy, tka->win, HTML_ATTR(gc), x, y, 2*radius,
		2*radius, 0, 23040);
}
Exemplo n.º 4
0
 */

#undef	HTML_ATTR
#define	HTML_ATTR(t,a)		{ #a }
#undef	HTML_ATTRIBUTES
#define	HTML_ATTRIBUTES(t)	{ 0 }

/*
**	ATTRIBUTE LISTS
*/

PRIVATE HTAttr no_attr[1] = 
	{{ 0 }};

PRIVATE HTAttr body_attr[HTML_BODY_ATTRIBUTES+1] = {	/* to catch images */
	HTML_ATTR(BODY,ALINK),
	HTML_ATTR(BODY,BACKGROUND),
	HTML_ATTR(BODY,BGCOLOR),
	HTML_ATTR(BODY,CLASS),
	HTML_ATTR(BODY,DIR),
	HTML_ATTR(BODY,ID),
	HTML_ATTR(BODY,LANG),
	HTML_ATTR(BODY,LINK),
	HTML_ATTR(BODY,STYLE),
	HTML_ATTR(BODY,TEXT),
	HTML_ATTR(BODY,TITLE),
	HTML_ATTR(BODY,VLINK),
	HTML_ATTRIBUTES(BODY)
};	

PRIVATE HTAttr frame_attr[HTML_FRAME_ATTRIBUTES+1] = {	/* frame attributes */
Exemplo n.º 5
0
/*****
* Name: 		_PLC_GIF_Init
* Return Type: 	void
* Description: 	image initializer for GIF images
* In: 
*	plc:		current PLC 
* Returns:
*	Nothing but PLC is updated.
* Note:
*	As this routine must be fully re-entrant, it needs a lot of checks
*	to make sure we have the data we want fully available.
*	The drawback is that if we are being suspended while doing this
*	initialization, everything must be reset and repeated the next time
*	this routine is called.
*****/
void
_PLC_GIF_Init(PLC *plc)
{
	Byte buf[16], c;
	PLCImageGIF *gif;

	gif = &(plc->object->plc_gif_image);

	_XmHTMLDebug(15, ("plc.c: _PLC_GIF_Init for %s\n", plc->url));

	/* this plc is active */
	plc->plc_status = PLC_ACTIVE;

	/*****
	* When this routine is called, the init method of this PLC has already
	* been called to determine the type of this PLC Image object. Therefore
	* we already have data available and we need to rewind the input buffer
	* back to the beginning.
	*****/
	_PLCRewindInputBuffer(plc);

	/* we know this is a gif image, so skip magic */
	gif->info->type = IMAGE_GIF;
	(void)_PLCReadOK(plc, buf, 6);

	/* read logical screen descriptor */
	(void)_PLCReadOK(plc, buf, 7);

	/* image dimensions */
	gif->width   = LM_to_uint(buf[0],buf[1]);
	gif->height  = LM_to_uint(buf[2],buf[3]);

	/* set colorspace and allocate a colormap */
	gif->colorclass = XmIMAGE_COLORSPACE_INDEXED;
	gif->cmapsize   = 2<<(buf[4]&0x07);

	/*
	* We may have been called before (but returned 'cause not enough data
	* was available).
	*/
	if(gif->cmap == NULL)
		gif->cmap = (XCOLOR*)calloc(gif->cmapsize, sizeof(XCOLOR));

	/* image is initially fully opaque */
	gif->transparency = XmNONE;
	gif->bg_pixel = -1;

	/*
	* Incoming data buffer. This is *way* too much as the incoming data
	* will be compressed (but it does make sure there is enough room)
	*/
	gif->buf_size   = gif->width*gif->height;
	gif->buf_pos    = 0;	/* current pos in data received so far */
	gif->byte_count = 0;	/* size of data received so far */
	if(gif->buffer == NULL)
		gif->buffer = (Byte*)calloc(gif->buf_size + 1, sizeof(Byte));

	/* check if a global colormap is available */
	if(BitSet(buf[4], LOCALCOLORMAP))
	{
		if(!(ReadColormap(plc, gif)))
		{
			/* premature end of data. */
			if(plc->plc_data_status == STREAM_END)
			{
				_XmHTMLWarning(__WFUNC__(gif->owner, "_PLC_GIF_Init"),
					XMHTML_MSG_106, plc->url, "global");
				plc->plc_status = PLC_ABORT;
			}
			return;	/* no global colormap! */
		}
	}

	/* process all extensions */
	c = 0;
	while(c != ',')
	{
		if(!_PLCReadOK(plc, &c, 1))
			return;

		if (c == ';') /* GIF terminator */
		{
			_XmHTMLWarning(__WFUNC__(gif->owner, "_PLC_GIF_Init"),
				XMHTML_MSG_107, plc->url, "pixel data");
			plc->plc_status = PLC_ABORT;
			return;
		}

		if(c == '!') /* Extension */
		{
			if(!_PLCReadOK(plc,&c,1))
			{
				if(plc->plc_data_status == STREAM_END)
				{
					_XmHTMLWarning(__WFUNC__(gif->owner, "_PLC_GIF_Init"),
						XMHTML_MSG_107, plc->url, "extension block type");
					plc->plc_status = PLC_ABORT;
				}
				return;
			}
			if(!(DoExtension(plc, c)))
			{
				if(plc->plc_data_status == STREAM_END)
				{
					_XmHTMLWarning(__WFUNC__(gif->owner, "_PLC_GIF_Init"),
						XMHTML_MSG_107, plc->url, "extension block");
					plc->plc_status = PLC_ABORT;
				}
				return;
			}
			continue;
		}
		if (c != ',')
			continue; /* Not a valid start character */
	}
	/* get image descriptor */
	if(!_PLCReadOK(plc, buf, 9))
		return;

	/* see if we are to use a local colormap */
	if(BitSet(buf[8], LOCALCOLORMAP))
	{
		/* local colormap size */
		gif->ncolors = 1<<((buf[8]&0x07)+1);

		/* do we also have a glocal colormap? */
		if(gif->cmap)
			free(gif->cmap);

		gif->cmapsize = gif->ncolors;
		gif->cmap = (XCOLOR*)calloc(gif->cmapsize, sizeof(XCOLOR));

		if(!(ReadColormap(plc, gif)))
		{
			/* premature end of data. */
			if(plc->plc_data_status == STREAM_END)
			{
				_XmHTMLWarning(__WFUNC__(gif->owner, "_PLC_GIF_Init"),
					XMHTML_MSG_106, plc->url, "local");
				plc->plc_status = PLC_ABORT;
			}
			return;	/* no global colormap! */
		}
	}
	gif->ncolors = gif->cmapsize;

	/* sanity check: image *must* have a colormap */
	if(gif->cmap == NULL)
	{
		_XmHTMLWarning(__WFUNC__(gif->owner, "_PLC_GIF_Init"),
			XMHTML_MSG_106, plc->url, "global or local");
		plc->plc_status = PLC_ABORT;
		return;	/* no global colormap! */
	}

	/* image depth (= codeSize in GIF images, unused in GZF images) */
	if(!(_PLCReadOK(plc, &c, 1)))
		return;

	gif->depth = (int)(c & 0xff);

	/* check interlacing */
	if(BitSet(buf[8], INTERLACE))
	{
		/* interlaced gifs require 4 passes and use an initial rowstride of 8 */
		gif->npasses = 4;
		gif->stride  = 8;
	}
	else
	{
		/* regular gif, 1 pass will get us the entire image */
		gif->npasses = 1;
		gif->stride  = 0;
	}
	gif->curr_pass = 0;
	gif->curr_scanline = 0;

	/*****
	* This routine is also used for GZF images, so before initializing
	* the LZWStream object we need to make sure we have been called for
	* a true GIF image.
	*****/
	if(plc->object->type == plcGIF)
	{
		XmHTMLWidget html  = plc->object->plc_any.owner;

		if(HTML_ATTR(gif_proc) != NULL)
		{
			gif->external_codec = True;
			gif->inflate = HTML_ATTR(gif_proc);
			if((gif->gstream =
				(XmHTMLGIFStream*)malloc(sizeof(XmHTMLGIFStream))) == NULL)
			{
				/* out of memory, too bad then */
				_XmHTMLWarning(__WFUNC__(gif->owner, "_PLC_GIF_Init"),
					XMHTML_MSG_113, plc->url, sizeof(XmHTMLGIFStream));
				plc->plc_status = PLC_ABORT;
				return;
			}

			/* initialize GIFStream object */
			memset(gif->gstream, 0, sizeof(XmHTMLGIFStream));

			gif->gstream->codesize  = (int)c;
			gif->gstream->state     = GIF_STREAM_INIT;
			gif->gstream->next_out  = gif->buffer;
			gif->gstream->avail_out = gif->buf_size + 1;
			gif->gstream->is_progressive = True;
			/*
			* and call external decoder so it can initialize its own data
			* structures
			*/
			if((gif->inflate(gif->gstream)) != GIF_STREAM_OK)
			{
				if(gif->gstream->msg != NULL)
				{
					_XmHTMLWarning(__WFUNC__(gif->owner, "_PLC_GIF_Init"),
						XMHTML_MSG_109, plc->url,
						gif->gstream->msg ? gif->gstream->msg :
						"(unknown error)");
				}
				/* external decoder initalization failed, abort and return */
				plc->plc_status = PLC_ABORT;
				return;
			}
			gif->gstream->state = GIF_STREAM_OK;
		}
		else
		{
			/* initialize local data buffer */
			gif->ib.file   = plc->url;
			gif->ib.buffer = gif->buffer;	
			gif->ib.size   = 0;
			gif->ib.next   = 0;
			gif->ib.type   = IMAGE_GIF;
			gif->ib.depth  = gif->depth;
			gif->ib.may_free = False;

			/* initialize LZWStream object */
			if(gif->lstream == NULL)
			{
				if((gif->lstream = LZWStreamCreate(&(gif->ib),
									html->html.zCmd)) == NULL)
				{
					/* couldn't create stream, abort and return */
					plc->plc_status = PLC_ABORT;
					return;
				}
				/* set read functions */
				gif->lstream->readOK  = _XmHTMLGifReadOK;
				gif->lstream->getData = _XmHTMLGifGetDataBlock;
			}
			/* first byte in buffer is gif codesize */
			gif->ib.buffer[0] = c;
			gif->ib.size = 1;
		}
		/* allocate room for final image data */
		if(gif->data == NULL)
		{
			gif->data = (Byte*)calloc(gif->buf_size + 1, sizeof(Byte));

			/* don't allocate clipmask yet, it's done in the plc code */
		}
		gif->data_size = gif->buf_size;
		gif->data_pos  = 0;
	}

	/* object has been initialized */
	plc->initialized = True;

	plc->curr_obj_func = 0;	/* move to GIF scanline reader */
	return;
}
Exemplo n.º 6
0
/*****
* Name:			XmHTMLTextGetFormatted
* Return Type: 	String
* Description: 	returns a formatted copy of the current document.
* In: 
*	w:			XmHTMLWidget id;
*	papertype:	type of paper to use (any of the XmHTMLTEXT_PAPERSIZE enums);
*	papersize:	size of paper for custom stuff, or default overrides;
*	type:		type of output wanted, plain, formatted or PS;
*	PSoptions:	options to use when creating postscript output.
* Returns:
*	a string which needs to be freed by the caller.
*****/
String
XmHTMLTextGetFormatted(Widget w, unsigned char papertype,
	XmHTMLPaperSize *paperdef, unsigned char type, unsigned char PSoptions)
{
	XmHTMLWidget html;
	XmHTMLPaperSize *pdef, pbase;
	String ret_val = NULL;

	/* sanity check */
	if(!w || !XmIsHTML(w))
	{
		_XmHTMLBadParent(w, "TextGetFormatted");
		return(NULL);
	}

	/* custom papersize requires a paper definition. */
	if(papertype == XmHTMLTEXT_PAPERSIZE_CUSTOM && paperdef == NULL)
	{
		_XmHTMLWarning(__WFUNC__(w, "XmHTMLTextGetFormatted"), XMHTML_MSG_23);
		return(NULL);
	}

	/* widget ptr */
	html = (XmHTMLWidget)w;

	/*****
	* get appropriate papersize definitions if not given.
	*****/
	if(papertype != XmHTMLTEXT_PAPERSIZE_CUSTOM && paperdef == NULL)
	{
		/* formatting routines use point size */
		if(papertype == XmHTMLTEXT_PAPERSIZE_A4)
		{
			pbase.unit_type     = XmHTML_POINT;
			pbase.paper_type    = XmHTMLTEXT_PAPERSIZE_A4;
			pbase.width         = 597;	/* 210mm */
			pbase.height        = 845;	/* 297mm */
			pbase.left_margin   = 57;	/* 20mm  */
			pbase.right_margin  = 57;
			pbase.top_margin    = 57;
			pbase.bottom_margin = 57;
		}
		else 	/* XmHTMLTEXT_PAPERSIZE_LETTER */
		{
			pbase.unit_type     = XmHTML_POINT;
			pbase.paper_type    = XmHTMLTEXT_PAPERSIZE_LETTER;
			pbase.width         = 614;	/* 8.5in */
			pbase.height        = 795;	/* 11in  */
			pbase.left_margin   = 65;	/* 0.9in */
			pbase.right_margin  = 65;
			pbase.top_margin    = 65;
			pbase.bottom_margin = 51;	/* 0.7in */
		}
		/* convert to correct output type */
		pdef = _XmHTMLTextCheckAndConvertPaperDef(html, &pbase, type);
	}
	else	/* check validity of paper definition and convert to correct type */
		pdef = _XmHTMLTextCheckAndConvertPaperDef(html, paperdef, type);

	if(pdef == NULL)
		return(NULL);

	switch(type)
	{
		case XmHTMLTEXT_PLAIN:
			ret_val = _XmHTMLTextGetPlain(html, pdef, HTML_ATTR(formatted),
				NULL, 0);
			break;
		case XmHTMLTEXT_FORMATTED:
			ret_val = _XmHTMLTextGetFormatted(html, pdef, HTML_ATTR(formatted),
				NULL, 0);
			break;
		case XmHTMLTEXT_POSTSCRIPT:
			ret_val = _XmHTMLTextGetPS(html, pdef, HTML_ATTR(formatted),
				NULL, PSoptions);
			break;
		default:
			_XmHTMLWarning(__WFUNC__(w, "XmHTMLTextGetFormatted"),
				XMHTML_MSG_24);
	}
	/* no longer needed */
	free(pdef);

	return(ret_val);
}
Exemplo n.º 7
0
/*****
* Name:			_XmHTMLTextGetPS
* Return Type: 	String
* Description: 	converts text between start & end into a postscript document
* In: 
*	html:		XmHTMLWidget id;
*	pdef:		papersize definition. unittype must be XmHTML_POINT;
*	start:		start object;
*	end:		end object;
*	options:	postscript options (font to use, header, footer cmds);
* Returns:
*	a String with postscript commands. Must be freed by caller.
*****/
String
_XmHTMLTextGetPS(XmHTMLWidget html, XmHTMLPaperSize *pdef, 
	XmHTMLObjectTableElement start, XmHTMLObjectTableElement end,
	Byte options)
{
	PIXMAP pixmap;
	WINDOW save;
	int scroll_x, scroll_y;
	int paint_x, paint_y, paint_w, paint_h;
	int margin_w, margin_h, work_w;
	ToolkitAbstraction *tka;
	String buf, ret_val = NULL;
	XpmAttributes xpm;
	int xpm_err = XpmSuccess;
	GC gc, bg_gc;
	int y = 0;
	XmHTMLObjectTable *pstart, *pend;

	if(pdef->unit_type != XmHTML_POINT)
	{
		_XmHTMLWarning(__WFUNC__(html, "_XmHTMLTextGetPS"),
			XMHTML_MSG_88, "POINT");
		return(NULL);
	}

	/*****
	* dirty trick: create a single pixmap in which we will draw each 
	* page. Set it as the drawable in the current tka, adjust the document
	* dimensions to reflect the selected paper properties, recalculate
	* the layout and paint each page. When a page has been rendered,
	* convert it to postscript and append to the return buffer.
	*****/

	tka = HTML_ATTR(tka);

	if(pdef->width > (Dimension)~0 || pdef->height > (Dimension)~0)
	{
		_XmHTMLWarning(__WFUNC__(html, "_XmHTMLTextGetPS"),
			"Selected paper to large. Can't convert to postscript (yet)");
		return(NULL);
	}

	if((pixmap = tka->CreatePixmap(tka->dpy, tka->DefaultRoot,
		pdef->width, pdef->height, XCCGetDepth(HTML_ATTR(xcc)))) == None)
	{
		_XmHTMLWarning(__WFUNC__(html, "_XmHTMLTextGetPS"),
			XMHTML_MSG_66, "(postscript stage 1 output)");
		return(NULL);
	}

	/* save current drawable */
	save = (WINDOW)tka->win;

	/* save all settins that will get altered */
	scroll_x = HTML_ATTR(scroll_x);
	scroll_y = HTML_ATTR(scroll_y);
	paint_y  = HTML_ATTR(paint_y);
	paint_h  = HTML_ATTR(paint_height);
	paint_x  = HTML_ATTR(paint_x);
	paint_w  = HTML_ATTR(paint_width);
	pstart   = HTML_ATTR(paint_start);
	pend     = HTML_ATTR(paint_end);
	margin_w = HTML_ATTR(margin_width);
	margin_h = HTML_ATTR(margin_height);
	work_w   = HTML_ATTR(work_width);
	gc       = HTML_ATTR(gc);
	bg_gc    = HTML_ATTR(bg_gc);

	/* reset and set paper properties */
	HTML_ATTR(scroll_x) = 0;
	HTML_ATTR(scroll_y) = 0;
	HTML_ATTR(paint_y) = 0;
	HTML_ATTR(paint_x) = 0;
	HTML_ATTR(paint_width) = pdef->width;
	HTML_ATTR(paint_height) = pdef->height - pdef->bottom_margin;
	HTML_ATTR(paint_start)  = NULL;
	HTML_ATTR(paint_end)  = NULL;
	HTML_ATTR(margin_width) = pdef->left_margin;
	HTML_ATTR(margin_height) = pdef->top_margin;
	HTML_ATTR(work_width) = pdef->width - pdef->right_margin;

	/* we also will be needing seperate GC's for this */
	HTML_ATTR(gc) = tka->CreateGC(tka->dpy, pixmap, 0, NULL);
	tka->SetFunction(tka->dpy, HTML_ATTR(gc), tka->gc_func[GC_GXcopy]);
	tka->SetForeground(tka->dpy, HTML_ATTR(gc), HTML_ATTR(body_fg));
	tka->SetBackground(tka->dpy, HTML_ATTR(gc), HTML_ATTR(body_bg));

	HTML_ATTR(bg_gc) = tka->CreateGC(tka->dpy, pixmap, 0, NULL);
	tka->CopyGC(tka->dpy, HTML_ATTR(gc), 0xFFFF, HTML_ATTR(bg_gc));

	/* set new drawable */
	_XmHTMLToolkitAbstractionSetDrawable(tka, pixmap);

	/* Recompute layout for new paper definition */
	_XmHTMLComputeLayout(html);

	/* and paint & convert each page in turn */
	while(HTML_ATTR(scroll_y) < HTML_ATTR(formatted_height))
	{
		/*****
		* Initialize pixmap if we don't have a body image. Refresh will
		* do perform background image stuff.
		*****/
		if(!HTML_ATTR(body_image))
		{
			tka->SetForeground(tka->dpy, HTML_ATTR(gc), HTML_ATTR(body_bg));
			tka->FillRectangle(tka->dpy, tka->win, HTML_ATTR(gc), 0, 0,
				pdef->width, pdef->height);
		}

		/* paint this page */
		_XmHTMLRefresh(html, 0, 0, pdef->width, pdef->height);

		/* move to next page */
		HTML_ATTR(scroll_y) += pdef->height;

		/*****
		* For now, let xpm create an XPM data buffer from the created
		* pixmap (libXpm puts the pixmap into an XImage and converts
		* the resulting data).
		* Later on we will do this by ourselves.
		*****/

		xpm.width = pdef->width;
		xpm.height = pdef->height;
		xpm.valuemask = XpmSize;
		xpm_err = XpmCreateBufferFromPixmap(tka->dpy, &buf, pixmap, None, &xpm);

		/* too bad if it fails */
		if(xpm_err != XpmSuccess)
		{
			if(buf != NULL)
				free(buf);
			switch(xpm_err)
			{
				case XpmColorError:
				case XpmColorFailed:
					fprintf(stderr, "XPM: color allocation error.\n");
					break;
				case XpmNoMemory:
					fprintf(stderr, "XPM: out of memory\n");
					break;
				default:
					fprintf(stderr, "XPM: unknown error\n");
			}
			if(ret_val)
				free(ret_val);
			ret_val = NULL;
			goto done;
		}
		else
		{
			/*****
			* TODO
			* Convert the xpm data to an XmImageInfo structure and convert
			* that to postscript.
			*
			* For now, we append the xpm data to the already received
			* pages. This will result in a multi-image pixmap, which
			* only few programs support (ImageMagick is one if I'm not
			* mistaking). Postscript output can be obtained by splitting
			* the return buffer into seperate pages and then running
			* each page through netpbm
			* (xpmtoppm image.xpm | pnmtops > page.ps)
			*****/
			if(ret_val)
			{
				ret_val = realloc(ret_val, strlen(ret_val) + strlen(buf) + 1);
				strcat(ret_val, buf);
			}
			else
				ret_val = strdup(buf);
			free(buf);
		}
	}

done:
	/* reset everything */
	HTML_ATTR(scroll_x) = scroll_x;
	HTML_ATTR(scroll_y) = scroll_y;
	HTML_ATTR(paint_y) = paint_y;
	HTML_ATTR(paint_x) = paint_x;
	HTML_ATTR(paint_width) = paint_w;
	HTML_ATTR(paint_height) = paint_h;
	HTML_ATTR(paint_start)  = pstart;
	HTML_ATTR(paint_end)  = pend;
	HTML_ATTR(margin_width) = margin_w;
	HTML_ATTR(margin_height) = margin_h;
	HTML_ATTR(work_width) = work_w;

	/* free allocated gc's */
	tka->FreeGC(tka->dpy, HTML_ATTR(gc));
	tka->FreeGC(tka->dpy, HTML_ATTR(bg_gc));

	/* restore original gc's */
	HTML_ATTR(gc) = gc;
	HTML_ATTR(bg_gc) = bg_gc;

	_XmHTMLToolkitAbstractionSetDrawable(tka, save);

	/* Do a redisplay to restore everyting correctly */
	XmHTMLRedisplay((Widget)html);

	return(ret_val);
}