//
// 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/Intrinsic.h>
#include <X11/StringDefs.h>
#include <WSCdevice.h>
#include <WSCcolorSet.h>
#include <WSCimageSet.h>
#include <WSCbase.h>
#include <WSDmouse.h>
#include <WSCbaseList.h>
#include <x11/WSDxformDev.h>
#include <x11/WSDxappDev.h>
#include <x11/WSDxdraw.h>
#include <x11/WSxcom.h>
#include <x11/WSDxdragDrop.h>
#include <form.h>
//TEST
#include <x11/WSDxscrFrameDev.h>
//TEST

WSMFclassInit(WSDxformDev,WSDwindowDev);

WSDdev* _wsdxformdev_init_(){
  return new WSDxformDev();
}

class _WSDxformDev_init_ {
  public:_WSDxformDev_init_(){
     WSGIappDevice()->setCreateHandler("formDev",_wsdxformdev_init_);
  };
};
static _WSDxformDev_init_ _init_to_run_WSDxformDev_;

//static WSDxdraw* draw_of_xform = NULL;

WSDxformDev::WSDxformDev(){
  _pwidget = 0;
  _widget  = 0;
  _pixmap  = 0;
  _gc      = 0;
  _bg = -1;
  _bg_pix = -1;
  _mno = 0;
  _click_time = 0;

//  if (draw_of_xform == NULL){
//      draw_of_xform = new WSDxdraw();
//  }
//  setDraw(draw_of_xform);
}

WSDxformDev::~WSDxformDev(){
  destroyContext();
  destroyPixmap();
  destroyWindow();
}

WSDdev* WSDxformDev::getEventParentDev(){
  return this;
}

Widget WSDxformDev::getWidget(){
  return _widget;
}

long WSDxformDev::setValue(long kind,void* data){
  short bx,by;
  WSCushort bw,bh;
  if (kind == WSDEV_X && *(short*)data == _w_x){
    return WS_NO_ERR;
  }
  if (kind == WSDEV_Y && *(short*)data == _w_y){
    return WS_NO_ERR;
  }
  if (kind == WSDEV_WIDTH && *(WSCushort*)data == _w_w){
    return WS_NO_ERR;
  }
  if (kind == WSDEV_HEIGHT && *(WSCushort*)data == _w_h){
    return WS_NO_ERR;
  }

  WSDwindowDev::setValue(kind,data);

  Arg args[4];
  WSDcolor* color;
  WSDimage* image;
  WSCbool unmanaged = False;
  WSCbool fl;
  switch(kind){
    case WSDEV_X: 
             if (_widget == NULL){
               break;
             }
             if (getVisible() == True){
                WSDxformDev* pdev = getParentAreaDev();
                XtSetArg(args[0],XtNx,&bx);
                XtSetArg(args[1],XtNwidth,&bw);
                XtGetValues((Widget)_widget,args,2);
                if (pdev != NULL &&
                    (pdev->getWidth()-1  < *(short*)data + bw 
                     || pdev->getWidth()-1  < bx + bw  
                     || pdev->getHeight()-1 < _w_y + _w_h) ){
                  unmanaged = True;
                  XtUnmanageChild((Widget)_widget);
                }
             }

             XtSetArg(args[0],XtNx,*(short*)data);
             XtSetValues((Widget)_widget,args,1);
             if (unmanaged == True){
               XtManageChild((Widget)_widget);
             }
             break;
    case WSDEV_Y:
             if (_widget == NULL){
               break;
             }
             if (getVisible() == True){
                WSDxformDev* pdev = getParentAreaDev();
                XtSetArg(args[0],XtNy,&by);
                XtSetArg(args[1],XtNheight,&bh);
                XtGetValues((Widget)_widget,args,2);
                if (pdev != NULL &&
                    (pdev->getHeight() -1 < *(short*)data + bh
                     || pdev->getHeight() -1  < by + bh
                     || pdev->getWidth() -1 < _w_x + _w_w )){
                  XtUnmanageChild((Widget)_widget);
                  unmanaged = True;
                }
             }

             XtSetArg(args[0],XtNy,*(short*)data);
             XtSetValues((Widget)_widget,args,1);
             if (unmanaged == True){
               XtManageChild((Widget)_widget);
             }
             break;
    case WSDEV_WIDTH:
             if (_widget == NULL){
               break;
             }
             if (getPixmapStyle() != WS_DIRECT_WINDOW){
               destroyPixmap();
             }
             if (*(WSCushort*)data > 0){
               XtSetArg(args[0],XtNwidth,*(WSCushort*)data);
               XtSetValues((Widget)_widget,args,1);
             }
             break;
    case WSDEV_HEIGHT:
             if (_widget == NULL){
               break;
             }
             if (getPixmapStyle() != WS_DIRECT_WINDOW){
               destroyPixmap();
             }
             if (*(WSCushort*)data > 0){
               XtSetArg(args[0],XtNheight,*(WSCushort*)data);
               XtSetValues((Widget)_widget,args,1);
             }
             break;
    case WSDEV_BACKCOLOR:
             color = WSGIappColorSet()->getColor(*(short*)data);
             _bg = *(short*)data;
             if (_widget == NULL){
               break;
             }
             if (color != NULL){
               XtSetArg(args[0],XtNbackground,color->getValue1());
               XtSetValues((Widget)_widget,args,1);
             }
             break;
    case WSDEV_BACK_PIXMAP:
             _bg_pix = *(short*)data;
             if (_widget == NULL){
               break;
             }
             if (*(short*)data == -2 ){
               XtSetArg(args[0],XtNbackgroundPixmap,0);
               XtSetValues((Widget)_widget,args,1);
             }else
             if (*(short*)data == -1){
               XtSetArg(args[0],XtNbackgroundPixmap,UNSPECIFIED_PIXMAP);
               XtSetValues((Widget)_widget,args,1);
             }else{
               image = WSGIappImageSet()->getImage(*(short*)data);
               if (image != NULL){
                 if (image->getValue1() == -1){
                   XtSetArg(args[0],XtNbackgroundPixmap,UNSPECIFIED_PIXMAP);
                 }else{
                   Pixmap pid = (Pixmap)image->getValue1();
                   XtSetArg(args[0],XtNbackgroundPixmap,pid);
                 }
                 XtSetValues((Widget)_widget,args,1);
               }
             }
             break;
    case WSDEV_GRAB_POINTER:
             if (_widget == NULL){
               break;
             }
             fl = *(WSCbool*)data;
             if (fl != False){
               XGrabPointer(XtDisplay(_widget),XtWindow(_widget),False,
                  ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
                  GrabModeAsync,GrabModeAsync,None,None,CurrentTime);
               XGrabKeyboard(XtDisplay(_widget),XtWindow(_widget),False,
                  GrabModeAsync,GrabModeAsync,CurrentTime);
             }else{
               XUngrabPointer(XtDisplay(_widget),CurrentTime);
               XUngrabKeyboard(XtDisplay(_widget),CurrentTime);
             }
             break;
     case WSDEV_MOUSE_NO:
             _mno = *(WSCushort*)data;
             if (_widget != NULL && XtWindow(_widget) != 0){
               long val = WSGIappMouse()->getMouseCursor(_mouse_no);
               if (val != 0){
                 XDefineCursor(XtDisplay(_widget),XtWindow(_widget),val);
               }
             }
             break;
     default:
      return WS_NO_ERR;
  }
  return WS_NO_ERR;
}
WSCushort WSDxformDev::getMouseNo(){
  return _mno;
}
void WSDxformDev::_copy_area(long x,long y,WSCulong w,WSCulong h,long dx,long dy,WSCuchar fl){
  if (_widget == NULL){
    return;
  }
  Display* disp = WSGIxwinAppDev()->display();
  GC gc = getGC();
  if (fl == WS_PIXMAP_TO_WINDOW){
     Pixmap pix = getPixmap();
     if (pix == 0 || gc  == 0){
        return;
     }
     XCopyArea( disp,pix,XtWindow(_widget),gc,
          (int)x, (int)y, (WSCuint)w, (WSCuint)h, (int)dx, (int)dy);
  }else{
     XCopyArea( disp,XtWindow(_widget),XtWindow(_widget),gc,
          (int)x, (int)y, (WSCuint)w, (WSCuint)h, (int)dx, (int)dy);
     while(1){
       XFlush(disp);
       XEvent e;
       Bool fl =  XCheckTypedWindowEvent(disp,XtWindow(_widget),
                   GraphicsExpose,&e);
       if (fl == 1){
         e.type = Expose;
         XtDispatchEvent(&e);
         WSGIappObjectList()->execInitialize();
         WSGIappObjectList()->execUpdate();
         break;
       }
       fl =  XCheckTypedWindowEvent(disp,XtWindow(_widget),
                   NoExpose,&e);
       if (fl == 1){
         break;
       }
     }
  }
}

void WSDxformDev::_clear_area(long x,long y,WSCulong w,WSCulong h){
  if (_widget == NULL){
    return;
  }
  XClearArea(XtDisplay(_widget),XtWindow(_widget),x,y,w,h,False);
}
WSDxformDev* WSDxformDev::getParentAreaDev(){
  WSDdev*      pdev = WSDxformDev::getParentDev();
  if (pdev == NULL){
    return NULL;
  }

  WSDxformDev* xdev = (WSDxformDev*)pdev->cast("WSDxformDev");
  if (xdev == NULL){
    while(xdev == NULL){
      pdev = pdev->getParentDev();
      if (pdev == NULL){
        return NULL;
      }
      xdev = (WSDxformDev*)pdev->cast("WSDxformDev");
    }
  }
  return xdev;
}

void WSDxformDev::_setup_pixmap(short x,short y,WSCushort w,WSCushort h,short bg,short img_no){
  WSDcolor*  color = WSGIappColorSet()->getColor(bg);


  GC gc = WSGIxwinAppDev()->appGC2();
  if (gc == 0){
      return;
  }
  Display* disp = WSGIxwinAppDev()->display();
  if (color != NULL){
      WSCulong  pixel = (WSCulong )color->getValue1();
      XSetForeground(disp,gc,pixel);
  }

  Pixmap pix = getPixmap();
  if (getPixmap() != 0){
    if (img_no != -1 && img_no != 0){
      WSDimage* image = WSGIappImageSet()->getImage(img_no);
      if (image != NULL && image->getValue1() != -1){
         WSCushort pw = image->getImageWidth();
         WSCushort ph = image->getImageHeight();
         Pixmap pid = (Pixmap)image->getValue1();
         short cw = 0;
         while(1){
             short ch = 0;
             while(1){
               XCopyArea( disp,pid,pix,gc,
                         (int)0, (int)0, (WSCuint)pw, (WSCuint)ph,
                         (int)cw, (int)ch);
               ch += ph;
               if (ch > h) break;
             }
             cw += pw;
             if (cw > w) break;
         }

      }else{
        XFillRectangle(disp,pix, gc,(int)x,(int)y,(WSCuint)w,(WSCuint)h);
      }
    }else{
      XFillRectangle(disp,pix, gc,(int)x,(int)y,(WSCuint)w,(WSCuint)h);
    }
  }
  return;
}

long WSDxformDev::createWindow(){
  if (_widget != 0){
    WSDxformDev* xdev = getParentAreaDev();
    if (xdev != NULL && xdev->getWidget() != _pwidget){
      XtRemoveCallback(_widget,XtNdestroyCallback,_evh_delete2,this);
    }else{
      //In this case,it needs no re-creation...
      return WS_NO_ERR;
    }
  }

  short x,y;    
  WSCushort w,h;    
  getWindowSize(&x,&y,&w,&h);
  if (w == 0){
    w = 1;
  }
  if (h == 0){
    h = 1;
  }

  WSDxformDev* xdev;
  xdev = getParentAreaDev();

  if (xdev == NULL){
    return WS_ERR;
  }

  Arg args[15];
  long anum = 0;
  XtSetArg(args[anum],XtNx,x); anum++;
  XtSetArg(args[anum],XtNy,y); anum++;
  XtSetArg(args[anum],XtNwidth,w); anum++;
  XtSetArg(args[anum],XtNheight,h); anum++;
  if (_bg != -1){
    WSDcolor* color = WSGIappColorSet()->getColor(_bg);
    if (color != NULL){
       XtSetArg(args[anum],XtNbackground,color->getValue1()); anum++;
    }
  }
  if (_bg_pix == -1){
    XtSetArg(args[anum],XtNbackgroundPixmap,UNSPECIFIED_PIXMAP); anum++;
  }else{
    WSDimage*  image = WSGIappImageSet()->getImage(_bg_pix);
    if (image != NULL){
      if (image->getValue1() == -1){
          XtSetArg(args[anum],XtNbackgroundPixmap,UNSPECIFIED_PIXMAP); anum++;
      }else{
         Pixmap pid = (Pixmap)image->getValue1();
         XtSetArg(args[anum],XtNbackgroundPixmap,pid); anum++;
      }
    }else{
      XtSetArg(args[anum],XtNbackgroundPixmap,UNSPECIFIED_PIXMAP); anum++;
    }
  }
  XtSetArg(args[anum],XtNborderWidth,0); anum++;
  _pwidget = xdev->getWidget();
  _widget = XtCreateWidget("wscdxwa",formWidgetClass,xdev->getWidget(),args,anum);
  XtAddEventHandler(_widget,ExposureMask,False,(XtEventHandler)_evh_expose,this);
  XtAddEventHandler(_widget,ButtonPressMask,False,(XtEventHandler)_evh_btn_press,this);
  XtAddEventHandler(_widget,ButtonReleaseMask,False,(XtEventHandler)_evh_btn_release,this);
  XtAddEventHandler(_widget,ButtonMotionMask | PointerMotionMask,False,(XtEventHandler)_evh_mouse_move,this);
  XtAddEventHandler(_widget,StructureNotifyMask,False,(XtEventHandler)_evh_resize,this);
  XtAddEventHandler(_widget,EnterWindowMask,False,(XtEventHandler)_evh_mouse_in,this);
  XtAddEventHandler(_widget,LeaveWindowMask,False,(XtEventHandler)_evh_mouse_out,this);
  XtAddEventHandler(_widget,KeyPressMask | KeyReleaseMask,False,(XtEventHandler)_evh_dummy,this);
  XtAddCallback(_widget,XtNdestroyCallback,_evh_delete2,this);

//printf("WSDxformDev::createWindow()=0x%x p=0x%x %s\n",_widget,_pwidget,getAttachedClient()->getInstanceName());
  return WS_NO_ERR;
}

long WSDxformDev::setPixmap(Pixmap pixmap){
   if ( _pixmap != 0){
     WSGFxReleasePixmap(_pixmap);
   }
   _pixmap = pixmap;
   return WS_NO_ERR;
}

long WSDxformDev::getDeviceResource(){
   if (_widget == 0 || XtDisplay(_widget) == 0){
     return -1;
   }
   return (long)XtDisplay(_widget);
}

long WSDxformDev::createPixmap(){
  if (getGC() == 0){
     return WS_ERR;
  }

  short x,y;    
  WSCushort w,h;    
  getWindowSize(&x,&y,&w,&h);
  if (w <1){
    w = 1;
  }
  if (h <1){
    h = 1;
  }

  Pixmap pix = WSGFxGetPixmap(w,h);

  setPixmap(pix);
  _setup_pixmap(0,0,w,h,_bg_no,_bp_no);
  exposeExecute(0,0,w,h);
  return WS_NO_ERR;
}

long WSDxformDev::getContextResource(){
  long ret = (long)getGC();
  if (ret == 0){
    return -1;
  }
  return ret;
}

long WSDxformDev::getSpecialResource(){
   return (long)_widget;
}

long WSDxformDev::createContext(){
  destroyContext();  
  WSDxappDev* app   = WSGIxwinAppDev();
  GC gc = app->appGC();
  setGC(gc);
  return WS_NO_ERR;
}

long WSDxformDev::getWindowResource(){
  return (long)getWindow();
}


GC WSDxformDev::getGC(){
  return _gc;
}

Pixmap WSDxformDev::getPixmap(){
  return _pixmap;
}

Window WSDxformDev::getWindow(){
  if (getPixmapStyle() != WS_DIRECT_WINDOW ){
    if ( getPixmap() != 0 ){
      return getPixmap();
    }else{
        return (Window)-1;
    }
  }
  if (_widget == 0){
    return (Window)-1;
  }
  return XtWindow(_widget);
}

long WSDxformDev::destroyWindow(){

  if (_widget != 0){
    XtRemoveEventHandler(_widget,ExposureMask,False,(XtEventHandler)_evh_expose,this);
    XtRemoveEventHandler(_widget,ButtonPressMask,False,(XtEventHandler)_evh_btn_press,this);
    XtRemoveEventHandler(_widget,ButtonReleaseMask,False,(XtEventHandler)_evh_btn_release,this);
    XtRemoveEventHandler(_widget,ButtonMotionMask | PointerMotionMask,False,(XtEventHandler)_evh_mouse_move,this);
    XtRemoveEventHandler(_widget,StructureNotifyMask,False,(XtEventHandler)_evh_resize,this);
    XtRemoveEventHandler(_widget,EnterWindowMask,False,(XtEventHandler)_evh_mouse_in,this);
    XtRemoveEventHandler(_widget,LeaveWindowMask,False,(XtEventHandler)_evh_mouse_out,this);
    XtRemoveEventHandler(_widget,KeyPressMask | KeyReleaseMask,False,(XtEventHandler)_evh_dummy,this);
    XtRemoveCallback(_widget,XtNdestroyCallback,_evh_delete2,this);
    XtDestroyWidget(_widget);
  }
  _clear_widget();
  return WS_NO_ERR;
}

long WSDxformDev::destroyPixmap(){
  setPixmap(0);
  WSDwindowDev::destroyPixmap();
  return WS_NO_ERR;
}

long WSDxformDev::setGC(GC gc){
  _gc = gc;
  return WS_NO_ERR;
}

void WSDxformDev::setWidget(Widget w){
  _widget = w;
}

long WSDxformDev::destroyContext(){
  setGC(0);
 return WS_NO_ERR;
}

long WSDxformDev::setVisible(WSCbool fl){
  WSCbool bk = getVisible();
  WSDdev::setVisible(fl);
  if (fl == False){
    WSDxformDev* xdev = getParentAreaDev();
    if (xdev != NULL && xdev->getWidget() == 0){
      destroyWindow();
    }else{
      if (_widget != 0){
        XtUnmanageChild(_widget);
      }
    }
  }else{
    if (_widget == 0){
       createWindow();
    }

    if (getPixmapStyle() != WS_DIRECT_WINDOW){
      if (bk == False){
        //delete the pixmap to create after in the expose cb..
        destroyPixmap();
      }
//DEVELOP//////////////////////////////////////////////////////////////////////
//       //後ほど、pixmap style で static dynamic の処理をそれぞれ行なう
//        createPixmap();
//DEVELOP//////////////////////////////////////////////////////////////////////
    }

    XtManageChild(_widget);
  }
  return WS_NO_ERR;
}

void WSDxformDev::_evh_mouse_in(Widget,XtPointer ptr,XEvent* ev,WSCbool*){
  if (WSGIappDev()->getMode() == WS_MODE_NS_PLUGIN){
    WSGIxwinAppDev()->_dispatchEvent(False,ev);
  }
  WSGIxwinAppDev()->setXEvent(ev);
  WSDxformDev* dev = (WSDxformDev*)ptr;

  WSCpoint point;
  point.setPoint( ev->xcrossing.x, ev->xcrossing.y );

  long val = WSGIappMouse()->getMouseCursor(dev->_mouse_no);
  Display* disp = WSGIxwinAppDev()->display();
  if (val != 0){
    XDefineCursor(disp,XtWindow((Widget)dev->_widget),val);
  }

  dev->onMouseIn(&point);
  WSGIxwinAppDev()->setXEvent(NULL);
}

void WSDxformDev::_evh_mouse_out(Widget,XtPointer ptr,XEvent* ev,WSCbool*){
  if (WSGIappDev()->getMode() == WS_MODE_NS_PLUGIN){
    WSGIxwinAppDev()->_dispatchEvent(False,ev);
  }
   if (ev->xcrossing.mode != NotifyNormal){
     return;
   }
   WSGIxwinAppDev()->setXEvent(ev);
   WSDxformDev* dev = (WSDxformDev*)ptr;

  dev->onMouseOut();
  WSGIxwinAppDev()->setXEvent(NULL);
}

void WSDxformDev::_evh_mouse_move(Widget,XtPointer ptr,XEvent* ev,WSCbool*){
  if (WSGIappDev()->getMode() == WS_MODE_NS_PLUGIN){
    WSGIxwinAppDev()->_dispatchEvent(False,ev);
  }
   WSGIxwinAppDev()->setXEvent(ev);
   WSDxformDev* dev = (WSDxformDev*)ptr;

   WSCpoint point;
   point.setPoint( ev->xmotion.x, ev->xmotion.y );

   WSCbool b1 =  (ev->xmotion.state & Button1Mask) != 0 ? True:False;
   WSCbool b2 =  (ev->xmotion.state & Button2Mask) != 0 ? True:False;
   WSCbool b3 =  (ev->xmotion.state & Button3Mask) != 0 ? True:False;

   long state = WSGIappMouse()->getStatus();
   if (b1){
     state |= WS_MOUSE_BTN1;
   }
   if (b2){
     state |= WS_MOUSE_BTN2;
   }
   if (b3){
     state |= WS_MOUSE_BTN3;
   }
   WSGIappMouse()->setStatus(state);

   dev->onMouseMove(&point);
   WSGIxwinAppDev()->setXEvent(NULL);

}


void WSDxformDev::_evh_expose(Widget,XtPointer ptr,XEvent* ev,WSCbool*){
  if (WSGIappDev()->getMode() == WS_MODE_NS_PLUGIN){
    WSGIxwinAppDev()->_dispatchEvent(False,ev);
  }
   WSDxformDev* dev = (WSDxformDev*)ptr;
   WSGIxwinAppDev()->setXEvent(ev);

   if (dev->getAttachedClient() == NULL){
      dev->setVisible(False);
      return;
   }else if (dev->getAttachedClient()->getVisible() == False){
      dev->setVisible(False);
      return;
   }

   if (dev->getGC() == 0){
      dev->createContext();
   }

   WSCrect area;
   area.setRect( (short)ev->xexpose.x, (short)ev->xexpose.y,
             (WSCushort)ev->xexpose.width, (WSCushort)ev->xexpose.height);
   dev->onExpose(&area);
   WSGIxwinAppDev()->setXEvent(NULL);
}

void WSDxformDev::_evh_resize(Widget,XtPointer ptr,XEvent* ev,WSCbool*){
  if (WSGIappDev()->getMode() == WS_MODE_NS_PLUGIN){
    WSGIxwinAppDev()->_dispatchEvent(False,ev);
  }
  WSGIxwinAppDev()->setXEvent(ev);
  WSDxformDev* dev = (WSDxformDev*)ptr;
  if (ev->type == ConfigureNotify){
    Arg args[4];
    Position x,y;
    Dimension w,h;
    XtSetArg(args[0],XtNx,&x);
    XtSetArg(args[1],XtNy,&y);
    XtSetArg(args[2],XtNwidth,&w);
    XtSetArg(args[3],XtNheight,&h);
    XtGetValues(dev->_widget,args,4);

    WSCrect area;
    area.setRect(x,y,w,h);
    dev->onResize(&area);
    WSGIxwinAppDev()->setXEvent(NULL);
  }
}

void WSDxformDev::_evh_btn_press(Widget w,XtPointer ptr,XEvent* ev,WSCbool*){
  if (WSGIappDev()->getMode() == WS_MODE_NS_PLUGIN){
//printf("XtSetKeyboardFocus..\n");
    Widget w2 = XtGetKeyboardFocusWidget(w);
    XtSetKeyboardFocus(w2,w);
    WSGIxwinAppDev()->_dispatchEvent(False,ev);
  }
   WSGIxwinAppDev()->setXEvent(ev);
   WSDxformDev* dev = (WSDxformDev*)ptr;
   WSCpoint point;
   point.setPoint( ev->xbutton.x,ev->xbutton.y );
#if 0
   long state = WSGIappMouse()->getStatus();
   if (ev->xbutton.button == 1){
     state |= WS_MOUSE_BTN1;
     WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN1);
   }else if (ev->xbutton.button == 2){
     state |= WS_MOUSE_BTN2;
     WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN2);
   }else if (ev->xbutton.button == 3){
     state |= WS_MOUSE_BTN3;
     WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN3);
   }
   WSGIappMouse()->setStatus(state);
#endif
   long clk = WSGFclocktime();

   if (ev->xbutton.button == 4){
     WSCbase* fcl = WSGIappMouse()->getMouseFocusClient();
     if (fcl != NULL){
       fcl->onMousePress(&point);
     }
   }else if (ev->xbutton.button == 5){
     WSCbase* fcl = WSGIappMouse()->getMouseFocusClient();
     if (fcl != NULL){
       fcl->onMousePress(&point);
     }
   }
   dev->onMousePress(&point);
   if ((WSCulong)clk - (WSCulong)dev->_click_time < 250){
     dev->onMouseDoubleClick(&point);
   }
   dev->_click_time = clk;
   WSGIxwinAppDev()->setXEvent(NULL);
}

void WSDxformDev::_evh_btn_release(Widget,XtPointer ptr,XEvent* ev,WSCbool*){
  if (WSGIappDev()->getMode() == WS_MODE_NS_PLUGIN){
    WSGIxwinAppDev()->_dispatchEvent(False,ev);
  }
   WSGIxwinAppDev()->setXEvent(ev);
   WSDxformDev* dev = (WSDxformDev*)ptr;
   WSDxdragDrop* xdd = WSGIxappDragDrop();
   if (xdd != NULL){
     if (xdd->getDragState() != 0){
       xdd->executeDrop();
	   return;
	 }
   }
   WSCpoint point;
   point.setPoint( ev->xbutton.x, ev->xbutton.y );
#if 0
   long state = WSGIappMouse()->getStatus();
   if (ev->xbutton.button == 1){
     state &= ~WS_MOUSE_BTN1;
     WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN1);
   }else if (ev->xbutton.button == 2){
     state &= ~WS_MOUSE_BTN2;
     WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN2);
   }else if (ev->xbutton.button == 3){
     state &= ~WS_MOUSE_BTN3;
     WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN3);
   }
   WSGIappMouse()->setStatus(state);
#endif
   dev->onMouseRelease(&point);
   WSGIxwinAppDev()->setXEvent(NULL);
}


void WSDxformDev::_evh_delete(Widget,XtPointer ptr,XEvent* ev,WSCbool*){
  Display* disp = WSGIxwinAppDev()->display();
  if (ev->type == ClientMessage){
    if (ev->xclient.message_type ==  XInternAtom(disp,"WM_PROTOCOLS",False) &&
        (WSCulong)ev->xclient.data.l[0] == XInternAtom(disp,"WM_DELETE_WINDOW",False)){
      WSDxformDev* dev = (WSDxformDev*)ptr;
      dev->onUnmap();
    }
  }
}


void WSDxformDev::_evh_delete2(Widget w,void* ptr,void*){
   WSDxformDev* dev = (WSDxformDev*)ptr;
   if (dev->_widget != w){
     return;
   }
   dev->_clear_widget();
}

void WSDxformDev::_evh_dummy(Widget ,XtPointer ,XEvent* ev,WSCbool*){
  if (WSGIappDev()->getMode() == WS_MODE_NS_PLUGIN){
    WSGIxwinAppDev()->_dispatchEvent(False,ev);
  }
}

long WSDxformDev::raise(){
  if ( _widget == 0){
    return WS_ERR;
  }
  if ( XtWindow(_widget) != 0){
    XRaiseWindow(XtDisplay(_widget),XtWindow(_widget));
    return WS_NO_ERR;
  }
  return WS_ERR;
}
long WSDxformDev::lower(){
  if ( _widget == 0){
    return WS_ERR;
  }
  if ( XtWindow(_widget) != 0){
    XLowerWindow(XtDisplay(_widget),XtWindow(_widget));
    return WS_NO_ERR;
  }
  return WS_ERR;
}
void WSDxformDev::_clear_widget(){
  _pwidget = 0;
  _widget = 0;
  setInitialized(False);
}
void WSDxformDev::clearChildWidgets(){
  WSCbase* client = getAttachedClient();
  if (client != NULL){
//printf("WSDxformDev::clearChildWidgets %s\n",getAttachedClient()->getInstanceName());
    WSClistData children = client->getChildren();
    long i;
    long num = children.getNum();
    for(i=0; i<num; i++){
      WSCbase* child = (WSCbase*)children[i];
      WSDdev* dev = child->getowndev();
      if (dev != NULL && dev->cast("WSDxformDev")){
        WSDxformDev* xfdev = (WSDxformDev*)dev->cast("WSDxformDev");
        xfdev->clearChildWidgets();
      }
    }
  }
  _clear_widget();
}
