//
// 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 <x11/WSDxmouse.h>
#include <x11/WSDxappDev.h>
#include <x11/WSDxformDev.h>
#include <x11/WSDxcolor.h>
#include <WSCbase.h>
#include <WSCcolorSet.h>
#include <WSDfileSystem.h>

WSMFclassInit(WSDxmouse,WSDmouse);

WSDmouse* _xmouse_create_handler(){
  return new WSDxmouse();
}

class _xmouse_init{
  public: _xmouse_init(){
    WSDmouse::setCreateInstanceHandler(_xmouse_create_handler);
  };
};

_xmouse_init _xmouse_init_run_constructor;


WSDxmouse* WSGIxappMouse(){
  WSDmouse* mouse = WSGIappMouse();
  if (mouse == NULL){
    return NULL;
  }
  WSDxmouse* xmouse =(WSDxmouse*)mouse->cast("WSDxmouse");
  return xmouse;

}

char* dmnames[]={
//no  img1  img2
" 0     132        0          black      white",
" 128   0          0          black      white",
" 129   2          0          black      white",
" 130   4          0          black      white",
" 131   6          0          black      white",
" 132   8          0          black      white",
" 133   10         0          black      white",
" 134   12         0          black      white",
" 135   14         0          black      white",
" 136   16         0          black      white",
" 137   18          0          black      white",
" 138   20          0          black      white",
" 139   22          0          black      white",
" 140   24          0          black      white",
" 141   26          0          black      white",
" 142   28          0          black      white",
" 143   30          0          black      white",
" 144   32          0          black      white",
" 145   34          0          black      white",
" 146   36          0          black      white",
" 147   38          0          black      white",
" 148   40          0          black      white",
" 149   42          0          black      white",
" 150   44          0          black      white",
" 151   46          0          black      white",
" 152   48          0          black      white",
" 153   50          0          black      white",
" 154   52          0          black      white",
" 155   54          0          black      white",
" 156   56          0          black      white",
" 157   58          0          black      white",
" 158   60          0          black      white",
" 159   62          0          black      white",
" 160   64          0          black      white",
" 161   66          0          black      white",
" 162   68          0          black      white",
" 163   70          0          black      white",
" 164   72         0          black      white",
" 165   74         0          black      white",
" 166   76         0          black      white",
" 167   78         0          black      white",
" 168   80         0          black      white",
" 169   82          0          black      white",
" 170   84          0          black      white",
" 171   86          0          black      white",
" 172   88          0          black      white",
" 173   90          0          black      white",
" 174   92          0          black      white",
" 175   94          0          black      white",
" 176   96          0          black      white",
" 177   98          0          black      white",
" 178   100          0          black      white",
" 179   102          0          black      white",
" 180   104          0          black      white",
" 181   106          0          black      white",
" 182   108          0          black      white",
" 183   110          0          black      white",
" 184   112          0          black      white",
" 185   114          0          black      white",
" 186   116          0          black      white",
" 187   118          0          black      white",
" 188   120          0          black      white",
" 189   122          0          black      white",
" 190   124          0          black      white",
" 191   126          0          black      white",
" 192   128          0          black      white",
" 193   130          0          black      white",
" 194   132          0          black      white",
" 195   134          0          black      white",
" 196   136          0          black      white",
" 197   138          0          black      white",
" 198   140          0          black      white",
" 199   142          0          black      white",
" 200   144          0          black      white",
" 201   146          0          black      white",
" 202   148          0          black      white",
" 203   150          0          black      white",
" 204   152          0          black      white",
NULL
};

WSDxmouse::WSDxmouse(){}
WSDxmouse::~WSDxmouse(){}

void WSDxmouse::resetMouseCursors(){
  long cnt = 0;
  while(1){
    long id = getMouseCursorId(cnt);
    if (id == 0){
      cnt++;
    }else if (id > -1){
      delMouseCursor(cnt);
    }else{
      break;
    }
  }
}

void WSDxmouse::setMouseCursor(long mno){}
void WSDxmouse::initialize(){
  long num = 0;
  while(dmnames[num] != NULL){
    WSGIxappMouse()->setupMouseCursor(dmnames[num]);
    num++;
  };
}


void WSDxmouse::setupMouseCursor(char* data){
  long id;
  char img1[1024];
  char img2[1024];
  char forec[64];
  char backc[64];
  sscanf(data,"%d %s %s %s %s",&id,img1,img2,forec,backc);
  long img = atoi(img1);
  long val = 0;
  if (img != 0){
    val = (long)XCreateFontCursor(WSGIxwinAppDev()->display(),img);
    WSDcolor* fg = WSGIappColorSet()->getColor(forec);
    WSDcolor* bg = WSGIappColorSet()->getColor(backc);
    WSDxcolor* xfg = (WSDxcolor*)fg->cast("WSDxcolor");
    WSDxcolor* xbg = (WSDxcolor*)bg->cast("WSDxcolor");
    XRecolorCursor( WSGIxwinAppDev()->display(),val,xfg->getXColor1(),xbg->getXColor1() );
  }else if ( img == 0 && strcmp("0",img1) ){
    Pixmap bm1 = 0;
    Pixmap bm2 = 0;
    WSCuint w,h;
    int x,y,x2,y2;
    XReadBitmapFile (WSGIxwinAppDev()->display(),
         XtWindow(WSGIxwinAppDev()->appWidget()),
         WSGIappFileSystem()->adjustFileName(img1), &w,&h,&bm1,&x,&y);
    if ( atoi(img2) == 0 && strcmp("0",img2) ){
      XReadBitmapFile (WSGIxwinAppDev()->display(),
         XtWindow(WSGIxwinAppDev()->appWidget()),
         WSGIappFileSystem()->adjustFileName(img2), &w,&h,&bm2,&x2,&y2);
    }
    if (bm2 == 0){
      bm2 = bm1;
    }
    if (x < 0 ){
      x =0;
    }
    if (y < 0 ){
      y =0;
    }
    if (bm1 == 0){
      val = (long)XCreateFontCursor(WSGIxwinAppDev()->display(),132);
    }else{
      WSDcolor* fg = WSGIappColorSet()->getColor(forec);
      WSDcolor* bg = WSGIappColorSet()->getColor(backc);
      WSDxcolor* xfg = (WSDxcolor*)fg->cast("WSDxcolor");
      WSDxcolor* xbg = (WSDxcolor*)bg->cast("WSDxcolor");
      val =(long)XCreatePixmapCursor( WSGIxwinAppDev()->display(),bm1,bm2,
      xfg->getXColor1(),xbg->getXColor1(),x,y);
    }

  }
  addMouseCursor(id,val,data);
}
long WSDxmouse::getDefaultMouseCursor(){
static long _default_mouse = 0;
  if (_default_mouse == 0){
    long img = 132; // x mouse arrow
    long val = (long)XCreateFontCursor(WSGIxwinAppDev()->display(),img);
    WSDcolor* fg = WSGIappColorSet()->getColor("black");
    WSDcolor* bg = WSGIappColorSet()->getColor("white");
    WSDxcolor* xfg = (WSDxcolor*)fg->cast("WSDxcolor");
    WSDxcolor* xbg = (WSDxcolor*)bg->cast("WSDxcolor");
    XRecolorCursor( WSGIxwinAppDev()->display(),val,xfg->getXColor1(),xbg->getXColor1() );
    _default_mouse = val;
  }
  return _default_mouse;
}


Window WSDxmouse::getCurrentMouseWindow(){
   int x,y,dx,dy;
   Window dr,dc;
   WSCuint ds;
   Window src = DefaultRootWindow(WSGIxwinAppDev()->display());
   while(1){
     WSCbool ret = XQueryPointer(WSGIxwinAppDev()->display(),src,
                               &dr,&dc,&dx,&dy,&x,&y,&ds);
     if (ret == False){
	   return 0;
	 }
	 if (dc == 0){
	   return src;
	 }
     src = dc;
   }
   return dc;
}

WSCbool WSDxmouse::getMousePosition(short* ox,short* oy){
   int x,y,dx,dy;
   Window dr,dc;
   WSCuint ds;
   WSCbool ret = XQueryPointer(WSGIxwinAppDev()->display(),
                               DefaultRootWindow(WSGIxwinAppDev()->display()),
                               &dr,&dc,&dx,&dy,&x,&y,&ds);
   *ox = x;
   *oy = y;
   return ret;
}


WSCbool WSDxmouse::getMousePosition(short* ox,short* oy,WSCbase* client){
   long     cnt = 0;
   Window w = DefaultRootWindow(WSGIxwinAppDev()->display());
   if (client != NULL){
       WSCbase* target = client;
       while(1){
         WSDdev* dev = target->getdev();
         if (dev == NULL){
           *ox = 0;
           *oy = 0;
           return False;
         }
         WSDxformDev* xdev = (WSDxformDev*)dev->cast("WSDxformDev");
         if (xdev == NULL){
            cnt++;
         }else{
            if (XtIsManaged(xdev->getWidget()) == True &&
                XtIsRealized(xdev->getWidget()) == True){
              w = XtWindow(xdev->getWidget());
              break;
            }else{
              *ox = 0;
              *oy = 0;
              return False;
            }
         }
         target = target->getParent();
         if (target == NULL){
              *ox = 0;
              *oy = 0;
              return False;
         }
       }
   }

   int x,y,dx,dy;
   Window dr,dc;
   WSCuint ds;
   WSCbool ret = XQueryPointer(WSGIxwinAppDev()->display(),w,
                               &dr,&dc,&dx,&dy,&x,&y,&ds);


   WSCbase* parent = client;
   long i;
   for(i=0; i< cnt; i++){
     short px,py;
     parent->getPropertyV(WSNx,&px);
     parent->getPropertyV(WSNy,&py);
     x -= px;
     y -= py;
     parent = client->getParent();
     if (parent == NULL){
       break;
     }
   }

   *ox = x;
   *oy = y;
   return ret;
}

long WSDxmouse::getMouseStatus(){
   int x,y,dx,dy;
   Window dr,dc;
   WSCuint ds;
   XQueryPointer(WSGIxwinAppDev()->display(),
                 DefaultRootWindow(WSGIxwinAppDev()->display()),
                 &dr,&dc,&dx,&dy,&x,&y,&ds);
   return ds;
}

void WSDxmouse::setMousePosition(short x,short y){
  XWarpPointer(WSGIxwinAppDev()->display(),None,
       DefaultRootWindow(WSGIxwinAppDev()->display()),0,0,0,0,x,y);
}


