//
// Copyright (C) 1999-2002 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 <WSCdevice.h>
#include <WSCcolorSet.h>
#include <WSCimageSet.h>
#include <WSCbase.h>
#include <WSDmouse.h>
#include <WSCbaseList.h>
#include <nx/WSDnxFormDev.h>
#include <nx/WSDnxAppDev.h>
#include <nx/WSDnxDraw.h>
#include <nx/WSDnxMouse.h>
#include <nx/WSDnxDragDrop.h>
#include <WSCcolorSet.h>

#define SMARTUPDATE

WSMFclassInit(WSDnxFormDev,WSDwindowDev);

WSDdev* _wsdnxFormdev_init_(){
dbprintf("_wsdnxFormdev_init_() %s;%d started.\n",__FILE__,__LINE__);
  return new WSDnxFormDev();
}

class _WSDnxFormDev_init_ {
  public:_WSDnxFormDev_init_(){
dbprintf("_WSDnxFormDev_init_() %s;%d started.\n",__FILE__,__LINE__);
     WSGIappDevice()->setCreateHandler("formDev",_wsdnxFormdev_init_);
  };
};
static _WSDnxFormDev_init_ _init_to_run_WSDnxFormDev_;

static WSDnxDraw* draw_of_nxForm = NULL;

static WSClistData _valid_list;
WSCbool WSDnxFormDev::_expose_sequence = 0;
WSClistData WSDnxFormDev::_update_list;
WSClistData WSDnxFormDev::_geometry_update_list;
WSClistData WSDnxFormDev::_expose_list;

short WSDnxFormDev::_global_region_x = 0;
short WSDnxFormDev::_global_region_y = 0;
WSCushort WSDnxFormDev::_global_region_w = 0;
WSCushort WSDnxFormDev::_global_region_h = 0;

short WSDnxFormDev::_exposed_global_region_x = 0;
short WSDnxFormDev::_exposed_global_region_y = 0;
WSCushort WSDnxFormDev::_exposed_global_region_w = 0;
WSCushort WSDnxFormDev::_exposed_global_region_h = 0;


WSDnxFormDev::WSDnxFormDev(){
  _window = 0;
  _context = 0;
  _mem_context = 0;
  _expose_sequence = False;
  _clip_num = 0;
  _bg = -1;
  _bg_pix = -1;
  _mno = 0;
  _click_time = 0;
#ifdef F_MEMGID
  setPixmapStyle(WS_DYNAMIC_PIXMAP);
#endif

  if (draw_of_nxForm == NULL){
      draw_of_nxForm = new WSDnxDraw();
  }
  setDraw(draw_of_nxForm);
  _valid_list.add((void*)this);
  _added_to_child_dev_list = False;
}

WSDnxFormDev::~WSDnxFormDev(){
  if (WSGInxAppDev()->getGrabTarget() != NULL &&
      WSGInxAppDev()->getGrabTarget()->getParentWindow() == getParentWindow()){
    WSGInxAppDev()->setGrabTarget(NULL);
  }
  if (WSGInxAppDev()->getBtnPressGrabTarget() != NULL &&
      WSGInxAppDev()->getBtnPressGrabTarget()->getParentWindow() == getParentWindow()){
    WSGInxAppDev()->setBtnPressGrabTarget(NULL);
  }
  if (getChildDevListFlag() != False){
    WSDnxFormDev* pdev = getParentAreaDev();
    if (pdev != NULL){
      pdev->delChildDevList(this);
    }else{
      setChildDevListFlag(False);
    }
  }

  long num = _child_dev_list.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDnxFormDev* child = (WSDnxFormDev*)_child_dev_list[i];
    child->setChildDevListFlag(False);
  }
  _child_dev_list.clear();
  
  destroyContext();
  destroyPixmap();
  destroyWindow();
  _valid_list.del((void*)this);  
}

void WSDnxFormDev::setChildDevListFlag(WSCbool fl){
  _added_to_child_dev_list = fl;
}
WSCbool WSDnxFormDev::getChildDevListFlag(){
  return _added_to_child_dev_list;
}
WSClistData WSDnxFormDev::getChildDevList(){
  long num = _child_dev_list.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDnxFormDev* child =(WSDnxFormDev*)_child_dev_list[i];
    if (isValidInstance(child) == False){
      _child_dev_list.del((void*)child);
      i--;
      num = _child_dev_list.getNum();
    }
  }
  return _child_dev_list;
}
void WSDnxFormDev::addChildDevList(WSDnxFormDev* child){
  WSCbool fl = child->getChildDevListFlag();
  if (fl == False){
    _child_dev_list.add((void*)child);
    child->setChildDevListFlag(True);
  }
}
void WSDnxFormDev::delChildDevList(WSDnxFormDev* child){
  _child_dev_list.del((void*)child);
  child->setChildDevListFlag(False);
}

WSCbool WSDnxFormDev::isValidInstance(WSDnxFormDev* inst){
  long i;
  long num = _valid_list.getNum();
  for(i=0; i<num; i++){
    WSDnxFormDev* item = (WSDnxFormDev*)_valid_list[i];
    if (item == inst){
      return True;
    }
  }
  return False;
}
WSDdev* WSDnxFormDev::getEventParentDev(){
  return this;
}

//Widget WSDnxFormDev::getWidget(){
//  return _widget;
//}

long WSDnxFormDev::setValue(long kind,void* data){
  WSCbool fl = False;
  if (kind == WSDEV_PIXMAP_STYLE ){ 
    return WS_NO_ERR;
  }
  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;
  }
  short bk_x,bk_y;
  WSDnxFormDev* pdev;
  switch(kind){
    case WSDEV_X: 
    case WSDEV_Y: 
             fl = True;
             getAbstPos(&bk_x,&bk_y);
    case WSDEV_WIDTH: 
    case WSDEV_HEIGHT: 
dbprintf("WSDnxFormDev::setValue need implement!!!!! %s:%d\n",__FILE__,__LINE__);
             WSDwindowDev::setValue(kind,data);
             if (getParentVisible() != False){
               addGeometryUpdateList();
               pdev = getMostParentAreaDev();
               if (pdev != NULL && pdev->getParentVisible() != False){
                 pdev->addUpdateList();
#ifndef SMARTUPDATE
                 pdev->destroyPixmap();
#endif
               }
             }
             return WS_NO_ERR;

    case WSDEV_BACKCOLOR:
             WSDwindowDev::setValue(kind,data);
             _bg = *(short*)data;
             return WS_NO_ERR;
    case WSDEV_BACK_PIXMAP:
             WSDwindowDev::setValue(kind,data);
             _bg_pix = *(short*)data;
             if (getParentVisible() != False){
               short x,y;
               getAbstPos(&x,&y);
               WSCrect r;
               r.setRect(x, y, _w_w, _w_h);
               _expose_ex(&r);
             }
             return WS_NO_ERR;
    case WSDEV_GRAB_POINTER:
             WSDwindowDev::setValue(kind,data);
             fl = *(WSCbool*)data;
             if (fl != False){
               WSGInxAppDev()->setGrabTarget(this);
             }else{
               WSGInxAppDev()->setGrabTarget(NULL);
             }
             return WS_NO_ERR;
    case WSDEV_MOUSE_NO:
             WSDwindowDev::setValue(kind,data);
             {
               _mno = *(WSCushort*)data;
               _nx_mouse_value* val = (_nx_mouse_value*)WSGIappMouse()->getMouseCursor(_mno);
               if (val != NULL){
                 // TODO set value to mouse
               }
             }
             return WS_NO_ERR;
    default:
             WSDwindowDev::setValue(kind,data);
             return WS_NO_ERR;
  }
  WSDwindowDev::setValue(kind,data);
  return WS_NO_ERR;
}

void WSDnxFormDev::_copy_area(long x,long y,WSCulong w,WSCulong h,long dx,long dy,WSCuchar fl){

  short px,py;
  getAbstPos(&px,&py);

  if (fl == WS_PIXMAP_TO_WINDOW){
#ifndef F_MEMGID
    WSDnxFormDev* parent = getParentAreaDev();
    if (parent != NULL){
      parent->_copy_area(x + _w_x,y + _w_y,w,h,dx +_w_x,dy+_w_y,fl);
    }else{
      if (_mem_gid == NULL){
//printf("WSDnxFormDev::_copy_area err return1\n");
        return;
      }
      if (_gid == NULL){
//printf("WSDnxFormDev::_copy_area err return2\n");
        return;
      }
      px =0;
      py =0;
      WSCrect from;
      from.x = x + px;
      from.y = y + py;
      from.width = w;
      from.height = h;

      WSCrect to;
      to.x = dx + px;
      to.y = dy + py;
      to.width = w;
      to.height = h;

      // TODO bit build from _mem_context to _context or _window  
    }
#else
    WSCrect from;
    from.x = x + px;
    from.y = y + py;
    from.width = w;
    from.height = h;

    WSCrect to;
    to.x = dx + px;
    to.y = dy + py;
    to.width = w;
    to.height = h;

    // TODO set clip other form mask with  NULL to getParentMemContext().
    // TODO set clip visible mask with  "from" value to getParentMemContext().
    // TODO set clip other form mask with  NULL to getParentContext().
    if (_expose_sequence == False ||
        WSGInxAppDev()->getActiveWindow() != (void*)getWindowResource()){
      // TODO set clip visible mask with  "to" value to getParentContext().
    }else{
      long gx,gy;
      WSCulong gw,gh;
      WSGFandArea(_exposed_global_region_x,
                  _exposed_global_region_y,
                  _exposed_global_region_w,
                  _exposed_global_region_h,
                  dx + px, dy + py,w,h,
                  &gx,&gy,&gw,&gh);
      WSCrect vis;
      vis.x = gx;
      vis.y = gy;
      vis.width = gw;
      vis.height = gh;
      // TODO set clip visible mask with  "vis" value to getParentContext().
    }

    setDefaultRegion();
    // TODO bit build from getParentMemContext() to getParentContext()
#endif
  }else{
    if (getParentMemContext() == NULL){
      return;
    }
    WSCrect from;
    from.x = x + px;
    from.y = y + py;
    from.width = w;
    from.height = h;

    WSCrect to;
    to.x = dx+px;
    to.y = dy+py;
    to.width = w;
    to.height = h;

    // TODO set other form clip mask NULL to getParentContext()
    if (_expose_sequence == False ||
        WSGInxAppDev()->getActiveWindow() != (void*)getWindowResource()){
      // TODO set clip visible mask with  "to" value to getParentContext().
    }else{
      long gx,gy;
      WSCulong gw,gh;
      WSGFandArea(_exposed_global_region_x,
                  _exposed_global_region_y,
                  _exposed_global_region_w,
                  _exposed_global_region_h,
                  dx + px, dy + py,w,h,
                  &gx,&gy,&gw,&gh);
      WSCrect vis;
      vis.x = gx;
      vis.y = gy;
      vis.width = gw;
      vis.height = gh;
      // TODO set clip visible mask with  "vis" value to getParentContext().
    }

    if (getParentContext() != NULL){
      // TODO bit build from "from" area of getParentContext()
      //      to "to" area of getParentContext()
    }
  }
}

void WSDnxFormDev::_clear_area(long x,long y,WSCulong w,WSCulong h){
  if ((void*)getContextResource() == NULL){
    return;
  }
#ifdef F_MEMGID
  if (getPixmapStyle() != WS_DIRECT_WINDOW){
    _setup_pixmap(x,y,w,h,_bg,_bg_pix);
  }
  short dx,dy;
  getAbstPos(&dx,&dy);
  WSCrect r;
  r.x = dx+x;
  r.y = dx+y;
  r.width = _w_w;
  r.height = _w_h;
  // TODO bit build the area "r"
  //      from getParentMemContext() to getParentContext()
#else 
  if (getUseMemGID() == False){
    drawBackGround(x,y,w,h);
  }
#endif
}
WSDnxFormDev* WSDnxFormDev::getParentAreaDev(){
  WSDdev*      pdev = WSDnxFormDev::getParentDev();
  if (pdev == NULL){
    return NULL;
  }

  WSDnxFormDev* xdev = (WSDnxFormDev*)pdev->cast("WSDnxFormDev");
  if (xdev == NULL){
    while(xdev == NULL){
      pdev = pdev->getParentDev();
      if (pdev == NULL){
        return NULL;
      }
      xdev = (WSDnxFormDev*)pdev->cast("WSDnxFormDev");
    }
  }
  return xdev;
}
WSDnxFormDev* WSDnxFormDev::getMostParentAreaDev(){
  WSDdev*      pdev = WSDnxFormDev::getParentDev();
  if (pdev == NULL){
    return this;
  }
  if (_window > 0){
    return this;
  }

  WSDnxFormDev* xdev = (WSDnxFormDev*)pdev->cast("WSDnxFormDev");
  if (xdev != NULL){
    return xdev->getMostParentAreaDev();
  }
  return this;
}
void WSDnxFormDev::_setup_pixmap(short x,short y,WSCushort w,WSCushort h,short bg,short img_no){
  if (getParentVisible() == False){
dbprintf("## WSDnxFormDev::_setup_pixmap vis=False return!!!\n");
    return;
  }
  if (getParentMemContext() == NULL){
    return;
  }

  if (w < 1){
    return;
  }
  if (h < 1){
    return;
  }

  // TODO get color value.
  WSDcolor* color = WSGIappColorSet()->getColor(bg);
  if (color != NULL){
    // TODO get default color value.
  }
  short vx,vy;
  WSCushort vw,vh;
  getAbstSize(&vx,&vy,&vw,&vh);


  WSCrect v;
  v.x = vx;
  v.y = vy;
  v.width = vw;
  v.height = vh;
  // TODO set visible clip region to getParentMemContext()...

  short px,py;
  getAbstPos(&px,&py);
  setDefaultRegion(); 

  WSCrect rect;
  rect.x = x+px;
  rect.y = y+py;
  rect.width = w;
  rect.height = h;
  // TODO fill rect the area "rect" of getParentMemContext()

  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();

      long pid = (long)image->getValue1();
      long pid2 = (long)image->getValue2();
      short cw = 0;
      WSCrect from;
      WSCrect to;
      if (pid == 0 || pid == -1){
        return;
      }     
      while(1){
        short ch = 0;
        while(1){
          from.x = 0;
          from.y = 0;
          from.width = pw;
          from.height = ph;

          to.x = cw + px;
          to.y = ch + py;
          to.width = pw;
          to.height = ph;
          if (pid2 != 0 && pid2 != -1){
            // TODO bit build with AND operation
            //      with  pid2 and getParentMemContext()
            // TODO bit build with OR operation
            //      with  pid and getParentMemContext()
          }else{
            // TODO bit build from pid to getParentMemContext()
          }

          ch += ph;
          if (ph <1){
            break;
          }
          if (ch > h) break;
        }
        cw += pw;
        if (pw <1){
          break;
        }
        if (cw > w) break;
      }
    }
  }

  return;
}

long WSDnxFormDev::createWindow(){
  if (getParentVisible() == False){
    return WS_ERR;
  }
dbprintf("WSDnxWinDev::createWindow %d,%d,%d,%d\n",_w_x,_w_y,_w_w,_w_h);

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

  WSDnxFormDev* parent = getParentAreaDev();
  if (parent == NULL){
    return WS_ERR;
  }

  drawBackGround(0,0,w,h);

  WSDnxFormDev* pdev = getParentAreaDev();
  if (pdev != NULL){
    pdev->addChildDevList(this);
  }
  return WS_NO_ERR;
}

long WSDnxFormDev::getDeviceResource(){
#ifdef F_MEMGID
  return (long)getParentContext();
#else
  return 0;
#endif
}

long WSDnxFormDev::createPixmap(){
  short x,y;    
  WSCushort w,h;    
  getWindowSize(&x,&y,&w,&h);
  if (w <1){
    w = 1;
  }
  if (h <1){
    h = 1;
  }
  if (getParentMemContext() == 0){
    return WS_ERR;
  }
  WSDwindowDev::createPixmap();
  _setup_pixmap(0,0,w,h,_bg,_bg_pix);
  exposeExecute(0,0,w,h);

#ifdef F_MEMGID
  WSClistData children = getChildDevList();
  long num = children.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDnxFormDev* child =(WSDnxFormDev*)children[i];
    if (WSDnxFormDev::isValidInstance(child) == False){
      continue;
    }
    if (child->getParentVisible() != False){
      child->createPixmap();
    }
  }
#endif

  return WS_NO_ERR;
}
void WSDnxFormDev::recursiveExposeExecute(short x,short y,WSCushort w,WSCushort h){
  if (w <1){
    w = 1;
  }
  if (h <1){
    h = 1;
  }
  if (getParentMemContext() == 0){
    return;
  }
  _setup_pixmap(x,x,w,h,_bg,_bg_pix);
  exposeExecute(x,y,w,h);
  short px,py;
  getAbstPos(&px,&py);

#ifdef F_MEMGID
  WSClistData children = getChildDevList();
  long num = children.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDnxFormDev* child =(WSDnxFormDev*)children[i];
    if (WSDnxFormDev::isValidInstance(child) == False){
      continue;
    }
    if (child->getParentVisible() != False){
      short cx,cy;
      WSCushort cw,ch;
      child->getAbstSize(&cx,&cy,&cw,&ch);
      long dx,dy;
      WSCulong dw,dh;
      WSGFandArea(cx,cy,cw,ch,x+px,y+py,w,h,&dx,&dy,&dw,&dh);
      child->recursiveExposeExecute(dx -cx, dy -cy, dw, dh);
    }
  }
#endif
}
long WSDnxFormDev::getContextResource(){
  WSDnxFormDev* parent = getParentAreaDev();
  if (parent != NULL){
    return parent->getContextResource();
  }
  return -1;
}

long WSDnxFormDev::getSpecialResource(){
   return 0;
}

long WSDnxFormDev::createContext(){
  return WS_NO_ERR;
}

long WSDnxFormDev::getWindowResource(){
  WSDnxFormDev* parent = getParentAreaDev();
  if (parent != NULL){
    return parent->getWindowResource();
  }
  return (long)0;
}
void* WSDnxFormDev::getWindow(){
  return _window;
}
void* WSDnxFormDev::getContext(){
  return _context;
}
void* WSDnxFormDev::getMemContext(){
  return _mem_context;
}
WSCbool WSDnxFormDev::getUseMemContext(){
  if (_mem_context != NULL){
    return True;
  }
  WSDnxFormDev* pdev = (WSDnxFormDev*)getParentAreaDev();
  if (pdev !=NULL){
    return pdev->getUseMemContext();
  }
  return False;
}
long WSDnxFormDev::destroyWindow(){
  if (getChildDevListFlag() != False){
    WSDnxFormDev* pdev = getParentAreaDev();
    if (pdev != NULL){
      pdev->delChildDevList(this);
    }else{
      setChildDevListFlag(False);
    }
  }
  return WS_NO_ERR;
}

long WSDnxFormDev::destroyPixmap(){
  WSDwindowDev::destroyPixmap();
  WSClistData children = getChildDevList();
  long num = children.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDnxFormDev* child =(WSDnxFormDev*)children[i];
    if (WSDnxFormDev::isValidInstance(child) == False){
      continue;
    }
    child->destroyPixmap();
  }
  return WS_NO_ERR;
}

long WSDnxFormDev::destroyContext(){
  return WS_NO_ERR;
}
void WSDnxFormDev::redrawAll(){
  WSDnxFormDev* pdev = getMostParentAreaDev();
  if (pdev != NULL && pdev->getVisible() != False){
    short dx,dy;
    WSCushort dw,dh;
    getAbstSize(&dx,&dy,&dw,&dh);
    pdev->recursiveExposeExecute(dx,dy,dw,dh);
    WSCrect r;
    r.x = dx;
    r.y = dy;
    r.width = dw;
    r.height = dh;
    pdev->_evh_expose(&r);
  }
}

long WSDnxFormDev::setVisible(WSCbool fl){
dbprintf("WSDnxFormDev::setVisible fl=%d\n",fl);
//  WSCbool bk = getVisible();
  WSCbool bk2 = getParentVisible();
  WSDdev::setVisible(fl);
  if (fl == False){
    if (_window != 0){
      destroyWindow();
    }
    if (getPixmapStyle() == WS_DYNAMIC_PIXMAP){
      destroyPixmap();
    }

    if (bk2 != fl){
      redrawAll();
    }

    if (WSGInxAppDev()->getGrabTarget() != NULL &&
        WSGInxAppDev()->getGrabTarget()->getParentWindow() == getParentWindow()){
      WSGInxAppDev()->setGrabTarget(NULL);
    }
    if (WSGInxAppDev()->getBtnPressGrabTarget() != NULL &&
        WSGInxAppDev()->getBtnPressGrabTarget()->getParentWindow() == getParentWindow()){
      WSGInxAppDev()->setBtnPressGrabTarget(NULL);
    }

  }else{
    if (_window == 0){
       createWindow();
    }
    if (getPixmapStyle() == WS_DYNAMIC_PIXMAP){

      createPixmap();
      _copy_area(0,0,_w_w,_w_h,0,0,WS_PIXMAP_TO_WINDOW);
    }
  }
  return WS_NO_ERR;
}
void WSDnxFormDev::_evh_mouse_in(short x, short y){
  short dx,dy;
  getAbstPos(&dx,&dy);

  WSCpoint point;
  point.setPoint(x-dx,y-dy);

  _nx_mouse_value* val = (_nx_mouse_value*)WSGIappMouse()->getMouseCursor(_mno);
  if (val != NULL){
    // TODO set value to mouse..
  }
  onMouseIn(&point);
}

void WSDnxFormDev::_evh_mouse_out(){
  onMouseOut();
}

void WSDnxFormDev::_evh_mouse_move(void* ev){
  long state = WSGIappMouse()->getStatus();
  //TODO check the button status and set "state"
  //example. if (ev->s.stat & ES_BUT){
  //example.   state |= WS_MOUSE_BTN1;
  //example.   WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN1);
  //example. }else if (ev->s.stat & ES_BUT2){
  //example.   state |= WS_MOUSE_BTN3;
  //example.   WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN3);
  //example. }
  WSGIappMouse()->setStatus(state);

  short dx,dy;
  getAbstPos(&dx,&dy);

  // TODO get the mouse position related with the window.
  //example. PNT pt;
  //example. W w = getParentWindow();
  //example. if (ev->s.wid == w){
  //example.   pt.x = ev->e.pos.x -dx;
  //example.   pt.y = ev->e.pos.y -dy;
  //example. }else{
  //example.   short x,y;
  //example.   WSGIappMouse()->getMousePosition(&x,&y);
  //example.   pt.x = x;
  //example.   pt.y = y;
  //example.   gcnv_rel(getParentGID(),&pt);
  //example.   pt.x = pt.x - dx;
  //example.   pt.y = pt.y - dy;
  //example. }

   WSCpoint point;
   // TODO set the mouse potision to "point" 
   onMouseMove(&point);
}

WSDnxFormDev* WSDnxFormDev::getChildWithPoint(short x,short y){
  if (getParentVisible() == False){
    return NULL;
  }
  short dx,dy;
  WSCushort dw,dh;
  getAbstSize(&dx,&dy,&dw,&dh);
  if (dx <= x && x <= dx + dw &&
      dy <= y && y <= dy + dh){
    //continue.
  }else{
    return NULL;
  }
  WSClistData children = getChildDevList();
  long num = children.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDnxFormDev* child = (WSDnxFormDev*)children[num-1 - i];
    short cx,cy;
    WSCushort cw,ch;
    child->getAbstSize(&cx,&cy,&cw,&ch);
    if (child->getParentVisible() == False){
      continue;
    }
    if (cx <= x && x <= cx + cw &&
        cy <= y && y <= cy + ch){
      WSDnxFormDev* gchild = child->getChildWithPoint(x,y);
      if (gchild == NULL){
        return child;
      }else{
        return gchild;
      }
    }
  }
  return this;
}

void WSDnxFormDev::_evh_expose(WSCrect* r){
  if (getParentVisible() == False){
    return;
  }
  if (getAttachedClient() == NULL){
    setVisible(False);
    return;
  }else if (getAttachedClient()->getParentVisible() == False){
    setVisible(False);
    return;
  }
  _expose_sequence = True;
  
  _exposed_global_region_x =  r->x;
  _exposed_global_region_y =  r->y;
  _exposed_global_region_w =  r->width;
  _exposed_global_region_h =  r->height;

  setDefaultRegion();

  short x,y;
  getAbstPos(&x,&y);
  if (getUseMemContext() == False){
    drawBackGround(r->x -x, r->y -y, r->width, r->height);
  }
  WSCrect area;
  area.setRect( (short)r->x, (short)r->y,
             (WSCushort)r->width, (WSCushort)r->height);
  if (area.width == 0 || area.height == 0){
    area.width = _w_w;
    area.height = _w_h;
  }
  onExpose(&area);

  WSClistData children = getChildDevList();
  long num = children.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDnxFormDev* child =(WSDnxFormDev*)children[i];
    if (child->getParentVisible() == False){
      continue;
    }
    short cx,cy;
    WSCushort cw,ch;
    child->getAbstSize(&cx,&cy,&cw,&ch);
    long dx,dy;
    WSCulong dw,dh;
    WSGFandArea(cx,cy,cw,ch,area.x,area.y,area.width,area.height,
                &dx,&dy,&dw,&dh);
    WSCrect carea;
    carea.setRect(dx,dy,dw,dh);
    child->_expose_ex(&carea);
  }
  _expose_sequence = False;
  _exposed_global_region_x =  0;
  _exposed_global_region_y =  0;
  _exposed_global_region_w =  0;
  _exposed_global_region_h =  0;

//printf("WSDnxForm::_evh_expose done %s\n",getAttachedClient()->getInstanceName());
}
void WSDnxFormDev::_expose_ex(WSCrect* r){
  if (getParentVisible() == False){
    return;
  }
  if (getAttachedClient() == NULL){
dbprintf("WSDnxFormDev::_expose_ex %d,%d,%d,%d exit1!!!!\n",r->x,r->y,r->width,r->height);
    setVisible(False);
    return;
  }else if (getAttachedClient()->getParentVisible() == False){
    setVisible(False);
    return;
  }

  WSDcolor* color = WSGIappColorSet()->getColor(_bg);
  // TODO get color value.
  if (color != NULL){
    // TODO get default color value.
  }
  WSCrect rc;
  rc.x = r->x;
  rc.y = r->y;
  rc.width = r->width;
  rc.height = r->height;
  if (r->width == 0 || r->height == 0){
    return;
  }
  // TODO set visible region "rc" to getContextResource()


  setDefaultRegion();
  short dx,dy;
  getAbstPos(&dx,&dy);
  if (getPixmapStyle() == WS_DIRECT_WINDOW){
    drawBackGround(r->x - dx, r->y -dy, r->width,r->height);
  }

  WSCrect area;
  area.setRect(r->x - dx,r->y - dy,r->width,r->height);
  onExpose(&area);

  WSClistData children = getChildDevList();
  long num = children.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDnxFormDev* child =(WSDnxFormDev*)children[i];
    if (child->getParentVisible() == False){
      continue;
    }
    short cx,cy;
    WSCushort cw,ch;
    child->getAbstSize(&cx,&cy,&cw,&ch);
    long dx,dy;
    WSCulong dw,dh;
    WSGFandArea(cx,cy,cw,ch,r->x,r->y,r->width,r->height,
                &dx,&dy,&dw,&dh);
    WSCrect carea;
    carea.setRect(dx,dy,dw,dh);
    child->_expose_ex(&carea);
  }
}
void WSDnxFormDev::_evh_expose_abs(WSCrect* r){
  if (getParentVisible() == False){
    return;
  }
  if (getAttachedClient() == NULL){
    setVisible(False);
    return;
  }else if (getAttachedClient()->getParentVisible() == False){
    setVisible(False);
    return;
  }
  setDefaultRegion();
  short vx,vy;
  WSCushort vw,vh;
  getAbstSize(&vx,&vy,&vw,&vh);
  WSCrect v;
  v.x = vx;
  v.y = vy;
  v.width = vw;
  v.height = vh;
  // TODO set visible region "v" to getContextResource()

  short x,y;
  getAbstPos(&x,&y);
  if (getUseMemContext() == False){
    drawBackGround(r->x -x, r->y -y, r->width, r->height);
  }else{
    _setup_pixmap(r->x -x, r->y -y, r->width, r->height,_bg,_bg_pix);
  }
  WSCrect area;
  area.setRect( (short)r->x, (short)r->x,
             (WSCushort)r->width,(WSCushort)r->height);
  if (area.width == 0 || area.height == 0){
    area.width = _w_w;
    area.height = _w_h;
  }
  exposeExecute((short)r->x,(short)r->y,
             (WSCushort)r->width,
             (WSCushort)r->height);
  onExpose(&area);

  WSClistData children = getChildDevList();
  long num = children.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDnxFormDev* child =(WSDnxFormDev*)children[i];
    if (child->getParentVisible() == False){
      continue;
    }
    short cx,cy;
    WSCushort cw,ch;
    child->getAbstSize(&cx,&cy,&cw,&ch);
    long dx,dy;
    WSCulong dw,dh;
    WSGFandArea(cx,cy,cw,ch,area.x,area.y,area.width,area.height,
                &dx,&dy,&dw,&dh);
    WSCrect carea;
    carea.setRect(dx,dy,dw,dh);
    child->_expose_ex_abs(&carea);
  }
}
void WSDnxFormDev::_expose_ex_abs(WSCrect* r){
  if (getParentVisible() == False){
    return;
  }
  if (getAttachedClient() == NULL){
    setVisible(False);
    return;
  }else if (getAttachedClient()->getParentVisible() == False){
    setVisible(False);
    return;
  }

  WSDcolor* color = WSGIappColorSet()->getColor(_bg);
  // TODO get color value
  if (color != NULL){
    // TODO get default color value
  }
  WSCrect rc;
  rc.x = r->x;
  rc.y = r->y;
  rc.width = r->width;
  rc.height = r->height;
  if (r->width == 0 || r->height == 0){
    return;
  }
  setDefaultRegion();
  // TODO set visible region "rc" to getContextResource()

  short dx,dy;
  getAbstPos(&dx,&dy);
  if (getPixmapStyle() == WS_DIRECT_WINDOW){
    drawBackGround(r->x - dx, r->y -dy, r->width,r->height);
  }else{
    _setup_pixmap(r->x - dx, r->y -dy, r->width,r->height,_bg,_bg_pix);
  }

  WSCrect area;
  area.setRect(r->x - dx,r->y - dy,r->width,r->height);
  exposeExecute(r->x - dx,r->y - dy,r->width,r->height);
  onExpose(&area);

  WSClistData children = getChildDevList();
  long num = children.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDnxFormDev* child =(WSDnxFormDev*)children[i];
    if (child->getParentVisible() == False){
      continue;
    }
    short cx,cy;
    WSCushort cw,ch;
    child->getAbstSize(&cx,&cy,&cw,&ch);
    long dx,dy;
    WSCulong dw,dh;
    WSGFandArea(cx,cy,cw,ch,r->x,r->y,r->width,r->height,
                &dx,&dy,&dw,&dh);
    WSCrect carea;
    carea.setRect(dx,dy,dw,dh);
    child->_expose_ex_abs(&carea);
  }
}

void WSDnxFormDev::_evh_resize(WSCrect* r){

  WSCrect area;
  area.setRect(r->x,r->y,r->width,r->height);

  WSCrect vis;
  vis.x = 0;
  vis.y = 0;
  vis.width = r->width;
  vis.height = r->height;

  // TODO set visible region "vis" to _context
  if (_mem_context != 0){
    // TODO set visible region "vis" to _mem_context
  }

  WSCushort wbk = _w_w;
  WSCushort hbk = _w_h;
  onResize(&area);
  if ( wbk != area.width || hbk != area.height){
// need to fix a re-create exposure err...
    if (getPixmapStyle() == WS_DYNAMIC_PIXMAP){
      createPixmap();
      WSCrect rct;
      rct.x = 0;
      rct.y = 0;
      rct.width = _w_w;
      rct.height = _w_h;
      _evh_expose(&rct);
    }
  }
}

void WSDnxFormDev::_evh_btn_press(void* ev){
  short dx,dy;
  getAbstPos(&dx,&dy);
  // TODO get mouse position related with the window.
  short x = 0;
  short y = 0;

  WSCpoint point;
  point.setPoint( x, y );

  long state = WSGIappMouse()->getStatus();
  // TODO get the mouse button status and set it to "state" 
  // example. if (ev->s.stat & ES_BUT){
  // example.   state |= WS_MOUSE_BTN1;
  // example.   WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN1);
  // example. }else if (ev->s.stat & ES_BUT2){
  // example.   state |= WS_MOUSE_BTN3;
  // example.   WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN3);
  // example. }
  WSGIappMouse()->setStatus(state);

  long clk = WSGFclocktime();
  WSGInxAppDev()->setBtnPressGrabTarget(this);
  onMousePress(&point);
  if ((WSCulong)clk - (WSCulong)_click_time < 250){
    onMouseDoubleClick(&point);
  }
  _click_time = clk;
}
void WSDnxFormDev::_evh_btn_release(void* ev){
  short dx,dy;
  getAbstPos(&dx,&dy);
  // TODO get mouse position related with the window.
  long x = 0;
  long y = 0;

  WSCpoint point;
  point.setPoint( x, y );

  long state = WSGIappMouse()->getStatus();
  // TODO get the mouse button status and set it to "state" 
  // example. if ((ev->s.stat & ES_BUT) == 0){
  // example.   if (state & WS_MOUSE_BTN1){
  // example.     state &= ~WS_MOUSE_BTN1;
  // example.     WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN1);
  // example.   }
  // example. }
  // example. if ((ev->s.stat & ES_BUT2) == 0){
  // example.   if (state & WS_MOUSE_BTN3){
  // example.     state &= ~WS_MOUSE_BTN3;
  // example.     WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN3);
  // example.   }
  // example. }
  // example. if ((state & WS_MOUSE_BTN1) == 0 &&
  // example.     (state & WS_MOUSE_BTN2) == 0 &&
  // example.     (state & WS_MOUSE_BTN3) == 0 ){
  // example.   WSGInxAppDev()->setBtnPressGrabTarget(NULL);
  // example. }
  WSGIappMouse()->setStatus(state);
  onMouseRelease(&point);
  WSDnxDragDrop* bdd = WSGInxAppDragDrop();
  if (bdd != NULL){
    if (bdd->getDragState() != 0){
      bdd->executeDrop();
      return;
    }
  }
}

long WSDnxFormDev::raise(){
  return WS_ERR;
}
long WSDnxFormDev::lower(){
  return WS_ERR;
}

void WSDnxFormDev::getAbstSize(short* x,short* y,WSCushort* w,WSCushort* h){
  if (haveWindow() != False){
    if (_exposed_global_region_w !=0 && _exposed_global_region_h != 0){
//printf("fep_mask=%d,%d,%d,%d\n",_global_region_x,_global_region_y,_global_region_w,_global_region_h);
      long dx,dy;
      WSCulong dw,dh;
      WSGFandArea(_exposed_global_region_x,_exposed_global_region_y,
                  _exposed_global_region_w,_exposed_global_region_h,
                  0,0,_w_w,_w_h,&dx,&dy,&dw,&dh);
      *x = dx;
      *y = dy;
      *w = dw;
      *h = dh;
    }else{
      *x = 0;
      *y = 0;
      *w = _w_w;
      *h = _w_h;
    }
    return;
  }
  WSDnxFormDev* parent = getParentAreaDev();

  short px,py;
  WSCushort pw,ph;
  parent->getAbstSize(&px,&py,&pw,&ph);
  long dx,dy;
  WSCulong dw,dh;

  short px2,py2;
  parent->getAbstPos(&px2,&py2);

  WSGFandArea(px,py,pw,ph,px2 + _w_x,py2 + _w_y,_w_w,_w_h,&dx,&dy,&dw,&dh);
  *x = dx;
  *y = dy;
  *w = dw;
  *h = dh;
}
void WSDnxFormDev::getAbstPos(short* x,short* y){
  if (haveWindow() != False){
    *x = 0;
    *y = 0;
    return;
  }
  WSDnxFormDev* parent = getParentAreaDev();

  short px,py;
  parent->getAbstPos(&px,&py);
  *x = px +_w_x;
  *y = py +_w_y;
}

WSCbool WSDnxFormDev::haveWindow(){
  return False;
}

void WSDnxFormDev::setDefaultRegion(){
  WSClistData dlist = getChildDevList();
  long num = dlist.getNum();
#define N_VIEWR 64
  WSCrectList rlist[2+N_VIEWR];
  long cnt = 0;

extern void* _fep_popup;
  if (_fep_popup != NULL){
    // TODO get window size of _fep_popup
    // and set it to rlist[cnt]..
    rlist[cnt].rect.x = 0;
    rlist[cnt].rect.y = 0;
    rlist[cnt].rect.width = 0;
    rlist[cnt].rect.height = 0;
    rlist[cnt].next = NULL;
    cnt++;
  }

  if (_global_region_w !=0 && _global_region_h != 0){
    short ax,ay;
    getParentAbstPos(&ax,&ay);
    rlist[cnt].rect.x = ax + _global_region_x;
    rlist[cnt].rect.y = ay + _global_region_y;
    rlist[cnt].rect.width = _global_region_w;
    rlist[cnt].rect.height = _global_region_h;
    rlist[cnt].next = NULL;
    if (cnt > 0){
      rlist[cnt-1].next = &rlist[cnt];
    }
    cnt++;
  }

  long i;
  for(i=0; i<N_VIEWR; i++){
    if (i == _clip_num){
      break;
    }
    rlist[cnt] = _clip_fore_list[i];
    rlist[cnt].next = NULL;
    if (cnt > 0){
      rlist[cnt-1].next = &rlist[cnt];
    }
    cnt++;
  }
  void* winlist[N_VIEWR];
  memset(winlist,0,sizeof(winlist));
  // TODO get window lists which exists on the window,
  // and set it to clip mask list "rlist".
  for(i=0; i<N_VIEWR; i++){
    if (N_VIEWR < cnt){
      break;
    }
    if (winlist[i] == 0){
      break;
    }
    if (winlist[i] == getParentWindow()){
      break;
    }
    // TODO get window size from the window of listss,
    // and the size to set rlist.
    rlist[cnt].rect.x = 0; //set the window x
    rlist[cnt].rect.y = 0; //set the window y
    rlist[cnt].rect.width = 0; // set the window width
    rlist[cnt].rect.height = 0; // set the window height
    rlist[cnt].next = NULL;
    if (cnt > 0){
      rlist[cnt-1].next = &rlist[cnt];
    }
    cnt++;
  }

  if (cnt > 0){
    // TODO set clip mask "rlist" getParentContext().
  }else{
    // TODO clear clip mask "rlist" getParentContext().
  }

  if (num == 0){
    // TODO clear clip mask "rlist" getContextResource()
    return;
  }

  long next=0;
  short dx,dy;
  WSCushort dw,dh;
  getAbstSize(&dx,&dy,&dw,&dh);

  WSCrectList* rc = new WSCrectList[num+1];
  rc[0].next = NULL;
  for(i=0; i<num; i++){
    WSDnxFormDev* dev = (WSDnxFormDev*)dlist[i];
    if (WSDnxFormDev::isValidInstance(dev) == False){
      continue;
    }
    if (dev->getParentVisible() == False){
      continue;
    }
    short cx,cy;
    WSCushort cw,ch;
    dev->getAbstSize(&cx,&cy,&cw,&ch);
    rc[next].next = NULL;
    if (cw <1){
      continue;
    }
    if (ch <1){
      continue;
    }
    short ax,ay;
    getParentAbstPos(&ax,&ay);
    rc[next].rect.x = ax + cx;
    rc[next].rect.y = ay + cy;
    rc[next].rect.width = cw;
    rc[next].rect.height = ch;
    if (i == 0){
    }else{
      rc[next-1].next = &rc[next];
    }
    next++;
  }
  if (next != 0){
    // TODO set clip child mask "rc" to getContextResource()
  }else{
    // TODO clear clip child mask "rc" to getContextResource()
  }
  delete[] rc;
}
void WSDnxFormDev::drawBackGround(long x,long y,WSCulong w,WSCulong h){
  if (getParentVisible() == False){
    return;
  }
  if (w < 1){
    return;
  }
  if (h < 1){
    return;
  }
  WSDnxFormDev* parent = getParentAreaDev();
  if (parent == NULL){
    if (cast("WSDnxWinDev")){
      parent = this;
    }else{
      return;
    }
  }

  WSDcolor* color = WSGIappColorSet()->getColor(_bg);
  // TODO get color value
  if (color != NULL){
    // TODO get default color value
  }

  short px,py;
  WSCushort pw,ph;
  parent->getAbstSize(&px,&py,&pw,&ph);

  short cx,cy;
  getAbstPos(&cx,&cy);

  long dx,dy;
  WSCulong dw,dh;
  WSGFandArea(cx + x,cy + y,w,h, px,py,pw,ph,&dx,&dy,&dw,&dh);

  setDefaultRegion();
  WSCrect rect;
  rect.x = dx;
  rect.y = dy;
  rect.width = dw;
  rect.height = dh;
  // TODO fill_rect area "rect" of getContextResource() 

  if (_bg_pix != -1 && _bg_pix != 0){
    WSDimage* image = WSGIappImageSet()->getImage(_bg_pix);
    if (image != NULL && image->getValue1() != -1){
      WSCushort pw = image->getImageWidth();
      WSCushort ph = image->getImageHeight();
      long pid = (long)image->getValue1();
      long pid2 = (long)image->getValue2();
      if (pid==0){
        return;
      }
      short cw = 0;
      WSCrect from;
      WSCrect to;
     
      while(1){
        short ch = 0;
        while(1){
          from.x = 0;
          from.y = 0;
          from.width = pw;
          from.height = ph;

          to.x = cw + cx;
          to.y = ch + cy;
          to.width = pw;
          to.height = ph;
          if (pid2 != 0 || pid2 != -1){
            // TODO bit build with AND operation
            //      from pid2 to getContextResource()
            // TODO bit build with OR operation
            //      from pid to getContextResource()
          }else{
            // TODO bit build from pid to getContextResource()
          }
          ch += ph;
          if ((WSCulong)ch > h) break;
        }
        cw += pw;
        if ((WSCulong)cw > w) break;
      }
    }
  }
}
void* WSDnxFormDev::getParentWindow(){
  if (_window != NULL){
    return _window;
  }
  WSDnxFormDev* pdev = this;
  while(1){
    if (pdev != NULL){
      void* w = pdev->getWindow();
      if (w != NULL){
        return w;
      }
      pdev = pdev->getParentAreaDev();
    }else{
      return NULL;
    }
  }
  return NULL;
}
void* WSDnxFormDev::getParentContext(){
  if (_context != NULL){
    return _context;
  }
  WSDnxFormDev* pdev = this;
  while(1){
    if (pdev != NULL){
      void* c = pdev->getContext();
      if (c != NULL){
        return c;
      }
      pdev = pdev->getParentAreaDev();
    }else{
      return NULL;
    }
  }
  return NULL;
}
void* WSDnxFormDev::getParentMemContext(){
  if (_mem_context != NULL){
    return _mem_context;
  }
  WSDnxFormDev* pdev = this;
  while(1){
    if (pdev != NULL){
      void* c = pdev->getMemContext();
      if (c != NULL){
        return c;
      }
      pdev = pdev->getParentAreaDev();
    }else{
      return NULL;
    }
  }
  return NULL;
}
void WSDnxFormDev::exposeExecute(short x,short y,WSCushort w,WSCushort h){
  WSDwindowDev::exposeExecute(x,y,w,h);
}
void WSDnxFormDev::addUpdateList(){
  long num = _update_list.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDnxFormDev* item =(WSDnxFormDev*)_update_list[i];
    if (item == this){
      return;
    }
  }
  _update_list.add((void*)this);
}
void WSDnxFormDev::addGeometryUpdateList(){
  long num = _geometry_update_list.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDnxFormDev* item =(WSDnxFormDev*)_geometry_update_list[i];
    if (item == this){
      return;
    }
  }
  _geometry_update_list.add((void*)this);
}
void WSDnxFormDev::executeUpdate(){
  long num = _geometry_update_list.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDnxFormDev* item =(WSDnxFormDev*)_geometry_update_list[i];
    if (item != NULL && isValidInstance(item) != False){
      short dx,dy;
      WSCushort dw,dh;
      item->getWindowSize(&dx,&dy,&dw,&dh);
      WSCrect area;
      area.setRect(dx,dy,dw,dh);
      item->onResize(&area);
      short dx2,dy2;
      WSCushort dw2,dh2;
      item->getWindowSize(&dx2,&dy2,&dw2,&dh2);
      if ( dx != dx2 || dy != dy2 || dw != dw2 || dh != dh2){
        if (item->getPixmapStyle() == WS_DYNAMIC_PIXMAP){
          long j;
          long wid = (long)item->getWindowResource();
          long update = True;
          long unum = _expose_list.getNum();
          for(j=0; j<unum;j++){
            long item = (long)_expose_list[j];
            if (item == wid){
              update = False;
              break;
            }
          }
          if (update == True){
            _expose_list.add((void*)wid);
          }
        }
      }
    }
  }
  _geometry_update_list.clear();

  num = _update_list.getNum();
  for(i=0; i<num; i++){
    WSDnxFormDev* item =(WSDnxFormDev*)_update_list[i];
    if (item != NULL && isValidInstance(item) != False &&
        item->getParentVisible() != False){
      long j;
      long wid = (long)item->getWindowResource();
      long update = True;
      long unum = _expose_list.getNum();
      for(j=0; j<unum;j++){
        long item = (long)_expose_list[j];
        if (item == wid){
          update = False;
          break;
        }
      }
      if (update == True){
        _expose_list.add((void*)wid);
      }
    }
  }
  _update_list.clear();
  num = _expose_list.getNum();
  for(i=0; i<num; i++){
    long wid = (long)_expose_list[i];
    WSDnxFormDev* dev = NULL;
    // TODO get this point from window id "wid"..
    if (dev != NULL &&
      WSDnxFormDev::isValidInstance(dev) != False){
      dev->redrawAll();
    }
  }
  _expose_list.clear();
}

long WSDnxFormDev::exposeArea(long x,long y,WSCulong w,WSCulong h,WSCbool scale){

  short ax,ay;
  getAbstPos(&ax,&ay);
  WSCrect rc;
  rc.x = ax + x;
  rc.y = ay + y;
  rc.width = w;
  rc.height = h;
  if (w == 0 || h == 0){
    return WS_NO_ERR;
  }
  setDefaultRegion();

  // TODO set visible region "rc" to getContextResource() 

  return WSDwindowDev::exposeArea(x,y,w,h,scale);
}
void WSDnxFormDev::setGlobalRegion(short x,short y,WSCushort w,WSCushort h){
  _global_region_x = x;
  _global_region_y = y;
  _global_region_w = w;
  _global_region_h = h;
}
void WSDnxFormDev::getGlobalRegion(short* x,short* y,WSCushort* w,WSCushort* h){
  *x = _global_region_x;
  *y = _global_region_y;
  *w = _global_region_w;
  *h = _global_region_h;
}
WSCrectList* WSDnxFormDev::getClipList(){
  return _clip_fore_list;
}
void WSDnxFormDev::clearClipList(){
  long i;
  for(i=0; i<N_VIEWR-1; i++){
    _clip_fore_list[i].next = &(_clip_fore_list[i+1]);
  }
  _clip_fore_list[N_VIEWR-1].next = NULL;
  _clip_num = 0;
}
void WSDnxFormDev::setClipNum(long num){
  _clip_num = num;
}
void WSDnxFormDev::_evh_destroy(void* ev){
  WSCbase* client = getAttachedClient();
  if (client != NULL){
    client->setVisible(False);
  }
}
WSCbool WSDnxFormDev::getParentVisible(){
  if (getVisible() == False){
    return False;
  }
  WSDnxFormDev* parent = getParentAreaDev();
  if (parent != NULL){
    return parent->getParentVisible();
  }
  return True;
}
void WSDnxFormDev::getParentAbstPos(short* x,short* y){
  WSDnxFormDev* parent = getParentAreaDev();
  if (parent != NULL){
    return parent->getParentAbstPos(x,y);
  }
  *x = _w_x;
  *y = _w_y;
  return;
}
