#ifndef CODE_XSHADOW_CXX
#define CODE_XSHADOW_CXX

/*-----------------------------------------------------------------------
 * Xclasses code file
 * ($Id: Xshadow.cxx,v 1.1.1.1 1998/07/16 19:29:31 cvs Exp $)
 * 
 * Copyright (C) 1998 Jürgen Schmitz
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 *-----------------------------------------------------------------------
 */

#include <stdlib.h>
#include "types.h"
#include <Xclasses/Xcolors.h>
#include <Xclasses/Xshadow.h>
#include <Xclasses/tools.h>
#include <Xclasses/gadget.h>
#include "include/Xshadow_p.h"

#ifdef SHAPE
#include <X11/extensions/shape.h>
#define SCHATTEN	8

 static int do_shape=-1;
#else
#define SCHATTEN	0

 static int do_shape=0;
#endif

Xshadow::Xshadow(void) : Xwindows()
{
	if (!(p=new pXshadow))
	{
		eprintf("Out of memory, can't allocate private memory\nTerminating.");
		exit(10);
	}
	p->o=this;
	Name("Xshadow");
}
pXshadow::pXshadow(void) : shape_gg()
{
	shape_map=0;
	shape_gc=0;
	win_gc=0;
	mywin=NULL;
}
pXshadow::~pXshadow()
{
}
Xshadow::~Xshadow()
{
	Destroy();
	if (p) delete p;
}
void pXshadow::shadow(void)
{
	XSync(o->display(),0);
#ifdef SHAPE
	if (do_shape==-1)
	{
		int shape_event_base, shape_error_base;
		if (!XShapeQueryExtension(o->display(),
			&shape_event_base,&shape_error_base))
		{
			warn_printf ("no shape extension on this display",o);
			do_shape = 0;
		}
		else
		{
			do_shape=1;
		}
	}

	if (do_shape)
	{
		int w,h;
		o->Size(w,h);
		if (shape_map || (shape_map=XCreatePixmap(o->display(),o->rootwindow(),w,h,1)))
		{
			if (win_gc || (win_gc=XCreateGC(o->display(),o->window(),0,0)))
			{
				if (shape_gc || (shape_gc=XCreateGC(o->display(),shape_map,0,0)))
				{
        	        char dot[]={1,1};
            	    int cc=0,j=w-SCHATTEN;

					XSetForeground(o->display(),shape_gc,0);
					XFillRectangle(o->display(),shape_map,shape_gc,0,0,w,h);

					XSetForeground(o->display(),shape_gc,1);
					XSetDashes(o->display(),shape_gc,0,dot,2);
					XSetLineAttributes(o->display(),shape_gc,0,LineOnOffDash,CapButt,JoinRound);

					for(int i=SCHATTEN;i<h;i++)
					{
	        	        XSetDashes(o->display(),shape_gc,cc,dot,2);
	            	    cc=1-cc;
						XDrawLine(o->display(),shape_map,shape_gc,w-j,i,w,i);
					}
					XSetForeground(o->display(),shape_gc,1);
					XFillRectangle(o->display(),shape_map,shape_gc,0,0,w-SCHATTEN+2,h-SCHATTEN+2);

    	            XSetLineAttributes(o->display(),shape_gc,0,LineSolid,CapButt,JoinRound);
					XShapeCombineMask(o->display(),o->window(),ShapeBounding,
										0,0,shape_map,ShapeSet);

					XSetForeground(o->display(),win_gc,o->col_black());
					XFillRectangle(o->display(),o->window(),win_gc,0,0,w,h);
				}
			}
			else
			{
				XFreePixmap(o->display(),shape_map);
				shape_map=0;
			}
		}
	}
#endif
}
void pXshadow::resize(void)
{
	XSync(o->display(),0);
	if (shape_gc)
	{
		XFreeGC(o->display(),shape_gc);
		shape_gc=0;
	}
	if (shape_map)
	{
		XFreePixmap(o->display(),shape_map);
		shape_map=0;
	}
	int w,h;
	o->Size(w,h);
	shape_gg.Resize(w,h);
	shadow();
}
int Xshadow::Create(Xwindows *wn)
{
	int x,y,w,h;

	p->mywin=wn;

	char *r=GetResource("shadow");
	if (r && !strcasecmp(r,"TRUE"))
	{
		wn->Position(x,y);
		wn->Size(w,h);

		if (Xwindows::Create(x,y,w-SCHATTEN,h-SCHATTEN))
		{
			OverrideRedirect();
			BorderWidth(0);
			Background(col_black());

			p->shape_gg.Dimensions(window(),0,0,w,h);
			p->shape_gg.Create();
			p->shadow();

			XReparentWindow(display(),wn->window(),window(),0,0);

			return 1;
		}
		return 0;
	}
	else
		return 1;
}
void Xshadow::Destroy(void)
{
	if (window())
	{
		if (p->mywin && p->mywin->window())
		{
			int x,y;
			Position(x,y);
			XReparentWindow(display(),p->mywin->window(),rootwindow(),x,y);
		}

		p->shape_gg.Free();
		Xwindows::Destroy();
		if (p->win_gc)
		{
			XFreeGC(display(),p->win_gc);
			p->win_gc=0;
		}
		if (p->shape_gc)
		{
			XFreeGC(display(),p->shape_gc);
			p->shape_gc=0;
		}
		if (p->shape_map)
		{
			XFreePixmap(display(),p->shape_map);
			p->shape_map=0;
		}
	}
	p->mywin=NULL;
}
void Xshadow::Move(int x,int y)
{
	if (window())
		Xwindows::Move(x,y);
	else
		p->mywin->Move(x,y);
}
void Xshadow::Move(int x,int y,int w,int h)
{
	if (window())
		Xwindows::Move(x,y,w+SCHATTEN,h+SCHATTEN);
	p->mywin->Resize(w,h);

	if (window())
		p->resize();
}
void Xshadow::Resize(int w,int h)
{
	if (window())
		Xwindows::Resize(w+SCHATTEN,h+SCHATTEN);
	p->mywin->Resize(w,h);

	if (window())
		p->resize();
}

void Xshadow::Open(void)
{
	if (window())
		Xwindows::Open();
	p->mywin->Open();
}
void Xshadow::OpenU(void)
{
	if (window())
		Xwindows::OpenU();
	p->mywin->OpenU();
}
void Xshadow::Close(void)
{
	p->mywin->Close();
	if (window())
		Xwindows::Close();
}
void Xshadow::CloseU(void)
{
	p->mywin->CloseU();
	if (window())
		Xwindows::CloseU();
}
void Xshadow::Raise(void)
{
	if (window())
		Xwindows::Raise();
	else
		p->mywin->Raise();
}
void Xshadow::Lower(void)
{
	if (window())
		Xwindows::Lower();
	else
		p->mywin->Lower();
}

#endif
