//
// Copyright (C) 1999-2004 Toshikaz Hirabayashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// TOSHIKAZ HIRABAYASHI BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Except as contained in this notice, the name of Toshikaz Hirabayashi shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization from
// Toshikaz Hirabayashi.

#include <WScom.h>
#include <WSkeysym.h>
#include <WSDkeyboard.h>
#include <WSCvmifield.h>
#include <WSCclassInformation.h>
#include <WSDdev.h>
#include <WSCdevice.h>
#include <WSCimageSet.h>
#include <WSDtimer.h>
#include <WSCfontSet.h>
#include <WSCblink.h>

WSMFguiClassInitialize(WSCvmifield,WSCvifield);
WSMFversion(WSCvmifield,WSCvifield);

#define WS_WORK_NORMAL       0
#define WS_WORK_CURSOR_CLEAR 1

WSMFpropertyValueChange(WSCvmifield,WSNreturnKeyFocus,WSCbool,True);


WSCvmifield::WSCvmifield(WSCbase* base,char* objname):
                WSCvifield(base,objname){

  _multi_lines = 1;
  _enable_max = False;
  _set_base_work_flag = WS_WORK_NORMAL;
  _return_key_focus = True;

  WSMFpropertyCreateStart
      WSMFparentCheckVerSrc(WSCvmifield);

      WSMFpropertyDelete(WSNenableFocusMove);
      WSMFpropertyDelete(WSNfillSpace);
      WSMFpropertyDelete(WSNinterCur);
      WSMFpropertyDelete(WSNmaxLength);
      WSMFpropertyDelete(WSNcolumns);
      WSMFpropertyDelete(WSNupward);
      WSMFpropertyDelete(WSNdownward);
      WSMFpropertyDelete(WSNleftward);
      WSMFpropertyDelete(WSNrightward);
      WSMFpropertyDelete(WSNreturn);
      WSMFpropertyDelete(WSNifieldSkipMode);

    WSMFpropertyValueChangeDef(WSCvmifield,WSNreturnKeyFocus,WSCbool);


  WSMFpropertyCreateEnd

}

void WSCvmifield::getCursorBase(long* bx,long* by){
  if (bx != NULL){
    *bx = _mx;
  }
  if (by != NULL){
    *by = _my;
  }
}
void WSCvmifield::setCursorBase(long bx,long by){
  
  short diffx = bx - _mx;
  short diffy = by - _my;
  short dw = 0;
  short dh = 0;
  if (diffx > 0){
     dw = _w - diffx;
  }else{
     dw = _w + diffx;
  }
  if (diffy > 0){
     dh = _h - diffy;
  }else{
     dh = _h + diffy;
  }
  _mx = bx;
  _my = by;
  _no_mcur_adjust = 1;

  short x = _x;
  short y = _y;
  short h = _h;

  if (_shadow_type != WS_SHADOW_TRANS){
    x += _shadow_thick;
    y += _shadow_thick;
    dw -= _shadow_thick*2;
    dh -= _shadow_thick*2;
    h -= _shadow_thick*2;
  }
  if (getVisible() == False){
    return;
  }
  WSDdev* dev = getowndev();
  if (dev == NULL){
    return;
  }
#ifndef MSW
  if (_use_pix != 0){
    WSCbool fl = 0;
    if (_dev != NULL){
      _dev->setValue(WSDEV_USE_PIXMAP,(void*)&fl);
    }
  }
#endif
  long padding = 0;
  if (_set_base_work_flag == WS_WORK_CURSOR_CLEAR){
    WSDfont* font = WSGIappFontSet()->getFont(_font);
    padding = font->getFontHeight() *2;
    if (padding > dh){
      dh = 0;
    }
  }
  if (dw > 0 && dh > 0){
    if (diffx <= 0 && diffy > 0){
      dev->copyArea(x,y + diffy, dw, dh - padding, x - diffx,y);
      dev->exposeArea( x - diffx -2,y + dh-2 - padding,dw+4,diffy+4 +padding);
      if (diffx != 0){
        dev->exposeArea(x-2, y-2, -diffx+4, h+4);
      }
    }else
    if (diffx < 0 && diffy == 0){
      dev->copyArea(x + padding, y, dw-padding, dh, x-diffx+padding, y-diffy);
//      if (diffy != 0){
//        dev->exposeArea(x-diffx-2,y-2,dw+4,-diffy+4 + padding);
//      }
      if (diffx != 0){
        dev->exposeArea(x-2,y-2,-diffx+4+padding,_h+4);
      }
    }else
    if (diffx > 0 && diffy == 0){
      dev->copyArea(x + diffx, y, dw - padding, dh, x, y);
//      if (diffy != 0){
//        dev->exposeArea(x-2,y-2,dw+4,-diffy+4 + padding);
//      }
      dev->exposeArea( x + dw-2 -padding,y-2, diffx +4 +padding, h+4);
    }else
    if (diffx > 0 && diffy > 0){
      dev->copyArea( x + diffx, y + diffy, dw, dh - padding, x, y);
      dev->exposeArea( x-2, y + dh-2 - padding,dw+4 ,diffy+4 + padding);
      dev->exposeArea( x + dw-2,y-2,diffx+4,h+4);
    }else
    if (diffx <= 0 && diffy <= 0){
      dev->copyArea(x, y + padding, dw, dh - padding, x-diffx, y-diffy + padding);
      if (diffy != 0){
        dev->exposeArea(x-diffx-2,y-2,dw+4,-diffy+4 + padding);
      }
      if (diffx != 0){
        dev->exposeArea(x-2,y-2,-diffx+4,_h+4);
      }
    }else
    if (diffx > 0 && diffy <= 0){
      dev->copyArea(x + diffx, y + padding, dw, dh - padding, x, y -diffy +padding);
      if (diffy != 0){
        dev->exposeArea(x-2,y-2,dw+4,-diffy+4 + padding);
      }
      dev->exposeArea( x + dw-2,y-2,diffx+4, h+4);
    }
  }else{
    WSCushort dw = _w;
    if (dw > _shadow_thick *2 ){
      dw -= _shadow_thick*2;
    }
    WSCushort dh = _h;
    if (dh > _shadow_thick *2 ){
      dh -= _shadow_thick*2;
    }
    dev->exposeArea(x,y,dw ,dh);
  }
#ifndef MSW
  if (_use_pix != 0){
    WSCbool fl = 1;
    if (_dev != NULL){
      _dev->setValue(WSDEV_USE_PIXMAP,(void*)&fl);
    }
  }
#endif
}

long  WSCvmifield::_cursor_move(char direction){
  long prex,prey;
  _get_disp_cur_pos(&prex,&prey);
  _cursor_fore = True;
  long ret = WSCvifield::_cursor_move(direction);
  if (ret != WS_NO_ERR){
    return ret;
  }
  short mdx = _shadow_thick + _margin_left;
  short mdy = _shadow_thick + _margin_top;
  short sw = 0;
  short sh = 0;
  if ( _w > _shadow_thick*2 + _margin_left + _margin_right){
    sw = _w -_shadow_thick*2 - _margin_left - _margin_right;
  }

  if ( _h > _shadow_thick*2 + _margin_top + _margin_bottom){
    sh = _h -_shadow_thick*2 - _margin_top - _margin_bottom;
  }


  long xx = 0,yy=0;
  long new_mx = _mx;
  long new_my = _my;
  if (_no_mcur_adjust == 0){
    _get_disp_cur_pos(&xx,&yy);
    if ( mdx +sw + _mx -WS_MLINE_MARGIN < xx ){
      new_mx += xx - (mdx + sw + _mx-WS_MLINE_MARGIN);
    }else
    if (xx < mdx + _mx ){
      new_mx -= (mdx+ _mx) -xx;
    }
    if (new_mx < 0){
      new_mx = 0;
    }
  }

  WSDfont* font = WSGIappFontSet()->getFont(_font);
  long fh = font->getFontHeight();
  WSCstring tmp("MM");
  long fw = font->getStringWidth(&tmp);

  if (_no_mcur_adjust == 0){
    if (yy > mdy + sh + _my - fh -WS_MLINE_MARGIN){
      new_my += yy - (mdy + sh + _my - fh -WS_MLINE_MARGIN);

    }else
    if (yy < mdy + _my ){
      new_my -= (mdy+ _my) -yy;
    }
    if (new_my < 0){
      new_my = 0;
    }
//printf("WSCvifield::_curmove here2 yy=%d _my=%d fh=%d sh=%d mdy=%d _mdy=%d\n",yy,_my,fh,sh,mdy,new_my);
  }

  if (new_mx != _mx || new_my != _my){
    _set_base_work_flag = WS_WORK_CURSOR_CLEAR;
    if (_no_mcur_adjust == 0){
      setCursorBase(new_mx,new_my);
      _no_mcur_adjust =0;
    }else{
      setCursorBase(new_mx,new_my);
    }
    _set_base_work_flag = WS_WORK_NORMAL;
    return ret;
  }

  if (getVisible() == False){
    return ret;
  }

  WSDdev* dev = getowndev();
  if (dev == NULL){
    return ret;
  }
//#ifndef MSW
#if 0
  if (_use_pix != 0){
    WSCbool fl = 0;
    if (_dev != NULL){
      _dev->setValue(WSDEV_USE_PIXMAP,(void*)&fl);
    }
  }
#endif
  short px = _x + mdx + xx - fw*2 - _mx;
  short py = _y + mdy + yy - fh*2 - _my;
  if (xx - 2*fw  < prex &&  prex < xx + 2*fw &&
      yy - 2*fh  < prey &&  prex < yy + 2*fh ){
    dev->exposeArea( px, py,fw*5 ,fh*5);
  }else{
    dev->exposeArea( _x + mdx, py,sw ,fh*5);
  }
//#ifndef MSW
#if 0
  if (_use_pix != 0){
    WSCbool fl = 1;
    if (_dev != NULL){
      _dev->setValue(WSDEV_USE_PIXMAP,(void*)&fl);
    }
  }
#endif
  return ret;
}
