

#include "WINGsP.h"

#include <X11/Xutil.h>





/********** data ************/


#define CHECK_BUTTON_ON_WIDTH 	16
#define CHECK_BUTTON_ON_HEIGHT 	16

static char *CHECK_BUTTON_ON[] = {
"               %",
" .............%#",
" ........... .%#",
" .......... #.%#",
" ......... #%.%#",
" ........ #%..%#",
" ... #.. #%...%#",
" ... #% #%....%#",
" ... % #%.....%#",
" ...  #%......%#",
" ... #%.......%#",
" ...#%........%#",
" .............%#",
" .............%#",
" %%%%%%%%%%%%%%#",
"%###############"};

#define CHECK_BUTTON_OFF_WIDTH 	16
#define CHECK_BUTTON_OFF_HEIGHT	16

static char *CHECK_BUTTON_OFF[] = {
"               %",
" .............%#",
" .............%#",
" .............%#",
" .............%#",
" .............%#",
" .............%#",
" .............%#",
" .............%#",
" .............%#",
" .............%#",
" .............%#",
" .............%#",
" .............%#",
" %%%%%%%%%%%%%%#",
"%###############"};

#define RADIO_BUTTON_ON_WIDTH 	15
#define RADIO_BUTTON_ON_HEIGHT	15
static char *RADIO_BUTTON_ON[] = {
".....%%%%%.....",
"...%%#####%%...",
"..%##.....%.%..",
".%#%..    .....",
".%#.        ...",
"%#..        .. ",
"%#.          . ",
"%#.          . ",
"%#.          . ",
"%#.          . ",
".%%.        . .",
".%..        . .",
"..%...    .. ..",
".... .....  ...",
".....     .....",
};

#define RADIO_BUTTON_OFF_WIDTH 	15
#define RADIO_BUTTON_OFF_HEIGHT	15
static char *RADIO_BUTTON_OFF[] = {
".....%%%%%.....",
"...%%#####%%...",
"..%##.......%..",
".%#%...........",
".%#............",
"%#............ ",
"%#............ ",
"%#............ ",
"%#............ ",
"%#............ ",
".%%.......... .",
".%........... .",
"..%......... ..",
".... .....  ...",
".....     .....",
};


static char *BUTTON_ARROW[] = {
"..............%",
"....##....#### ",
"...#.%....#... ",
"..#..%#####... ",
".#............ ",
"#............. ",
".#............ ",
"..#..          ",
"...#. .........",
"....# ........."
};

#define BUTTON_ARROW_WIDTH	15
#define BUTTON_ARROW_HEIGHT	10


static char *BUTTON_ARROW2[] = {
"               ",
"    ##    ####.",
"   # %    #   .",
"  #  %#####   .",
" #            .",
"#             .",
" #            .",
"  #  ..........",
"   # .         ",
"    #.         "
};

#define BUTTON_ARROW2_WIDTH	15
#define BUTTON_ARROW2_HEIGHT	10



#define NORMAL_FONT "-*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*"
#define LARGE_FONT "-*-helvetica-bold-r-*-*-24-*-*-*-*-*-*-*"


#define LIGHT_STIPPLE_WIDTH 4
#define LIGHT_STIPPLE_HEIGHT 4
static unsigned char LIGHT_STIPPLE_BITS[] = {
   0x05, 0x0a, 0x05, 0x0a};

#define DARK_STIPPLE_WIDTH 4
#define DARK_STIPPLE_HEIGHT 4
static unsigned char DARK_STIPPLE_BITS[] = {
   0x0a, 0x04, 0x0a, 0x01};


/*****  end data  ******/




static void
renderPixmap(W_Screen *screen, Pixmap d, char **data, int width, int height)
{
    int x, y;
    

    for (y = 0; y < height; y++) {
	for (x = 0; x < width; x++) {
	    switch (data[y][x]) {
	     case ' ':
	     case 'w':
		XDrawPoint(screen->display, d, screen->whiteGC, x, y);
		break;

	     case '.':
	     case 'l':
		XDrawPoint(screen->display, d, screen->lightGC, x, y);
		break;
		
	     case '%':
	     case 'd':
		XDrawPoint(screen->display, d, screen->darkGC, x, y);
		break;
		
	     case '#':
	     case 'b':
	     default:
		XDrawPoint(screen->display, d, screen->blackGC, x, y);
		break;
	    }
	}
    }
}



static WMPixmap*
makePixmap(W_Screen *sPtr, char **data, int width, int height)
{
    Pixmap pixmap;
    
    pixmap = XCreatePixmap(sPtr->display, sPtr->rootWin, width, height, 
			   sPtr->depth);

    renderPixmap(sPtr, pixmap, data, width, height);

    return WMCreatePixmapFromXPixmaps(sPtr, pixmap, None, width, height, 
				      sPtr->depth);
}


#ifdef WMAKER
WMScreen*
WMCreateScreen(Display *display, int screen, RContext *context)
#else
WMScreen*
WMCreateScreen(Display *display, int screen)
#endif
{
    W_Screen *scrPtr;
    XColor color;
    XGCValues gcv;
    
    scrPtr = malloc(sizeof(W_Screen));
    if (!scrPtr)
	return NULL;
    memset(scrPtr, 0, sizeof(W_Screen));
    
    scrPtr->display = display;
    scrPtr->screen = screen;

    scrPtr->depth = DefaultDepth(display, screen);

    scrPtr->visual = DefaultVisual(display, screen);
    scrPtr->lastEventTime = 0;

    scrPtr->colormap = DefaultColormap(display, screen);

    scrPtr->whitePixel = WhitePixel(display, screen);
    
    scrPtr->blackPixel = BlackPixel(display, screen);

#ifndef WMAKER
    scrPtr->rcontext = RCreateContext(display, screen, NULL);
#else
    scrPtr->rcontext = context;
#endif
	
    if (scrPtr->depth > 1) {
	color.flags = DoRed|DoGreen|DoBlue;
    
	color.red = 0xaeba;
	color.green = 0xaaaa;
	color.blue = 0xaeba;
	if (!XAllocColor(display, scrPtr->colormap, &color)) {
	    wWarning("could not allocate light gray color");
	    scrPtr->lightPixel = scrPtr->whitePixel;
	} else {
	    scrPtr->lightPixel = color.pixel;
	}
	
	color.red = 0x5144;
	color.green = 0x5555;
	color.blue = 0x5144;
	if (!XAllocColor(display, scrPtr->colormap, &color)) {
	    wWarning("could not allocate dark gray color");
	} else {
	    scrPtr->darkPixel = scrPtr->blackPixel;
	}
	scrPtr->darkPixel = color.pixel;
    }
    
    scrPtr->rootWin = RootWindow(display, screen);

    
    gcv.function = GXcopy;
    scrPtr->copyGC = XCreateGC(display, scrPtr->rootWin, GCFunction, &gcv);
    
    gcv.foreground = scrPtr->whitePixel;
    scrPtr->whiteGC = XCreateGC(display, scrPtr->rootWin, GCForeground, &gcv);

    gcv.foreground = scrPtr->blackPixel;
    scrPtr->blackGC = XCreateGC(display, scrPtr->rootWin, GCForeground, &gcv);

    if (scrPtr->depth > 1) {
	gcv.foreground = scrPtr->lightPixel;
	scrPtr->lightGC = XCreateGC(display, scrPtr->rootWin, GCForeground, 
				    &gcv);

	gcv.foreground = scrPtr->darkPixel;
	scrPtr->darkGC = XCreateGC(display, scrPtr->rootWin, GCForeground, 
				   &gcv);
    } else {
	Pixmap lightStipple, darkStipple;
	
	lightStipple = XCreateBitmapFromData(display, scrPtr->rootWin, 
					     LIGHT_STIPPLE_BITS, 
					     LIGHT_STIPPLE_WIDTH,
					     LIGHT_STIPPLE_HEIGHT);

	darkStipple = XCreateBitmapFromData(display, scrPtr->rootWin, 
					    DARK_STIPPLE_BITS, 
					    DARK_STIPPLE_WIDTH,
					    DARK_STIPPLE_HEIGHT);

	gcv.foreground = scrPtr->whitePixel;
	gcv.background = scrPtr->blackPixel;
	gcv.fill_style = FillStippled;
	gcv.stipple = lightStipple;
	scrPtr->lightGC = XCreateGC(display, scrPtr->rootWin,
				    GCForeground|GCBackground|GCStipple
				    |GCFillStyle, &gcv);

	gcv.foreground = scrPtr->whitePixel;
	gcv.background = scrPtr->blackPixel;
	gcv.fill_style = FillStippled;
	gcv.stipple = darkStipple;
	scrPtr->darkGC = XCreateGC(display, scrPtr->rootWin, 
				   GCForeground|GCBackground|GCStipple
				   |GCFillStyle, &gcv);

	XFreePixmap(display, lightStipple);
	XFreePixmap(display, darkStipple);
    }
    
    
    scrPtr->normalFont = WMLoadFont(scrPtr, NORMAL_FONT);
    gcv.font = scrPtr->normalFont->font->fid;
    gcv.foreground = scrPtr->blackPixel;
    scrPtr->normalFontGC = XCreateGC(display, scrPtr->rootWin, 
				     GCFont|GCForeground, &gcv);
    

    scrPtr->largeFont = WMLoadFont(scrPtr, LARGE_FONT);
    gcv.font = scrPtr->largeFont->font->fid;
    

    scrPtr->checkButtonImageOn = makePixmap(scrPtr, CHECK_BUTTON_ON,
					    CHECK_BUTTON_ON_WIDTH,
					    CHECK_BUTTON_ON_HEIGHT);

    scrPtr->checkButtonImageOff = makePixmap(scrPtr, CHECK_BUTTON_OFF,
					    CHECK_BUTTON_OFF_WIDTH,
					    CHECK_BUTTON_OFF_HEIGHT);

    scrPtr->radioButtonImageOn = makePixmap(scrPtr, RADIO_BUTTON_ON,
					    RADIO_BUTTON_ON_WIDTH,
					    RADIO_BUTTON_ON_HEIGHT);

    scrPtr->radioButtonImageOff = makePixmap(scrPtr, RADIO_BUTTON_OFF,
					    RADIO_BUTTON_OFF_WIDTH,
					    RADIO_BUTTON_OFF_HEIGHT);

    scrPtr->buttonArrow = makePixmap(scrPtr, BUTTON_ARROW, 
				     BUTTON_ARROW_WIDTH, BUTTON_ARROW_HEIGHT);

    scrPtr->pushedButtonArrow = makePixmap(scrPtr, BUTTON_ARROW2,
			           BUTTON_ARROW2_WIDTH, BUTTON_ARROW2_HEIGHT);

    
    scrPtr->internalMessage = XInternAtom(display, "_WINGS_MESSAGE", False);
    
    return scrPtr;
}



void
WMPlaceWidget(WMWidget *widget, int x, int y)
{
    W_View *view = W_VIEW(widget);

    W_MoveView(view, x, y);
}



void
WMSetApplicationIcon(WMScreen *scrPtr, WMPixmap *icon)
{
    scrPtr->applicationIcon = WMRetainPixmap(icon);
}


void 
WMHangData(WMWidget *widget, void *data)
{
    W_VIEW(widget)->hangedData = data;
}


void*
WMGetHangedData(WMWidget *widget)
{
    return W_VIEW(widget)->hangedData;
}



void
WMDestroyWidget(WMWidget *widget)
{
    W_DestroyView(W_VIEW(widget));
}


 
void
W_SetFocusToWidget(WMWidget *widget)
{
    W_SCREEN(widget)->focusedControl = W_VIEW(widget);
}



void
WMBindEvent(WMWidget *widget, WMEventType eventType, WMCallBack *callback, 
	    void *clientData)
{
    switch (W_CLASS(widget)) {
     case WC_Button:
	W_BindButtonEvent(widget, eventType, callback, clientData);
	break;
     default:
	wWarning("trying to bind an event handler for a invalid widget");
    }
}

#if 0
WMWidget*
WMCloneWidget(WMWidget *widget)
{
    switch (W_CLASS(widget)) {
     case WC_Button:
	W_CloneButton(widget);
	break;
    }
}
#endif


void
WMMapWidget(WMWidget *w)
{        
    if (!W_VIEW(w)->flags.realized) {
	W_RealizeView(W_VIEW(w));

	if (!W_VIEW(w)->flags.realized)
	    return;
    }
    
    if (!W_VIEW(w)->flags.mapped) {
	
	XMapRaised(W_SCREEN(w)->display, W_VIEW(w)->window);
#ifdef WMAKER
	if (W_VIEW(w)->wmakerParent!=None)
	    XMapRaised(W_SCREEN(w)->display, W_VIEW(w)->wmakerParent);
#endif
	XFlush(W_SCREEN(w)->display);
	
	W_VIEW(w)->flags.mapped = 1;
    }
}



void
WMMapSubwidgets(WMWidget *w)
{   
    W_View *view;
    
    if (!W_VIEW(w)->flags.realized) {
	W_RealizeView(W_VIEW(w));

	if (!W_VIEW(w)->flags.realized)
	    return;
    }
    
    XMapSubwindows(W_SCREEN(w)->display, W_VIEW(w)->window);
#ifdef WMAKER
    if (W_VIEW(w)->wmakerParent!=None)
    	XMapSubwindows(W_SCREEN(w)->display, W_VIEW(w)->wmakerParent);
#endif
    XFlush(W_SCREEN(w)->display);
    
    view = W_VIEW(w)->childrenList;
    while (view) {
	view->flags.mapped = 1;
	view = view->nextSister;
    }
}



void
WMUnmapWidget(WMWidget *w)
{    
    if (!W_VIEW(w)->flags.mapped)
	return;
    
    XUnmapWindow(W_SCREEN(w)->display, W_VIEW(w)->window);
#ifdef WMAKER
    if (W_VIEW(w)->wmakerParent!=None)
    	XUnmapWindow(W_SCREEN(w)->display, W_VIEW(w)->wmakerParent);
#endif
    XFlush(W_SCREEN(w)->display);
    
    W_VIEW(w)->flags.mapped = 0;
}
