//
// 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>
#ifdef TE
#include <btron/errcode.h>
#else
#include <errcode.h>
#endif
#include <WSCdevice.h>
#include <btron/WSDbtronScrFrameDev.h>
#include <WSCbase.h>
#include <WSCbaseList.h>
#include <btron/WSDbtronDraw.h>
#include <btron/WSDbtronWinDev.h>
#include <btron/WSDbtronAppDev.h>

//#define F_MEMGID
#define SMARTUPDATE

WSMFclassInit(WSDbtronScrFrameDev,WSDbtronFormDev);
WSDdev* _wsdbtronScrdev_init_(){
  return new WSDbtronScrFrameDev();
}

class _WSDbtronScrFrameDev_init_ {
  public:_WSDbtronScrFrameDev_init_(){
     WSGIappDevice()->setCreateHandler("scrFrameDev",_wsdbtronScrdev_init_);
  };
};
static _WSDbtronScrFrameDev_init_ _init_to_run_WSDbtronScrFrameDev_;

WSDbtronScrFrameDev::WSDbtronScrFrameDev(){
  _p1_x = 0;
  _p1_x = 0;
  _p2_y = 0;
  _p2_y = 0;
  _h_scr_pos = 0;
  _v_scr_pos = 0;
  _work_width =0;
  _work_height =0;
  _title_height = 0;
}

WSDbtronScrFrameDev::~WSDbtronScrFrameDev(){
  destroyWindow();
}

long WSDbtronScrFrameDev::setValue(long kind,void* data){
  if (kind == WSDEV_PIXMAP_STYLE ){
//    WSDbtronFormDev* pdev = getParentAreaDev();
//    if (pdev != NULL){
//      pdev->setValue(kind,data);
//    }
    return WS_NO_ERR;
  }

  WSDwindowDev::setValue(kind,data);
  long vl;
  char fl = 0;
  short     s1;
  short     bk_x,bk_y;
  WSCushort us1;
  WSDcolor* color;
  WSDbtronFormDev* pdev;
  switch(kind){
    case WSDEV_X:
    case WSDEV_Y:
             getAbstPos(&bk_x,&bk_y);
    case WSDEV_WIDTH:
    case WSDEV_HEIGHT:
             WSDwindowDev::setValue(kind,data);
             if (getParentVisible() != False){
#if 0
               short x,y;
               getAbstPos(&x,&y);
               WSCrect r;
               r.setRect(x+_h_scr_pos, y+_v_scr_pos, _w_w, _w_h);
               _expose_ex(&r);
#endif
#if 0
               {
                 pdev = getMostParentAreaDev();
                 if (pdev != NULL && pdev->getParentVisible() != False){
                   RECT r;
                   r.c.left = 0;
                   r.c.right = 32767;
                   r.c.top = 0;
                   r.c.bottom = 32767;
#ifdef F_MEMGID 
//printf("** scr::setValue %d,%d,%d,%d expose..\n",x,y,_w_w,_w_h);
//printf("** scr::setValue %d,%d,%d,%d clear expose..\n",bk_x,bk_y,_w_w,_w_h);
                   pdev->_evh_expose_abs(&r);
#else
                   pdev->_evh_expose(&r);
#endif
                 }
               }
#endif
               addGeometryUpdateList();
               pdev = getMostParentAreaDev();
               if (pdev != NULL && pdev->getParentVisible() != False){
                 pdev->addUpdateList();
#ifndef SMARTUPDATE
                 pdev->destroyPixmap();
#endif
               }
             }
             return WS_NO_ERR;
    case WSDEV_WORK_X:
             vl = *(WSCushort*)data;
             if (vl > _work_width - _w_w){
               vl = _work_width - _w_w;
               if (vl < 0){
                 vl = 0;
               }
             }
             if ( _h_scr_pos == vl){
               return WS_NO_ERR;
             }
             s1 = vl - _h_scr_pos;
             _h_scr_pos = vl;

             if (_addr_change_handler != NULL){
               _addr_change_handler(this,_handler_data);
             }
             if (getParentVisible() != False){
#if 0 //smart copy logic has some bugs..
               short x,y;
               getAbstPos(&x,&y);
               RECT c;
               RECT c2;
               if (s1 > 0){
                 if (_w_w > s1){ 
                   c.c.left = x + _h_scr_pos;
                   c.c.right = x + _w_w + _h_scr_pos;
                   c.c.top = y + _v_scr_pos;
                   c.c.bottom = y + _w_h + _v_scr_pos;
//                   c.c.left = 0;
//                   c.c.right = 32767;
//                   c.c.top = 0;
//                   c.c.bottom = 32767;
                   gset_for(getParentGID(),NULL);
                   gset_vis(getParentGID(),c);
                   gset_for(getParentMemGID(),NULL);
                   gset_vis(getParentMemGID(),c);
                   c.c.left = x + s1 + _h_scr_pos;
                   c.c.right = x + _w_w + _h_scr_pos;
                   c.c.top = y + _v_scr_pos;
                   c.c.bottom = y + _w_h + _v_scr_pos;

                   c2.c.left = x + _h_scr_pos;
                   c2.c.right = x + _w_w - s1 + _h_scr_pos;
                   c2.c.top = y + _v_scr_pos;
                   c2.c.bottom = y + _w_h + _v_scr_pos;
  
                   W ret =
                   gcop_bmp(getParentMemGID(),&c,getParentGID(),&c2,NULL,G_STORE);
                   gcop_bmp(getParentGID(),&c2,getParentMemGID(),&c2,NULL,G_STORE);
//                 wscr_wnd(getWindowResource(),&c,-s1,0,W_MOVE);
                   setDefaultRegion();
                   _setup_pixmap(_h_scr_pos + _w_w -s1,_v_scr_pos,s1,_w_h,_bg,_bg_pix);
                   exposeExecute(_h_scr_pos + _w_w -s1,_v_scr_pos,s1,_w_h);
                   _copy_area(_h_scr_pos + _w_w -s1,_v_scr_pos,s1,_w_h,
                              _h_scr_pos + _w_w -s1,_v_scr_pos,
                              WS_PIXMAP_TO_WINDOW);
                 }else{
                   setDefaultRegion();
                   _setup_pixmap(_h_scr_pos,_v_scr_pos,_w_w,_w_h,_bg,_bg_pix);
                   exposeExecute(_h_scr_pos,_v_scr_pos,_w_w,_w_h);
                   _copy_area(_h_scr_pos,_v_scr_pos,_w_w,_w_h,
                              _h_scr_pos,_v_scr_pos,WS_PIXMAP_TO_WINDOW);
                 }
               }else if (s1 < 0){
                 if (-_w_w < s1){
                   c.c.left = x + _h_scr_pos;
                   c.c.right = x + _w_w + _h_scr_pos;
                   c.c.top = y + _v_scr_pos;
                   c.c.bottom = y + _w_h + _v_scr_pos;
//                   c.c.left = 0;
//                   c.c.right = 32767;
//                   c.c.top = 0;
//                   c.c.bottom = 32767;
                   gset_for(getParentGID(),NULL);
                   gset_vis(getParentGID(),c);
                   gset_for(getParentMemGID(),NULL);
                   gset_vis(getParentMemGID(),c);
                   c.c.left = x + _h_scr_pos;
                   c.c.right = x + _w_w + s1 + _h_scr_pos;
                   c.c.top = y + _v_scr_pos;
                   c.c.bottom = y + _w_h + _v_scr_pos;
  
                   c2.c.left = x - s1 + _h_scr_pos;
                   c2.c.right = x + _w_w + _h_scr_pos;
                   c2.c.top = y + _v_scr_pos;
                   c2.c.bottom = y + _w_h + _v_scr_pos;

                   W ret =
                   gcop_bmp(getParentMemGID(),&c,getParentGID(),&c2,NULL,G_STORE);
                   gcop_bmp(getParentGID(),&c2,getParentMemGID(),&c2,NULL,G_STORE);
                   setDefaultRegion();
                   _setup_pixmap(_h_scr_pos,_v_scr_pos,-s1,_w_h,_bg,_bg_pix);
                   exposeExecute(_h_scr_pos,_v_scr_pos,-s1,_w_h);
                   _copy_area(_h_scr_pos,_v_scr_pos,-s1,_w_h,
                              _h_scr_pos,_v_scr_pos,WS_PIXMAP_TO_WINDOW);
                 }else{
                   setDefaultRegion();
                   _setup_pixmap(_h_scr_pos,_v_scr_pos,_w_w,_w_h,_bg,_bg_pix);
                   exposeExecute(_h_scr_pos,_v_scr_pos,_w_w,_w_h);
                   _copy_area(_h_scr_pos,_v_scr_pos,_w_w,_w_h,
                              _h_scr_pos,_v_scr_pos,WS_PIXMAP_TO_WINDOW);
                 }
               }
#else
               setDefaultRegion();
               _setup_pixmap(_h_scr_pos,_v_scr_pos,_w_w,_w_h,_bg,_bg_pix);
               exposeExecute(_h_scr_pos,_v_scr_pos,_w_w,_w_h);
               _copy_area(_h_scr_pos,_v_scr_pos,_w_w,_w_h,
                              _h_scr_pos,_v_scr_pos, WS_PIXMAP_TO_WINDOW);
#endif
             }
             return WS_NO_ERR;
    case WSDEV_WORK_Y:
             vl = *(WSCushort*)data;
             if (vl > _work_height - _w_h){
               vl = _work_height - _w_h;
               if (vl < 0){
                 vl = 0;
               }
             }
             if (_v_scr_pos == vl){
               return WS_NO_ERR;
             }
             s1 = vl - _v_scr_pos;
             _v_scr_pos = vl;
             if (_addr_change_handler != NULL){
               _addr_change_handler(this,_handler_data);
             }
             if (getParentVisible() != False){
#if 0 //start copy logic has some bugs..
               short x,y;
               getAbstPos(&x,&y);
               RECT c;
               RECT c2;
               if (s1 > 0){
                 if (_w_h > s1){
                   c.c.left = x +_h_scr_pos;
                   c.c.right = x + _w_w +_h_scr_pos;
                   c.c.top = y +_v_scr_pos;
                   c.c.bottom = y + _w_h +_v_scr_pos;
//                 c.c.left = 0;
//                 c.c.right = 32767;
//                 c.c.top = 0;
//                 c.c.bottom = 32767;
                   gset_for(getParentGID(),NULL);
                   gset_vis(getParentGID(),c);
                   gset_for(getParentMemGID(),NULL);
                   gset_vis(getParentMemGID(),c);

                   c.c.left = x + _h_scr_pos;
                   c.c.right = x + _w_w + _h_scr_pos;
                   c.c.top = y + s1 + _v_scr_pos;
                   c.c.bottom = y + _w_h + _v_scr_pos;
  
                   c2.c.left = x + _h_scr_pos;
                   c2.c.right = x + _w_w + _h_scr_pos;
                   c2.c.top = y + _v_scr_pos;
                   c2.c.bottom = y + _w_h - s1 + _v_scr_pos;
  
                   W ret =
                   gcop_bmp(getParentMemGID(),&c,getParentGID(),&c2,NULL,G_STORE);
                   gcop_bmp(getParentGID(),&c2,getParentMemGID(),&c2,NULL,G_STORE);
//                 W ret = wscr_wnd(getWindowResource(),&c,0,-s1,W_MOVE);
//printf("x,y,w,h=%d,%d,%d,%d  sl=%d\n",x,y,_w_w,_w_h,s1);
//printf("scr ret=%d %d %d %d %d\n",ret,EX_ADR,EX_WID,EX_WND,EX_WPRC);
                   setDefaultRegion();
                   _setup_pixmap(_h_scr_pos,_v_scr_pos+_w_h -s1,_w_w,s1,_bg,_bg_pix);

                   exposeExecute(_h_scr_pos,_v_scr_pos + _w_h -s1,_w_w,s1);
                   _copy_area(_h_scr_pos,_v_scr_pos + _w_h -s1,_w_w,s1,
                              _h_scr_pos,_v_scr_pos + _w_h -s1,
                              WS_PIXMAP_TO_WINDOW);
                 }else{
                   setDefaultRegion();
                   _setup_pixmap(_h_scr_pos,_v_scr_pos,_w_w,_w_h,_bg,_bg_pix);
                   exposeExecute(_h_scr_pos,_v_scr_pos,_w_w,_w_h);
                   _copy_area(_h_scr_pos,_v_scr_pos,_w_w,_w_h,
                              _h_scr_pos,_v_scr_pos,
                              WS_PIXMAP_TO_WINDOW);
                 }
               }else if (s1 < 0){
                 if (-_w_h < s1){
                   c.c.left = x +_h_scr_pos;
                   c.c.right = x + _w_w +_h_scr_pos;
                   c.c.top = y +_v_scr_pos;
                   c.c.bottom = y + _w_h +_v_scr_pos;
//                 c.c.left = 0;
//                 c.c.right = 32767;
//                 c.c.top = 0;
//                 c.c.bottom = 32767;
                   gset_for(getParentGID(),NULL);
                   gset_vis(getParentGID(),c);
                   gset_for(getParentMemGID(),NULL);
                   gset_vis(getParentMemGID(),c);
  
                   c.c.left = x + _h_scr_pos;
                   c.c.right = x + _w_w + _h_scr_pos;
                   c.c.top = y + _v_scr_pos;
                   c.c.bottom = y + _w_h + s1 + _v_scr_pos;
  
                   c2.c.left = x + _h_scr_pos;
                   c2.c.right = x + _w_w + _h_scr_pos;
                   c2.c.top = y - s1 + _v_scr_pos;
                   c2.c.bottom = y + _w_h + _v_scr_pos;
  
                   W ret =
                   gcop_bmp(getParentMemGID(),&c,getParentGID(),&c2,NULL,G_STORE);
                   gcop_bmp(getParentGID(),&c2,getParentMemGID(),&c2,NULL,G_STORE);
  
                   setDefaultRegion();
                   _setup_pixmap(_h_scr_pos,_v_scr_pos,_w_w,-s1,_bg,_bg_pix);
                   exposeExecute(_h_scr_pos,_v_scr_pos,_w_w,-s1);
                   _copy_area(_h_scr_pos,_v_scr_pos,_w_w,-s1,
                              _h_scr_pos,_v_scr_pos,
                              WS_PIXMAP_TO_WINDOW);
                 }else{
                   setDefaultRegion();
                   _setup_pixmap(_h_scr_pos,_v_scr_pos,_w_w,_w_h,_bg,_bg_pix);
                   exposeExecute(_h_scr_pos,_v_scr_pos,_w_w,_w_h);
                   _copy_area(_h_scr_pos,_v_scr_pos,_w_w,_w_h,
                              _h_scr_pos,_v_scr_pos,
                              WS_PIXMAP_TO_WINDOW);

                 }
               }
#else
               setDefaultRegion();
               _setup_pixmap(_h_scr_pos,_v_scr_pos,_w_w,_w_h,_bg,_bg_pix);
               exposeExecute(_h_scr_pos,_v_scr_pos,_w_w,_w_h);
               _copy_area(_h_scr_pos,_v_scr_pos,_w_w,_w_h,
                              _h_scr_pos,_v_scr_pos, WS_PIXMAP_TO_WINDOW);
#endif
             }
             return WS_NO_ERR;
    case WSDEV_WORK_WIDTH:
             s1 = 0;
             us1 = 0;
             if (getPixmapStyle() != WS_DIRECT_WINDOW){
               if (_work_width < *(WSCushort*)data){ //scrform expose
                                                     //redraw bugfix
//                 destroyPixmap();
                 addGeometryUpdateList();
                 pdev = getMostParentAreaDev();
                 if (pdev != NULL && pdev->getParentVisible() != False){
                   pdev->addUpdateList();
#ifndef SMARTUPDATE
                   pdev->destroyPixmap();
#endif
                 }
               }
             }
             if (_work_width - _h_scr_pos < _w_w && 
                 _work_width < *(WSCushort*)data){
               s1 = _work_width;
               us1 = *(WSCushort*)data - _work_width;
             }

             _work_width = *(WSCushort*)data;

             if (_h_scr_pos > _work_width - _w_w){
               _h_scr_pos = _work_width - _w_w;
               if (_h_scr_pos < 0){
                 _h_scr_pos = 0;
               }
               if (_addr_change_handler != NULL){
                 _addr_change_handler(this,_handler_data);
               }
             }
             if (getParentVisible() != False && us1 > 0){
               setDefaultRegion();
               _setup_pixmap(_h_scr_pos,_v_scr_pos,_w_w,_w_h,_bg,_bg_pix);
               exposeExecute(_h_scr_pos,_v_scr_pos,_w_w,_w_h);
               _copy_area(_h_scr_pos,_v_scr_pos,_w_w,_w_h,
                              _h_scr_pos,_v_scr_pos, WS_PIXMAP_TO_WINDOW);
#if 0
               short x,y;
               getAbstPos(&x,&y);
               WSCrect r;
               r.setRect(x+_h_scr_pos + s1,y+_v_scr_pos,us1,_w_h);
               _expose_ex(&r);
#endif
             }
             return WS_NO_ERR;

    case WSDEV_WORK_HEIGHT:
             s1 = 0;
             us1 = 0;
             if (getPixmapStyle() != WS_DIRECT_WINDOW){
               if (_work_height < *(WSCushort*)data){//scrform expose
                                                     //redraw bugfix
//                 destroyPixmap();
                 addGeometryUpdateList();
                 pdev = getMostParentAreaDev();
                 if (pdev != NULL && pdev->getParentVisible() != False){
                   pdev->addUpdateList();
#ifndef SMARTUPDATE
                   pdev->destroyPixmap();
#endif
                 }
               }
             }
             if (_work_height - _v_scr_pos < _w_h && 
                 _work_height < *(WSCushort*)data){
               s1 = _work_height;
               us1 = *(WSCushort*)data - _work_height;
             }
             _work_height = *(WSCushort*)data;
             if (_v_scr_pos > _work_height - _w_h){
               _v_scr_pos = _work_height - _w_h;
               if (_v_scr_pos < 0){
                 _v_scr_pos = 0;
               }
               if (_addr_change_handler != NULL){
                 _addr_change_handler(this,_handler_data);
               }
             }
             if (getParentVisible() != False && us1 > 0){
               setDefaultRegion();
               _setup_pixmap(_h_scr_pos,_v_scr_pos,_w_w,_w_h,_bg,_bg_pix);
               exposeExecute(_h_scr_pos,_v_scr_pos,_w_w,_w_h);
               _copy_area(_h_scr_pos,_v_scr_pos,_w_w,_w_h,
                              _h_scr_pos,_v_scr_pos, WS_PIXMAP_TO_WINDOW);
#if 0
               short x,y;
               getAbstPos(&x,&y);
               WSCrect r;
               r.setRect(x+_h_scr_pos,y+_v_scr_pos + s1,_w_w,us1);
               _expose_ex(&r);
#endif
             }
             return WS_NO_ERR;
    case WSDEV_PIXMAP_STYLE:
             fl = *(char*)data;
             setPixmapStyle(fl);
             destroyPixmap();
             return WS_NO_ERR;
    case WSDEV_VHEAD_X:
             _p1_x = *(WSCushort*)data;
             return WS_NO_ERR;
    case WSDEV_VHEAD_Y:
             _p1_y = *(WSCushort*)data;
             return WS_NO_ERR;
    case WSDEV_VFOOT_X:
             _p2_x = *(WSCushort*)data;
             return WS_NO_ERR;
    case WSDEV_VFOOT_Y:
             _p2_y = *(WSCushort*)data;
             return WS_NO_ERR;
    case WSDEV_TITLE_HEIGHT:
             _title_height = *(WSCushort*)data;
             return WS_NO_ERR;
    case WSDEV_GRAB_POINTER:
             return WS_NO_ERR;
  }
  WSDbtronFormDev::setValue(kind,data);
  return WS_NO_ERR;
}

long WSDbtronScrFrameDev::createPixmap(){
#if 0
  WSCushort w,h;
  w = _work_width;
  if (_work_width <1){
    w = 1;
  }
  h = _work_height;
  if (_work_height <1){
    h = 1;
  }
//  _setup_pixmap(0,0,w,h,_bg_no,_bp_no);
  exposeExecute(0,0,w,h);
  return WS_NO_ERR;
#endif
  return WSDbtronFormDev::createPixmap();
}

void WSDbtronScrFrameDev::getDispAddr(short* ox,short* oy){

  short gx,gy;
  WSDwindowDev::getDispAddr(&gx,&gy);

  gx -=_h_scr_pos;
  gy -=_v_scr_pos;

  *ox = gx;
  *oy = gy;
}

void WSDbtronScrFrameDev::getAbstPos(short* x,short* y){
  WSDbtronFormDev* parent = getParentAreaDev();
  short px,py;
  parent->getAbstPos(&px,&py);
  *x = px +_w_x - _h_scr_pos;
  *y = py +_w_y - _v_scr_pos;
}
void WSDbtronScrFrameDev::_copy_area(long x,long y,WSCulong w,WSCulong h,long dx,long dy,WSCuchar fl){
#ifndef F_MEMGID
  WSDbtronFormDev::_copy_area(x,y,w,h,dx,dy,fl);
#else
  WSDbtronFormDev::_copy_area(x,y,w,h,dx,dy,fl);
#endif
}
void WSDbtronScrFrameDev::_setup_pixmap(short x,short y,WSCushort w,WSCushort h,short bg,short img_no){
#ifndef F_MEMGID
  WSDbtronFormDev::_setup_pixmap(x,y,w,h,bg,img_no);
#else
  WSDbtronFormDev::_setup_pixmap(x-_h_scr_pos,y-_v_scr_pos,w,h,bg,img_no);
#endif
}
void WSDbtronScrFrameDev::_clear_area(long x,long y,WSCulong w,WSCulong h){
#ifndef F_MEMGID
  WSDbtronFormDev::_clear_area(x,y,w,h);
#else
  WSDbtronFormDev::_clear_area(x - _h_scr_pos,y - _v_scr_pos,w,h);
#endif
} 

