//
// 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 <basic.h>
#include <btron/hmi.h>
#include <WSCdevice.h>
#include <WSCcolorSet.h>
#include <WSCimageSet.h>
#include <WSCbase.h>
#include <WSDmouse.h>
#include <WSCbaseList.h>
#include <btron/WSDbtronFormDev.h>
#include <btron/WSDbtronAppDev.h>
#include <btron/WSDbtronDraw.h>
#include <btron/WSDbtronMouse.h>
#include <btron/WSDbtronDragDrop.h>
#include <WSCcolorSet.h>

#define SMARTUPDATE

WSMFclassInit(WSDbtronFormDev,WSDwindowDev);

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

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

static WSDbtronDraw* draw_of_btronForm = NULL;

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

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

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


WSDbtronFormDev::WSDbtronFormDev(){
//dbprintf("WSDbtronFormDev::WSDbtronFormDev() %s;%d started.\n",__FILE__,__LINE__);
  _window = 0;
  _gid = 0;
  _mem_gid = 0;
  _expose_sequence = False;
  _clip_num = 0;
//  _pwidget = 0;
//  _widget  = 0;
//  _pixmap  = 0;
//  _gc      = 0;
  _bg = -1;
  _bg_pix = -1;
  _mno = 0;
  _click_time = 0;
#ifdef F_MEMGID
  setPixmapStyle(WS_DYNAMIC_PIXMAP);
//printf("WSDbtronFormDev::WSDbtronFormDev  PIXMAP! \n");
#endif

  if (draw_of_btronForm == NULL){
      draw_of_btronForm = new WSDbtronDraw();
  }
  setDraw(draw_of_btronForm);
  _valid_list.add((void*)this);
  _added_to_child_dev_list = False;
//dbprintf("WSDbtronFormDev::WSDbtronFormDev() %s;%d done.\n",__FILE__,__LINE__);
}

WSDbtronFormDev::~WSDbtronFormDev(){
  if (WSGIbtronAppDev()->getGrabTarget() != NULL &&
      WSGIbtronAppDev()->getGrabTarget()->getParentWindow() == getParentWindow()){
    WSGIbtronAppDev()->setGrabTarget(NULL);
  }
  if (WSGIbtronAppDev()->getBtnPressGrabTarget() != NULL &&
      WSGIbtronAppDev()->getBtnPressGrabTarget()->getParentWindow() == getParentWindow()){
    WSGIbtronAppDev()->setBtnPressGrabTarget(NULL);
  }
  if (getChildDevListFlag() != False){
    WSDbtronFormDev* 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++){
    WSDbtronFormDev* child = (WSDbtronFormDev*)_child_dev_list[i];
    child->setChildDevListFlag(False);
  }
  _child_dev_list.clear();
  
  destroyContext();
  destroyPixmap();
  destroyWindow();
  _valid_list.del((void*)this);  
}

void WSDbtronFormDev::setChildDevListFlag(WSCbool fl){
  _added_to_child_dev_list = fl;
}
WSCbool WSDbtronFormDev::getChildDevListFlag(){
  return _added_to_child_dev_list;
}
WSClistData WSDbtronFormDev::getChildDevList(){
  long num = _child_dev_list.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDbtronFormDev* child =(WSDbtronFormDev*)_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 WSDbtronFormDev::addChildDevList(WSDbtronFormDev* child){
  WSCbool fl = child->getChildDevListFlag();
  if (fl == False){
    _child_dev_list.add((void*)child);
    child->setChildDevListFlag(True);
  }
}
void WSDbtronFormDev::delChildDevList(WSDbtronFormDev* child){
  _child_dev_list.del((void*)child);
  child->setChildDevListFlag(False);
}

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

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

long WSDbtronFormDev::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;
  WSDbtronFormDev* pdev;
  switch(kind){
    case WSDEV_X: 
    case WSDEV_Y: 
             fl = True;
             getAbstPos(&bk_x,&bk_y);
    case WSDEV_WIDTH: 
    case WSDEV_HEIGHT: 
dbprintf("WSDbtronFormDev::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){
//printf("WSDbtronFormDev::setValue WSDEV_GRAB_POINTER.. grabed.\n");
               WSGIbtronAppDev()->setGrabTarget(this);
             }else{
//printf("WSDbtronFormDev::setValue WSDEV_GRAB_POINTER.. cancel\n");
               WSGIbtronAppDev()->setGrabTarget(NULL);
             }
             return WS_NO_ERR;
    case WSDEV_MOUSE_NO:
             WSDwindowDev::setValue(kind,data);
             {
               _mno = *(WSCushort*)data;
               _btron_mouse_value* val = (_btron_mouse_value*)WSGIappMouse()->getMouseCursor(_mno);
               if (val != NULL){
                 W style = val->_style;
                 COLOR fg = (COLOR)val->_fg;
                 COLOR bg = (COLOR)val->_bg;
                 gset_ptr(style,NULL,fg,bg);
               }
             }
             return WS_NO_ERR;
    default:
             WSDwindowDev::setValue(kind,data);
             return WS_NO_ERR;
  }
  WSDwindowDev::setValue(kind,data);
  return WS_NO_ERR;
}

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

//printf("WSDbtronFormDev::_copy_area %d,%d,%d,%d -> %d,%d %s\n",x,y,w,h,dx,dy,getAttachedClient()->getInstanceName());
//  if (_gid == NULL){
//    return;
//  }
  short px,py;
  getAbstPos(&px,&py);

  if (fl == WS_PIXMAP_TO_WINDOW){
#ifndef F_MEMGID
    WSDbtronFormDev* 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("WSDbtronFormDev::_copy_area err return1\n");
        return;
      }
      if (_gid == NULL){
//printf("WSDbtronFormDev::_copy_area err return2\n");
        return;
      }
      px =0;
      py =0;
      RECT from;
      from.c.left = x + px;
      from.c.top = y + py;
      from.c.right = w +x + px;
      from.c.bottom = h +y + py;

      RECT to;
      to.c.left = dx + px;
      to.c.top = dy + py;
      to.c.right = w +dx + px;
      to.c.bottom = h +dy + py;
  
//    setDefaultRegion();
      gset_vis(_mem_gid,from);
      gset_vis(_gid,to);
//printf("WSDbtronFormDev::_copy_area %d,%d,%d,%d->%d,%d 0x%x->0x%x\n",x,y,w,h,dx,dy,_mem_gid,_gid);
      gcop_bmp(_mem_gid,&from,_gid,&to,NULL,G_STORE);
    }
#else
    RECT from;
//    from.c.left = 0;
//    from.c.top = 0;
//    from.c.right = 35767;
//    from.c.bottom = 35767;
//    gset_vis(getParentMemGID(),from);
//    gset_vis(getParentGID(),from);

    from.c.left = x + px;
    from.c.top = y + py;
    from.c.right = w +x + px;
    from.c.bottom = h +y + py;

    RECT to;
    to.c.left = dx + px;
    to.c.top = dy + py;
    to.c.right = w +dx + px;
    to.c.bottom = h +dy + py;
//printf("WSDbtronFormDev::_copy_area px,py=%d,%d\n",px,py);
//printf("WSDbtronFormDev::_copy_area %d,%d,%d,%d -> %d,%d %s\n",x+px,y+py,w,h,dx+px,dy+py,getAttachedClient()->getInstanceName());
    gset_for(getParentMemGID(),NULL);
    gset_vis(getParentMemGID(),from);
    gset_for(getParentGID(),NULL);
    W ppid;
    if (_expose_sequence == False || wget_act(&ppid) != getWindowResource()){
//printf("WSDbtronFormDev::_copy_area vis=%d,%d,%d,%d\n",px+dx,py+dy,w,h);
      gset_vis(getParentGID(),to);
    }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);
      RECT vis;
      vis.c.left = gx;
      vis.c.top = gy;
      vis.c.right = gx + gw;
      vis.c.bottom = gy + gh;
      gset_vis(getParentGID(),vis);
//printf("WSDbtronFormDev::_copy_area vis=%d,%d,%d,%d\n",gx,gy,gw,gh);
    }

    setDefaultRegion();
#if 0
//this logic cause no drawing in pulldown
    if (_expose_sequence == False &&
        WSGIbtronAppDev()->getMouseGrabbed() == False){
      long i;
      long num = _expose_list.getNum();
      long update = True;
      W wid = getWindowResource();
      for(i=0; i<num; i++){
        W item = (W)_expose_list[i];
        if (item == wid){
          update = False;
          break;
        }
      }
      if (update==True){
//printf("WSDbtronFormDev::_copy_area not expose sequence add list!!!!!!!!!!!!!!!!!!!!!!!>>>>>>>>>>>>>>>>>>\n");
        _expose_list.add((void*)wid);
      }
    }else{
      gcop_bmp(getParentMemGID(),&from,getParentGID(),&to,NULL,G_STORE);
    }
#else
    gcop_bmp(getParentMemGID(),&from,getParentGID(),&to,NULL,G_STORE);
#endif
#endif
  }else{
    if (getParentMemGID() == NULL){
      return;
    }
    RECT from;
    from.c.left = x + px;
    from.c.top = y + py;
    from.c.right = w +x + px;
    from.c.bottom = h +y + py;

    RECT to;
    to.c.left = dx+px;
    to.c.top = dy+py;
    to.c.right = w +dx + px;
    to.c.bottom = h +dy + py;

//    gset_for(getParentMemGID(),NULL);
//    gset_vis(getParentMemGID(),from);
    gset_for(getParentGID(),NULL);
    W ppid;
    if (_expose_sequence == False || wget_act(&ppid) != getWindowResource()){
//printf("WSDbtronFormDev::_copy_area vis=%d,%d,%d,%d\n",px+dx,py+dy,w,h);
      gset_vis(getParentGID(),to);
    }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);
      RECT vis;
      vis.c.left = gx;
      vis.c.top = gy;
      vis.c.right = gx + gw;
      vis.c.bottom = gy + gh;
      gset_vis(getParentGID(),vis);
//printf("WSDbtronFormDev::_copy_area vis=%d,%d,%d,%d\n",gx,gy,gw,gh);
    }

    if (getParentGID() != NULL){
      gcop_bmp(getParentGID(),&from,getParentGID(),&to,NULL,G_STORE);
    }
  }
}

void WSDbtronFormDev::_clear_area(long x,long y,WSCulong w,WSCulong h){
  if (getContextResource() == NULL){
//printf("WSDbtronFormDev::_clear_area.. err return\n");
    return;
  }
#ifdef F_MEMGID
  if (getPixmapStyle() != WS_DIRECT_WINDOW){
    _setup_pixmap(x,y,w,h,_bg,_bg_pix);
  }
  short dx,dy;
  getAbstPos(&dx,&dy);
  RECT r;
  r.c.left = dx+x;
  r.c.top = dx+y;
  r.c.right = dx+x+_w_w;
  r.c.bottom = dy+y+_w_h;
//printf("WSDbtronFormDev::_clear_area.. expose!\n");
//  _evh_expose(&r);
  gcop_bmp(getParentMemGID(),&r,getParentGID(),&r,NULL,G_AND);
#else 
  if (getUseMemGID() == False){
    drawBackGround(x,y,w,h);
  }
#endif
}
WSDbtronFormDev* WSDbtronFormDev::getParentAreaDev(){
  WSDdev*      pdev = WSDbtronFormDev::getParentDev();
  if (pdev == NULL){
    return NULL;
  }

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

  WSDbtronFormDev* xdev = (WSDbtronFormDev*)pdev->cast("WSDbtronFormDev");
  if (xdev != NULL){
    return xdev->getMostParentAreaDev();
  }
  return this;
}
void WSDbtronFormDev::_setup_pixmap(short x,short y,WSCushort w,WSCushort h,short bg,short img_no){
//printf("## WSDbtronFormDev::_setup_pixmap x,y,w,h=%d,%d,%d,%d!!\n",x,y,w,h);
  if (getParentVisible() == False){
dbprintf("## WSDbtronFormDev::_setup_pixmap vis=False return!!!\n");
    return;
  }
//printf("## WSDbtronFormDev::_setup_pixmap %s %d,%d,%d,%d\n",getAttachedClient()->getInstanceName(),x,y,w,h);
dbprintf("## WSDbtronFormDev::_setup_pixmap _mem_gid=0x%x\n",_mem_gid);
  if (getParentMemGID() == 0){
    return;
  }

  if (w < 1){
    return;
  }
  if (h < 1){
    return;
  }
//  WSDbtronFormDev* parent = getParentAreaDev();
//  if (parent == NULL){
//dbprintf("## WSDbtronFormDev::_setup_pixmap parent=NULL return!!!\n");
//    return;
//  }

//  W  gid = parent->getContextResource();
  W bgc = 0x10000000;
  WSDcolor* color = WSGIappColorSet()->getColor(bg);
  if (color != NULL){
    bgc = color->getValue1();
  }
  short vx,vy;
  WSCushort vw,vh;
  getAbstSize(&vx,&vy,&vw,&vh);


  RECT v;
  v.c.left = vx;
  v.c.top = vy;
  v.c.right = vx + vw;
  v.c.bottom = vy + vh;
  gset_vis(getParentMemGID(),v);

//  PAT pat = {0,16,16,bgc,bgc,FILL100};
  PAT pat;
  pat.spat.kind = 0;
  pat.spat.hsize = 16;
  pat.spat.vsize = 16;
  pat.spat.fgcol = bgc;
  pat.spat.bgcol = bgc;
  pat.spat.mask = FILL100;

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


  rect.c.left = x+px;
  rect.c.top = y+py;
  rect.c.right = w + x +px;
  rect.c.bottom = h + y +py;
//printf("## WSDbtronFormDev::_setup_pixmap %s fil=%d,%d,%d,%d col=%s\n",getAttachedClient()->getInstanceName(),x,y,w,h,color->getColorName());
//printf("## WSDbtronFormDev::_setup_pixmap %s fil=%d,%d,%d,%d col=%s\n",getAttachedClient()->getInstanceName(),x,y,w,h,color->getColorName());
//printf("## WSDbtronFormDev::_setup_pixmap fil=%d,%d,%d,%d bgc=0x%x\n",x,y,w,h,bgc);
//  gset_for(getContextResource(),NULL);
  gfil_rec(getParentMemGID(),rect,&pat,0,G_STORE);

  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();
      GID pid = (GID)image->getValue1();
      GID pid2 = (GID)image->getValue2();
      short cw = 0;
      RECT from;
      RECT to;
//printf("## WSDbtronFormDev::_setup_pixmap %s pix=0x%x pw,ph=%d,%d\n",getAttachedClient()->getInstanceName(),pid,pw,ph);
      if (pid == 0 || pid == -1){
        return;
      }     
      while(1){
        short ch = 0;
        while(1){
          from.c.left = 0;
          from.c.top = 0;
          from.c.right = pw;
          from.c.bottom = ph;

          to.c.left = cw + px;
          to.c.top = ch + py;
          to.c.right = pw +cw + px;
          to.c.bottom = ph +ch + py;
          if (pid2 != 0 && pid2 != -1){
            gcop_bmp(pid2,&from,getParentMemGID(),&to,NULL,G_AND);
            gcop_bmp(pid,&from,getParentMemGID(),&to,NULL,G_OR);
          }else{
            gcop_bmp(pid,&from,getParentMemGID(),&to,NULL,G_STORE);
          }

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

  return;
}

long WSDbtronFormDev::createWindow(){
  if (getParentVisible() == False){
    return WS_ERR;
  }
dbprintf("WSDbtronWinDev::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;
  }

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

  drawBackGround(0,0,w,h);

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

long WSDbtronFormDev::getDeviceResource(){
#ifdef F_MEMGID
  return getParentGID();
#else
  return 0;
#endif
}

long WSDbtronFormDev::createPixmap(){
//dbprintf("CC WSDbtronFormDev::createPixmap() %s\n",getAttachedClient()->getInstanceName());
  short x,y;    
  WSCushort w,h;    
  getWindowSize(&x,&y,&w,&h);
  if (w <1){
    w = 1;
  }
  if (h <1){
    h = 1;
  }

//  _mem_gid = WSGIbtronAppDev()->getNewMemGid(w,h);
  if (getParentMemGID() == 0){
//printf("WSDbtronFormDev::createPixmap() error return %s\n",w,h,getAttachedClient()->getInstanceName());
    return WS_ERR;
  }
  WSDwindowDev::createPixmap();
//printf("CC WSDbtronFormDev::createPixmap() wh=%d,%d %s\n",w,h,getAttachedClient()->getInstanceName());
//dbprintf("WSDbtronFormDev::createPixmap() wh=%d,%d %s\n",w,h,getAttachedClient()->getInstanceName());
  _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++){
    WSDbtronFormDev* child =(WSDbtronFormDev*)children[i];
    if (WSDbtronFormDev::isValidInstance(child) == False){
      continue;
    }
    if (child->getParentVisible() != False){
      child->createPixmap();
    }
  }
#endif

  return WS_NO_ERR;
}
void WSDbtronFormDev::recursiveExposeExecute(short x,short y,WSCushort w,WSCushort h){
  if (w <1){
    w = 1;
  }
  if (h <1){
    h = 1;
  }

  if (getParentMemGID() == 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++){
    WSDbtronFormDev* child =(WSDbtronFormDev*)children[i];
    if (WSDbtronFormDev::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 WSDbtronFormDev::getContextResource(){
//  if (getPixmapStyle() != WS_DIRECT_WINDOW){
//    return getMemGID();
//  }
  WSDbtronFormDev* parent = getParentAreaDev();
  if (parent != NULL){
    return parent->getContextResource();
  }
  return -1;
}

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

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

long WSDbtronFormDev::getWindowResource(){
  WSDbtronFormDev* parent = getParentAreaDev();
  if (parent != NULL){
    return parent->getWindowResource();
  }
  return (long)0;
}
W WSDbtronFormDev::getWindow(){
  return _window;
}
W WSDbtronFormDev::getGID(){
  return _gid;
}
W WSDbtronFormDev::getMemGID(){
  return _mem_gid;
}
WSCbool WSDbtronFormDev::getUseMemGID(){
  if (_mem_gid != NULL){
    return True;
  }
  WSDbtronFormDev* pdev = (WSDbtronFormDev*)getParentAreaDev();
  if (pdev !=NULL){
    return pdev->getUseMemGID();
  }
  return False;
}
long WSDbtronFormDev::destroyWindow(){
  if (getChildDevListFlag() != False){
    WSDbtronFormDev* pdev = getParentAreaDev();
    if (pdev != NULL){
      pdev->delChildDevList(this);
    }else{
      setChildDevListFlag(False);
    }
  }
  return WS_NO_ERR;
}

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

long WSDbtronFormDev::destroyContext(){
  return WS_NO_ERR;
}
void WSDbtronFormDev::redrawAll(){
  WSDbtronFormDev* pdev = getMostParentAreaDev();
  if (pdev != NULL && pdev->getVisible() != False){
    short dx,dy;
    WSCushort dw,dh;
    getAbstSize(&dx,&dy,&dw,&dh);
//      pdev->_setup_pixmap(dx - pdev->_w_x, dy - pdev->_w_y,
//                        dw, dh, pdev->_bg,pdev->_bg_pix);
//    pdev->_setup_pixmap(dx,dy,dw,dh,pdev->_bg,pdev->_bg_pix);
    pdev->recursiveExposeExecute(dx,dy,dw,dh);
    RECT r;
    r.c.left = dx;
    r.c.right = dx + dw;
    r.c.top = dy;
    r.c.bottom = dy + dh;
    pdev->_evh_expose(&r);
  }
}

long WSDbtronFormDev::setVisible(WSCbool fl){
dbprintf("WSDbtronFormDev::setVisible fl=%d\n",fl);
  WSCbool bk = getVisible();
  WSCbool bk2 = getParentVisible();
  WSDdev::setVisible(fl);
  if (fl == False){
    if (_window != 0){
      destroyWindow();
//      onUnmap();
    }
    if (getPixmapStyle() == WS_DYNAMIC_PIXMAP){
      destroyPixmap();
    }
#if 0    
    WSDbtronFormDev* pdev = getParentAreaDev();
    while(1){
      if (pdev == NULL){
        break;
      }
      if (pdev->getParentVisible() == False){
        pdev = pdev->getParentAreaDev();
      }else{
        break;
      }
    }
    if (pdev != NULL && pdev->getParentVisible() != False){
      if (bk != fl){
        short dx,dy;
        WSCushort dw,dh;
        getAbstSize(&dx,&dy,&dw,&dh);
        short px,py;
        pdev->getAbstPos(&px,&py);
//        pdev->_setup_pixmap(dx - pdev->_w_x, dy - pdev->_w_y,
//                          dw, dh, pdev->_bg,pdev->_bg_pix);
//        pdev->exposeExecute(dx - pdev->_w_x, dy - pdev->_w_y,dw,dh);

        pdev->setDefaultRegion();
        pdev->_setup_pixmap(dx-px,dy-py,dw,dh,pdev->_bg,pdev->_bg_pix);
        pdev->exposeExecute(dx-px,dy-py,dw,dh);
        pdev->_copy_area(dx-px,dy-py,dw,dh,dx-px,dy-py,WS_PIXMAP_TO_WINDOW);
      }
    }
#endif


    if (bk2 != fl){
      redrawAll();
    }
#if 0
    WSDbtronFormDev* pdev = getMostParentAreaDev();
    if (pdev != NULL && pdev->getVisible() != False){
      if (bk2 != fl){
        short dx,dy;
        WSCushort dw,dh;
        getAbstSize(&dx,&dy,&dw,&dh);
//        pdev->_setup_pixmap(dx - pdev->_w_x, dy - pdev->_w_y,
//                          dw, dh, pdev->_bg,pdev->_bg_pix);
        pdev->_setup_pixmap(dx,dy,dw,dh,pdev->_bg,pdev->_bg_pix);
        pdev->recursiveExposeExecute(dx,dy,dw,dh);
        RECT r;
        r.c.left = dx;
        r.c.right = dx + dw;
        r.c.top = dy;
        r.c.bottom = dy + dh;
        pdev->_evh_expose(&r);
      }
    }
#endif

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

  }else{
    if (_window == 0){
       createWindow();
    }
    if (getPixmapStyle() == WS_DYNAMIC_PIXMAP){
//printf("WSDbtronFormDev::setVisible fl=%d %s\n",fl,getAttachedClient()->getInstanceName());

      createPixmap();
//      if (WSGIbtronAppDev()->getMouseGrabbed() != False){
        _copy_area(0,0,_w_w,_w_h,0,0,WS_PIXMAP_TO_WINDOW);
//      }
    }
  }
  return WS_NO_ERR;
}
void WSDbtronFormDev::_evh_mouse_in(H x, H y){
  short dx,dy;
  getAbstPos(&dx,&dy);
//  WSCushort dw,dh;
//  getAbstSize(&dx,&dy,&dw,&dh);

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

//if (getAttachedClient() != NULL) dbprintf("WSDbtronFormDev::_evh_mouse_in %d,%d %s\n",x,y,getAttachedClient()->getInstanceName());
  _btron_mouse_value* val = (_btron_mouse_value*)WSGIappMouse()->getMouseCursor(_mno);
  if (val != NULL){
    W style = val->_style;
    COLOR fg = (COLOR)val->_fg;
    COLOR bg = (COLOR)val->_bg;
    gset_ptr(style,NULL,fg,bg);
  }
  onMouseIn(&point);
}

void WSDbtronFormDev::_evh_mouse_out(){
//if (getAttachedClient() != NULL) dbprintf("WSDbtronFormDev::_evh_mouse_out %s\n",getAttachedClient()->getInstanceName());

  onMouseOut();
}

void WSDbtronFormDev::_evh_mouse_move(WEVENT* ev){
  long state = WSGIappMouse()->getStatus();
  if (ev->s.stat & ES_BUT){
    state |= WS_MOUSE_BTN1;
    WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN1);
  }else if (ev->s.stat & ES_BUT2){
    state |= WS_MOUSE_BTN3;
    WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN3);
  }
  WSGIappMouse()->setStatus(state);

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

  PNT pt;
  W w = getParentWindow();
  if (ev->s.wid == w){
    pt.x = ev->e.pos.x -dx;
    pt.y = ev->e.pos.y -dy;
  }else{
    short x,y;
    WSGIappMouse()->getMousePosition(&x,&y);
    pt.x = x;
    pt.y = y;
    gcnv_rel(getParentGID(),&pt);
    pt.x = pt.x - dx;
    pt.y = pt.y - dy;
  }

   WSCpoint point;
   point.setPoint( pt.x,pt.y );
//printf("WSDbtronFormDev::_evh_mouse_move %s %d,%d\n",getAttachedClient()->getInstanceName(),pt.x,pt.y);
   onMouseMove(&point);
}

WSDbtronFormDev* WSDbtronFormDev::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++){
    WSDbtronFormDev* child = (WSDbtronFormDev*)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){
      WSDbtronFormDev* gchild = child->getChildWithPoint(x,y);
      if (gchild == NULL){
        return child;
      }else{
        return gchild;
      }
    }
  }
  return this;
}

void WSDbtronFormDev::_evh_expose(RECT* r){
//printf("WSDbtronForm::_evh_expose start %s\n",getAttachedClient()->getInstanceName());
  if (getParentVisible() == False){
    return;
  }
  if (getAttachedClient() == NULL){
    setVisible(False);
    return;
  }else if (getAttachedClient()->getParentVisible() == False){
    setVisible(False);
    return;
  }
  _expose_sequence = True;
//printf("WSDbtronWinDev::_evh_expose %d,%d,%d,%d client=%s\n",r->c.left,r->c.top,r->c.right - r->c.left,r->c.bottom - r->c.top,getAttachedClient()->getInstanceName());
  
  _exposed_global_region_x =  r->c.left;
  _exposed_global_region_y =  r->c.top;
  _exposed_global_region_w =  r->c.right - r->c.left;
  _exposed_global_region_h =  r->c.bottom - r->c.top;

  setDefaultRegion();

  short x,y;
  getAbstPos(&x,&y);
  if (getUseMemGID() == False){
    drawBackGround(r->c.left -x, r->c.top -y,
                 r->c.right -r->c.left,
                 r->c.bottom -r->c.top);
  }
  WSCrect area;
  area.setRect( (short)r->c.left, (short)r->c.top,
             (WSCushort)(r->c.right - r->c.left),
             (WSCushort)(r->c.bottom - r->c.top));
  if (area.width == 0 || area.height == 0){
    area.width = _w_w;
    area.height = _w_h;
  }
//printf("WSDbtronForm::_evh_expose %s\n",getAttachedClient()->getInstanceName());
  onExpose(&area);
//printf("WSDbtronForm::_evh_expose next %s\n",getAttachedClient()->getInstanceName());
  WSClistData children = getChildDevList();
  long num = children.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDbtronFormDev* child =(WSDbtronFormDev*)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("WSDbtronForm::_evh_expose done %s\n",getAttachedClient()->getInstanceName());
}
void WSDbtronFormDev::_expose_ex(WSCrect* r){
   if (getParentVisible() == False){
     return;
   }
   if (getAttachedClient() == NULL){
dbprintf("WSDbtronFormDev::_expose_ex %d,%d,%d,%d exit1!!!!\n",r->x,r->y,r->width,r->height);
     setVisible(False);
     return;
   }else if (getAttachedClient()->getParentVisible() == False){
//dbprintf("WSDbtronFormDev::_expose_ex %d,%d,%d,%d exit2!!!! client=%s\n",r->x,r->y,r->width,r->height,getAttachedClient()->getInstanceName());
     setVisible(False);
     return;
   }

   W bgc = 0x10000000;
   WSDcolor* color = WSGIappColorSet()->getColor(_bg);
                                                                                
  if (color != NULL){
    bgc = color->getValue1();
  }
  RECT rc;
  rc.c.left = r->x;
  rc.c.top = r->y;
  rc.c.right = r->x + r->width;
  rc.c.bottom = r->y + r->height;
  if (r->width == 0 || r->height == 0){
//dbprintf("WSDbtronFormDev::_expose_ex %d,%d,%d,%d exit3!!!! client=%s\n",r->x,r->y,r->width,r->height,getAttachedClient()->getInstanceName());
    return;
  }
//printf("EX> WSDbtronFormDev::_expose_ex %d,%d,%d,%d setvis! client=%s\n",r->x,r->y,r->width,r->height,getAttachedClient()->getInstanceName());

  gset_vis(getContextResource(),rc);
  setDefaultRegion();

  short dx,dy;
  getAbstPos(&dx,&dy);
//dbprintf("!!WSDbtronFormDev::_expose_ex %d,%d,%d,%d %s abst=%d,%d\n",r->x,r->y,r->width,r->height,getAttachedClient()->getInstanceName(),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++){
    WSDbtronFormDev* child =(WSDbtronFormDev*)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 WSDbtronFormDev::_evh_expose_abs(RECT* 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);
  RECT v;
  v.c.left = vx;
  v.c.right = vx + vw;
  v.c.top = vy;
  v.c.right = vy + vh;
  gset_vis(getContextResource(),v);
//printf("_evh_expose_abs %d,%d,%d,%d %s\n",vx,vy,vw,vh,getAttachedClient()->getInstanceName());
  short x,y;
  getAbstPos(&x,&y);
  if (getUseMemGID() == False){
    drawBackGround(r->c.left -x, r->c.top -y,
                 r->c.right -r->c.left,
                 r->c.bottom -r->c.top);
  }else{
    _setup_pixmap(r->c.left -x, r->c.top -y,
                 r->c.right -r->c.left,
                 r->c.bottom -r->c.top,_bg,_bg_pix);
  }
  WSCrect area;
  area.setRect( (short)r->c.left, (short)r->c.top,
             (WSCushort)(r->c.right - r->c.left),
             (WSCushort)(r->c.bottom - r->c.top));
  if (area.width == 0 || area.height == 0){
    area.width = _w_w;
    area.height = _w_h;
  }
  exposeExecute((short)r->c.left,(short)r->c.top,
             (WSCushort)(r->c.right - r->c.left),
             (WSCushort)(r->c.bottom - r->c.top));
  onExpose(&area);

  WSClistData children = getChildDevList();
  long num = children.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDbtronFormDev* child =(WSDbtronFormDev*)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 WSDbtronFormDev::_expose_ex_abs(WSCrect* r){
   if (getParentVisible() == False){
     return;
   }
   if (getAttachedClient() == NULL){
//dbprintf("WSDbtronFormDev::_expose_ex %d,%d,%d,%d exit1!!!!\n",r->x,r->y,r->width,r->height);
     setVisible(False);
     return;
   }else if (getAttachedClient()->getParentVisible() == False){
//dbprintf("WSDbtronFormDev::_expose_ex %d,%d,%d,%d exit2!!!! client=%s\n",r->x,r->y,r->width,r->height,getAttachedClient()->getInstanceName());
     setVisible(False);
     return;
   }

   W bgc = 0x10000000;
   WSDcolor* color = WSGIappColorSet()->getColor(_bg);
                                                                                
  if (color != NULL){
    bgc = color->getValue1();
  }
  RECT rc;
  rc.c.left = r->x;
  rc.c.top = r->y;
  rc.c.right = r->x + r->width;
  rc.c.bottom = r->y + r->height;
  if (r->width == 0 || r->height == 0){
    return;
  }
  setDefaultRegion();
  gset_vis(getContextResource(),rc);

  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++){
    WSDbtronFormDev* child =(WSDbtronFormDev*)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 WSDbtronFormDev::_evh_resize(RECT* r){
//printf("RR> _evh_resize ... %s\n",getAttachedClient()->getInstanceName());
  PNT pt;
  pt.x = 0;
  pt.y = 0;
  gcnv_rel(getParentGID(),&pt);
  
  WSCrect area;
  area.setRect(-pt.x,-pt.y,r->c.right - r->c.left,r->c.bottom - r->c.top);

  RECT rect;
  wget_wrk(_window,&rect);
#if 1
  RECT r2;
  r2.c.left = 0;
  r2.c.top = 0;
  r2.c.right = rect.c.right - rect.c.left;
  r2.c.bottom = rect.c.bottom - rect.c.top;
  gset_vis(_gid,r2);
  if (_mem_gid > 0){
    gset_vis(_mem_gid,r2);
  }
#else
  gset_vis(_gid,*r);
  if (_mem_gid > 0){
    gset_vis(_mem_gid,*r);
  }
#endif
  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();
      RECT rct;
      rct.c.left = 0;
      rct.c.top = 0;
      rct.c.right = _w_w;
      rct.c.bottom = _w_h;
      _evh_expose(&rct);
    }
  }
}

void WSDbtronFormDev::_evh_btn_press(WEVENT* ev){
   PNT pt;
   pt.x = ev->e.pos.x;
   pt.y = ev->e.pos.y;
   if (ev->s.type == EV_MENU){
     gcnv_rel(getParentGID(),&pt);
   }
   short dx,dy;
   getAbstPos(&dx,&dy);
   pt.x = pt.x - dx;
   pt.y = pt.y - dy;

   WSCpoint point;
   point.setPoint( pt.x,pt.y );
//if (getAttachedClient() != NULL) dbprintf("WSDbtronFormDev::_evh_btn_press %d,%d %s\n",pt.x,pt.y,getAttachedClient()->getInstanceName());
   long state = WSGIappMouse()->getStatus();
   if (ev->s.stat & ES_BUT){
     state |= WS_MOUSE_BTN1;
     WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN1);
   }else if (ev->s.stat & ES_BUT2){
     state |= WS_MOUSE_BTN3;
     WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN3);
   }
   WSGIappMouse()->setStatus(state);

   long clk = WSGFclocktime();
   WSGIbtronAppDev()->setBtnPressGrabTarget(this);
   onMousePress(&point);
   if ((WSCulong)clk - (WSCulong)_click_time < 250){
     onMouseDoubleClick(&point);
   }
   _click_time = clk;
}
void WSDbtronFormDev::_evh_btn_release(WEVENT* ev){
   PNT pt;
   pt.x = ev->e.pos.x;
   pt.y = ev->e.pos.y;
   if (ev->s.type == EV_NULL){
     gcnv_rel(getParentGID(),&pt);
   }

   short dx,dy;
   getAbstPos(&dx,&dy);
   pt.x = pt.x - dx;
   pt.y = pt.y - dy;

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

   long state = WSGIappMouse()->getStatus();
//dbprintf("WSDbtronFormDev::_evh_btn_release %d,%d ev.stat=0x%x bt1=0x%x\n",pt.x,pt.y,ev->s.stat,ES_BUT);
   if ((ev->s.stat & ES_BUT) == 0){
     if (state & WS_MOUSE_BTN1){
       state &= ~WS_MOUSE_BTN1;
       WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN1);
     }
   }
   if ((ev->s.stat & ES_BUT2) == 0){
     if (state & WS_MOUSE_BTN3){
       state &= ~WS_MOUSE_BTN3;
       WSGIappMouse()->setTargetBtn(WS_MOUSE_BTN3);
     }
   }
//dbprintf("WSDbtronFormDev::_evh_btn_release %d,%d stat=%x bt1=0x%x\n",pt.x,pt.y,state);
   if ((state & WS_MOUSE_BTN1) == 0 &&
       (state & WS_MOUSE_BTN2) == 0 &&
       (state & WS_MOUSE_BTN3) == 0 ){
     WSGIbtronAppDev()->setBtnPressGrabTarget(NULL);
   }
   WSGIappMouse()->setStatus(state);
   onMouseRelease(&point);
   WSDbtronDragDrop* bdd = WSGIbtronAppDragDrop();
   if (bdd != NULL){
     if (bdd->getDragState() != 0){
       bdd->executeDrop();
       return;
     }
   }

}

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

void WSDbtronFormDev::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;
  }
  WSDbtronFormDev* 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 WSDbtronFormDev::getAbstPos(short* x,short* y){
  if (haveWindow() != False){
    *x = 0;
    *y = 0;
    return;
  }
  WSDbtronFormDev* parent = getParentAreaDev();

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

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

void WSDbtronFormDev::setDefaultRegion(){
//dbprintf("WSDbtronFormDev::setDefaultRegion this->%s\n",getAttachedClient()->getInstanceName());
extern W _fep_popup;
  WSClistData dlist = getChildDevList();
  long num = dlist.getNum();

//printf("fep_popup=0x%x\n",_fep_popup);
  RLIST rlist[2+N_VIEWR];
  long cnt = 0;
  if (_fep_popup != 0){
    WDSTAT wst;
    wget_sts(_fep_popup,&wst,NULL);
    rlist[cnt].rcomp.c.left = wst.r.c.left;
    rlist[cnt].rcomp.c.top = wst.r.c.top;
    rlist[cnt].rcomp.c.right = wst.r.c.right;
    rlist[cnt].rcomp.c.bottom = wst.r.c.bottom;
    rlist[cnt].next = NULL;
    cnt++;
  }
  if (_global_region_w !=0 && _global_region_h != 0){
//printf("fep_mask=%d,%d,%d,%d\n",_global_region_x,_global_region_y,_global_region_w,_global_region_h);
    PNT pt;
    pt.x = _global_region_x;
    pt.y = _global_region_y;
    gcnv_abs(getParentGID(),&pt);
    rlist[cnt].rcomp.c.left = pt.x;
    rlist[cnt].rcomp.c.top = pt.y;
    rlist[cnt].rcomp.c.right = pt.x + _global_region_w;
    rlist[cnt].rcomp.c.bottom = pt.y + _global_region_h;
    rlist[cnt].next = NULL;
    if (cnt > 0){
      rlist[cnt-1].next = &rlist[cnt];
    }
    cnt++;
  }
//dbprintf("##> setDefaultRegion _clip_num=%d\n",_clip_num);
  long i;
  for(i=0; i<N_VIEWR; i++){
    if (i == _clip_num){
      break;
    }
    rlist[cnt] = _clip_fore_list[i];
//dbprintf("##> setDefaultRegion i=%d lrtb=%d,%d,%d,%d\n",i,rlist[cnt].rcomp.c.left,rlist[cnt].rcomp.c.top ,rlist[cnt].rcomp.c.right ,rlist[cnt].rcomp.c.bottom);
    rlist[cnt].next = NULL;
    if (cnt > 0){
      rlist[cnt-1].next = &rlist[cnt];
    }
    cnt++;
  }
  W winlist[N_VIEWR];
  memset(winlist,0,sizeof(winlist));
  wget_inf(WI_WINLIST,winlist,sizeof(winlist));
  for(i=0; i<N_VIEWR; i++){
    if (N_VIEWR < cnt){
      break;
    }
    if (winlist[i] == 0){
      break;
    }
    if (winlist[i] == getParentWindow()){
      break;
    }
    WDSTAT wst;
//    wst.attr = WA_FRAME;
//    wst.attr = 0;
    wget_sts(winlist[i],&wst,NULL);
//printf("winlist[%d]=0x%x %d,%d\n",i,winlist[i],wst.org.c.left,wst.org.c.top);
    wcnv_rec(wst.attr,&wst.r,WA_FRAME);
    rlist[cnt].rcomp.c.left = wst.r.c.left;
    rlist[cnt].rcomp.c.top = wst.r.c.top;
    rlist[cnt].rcomp.c.right = wst.r.c.right;
    rlist[cnt].rcomp.c.bottom = wst.r.c.bottom;
//printf("winlist[%d]=0x%x %d,%d,%d,%d\n",i,winlist[i],wst.r.c.left,wst.r.c.top,wst.r.c.right,wst.r.c.bottom);
//printf("winlist[%d]=0x%x %d,%d\n",i,winlist[i],wst.r.c.left,wst.r.c.top);
    rlist[cnt].next = NULL;
    if (cnt > 0){
      rlist[cnt-1].next = &rlist[cnt];
    }
    cnt++;
  }

  if (cnt > 0){
    gset_for(getParentGID(),rlist);
  }else{
    gset_for(getParentGID(),NULL);
  }


  if (num == 0){
//dbprintf("WSDbtronFormDev::setDefaultRegion NULL\n");
    gset_for(getContextResource(),NULL);
    return;
  }

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

  RLIST* rc = new RLIST[num+1];
  rc[0].next = NULL;
  for(i=0; i<num; i++){
    WSDbtronFormDev* dev = (WSDbtronFormDev*)dlist[i];
//printf("setDefaultRegion %d %s vis=%d\n",i,dev->getAttachedClient()->getInstanceName(),dev->getParentVisible());
    if (WSDbtronFormDev::isValidInstance(dev) == False){
      continue;
    }
    if (dev->getParentVisible() == False){
      continue;
    }
    short cx,cy;
    WSCushort cw,ch;
    PNT pt;
    dev->getAbstSize(&cx,&cy,&cw,&ch);
    rc[next].next = NULL;
    if (cw <1){
      continue;
    }
    if (ch <1){
      continue;
    }
//dbprintf("WSDbtronFormDev::setDefaultRegion child->%s %d,%d,%d,%d\n",dev->getAttachedClient()->getInstanceName(),cx,cy,cw,ch);
    pt.x = cx;
    pt.y = cy;
    gcnv_abs((W)getContextResource(),&pt);
    rc[next].rcomp.c.left = pt.x;
    rc[next].rcomp.c.top = pt.y;
    rc[next].rcomp.c.right = pt.x + cw;
    rc[next].rcomp.c.bottom = pt.y + ch;
//dbprintf("WSDbtronFormDev::setDefaultRegion %d,%d,%d,%d\n",pt.x,pt.y,cw,ch);
    if (i == 0){
    }else{
      rc[next-1].next = &rc[next];
    }
    next++;
  }
  if (next == 0){
//dbprintf("WSDbtronFormDev::setDefaultRegion set_for=0x%x\n",getContextResource());
    gset_for(getContextResource(),NULL);
  }else{
//dbprintf("WSDbtronFormDev::setDefaultRegion set_for=0x%x\n",getContextResource());
    gset_for(getContextResource(),rc);
  }
  delete[] rc;
}
void WSDbtronFormDev::drawBackGround(long x,long y,WSCulong w,WSCulong h){
  if (getParentVisible() == False){
    return;
  }
  if (w < 1){
    return;
  }
  if (h < 1){
    return;
  }
  WSDbtronFormDev* parent = getParentAreaDev();
  if (parent == NULL){
    if (cast("WSDbtronWinDev")){
      parent = this;
    }else{
      return;
    }
  }

  W bgc = 0x10000000;
  WSDcolor* color = WSGIappColorSet()->getColor(_bg);
  if (color != NULL){
    bgc = color->getValue1();
  }

  PAT pat;
  pat.spat.kind = 0;
  pat.spat.hsize = 16;
  pat.spat.vsize = 16;
  pat.spat.fgcol = bgc;
  pat.spat.bgcol = bgc;
  pat.spat.mask = FILL100;

  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();
  RECT rect;
  rect.c.left = dx;
  rect.c.top = dy;
  rect.c.right = dw + dx;
  rect.c.bottom = dh + dy;
//dbprintf("## WSDbtronFormDev::drawBackGround %s fil=%d,%d,%d,%d col=%s bg=0x%x\n",getAttachedClient()->getInstanceName(),dx,dy,dw,dh,color->getColorName(),_bg_pix);
  gfil_rec(getContextResource(),rect,&pat,0,G_STORE);
//printf("## WSDbtronFormDev::drawBackGround %s fil=%d,%d,%d,%d col=%s bg=0x%x gid=0x%x\n",getAttachedClient()->getInstanceName(),dx,dy,dw,dh,color->getColorName(),_bg_pix,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();
      GID pid = (GID)image->getValue1();
      GID pid2 = (GID)image->getValue2();
      if (pid==0){
//dbprintf("##   pid=NULL..\n");
        return;
      }
      short cw = 0;
      RECT from;
      RECT to;
     
      while(1){
        short ch = 0;
        while(1){
          from.c.left = 0;
          from.c.top = 0;
          from.c.right = pw;
          from.c.bottom = ph;

          to.c.left = cw + cx;
          to.c.top = ch + cy;
          to.c.right = cw + cx + pw;
          to.c.bottom = ch + cy + ph;
          if (pid2 != 0 || pid2 != -1){
            gcop_bmp(pid2,&from,getContextResource(),&to,NULL,G_AND);
            gcop_bmp(pid,&from,getContextResource(),&to,NULL,G_OR);
          }else{
            gcop_bmp(pid,&from,getContextResource(),&to,NULL,G_STORE);
          }
//dbprintf("##   copy to=%d,%d,%d,%d\n",cw,ch,pw,ph);
          ch += ph;
          if (ch > h) break;
        }
        cw += pw;
        if (cw > w) break;
      }
    }
  }

}
W WSDbtronFormDev::getParentWindow(){
  if (_window != NULL){
    return _window;
  }
  WSDbtronFormDev* pdev = this;
  while(1){
    if (pdev != NULL){
      W w = pdev->getWindow();
      if (w != NULL){
        return w;
      }
      pdev = pdev->getParentAreaDev();
    }else{
      return 0;
    }
  }
  return 0;
}
W WSDbtronFormDev::getParentGID(){
  if (_gid != NULL){
    return _gid;
  }
  WSDbtronFormDev* pdev = this;
  while(1){
    if (pdev != NULL){
      W w = pdev->getGID();
      if (w != NULL){
        return w;
      }
      pdev = pdev->getParentAreaDev();
    }else{
      return 0;
    }
  }
  return 0;
}
W WSDbtronFormDev::getParentMemGID(){
  if (_mem_gid != NULL){
    return _mem_gid;
  }
  WSDbtronFormDev* pdev = this;
  while(1){
    if (pdev != NULL){
      W w = pdev->getMemGID();
      if (w != NULL){
        return w;
      }
      pdev = pdev->getParentAreaDev();
    }else{
      return 0;
    }
  }
  return 0;
}
void WSDbtronFormDev::exposeExecute(short x,short y,WSCushort w,WSCushort h){
  WSDwindowDev::exposeExecute(x,y,w,h);
}
void WSDbtronFormDev::addUpdateList(){
  long num = _update_list.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDbtronFormDev* item =(WSDbtronFormDev*)_update_list[i];
    if (item == this){
      return;
    }
  }
  _update_list.add((void*)this);
}
void WSDbtronFormDev::addGeometryUpdateList(){
  long num = _geometry_update_list.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDbtronFormDev* item =(WSDbtronFormDev*)_geometry_update_list[i];
    if (item == this){
      return;
    }
  }
  _geometry_update_list.add((void*)this);
}
void WSDbtronFormDev::executeUpdate(){
  long num = _geometry_update_list.getNum();
  long i;
  for(i=0; i<num; i++){
    WSDbtronFormDev* item =(WSDbtronFormDev*)_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;
          W wid = (W)item->getWindowResource();
          long update = True;
          long unum = _expose_list.getNum();
          for(j=0; j<unum;j++){
            W item = (W)_expose_list[j];
            if (item == wid){
              update = False;
              break;
            }
          }
          if (update == True){
            _expose_list.add((void*)wid);
          }
#if 0
 //          item->createPixmap();
          RECT rct;
          rct.c.left = 0;
          rct.c.top = 0;
          rct.c.right = dw2;
          rct.c.bottom = dh2;
          item->_evh_expose(&rct);
#endif
        }
      }
    }
  }
  _geometry_update_list.clear();

  num = _update_list.getNum();
  for(i=0; i<num; i++){
    WSDbtronFormDev* item =(WSDbtronFormDev*)_update_list[i];
    if (item != NULL && isValidInstance(item) != False &&
        item->getParentVisible() != False){
#if 0
      RECT r;
      r.c.left = 0;
      r.c.right = 32767;
      r.c.top = 0;
      r.c.bottom = 32767;
#ifdef F_MEMGID
      item->_evh_expose_abs(&r);
#else
      item->_evh_expose(&r);
#endif
#endif
      long j;
      W wid = (W)item->getWindowResource();
      long update = True;
      long unum = _expose_list.getNum();
      for(j=0; j<unum;j++){
        W item = (W)_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++){
    W wid = (W)_expose_list[i];
#ifndef SMARTUPDATE
    W ret = wreq_dsp(wid);
#else
    WSDbtronFormDev* dev = NULL;
    W ret = wget_dat(wid,(W*)&dev);
    if (ret == 0){
      if (dev != NULL &&
        WSDbtronFormDev::isValidInstance(dev) != False){
        dev->redrawAll();
#if 0
          short dx,dy;
          WSCushort dw,dh;
          dev->getAbstSize(&dx,&dy,&dw,&dh);
          RECT r;
          r.c.left = dx;
          r.c.top = dy;
          r.c.right = dx + dw;
          r.c.bottom = dy + dh; 
//          dev->destroyPixmap();
          dev->_evh_expose(&r);
#endif
      }
    }
#endif
dbprintf("WSDbtronFormDev::execUpdate update wid=0x%x ret=0x%x\n",wid,ret);
  }
  _expose_list.clear();
}

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

  short ax,ay;
  getAbstPos(&ax,&ay);
  RECT rc;
  rc.c.left = ax + x;
  rc.c.top = ay + y;
  rc.c.right = ax + x  + w;
  rc.c.bottom = ay + y + h;
  if (w == 0 || h == 0){
    return WS_NO_ERR;
  }
//printf("WSDbtronFormDev::exposeArea %d,%d,%d,%d\n",x,y,w,h);
  gset_vis(getContextResource(),rc);
  setDefaultRegion();
  return WSDwindowDev::exposeArea(x,y,w,h,scale);
}
void WSDbtronFormDev::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 WSDbtronFormDev::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;
}
RLIST* WSDbtronFormDev::getClipList(){
  return _clip_fore_list;
}
void WSDbtronFormDev::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 WSDbtronFormDev::setClipNum(long num){
  _clip_num = num;
}
void WSDbtronFormDev::_evh_destroy(WEVENT* ev){
  WSCbase* client = getAttachedClient();
  if (client != NULL){
    client->setVisible(False);
  }
}
WSCbool WSDbtronFormDev::getParentVisible(){
  if (getVisible() == False){
    return False;
  }
  WSDbtronFormDev* parent = getParentAreaDev();
  if (parent != NULL){
    return parent->getParentVisible();
  }
  return True;
}
