//
// 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 <nx/WSDnxScrFrameDev.h>
#include <WSCbase.h>
#include <WSCbaseList.h>
#include <nx/WSDnxDraw.h>
#include <nx/WSDnxWinDev.h>
#include <nx/WSDnxAppDev.h>

//#define F_MEMGID
#define SMARTUPDATE

WSMFclassInit(WSDnxScrFrameDev,WSDnxFormDev);
WSDdev* _wsdnxScrdev_init_(){
  return new WSDnxScrFrameDev();
}

class _WSDnxScrFrameDev_init_ {
  public:_WSDnxScrFrameDev_init_(){
     WSGIappDevice()->setCreateHandler("scrFrameDev",_wsdnxScrdev_init_);
  };
};
static _WSDnxScrFrameDev_init_ _init_to_run_WSDnxScrFrameDev_;

WSDnxScrFrameDev::WSDnxScrFrameDev(){
  _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;
}

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

long WSDnxScrFrameDev::setValue(long kind,void* data){
  if (kind == WSDEV_PIXMAP_STYLE ){
    return WS_NO_ERR;
  }

  WSDwindowDev::setValue(kind,data);
  long vl;
  char fl = 0;
  short     s1;
  short     bk_x,bk_y;
  WSCushort us1;
  WSDcolor* color;
  WSDnxFormDev* 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){
               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){
               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);
             }
             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){
               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);
             }
             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
                 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);
             }
             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
                 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);
             }
             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;
  }
  WSDnxFormDev::setValue(kind,data);
  return WS_NO_ERR;
}

long WSDnxScrFrameDev::createPixmap(){
  return WSDnxFormDev::createPixmap();
}

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

