//
// Copyright (C) 1999-2004 Toshikaz Hirabayashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// TOSHIKAZ HIRABAYASHI BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Except as contained in this notice, the name of Toshikaz Hirabayashi shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization from
// Toshikaz Hirabayashi.

#include <X11/Xlib.h>
#include <WScom.h>
#include <WSDenv.h>
#include <WSCcolorSet.h>
#include <x11/WSDxcolor.h>
#include <x11/WSDxappDev.h>
#include <x11/WSDunixFile.h>
#include <x11/WSDunixFS.h>
#include <unistd.h>
#include <signal.h>

WSMFclassInit(WSDxcolor,WSDcolor);

WSDcolor* _xcolor_create_handler(){
  WSDcolor* color = new WSDxcolor();
  return color;
};

void _xcolor_init(){
  extern int _ehandler(Display*,XErrorEvent*);
  XSetErrorHandler(_ehandler);
  WSGIappColorSet()->setCreateHandler(_xcolor_create_handler);
  WSGFinitUnixFileSystem();
};


WSDxcolor::WSDxcolor(){
  _private_cell = 0;
}

static Display* disp = NULL;
Colormap WSDxcolor::_colormap = (Colormap)NULL;

WSCbool WSDxcolor::colorIsStatic(){
static long _init = 0;
static long _bool = 0;
  if (_init != 0){
    return _bool;
  }
  _init = 1;

  if (disp == NULL){
       disp = XOpenDisplay((char*)NULL);
  }
  _bool = False;
  if (disp == NULL){
    return _bool;
  }
  Visual* vis = DefaultVisual(disp,DefaultScreen(disp));
  if (vis->c_class == PseudoColor || 
        vis->c_class == DirectColor){
    return _bool;
  }
  _bool = True;
  return _bool;
}

Colormap WSDxcolor::getColormap(){
  if (disp == NULL){
       disp = XOpenDisplay((char*)NULL);
  }
  if (disp == NULL){
       return (Colormap)NULL;
  }
  if (_colormap == (Colormap)NULL){
      _colormap = DefaultColormap(disp,DefaultScreen(disp));
  }
  return _colormap;
}


long WSDxcolor::initialize(){
   char* cname = getSrc();
   if (cname == NULL){
       cname = "black";
   }
   if ( colorIsStatic() == True || getUsePrivateCell() == False ){
     Colormap cmap;
     XColor c0;
     XColor c1;
     if (disp == NULL){
       disp = XOpenDisplay((char*)NULL);
     }
     if (disp == NULL){
       return WS_ERR;
     }
     cmap = getColormap();
     XAllocNamedColor(disp,cmap,cname,&c1,&c0);
     long pix = (long)c1.pixel;
     setValue1(pix);
     _xc1 = c0;

   }else{
     Colormap cmap;
     if (disp == NULL){
       disp = XOpenDisplay((char*)NULL);
     }
     if (disp == NULL){
       return WS_ERR;
     }
     cmap = getColormap();
     WSCulong dummy;
     if (_private_cell == 0){
       XAllocColorCells(disp,cmap,True, &dummy,0, &_private_cell,1);
     }

     XStoreNamedColor(disp,cmap, cname, _private_cell,
                      DoRed|DoGreen|DoBlue);
     XColor xc;
     xc.pixel = _private_cell;
     xc.flags = DoRed | DoGreen | DoBlue;
     XQueryColor(disp,cmap,&xc);

     long pix = (long)_private_cell;

     setValue1(pix);
     _xc1 = xc;
   }
   return WS_NO_ERR;
}
XColor* WSDxcolor::getXColor1(){
  return &_xc1;
}
long WSDxcolor::getRGB(long* r,long* g,long* b){
  if (WSDcolor::getRGB(r,g,b) == WS_ERR){
    *r = _xc1.red >>8;
    *g = _xc1.green >>8;
    *b = _xc1.blue >>8;
  }  
  return WS_NO_ERR;
}
