//
// 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 <WSCtextField.h>
#include <WSCclassInformation.h>
//#include <WSCscrFrame.h>
#include <WSCdevice.h>
#include <WSDdev.h>
#include <WSCvmifield.h>
#include <WSCfontSet.h>
#include <WSDappDev.h>
#include <WSDmouse.h>

WSMFguiClassInitialize(WSCtextField,WSCform);
WSMFversion(WSCtextField,WSCform);

WSMFpropertyValueChange( WSCtextField, WSNshadowType , char,WS_SHADOW_IN);

WSCtextField::WSCtextField(WSCbase* base,char* objname):
                WSCform(base,objname){
  _ifd = NULL;
  _v_scr = NULL;
  _h_scr = NULL;

  _bw = 16;
//  _work_back_color = WSGFcolor("gray80");
//  _bar_back_color    = WSGFcolor("gray75");
  _work_back_color = WS_DF_WORKBACKCOLOR;
  _bar_back_color  = WS_DF_BARSHADOWCOLOR;
  _margin = 4;
  _enable_input = 1;
  _vpos = 0;
  _hpos = 0;
//  _label_string = WSGFstrdup("");
  _font = (char)WSGIappFontSet()->getDefaultFontNo();
  _fw = 0;
  _fh = 0;
  _shadow_type = WS_SHADOW_IN;

  WSMFpropertyCreateStart
    WSMFparentCheckVerSrc(WSCtextField);

//    WSMFpropertyCreate(WSNlabelString, char*, _label_string,WSSlabelString );
    WSMFpropertyCreate(WSNbarThickness, WSCushort, _bw,WSSbarThickness );
    WSMFpropertyCreate(WSNworkBackColor,short,_work_back_color,WSSworkBackColor );
    WSMFpropertyCreate(WSNbarShadowColor, short,_bar_back_color, WSSbarShadowColor  );
    WSMFpropertyCreate(WSNmargin,WSCuchar,_margin,WSSmargin );
    WSMFpropertyCreate(WSNenableInput,WSCbool,_enable_input,WSSenableInput );
      WSMFpropertySetSelection(WSRbool3,WSRbool3D);

    WSMFpropertyValueChangeDef( WSCtextField,WSNshadowType ,char);

    WSMFpropertyCreate(WSNvbarValue,WSCulong,_vpos,WSSvbarValue );
    WSMFpropertyCreate(WSNhbarValue,WSCulong,_hpos,WSShbarValue );
    WSMFpropertyCreate(WSNfont, WSCuchar,   _font,WSSfont  );
    WSMFpropertyDelete(WSNusePixmap);
    WSMFpropertyDelete(WSNgradation);
    WSMFpropertyDelete(WSNgradationMargin);
    WSMFpropertyDelete(WSNusePixmap);

    WSMFaddTrigger(WSEV_VALUE_CH    );
    WSMFaddTrigger(WSEV_ACTIVATE    );
    WSMFaddTrigger(WSEV_KEY_HOOK    );
    WSMFaddTrigger(WSEV_KEY_PRESS   );
    WSMFaddTrigger(WSEV_KEY_RELEASE );
    WSMFaddExtTrigger(WSEV_SCR_MOUSE_PRESS,"SCR-MOUSE-PRESS"  );
    WSMFaddExtTrigger(WSEV_SCR_MOUSE_RELEASE,"SCR-MOUSE-RELEASE"  );
    WSMFaddExtTrigger(WSEV_SCR_MOUSE_MOVE,"SCR-MOUSE-MOVE"  );

  WSMFpropertyCreateEnd
}

//WSMFproperty( WSCtextField, WSNlabelString,char*,_label_string,WSGFstrdup(""));
WSMFproperty( WSCtextField, WSNbarThickness,  WSCushort, _bw, 16);
//WSMFproperty( WSCtextField, WSNworkBackColor, short, _work_back_color, WSGFcolor("gray80"));
WSMFproperty( WSCtextField, WSNworkBackColor, short, _work_back_color, WS_DF_WORKBACKCOLOR);
//WSMFproperty( WSCtextField, WSNbarShadowColor,short, _bar_back_color,WSGFcolor("gray75"));
WSMFproperty( WSCtextField, WSNbarShadowColor,short, _bar_back_color,WS_DF_BARSHADOWCOLOR);
WSMFproperty( WSCtextField, WSNmargin, WSCuchar,_margin,4);
WSMFproperty( WSCtextField, WSNenableInput, WSCbool,_enable_input,1);
WSMFproperty( WSCtextField, WSNvbarValue, WSCulong,_vpos,0);
WSMFproperty( WSCtextField, WSNhbarValue, WSCulong,_hpos,0);
WSMFproperty(WSCtextField, WSNfont, WSCuchar, _font,(char)WSGIappFontSet()->getDefaultFontNo());
#if 0
void WSCtextField::setWorkWSNlabelString(char* data){
//printf("WSCtextField::setWorkWSNlabelString\n");
//TEST
  return;
  _ifd->setPropertyV(WSNlabelString,data);
  if (_v_scr != NULL){
    WSCstring str = data;
    long lines = str.getWords("\n");
    long h = lines * _get_font_height();
    _v_scr->setPropertyV(WSNmaximum,(WSCulong)h);
  }
}
void WSCtextField::getWorkWSNlabelString(char** data){
  delete _label_string;
  _label_string = WSGFstrdup(_ifd->getProperty(WSNlabelString));
  *data = _label_string;
}
#endif

void WSCtextField::setWorkWSNvbarValue(WSCulong data){
  long bx,by;
  _ifd->getCursorBase(&bx,&by);
//printf("WSCtextField::setWokrWSNvbarValue %d\n",data);

  long slidersize = _v_scr->getProperty(WSNsliderSize);
  long max = _v_scr->getProperty(WSNmaximum);
  if ((long)data > max - slidersize){
    data = max - slidersize;
  }
  by = data;
  _v_scr->setProperty(WSNvalue,data);

  _ifd->setCursorBase(bx,by);
  _ifd->draw();
}
void WSCtextField::getWorkWSNvbarValue(WSCulong* data){
  long bx,by;
  _ifd->getCursorBase(&bx,&by);
  *data = by;
}
void WSCtextField::setWorkWSNhbarValue(WSCulong data){
  long bx,by;
  _ifd->getCursorBase(&bx,&by);
  bx = data;
//printf("WSCtextField::setWokrWSNhbarValue %d\n",data);
  _ifd->setCursorBase(bx,by);
  _ifd->draw();
}
void WSCtextField::getWorkWSNhbarValue(WSCulong* data){
  long bx,by;
  _ifd->getCursorBase(&bx,&by);
  *data = bx;
}
void WSCtextField::replaceSelectedString(char* str,long encode){
  setAbsoluteDraw(True);
  needUpdate();
  _ifd->replaceSelectedString(str,encode);
}
void WSCtextField::deleteSelectedString(){
  setAbsoluteDraw(True);
  needUpdate();
  _ifd->deleteSelectedString();
}
WSCstring WSCtextField::getSelectedString(){
  WSCstring tmp = _ifd->getSelectedString();
  return tmp;
}
void WSCtextField::setWorkWSNbarThickness(WSCushort){
  _adjust();
}
void WSCtextField::getWorkWSNbarThickness(WSCushort*){}

void WSCtextField::setWorkWSNmargin(WSCuchar){
}
void WSCtextField::getWorkWSNmargin(WSCuchar*){}


void WSCtextField::setWorkWSNtopShadowColor(short data){
  if (_ifd != NULL){
    _ifd->setPropertyV(WSNtopShadowColor,data);
    _h_scr->setPropertyV(WSNtopShadowColor,data);
    _v_scr->setPropertyV(WSNtopShadowColor,data);
  }
}
void WSCtextField::setWorkWSNbottomShadowColor(short data){
  if (_ifd != NULL){
    _ifd->setPropertyV(WSNbottomShadowColor,data);
    _h_scr->setPropertyV(WSNbottomShadowColor,data);
    _v_scr->setPropertyV(WSNbottomShadowColor,data);
  }
}
void WSCtextField::setWorkWSNshadowThickness(WSCuchar data){
  WSCform::setWorkWSNshadowThickness(data);
  if (_ifd != NULL){
    _h_scr->setPropertyV(WSNshadowThickness,data);
    _v_scr->setPropertyV(WSNshadowThickness,data);
    _adjust();
  }
}
void WSCtextField::setWorkWSNbackColor(short data){
  if (_ifd != NULL){
    _h_scr->setPropertyV(WSNbackColor,data);
    _v_scr->setPropertyV(WSNbackColor,data);
  }
  if (_dev != NULL){
    _dev->setValue(WSDEV_BACKCOLOR,(void*)&data);
  }
}

void WSCtextField::setWorkWSNforeColor(short data){
  if (_ifd != NULL){
    _h_scr->setPropertyV(WSNforeColor,data);
    _v_scr->setPropertyV(WSNforeColor,data);
  }
}

void WSCtextField::setWorkWSNbarShadowColor(short data){
  if (_ifd != NULL){
    _h_scr->setPropertyV(WSNbarShadowColor,data);
    _v_scr->setPropertyV(WSNbarShadowColor,data);
  }
}

void WSCtextField::getWorkWSNbarShadowColor(short*){ }

void WSCtextField::setWorkWSNworkBackColor(short data){
  if (_ifd != NULL){
    _ifd->setPropertyV(WSNbackColor,data);
  }
}
void WSCtextField::getWorkWSNworkBackColor(short*){ }
void WSCtextField::_adjust(){
  long mg = _margin;
  if (WSGIappDev()->getGuiPolicy() & WS_POLICY_WINDOWS){
    mg = 0;
  }
  long st = _shadow_thick;
  _form->setProperty(WSNx,st);
  _form->setProperty(WSNy,st);
  _form->setPropertyV(WSNwidth,(WSCushort)(_w - _bw - mg -st*2));
  _form->setPropertyV(WSNheight,(WSCushort)(_h - _bw - mg-st*2));
  _ifd->setProperty(WSNx,0);
  _ifd->setProperty(WSNy,0);
  _ifd->setPropertyV(WSNwidth,(WSCushort)(_w - _bw - mg-st*2));
  _ifd->setPropertyV(WSNheight,(WSCushort)(_h - _bw - mg-st*2));
  if (WSGIappDev()->getGuiPolicy() & WS_POLICY_ORIGINAL){
    _v_scr->setPropertyV(WSNx,(short)(_w - _bw));
    _v_scr->setPropertyV(WSNy,(short)0);
    _v_scr->setPropertyV(WSNwidth,(WSCushort)(_bw));
    _v_scr->setPropertyV(WSNheight,(WSCushort)(_h - _bw - mg));
    WSCulong ssize = (WSCulong)(_h - _bw - _shadow_thick*2- mg);
    if (ssize > _h){
      ssize = 1;
    }
    _v_scr->setPropertyV(WSNsliderSize,ssize);
    _h_scr->setPropertyV(WSNx,(short)0);
    _h_scr->setPropertyV(WSNy,(short)(_h - _bw));
    _h_scr->setPropertyV(WSNwidth,(WSCushort)(_w - _bw - mg));
    ssize = (WSCulong)(_w - _bw - _shadow_thick*2- mg);
    if (ssize > _w){
      ssize = 1;
    }
    _h_scr->setPropertyV(WSNsliderSize,ssize);
    _h_scr->setPropertyV(WSNheight,(WSCushort)(_bw));
  }else
  if (WSGIappDev()->getGuiPolicy() & WS_POLICY_WINDOWS){
    long st = _shadow_thick;
    _v_scr->setPropertyV(WSNx,(short)(_w - _bw -st));
    _v_scr->setPropertyV(WSNy,(short)st);
    _v_scr->setPropertyV(WSNwidth,(WSCushort)(_bw));
    _v_scr->setPropertyV(WSNheight,(WSCushort)(_h - _bw - mg -st*2));
    WSCulong ssize = (WSCulong)(_h - _bw - _shadow_thick*2- mg);
    if (ssize > _h){
      ssize = 1;
    }
    _v_scr->setPropertyV(WSNsliderSize,ssize);

    _h_scr->setPropertyV(WSNx,(short)st);
    _h_scr->setPropertyV(WSNy,(short)(_h - _bw -st));
    _h_scr->setPropertyV(WSNwidth,(WSCushort)(_w - _bw - mg -st*2));
    ssize = (WSCulong)(_w - _bw - _shadow_thick*2- mg);
    if (ssize > _w){
      ssize = 1;
    }
    _h_scr->setPropertyV(WSNsliderSize,ssize);
    _h_scr->setPropertyV(WSNheight,(WSCushort)(_bw));
  }
}
void WSCtextField::setWorkWSNwidth(WSCushort data){
  _adjust();
  WSCform::setWorkWSNwidth(data);
}

void WSCtextField::setWorkWSNheight(WSCushort data){
  _adjust();
  WSCform::setWorkWSNheight(data);
}

void WSCtextField::setWorkWSNenableInput(WSCbool data){
  _ifd->setSensitive(data);
}

void WSCtextField::getWorkWSNenableInput(WSCbool* data){}

void WSCtextField::setWorkWSNfont(WSCuchar data){ 
  _ifd->setPropertyV(WSNfont,data);
  WSCstring tmp("H");
  WSDfont* font = WSGIappFontSet()->getFont(_font);
  if (font != NULL){
    WSCushort sw = font->getStringWidth(&tmp);
    WSCushort sh = font->getStringHeight(&tmp);
    _fw = sw;
    _fh = sh;
    _h_scr->setPropertyV(WSNincrement,(WSCushort)(sw-1));
    _v_scr->setPropertyV(WSNincrement,(WSCushort)(sh-1));
  }
}
void WSCtextField::getWorkWSNfont(WSCuchar*){
}
long WSCtextField::_get_font_width(){
  if (_fw == 0){
    setWorkWSNfont(_font);
  }
  return _fw;
}
long WSCtextField::_get_font_height(){
  if (_fh == 0){
    setWorkWSNfont(_font);
  }
  return _fh;
}
WSCtextField::~WSCtextField(){
  WSCbase* fclient = WSGIappMouse()->getMouseFocusClient();
  if (fclient == this){
    WSGIappMouse()->setMouseFocusClient(NULL);
  }
}


long WSCtextField::initialize(){
  long mg = _margin;
  if (WSGIappDev()->getGuiPolicy() & WS_POLICY_WINDOWS){
    mg = 0;
  }

  WSCstring scrname(getInstanceName());
  scrname << "-form";
  _form = new WSCform(this,scrname.getString());
  _form->setInternalObject(True);
  _form->setUseParentBaseDev(True);
  _form->initialize();
  _form->setPropertyV(WSNx,(short)0);
  _form->setPropertyV(WSNy,(short)0);
  _form->setPropertyV(WSNwidth,(WSCushort)(_w - _bw - mg));
  _form->setPropertyV(WSNheight,(WSCushort)(_h - _bw - mg));
  _form->setNoRefresh(True);
  _form->setVisible(True);
  WSCprocedure* op_p = new WSCprocedure("scrmp",WSEV_MOUSE_PRESS);
  op_p->setInternal(True);
  op_p->setFunction(_scr_mouse_press,"_scr_mouse_press");
  _form->addProcedure(op_p);
  WSCprocedure* op_r = new WSCprocedure("scrmr",WSEV_MOUSE_RELEASE);
  op_r->setInternal(True);
  op_r->setFunction(_scr_mouse_release,"_scr_mouse_release");
  _form->addProcedure(op_r);
  WSCprocedure* op_m = new WSCprocedure("scrmm",WSEV_MOUSE_MOVE);
  op_m->setInternal(True);
  op_m->setFunction(_scr_mouse_move,"_scr_mouse_move");
  _form->addProcedure(op_m);

  scrname = getInstanceName();
  scrname << "-ifd";
  _ifd = new WSCvmifield(_form,scrname.getString());
  _ifd->setInternalObject(True);
  _ifd->initialize();
  _ifd->setPropertyV(WSNx,(short)0);
  _ifd->setPropertyV(WSNy,(short)0);
  _ifd->setPropertyV(WSNwidth,(WSCushort)(_w - _bw - mg));
  _ifd->setPropertyV(WSNheight,(WSCushort)(_h - _bw - mg));
  _ifd->setPropertyV(WSNbackColor,(short)_work_back_color);
  _ifd->setPropertyV(WSNtopShadowColor,_ts_color);
  _ifd->setPropertyV(WSNbottomShadowColor,_bs_color);
//  _ifd->setPropertyV(WSNshadowType,(char)WS_SHADOW_IN);
  _ifd->setProperty(WSNshadowThickness,0);
  _ifd->setPropertyV(WSNusePixmap,(WSCbool)True);
  _ifd->setVisible(True);
  _ifd->setUserData("CBASE",(void*)this);
  WSCprocedure* op0 = new WSCprocedure("value-ch",WSEV_VALUE_CH);
  op0->setInternal(True);
  op0->setFunction(_valuech_work,"_valuech_work");
  _ifd->addProcedure(op0);
  WSCprocedure* op01 = new WSCprocedure("key-press",WSEV_KEY_PRESS);
  op01->setInternal(True);
  op01->setFunction(_keypress_work,"_keypress_work");
  _ifd->addProcedure(op01);
  WSCprocedure* op02 = new WSCprocedure("key-release",WSEV_KEY_RELEASE);
  op02->setInternal(True);
  op02->setFunction(_keyrelease_work,"_keyrelease_work");
  _ifd->addProcedure(op02);
  WSCprocedure* op03 = new WSCprocedure("key-hook",WSEV_KEY_HOOK);
  op03->setInternal(True);
  op03->setFunction(_keyhook_work,"_keyhook_work");
  _ifd->addProcedure(op03);


  scrname.setString(getInstanceName());
  scrname << "-hscr";
  WSCbase* htmp = WSCbase::getNewInstance(getUseScrBarClass(),this,scrname.getString());
  _h_scr = (WSCvscrBar*)htmp->cast("WSCvscrBar");
  if (_h_scr == NULL){
    _h_scr = new WSCvscrBar(this,scrname.getString());
  }

  _h_scr->setInternalObject(True);
  _h_scr->setUseParentBaseDev(True);
  _h_scr->initialize();
  WSCprocedure* op1 = new WSCprocedure("value-ch",WSEV_VALUE_CH);
  op1->setInternal(True);
  op1->setFunction(_h_scr_work_op,"_h_scr_work_op");
  _h_scr->addProcedure(op1);
  WSCprocedure* op3 = new WSCprocedure("activate",WSEV_ACTIVATE);
  op3->setInternal(True);
  op3->setFunction(_ha_scr_work_op,"_ha_scr_work_op");
  _h_scr->addProcedure(op3);
  _h_scr->setPropertyV(WSNshadowThickness,(WSCuchar)_shadow_thick);
  _h_scr->setPropertyV(WSNbackColor,_back_color);
  _h_scr->setPropertyV(WSNforeColor,_fore_color);
  _h_scr->setPropertyV(WSNtopShadowColor,_ts_color);
  _h_scr->setPropertyV(WSNbottomShadowColor,_bs_color);
  _h_scr->setPropertyV(WSNbarShadowColor,_bar_back_color);
  _h_scr->setPropertyV(WSNx,(short)0);
  _h_scr->setPropertyV(WSNy,(short)(_h - _bw));
  _h_scr->setPropertyV(WSNwidth,(WSCushort)(_w - _bw - mg));
  _h_scr->setPropertyV(WSNheight,(WSCushort)(_bw));
  _h_scr->setPropertyV(WSNmaximum,(WSCulong)(10000));
  _h_scr->setPropertyV(WSNusePixmap,(WSCbool)True);
  _h_scr->setVisible(True);

  scrname.setString(getInstanceName());
  scrname << "-vscr";
  WSCbase* vtmp = WSCbase::getNewInstance(getUseScrBarClass(),this,scrname.getString());
  _v_scr = (WSCvscrBar*)vtmp->cast("WSCvscrBar");
  if (_v_scr == NULL){
    _v_scr = new WSCvscrBar(this,scrname.getString());
  }
  _v_scr->setInternalObject(True);
  _v_scr->setUseParentBaseDev(True);
  _v_scr->initialize();
  _v_scr->setPropertyV(WSNorientation,(WSCuchar)WS_VERTICAL);
  WSCprocedure* op2 = new WSCprocedure("value-ch",WSEV_VALUE_CH);
  op2->setInternal(True);
  op2->setFunction(_v_scr_work_op,"_v_scr_work_op");
  _v_scr->addProcedure(op2);
  WSCprocedure* op4 = new WSCprocedure("activate",WSEV_ACTIVATE);
  op4->setInternal(True);
  op4->setFunction(_va_scr_work_op,"_va_scr_work_op");
  _v_scr->addProcedure(op4);
  _v_scr->setPropertyV(WSNshadowThickness,(WSCuchar)_shadow_thick);
  _v_scr->setPropertyV(WSNbackColor,_back_color);
  _v_scr->setPropertyV(WSNforeColor,_fore_color);
  _v_scr->setPropertyV(WSNtopShadowColor,_ts_color);
  _v_scr->setPropertyV(WSNbottomShadowColor,_bs_color);
  _v_scr->setPropertyV(WSNbarShadowColor,_bar_back_color);
  _v_scr->setPropertyV(WSNx,(short)(_w - _bw));
  _v_scr->setPropertyV(WSNy,(short)0);
  _v_scr->setPropertyV(WSNwidth,(WSCushort)(_bw));
  _v_scr->setPropertyV(WSNheight,(WSCushort)(_h - _bw - mg));
  _v_scr->setPropertyV(WSNusePixmap,(WSCbool)True);
  _v_scr->setVisible(True);
  
  WSCstring tmp("H");
  WSDfont* font = WSGIappFontSet()->getFont(_font);
  if (font != NULL){
    WSCushort sw = font->getStringWidth(&tmp);
    WSCushort sh = font->getStringHeight(&tmp);
    _h_scr->setPropertyV(WSNincrement,(WSCushort)sw);
    _v_scr->setPropertyV(WSNincrement,(WSCushort)sh);
  }

  WSCform::initialize();
  _adjust();
  _scr_adjust();
  return WS_NO_ERR;
}

void WSCtextField::_ha_scr_work_op(WSCbase* obj){
  WSCbase* parent = obj->getParent();
  WSCtextField* scr = (WSCtextField*)parent->cast("WSCtextField");
  scr->onActivate();
} 
void WSCtextField::onActivate(){
  execProcedure(WSEV_ACTIVATE);
}
void WSCtextField::_h_scr_work_op(WSCbase* obj){
  WSCbase* parent = obj->getParent();
  WSCtextField* scr = (WSCtextField*)parent->cast("WSCtextField");
  WSCvscrBar* bar = (WSCvscrBar*)obj->cast("WSCvscrBar");
  WSCulong val;

  long cxbase,cybase;
  scr->_ifd->getCursorBase(&cxbase,&cybase);
  obj->getPropertyV(WSNvalue,&val);
  WSCushort sldw;
  obj->getPropertyV(WSNincrement,&sldw);
  if (val == 0 || cxbase - val > sldw ||
      val - cxbase > sldw || bar->getMaxSlideValue() <= val){
    if ( bar->getMaxSlideValue() < val){
      val = bar->getMaxSlideValue();
    }
    scr->_ifd->setCursorBase(val,cybase);
#if 0
    scr->_ifd->setAbsoluteDraw(True);
    scr->_ifd->draw();
    scr->onValueChange();
#endif
  }
}
void WSCtextField::onValueChange(){
  if (_data_source_clients != NULL){
    WSCvariant val;
    val = _ifd->getProperty(WSNlabelString);
    setDataToDataSourceClients(&val);
  }
  execProcedure(WSEV_VALUE_CH);
}
void WSCtextField::_va_scr_work_op(WSCbase* obj){
  WSCbase* parent = obj->getParent();
  WSCtextField* scr = (WSCtextField*)parent->cast("WSCtextField");
//  scr->execEventProc(WSEV_ACTIVATE,NULL);
  scr->onActivate();
}

void WSCtextField::_v_scr_work_op(WSCbase* obj){
  WSCbase* parent = obj->getParent();
  WSCtextField* scr = (WSCtextField*)parent->cast("WSCtextField");
  WSCvscrBar* bar = (WSCvscrBar*)obj->cast("WSCvscrBar");
  WSCulong val;

  long cxbase,cybase;
  scr->_ifd->getCursorBase(&cxbase,&cybase);
  obj->getPropertyV(WSNvalue,&val);

  WSCushort sldw;
  obj->getPropertyV(WSNincrement,&sldw);

  if (val == 0 || cybase - val > sldw ||
      val - cybase > sldw || bar->getMaxSlideValue() <= val){
//printf("WSCtextField::_v_scr_work_op  val=%d mv=%d\n",val,bar->getMaxSlideValue());
    if ( bar->getMaxSlideValue() < val){
      val = bar->getMaxSlideValue();
    }
    scr->_ifd->setCursorBase(cxbase,val);
#if 0
    scr->_ifd->setAbsoluteDraw(True);
    scr->_ifd->draw();
    scr->onValueChange();
#endif
  }
}
WSCbase* WSCtextField::getTextFrame(){
  return _ifd;
}
WSCbase* WSCtextField::getPropertyInheritChild(){
  return _ifd;
}
long WSCtextField::draw(){
  if (getVisible() == False){
    return WS_NO_ERR;
  }
  WSDdev* dev = getowndev();
  if (dev == NULL){
    return WS_ERR;
  }
  WSCbool absolute = getAbsoluteDraw();
  if (absolute == False  ){
    if (getDotMode() == False){
      if ( dev->isExposed(0,0,_w,_shadow_thick) == False &&
           dev->isExposed(0,0,_shadow_thick,_h) == False &&
           dev->isExposed(_w -_shadow_thick,0,_shadow_thick,_h) == False &&
           dev->isExposed(0,_h -_shadow_thick,_w,_shadow_thick) == False ){
        return WS_NO_ERR;
      }
    }else{
      if ( dev->isExposed(0,0,_w,_h) == False ){
        return WS_NO_ERR;
      }
    }
  }
  long err = dev->beginDraw(0,0,_w,_h,absolute);
  if (err != WS_NO_ERR){
    return WS_NO_ERR;
  }
  short ex = 0;
  short ey = 0;
  WSCushort ew = _w;
  WSCushort eh = _h;
  if (absolute == False){
    dev->getExposedArea(&ex,&ey,&ew,&eh);
  }
  WSCbase::update();
  setAbsoluteDraw(False);
  if (_bp_color == -1){
    dev->setForeColor(_back_color);
    dev->drawFillRect(0,0,_w,_h);
  }
  if (getDotMode() == True){
    dev->setForeColor(_fore_color);
    long i,j;
    for(i=0; i<_w; i+=10){
      for(j=0; j<_h; j+=10){
        if (ex < i && i < ex+ ew &&
            ey < j && j < ey+ eh ){
          dev->drawFillRect(i,j,1,1);
        }
      }
    }
  }
  if ( _shadow_thick > 0){
    if (WSGIappDev()->getGuiPolicy() & WS_POLICY_ORIGINAL){
      WSGFdrawShadow(dev,_shadow_type, _shadow_thick, _fore_color,
                   _ts_color,_bs_color,_back_color,
                   0,0,_w - _bw - _margin,_h - _bw - _margin);
    }else
    if (WSGIappDev()->getGuiPolicy() & WS_POLICY_WINDOWS){
      WSGFdrawShadow(dev,_shadow_type, _shadow_thick, _fore_color,
                   _ts_color,_bs_color,_back_color,
                   0,0,_w,_h);
    }
  }

  dev->endDraw();
  return WS_NO_ERR;
}
void WSCtextField::update(){
  _h_scr->update();
  _v_scr->update();
  long cx,cy;
  _ifd->getCursorBase(&cx,&cy);
  if (_hpos != (WSCulong)cx || _vpos != (WSCulong)cy){
    if (_v_scr != NULL){
      _scr_adjust();
      _hpos = cx;
      _vpos = cy;
    }
  }
  _ifd->redraw();
  _form->redraw();

  WSCform::update();
  redraw();
}

void WSCtextField::_valuech_work(WSCbase* ifd){
  WSCtextField* text = (WSCtextField*)ifd->getUserData("CBASE");
#ifdef TDBG
  printf("WSCtextField::_valuech %d\n",WSGFclocktime());
#endif
  if (text->_v_scr != NULL){
    text->_scr_adjust();
  }
  long cx,cy;
  text->_ifd->getCursorBase(&cx,&cy);
  text->_hpos = cx;
  text->_vpos = cy;
  text->onValueChange();
}

void WSCtextField::_keypress_work(WSCbase* ifd){
  WSCtextField* text = (WSCtextField*)ifd->getUserData("CBASE");
#ifdef TDBG
  printf("WSCtextField::_keypress %d\n",WSGFclocktime());
#endif
  long cx,cy;
  text->_ifd->getCursorBase(&cx,&cy);
  if (text->_hpos != (WSCulong)cx || text->_vpos != (WSCulong)cy){
    if (text->_v_scr != NULL){
      text->_scr_adjust();
      text->_hpos = cx;
      text->_vpos = cy;
    }
  }
  text->onKey(WSGIappKeyboard(),True);
}
void WSCtextField::_keyrelease_work(WSCbase* ifd){
  WSCtextField* text = (WSCtextField*)ifd->getUserData("CBASE");
  text->onKey(WSGIappKeyboard(),False);
}
void WSCtextField::_keyhook_work(WSCbase* ifd){
  WSCtextField* text = (WSCtextField*)ifd->getUserData("CBASE");
  text->onKeyHook(WSGIappKeyboard());
}
void WSCtextField::onKey(WSDkeyboard* ,WSCbool fl){
  if (fl == True){
    execProcedure(WSEV_KEY_PRESS);
  }else{
    execProcedure(WSEV_KEY_RELEASE);
  }
}
void WSCtextField::onKeyHook(WSDkeyboard*){
  execProcedure(WSEV_KEY_HOOK);
}

void WSCtextField::_scr_adjust(){
  long mg = _margin;
  if (WSGIappDev()->getGuiPolicy() & WS_POLICY_WINDOWS){
    mg = 0;
  }
  WSCushort* str = _ifd->getBuf();
  long lines = WSGFgetLinesUCS2(str);
  long fheight = _get_font_height();
#if 1
  long h = lines * fheight + 
           _h -  _shadow_thick*2 - _bw - mg + WS_MLINE_MARGIN - fheight;
#else
  long h = lines * fheight + WS_MLINE_MARGIN;
  if (h < (long)( _h -  _shadow_thick*2 - _bw - mg + WS_MLINE_MARGIN)){
    h = _h -  _shadow_thick*2 - _bw - mg + WS_MLINE_MARGIN;
  }
#endif
  _v_scr->setPropertyV(WSNmaximum,(WSCulong)h);
  long cx,cy;
  _ifd->getCursorBase(&cx,&cy);
  _v_scr->setPropertyV(WSNvalue,(WSCulong)cy);
  _h_scr->setPropertyV(WSNvalue,(WSCulong)cx);

  WSCulong vval;
  _v_scr->getPropertyV(WSNsliderSize,&vval);
  if (vval != _h -_bw -_shadow_thick*2 -mg){
    _v_scr->setPropertyV(WSNsliderSize,
                         (WSCulong)(_h -_bw -_shadow_thick*2 -mg));
  }
}
void WSCtextField::addString(char* str,long encode){
  long mg = _margin;
  if (WSGIappDev()->getGuiPolicy() & WS_POLICY_WINDOWS){
    mg = 0;
  }
  _ifd->addString(str);

//  long lines = WSGFgetLinesUCS2(_ifd->getBuf());
//  long fh = _get_font_height();

//  if (_h - _shadow_thick*2 - _bw - mg >= (WSCulong)lines * fh){
    _ifd->setAbsoluteDraw(True);
    _ifd->draw();
//  }
  _scr_adjust();
}
WSCushort* WSCtextField::getBuf(){
  return _ifd->getBuf();
}
static char* _scr_bar_cname = NULL;
void WSCtextField::setUseScrBarClass(char* cname){
  if (_scr_bar_cname != NULL){
    delete _scr_bar_cname;
    _scr_bar_cname = NULL;
  }
  if (cname != NULL){
    _scr_bar_cname = WSGFstrdup(cname);
  }
}
char* WSCtextField::getUseScrBarClass(){
  if (_scr_bar_cname == NULL){
    return "WSCvbscrBar";
  }
  return _scr_bar_cname;
}
long WSCtextField::setSelect(long pos,long len){
  setAbsoluteDraw(True);
  needUpdate();
  long ret = _ifd->setSelect(pos,len);
  long cx,cy;
  _ifd->getCursorBase(&cx,&cy);
//printf("_hpos=%d,vpos=%d  cx,cy=%d,%d\n",_hpos,_vpos,cx,cy);
  if (_hpos != (WSCulong)cx || _vpos != (WSCulong)cy){
    if (_v_scr != NULL){
      _scr_adjust();
      _hpos = cx;
      _vpos = cy;
    }
  }

  return ret;
}
long WSCtextField::getSelectedPos(){
  return _ifd->getSelectedPos();
}
WSCstring WSCtextField::getString(){
  return _ifd->getString();
}
char* WSCtextField::getDefaultProperty(){
  return WSNlabelString;
}
long WSCtextField::setTopLine(long pos){
  WSCushort fh  = _get_font_height();
  long max = _v_scr->getProperty(WSNmaximum);
  if (pos < 0){
    pos = max - fh;
    if (pos < 0){
      pos = 0;
    }
  }else{
    pos = pos * fh;
    if (pos > max){
      pos = max;
    }
  }
  long bx,by;
  _ifd->getCursorBase(&bx,&by);
  by = pos;
//printf("WSCtextField::setWokrWSNvbarValue %d\n",data);
  _ifd->setCursorBase(bx,by);
  _scr_adjust();
//  _ifd->draw();
  return 0;
}
long WSCtextField::getTopLine(){
  long pos = _v_scr->getProperty(WSNvalue);
  WSCushort fh  = _get_font_height();
  long ret = pos / fh;
  return ret;
}
long WSCtextField::getLines(){
  return WSGFgetLinesUCS2(_ifd->getBuf());
}
long WSCtextField::setBottomLine(long pos){
  WSCushort fh  = _get_font_height();
  long max = _v_scr->getProperty(WSNmaximum);
  if (pos < 0){
    pos = max;
  }else{
    pos = pos * fh;
    if (pos > max){
      pos = max;
    }
  }
  long mg = _margin;
  if (WSGIappDev()->getGuiPolicy() & WS_POLICY_WINDOWS){
    mg = 0;
  }
  long st = _shadow_thick;
  long vh = _h - _bw - mg-st*2;
  if (pos - vh < 0){
    pos = vh;
  }
//  setProperty(WSNvbarValue,(pos - vh));
  long bx,by;
  _ifd->getCursorBase(&bx,&by);
  by = pos -vh;
//printf("WSCtextField::setWokrWSNvbarValue %d\n",data);
  _ifd->setCursorBase(bx,by);
  _scr_adjust();
//  _v_scr->WSCbase::update();
//  _v_scr->setAbsoluteDraw(True);
//  _v_scr->draw();
//  _h_scr->WSCbase::update();
//  _h_scr->setAbsoluteDraw(True);
//  _h_scr->draw();
//  _ifd->draw();
  return 0;
}
long WSCtextField::getBottomLine(){
  WSCushort fh  = _get_font_height();
  long mg = _margin;
  if (WSGIappDev()->getGuiPolicy() & WS_POLICY_WINDOWS){
    mg = 0;
  }
  long st = _shadow_thick;
  long vh = (_h - _bw - mg-st*2)/fh;
  long pos = getTopLine() + vh;

  long lines = getLines();
  if (pos < lines){
    return pos;
  }
  return lines;
}
void WSCtextField::_scr_mouse_press(WSCbase* obj){
  WSCbase* parent = obj->getParent();
  WSCtextField* scr = (WSCtextField*)parent->cast("WSCtextField");
  WSGIappMouse()->setMouseFocusClient(scr);
  short x,y;
  obj->getMouseAddr(&x,&y);
  WSCpoint pt;
  pt.x = x;
  pt.y = y;
  scr->onScrMousePress(&pt);
}
void WSCtextField::_scr_mouse_release(WSCbase* obj){
  WSCbase* parent = obj->getParent();
  WSCtextField* scr = (WSCtextField*)parent->cast("WSCtextField");
  short x,y;
  obj->getMouseAddr(&x,&y);
  WSCpoint pt;
  pt.x = x;
  pt.y = y;
  scr->onScrMouseRelease(&pt);
}
void WSCtextField::_scr_mouse_move(WSCbase* obj){
  WSCbase* parent = obj->getParent();
  WSCtextField* scr = (WSCtextField*)parent->cast("WSCtextField");
  short x,y;
  obj->getMouseAddr(&x,&y);
  WSCpoint pt;
  pt.x = x;
  pt.y = y;
  scr->onScrMouseMove(&pt);
}

void WSCtextField::onScrMousePress(WSCpoint* pt){
  execProcedure(WSEV_SCR_MOUSE_PRESS);
}
void WSCtextField::onScrMouseRelease(WSCpoint* pt){
  execProcedure(WSEV_SCR_MOUSE_RELEASE);
}
void WSCtextField::onScrMouseMove(WSCpoint* pt){
  execProcedure(WSEV_SCR_MOUSE_MOVE);
}
void WSCtextField::onMousePress(WSCpoint* pt){
  if (WSGIappMouse()->getTargetBtn() == WS_MOUSE_BTN4){
    if (getVisible() == False){
      return;
    }
    long val = _vpos - 30;
    if (val < 0){
      setProperty(WSNvbarValue,0);
    }else{
      setProperty(WSNvbarValue,val);
    }
    return;
  }else
  if (WSGIappMouse()->getTargetBtn() == WS_MOUSE_BTN5){
    if (getVisible() == False){
      return;
    }
    long val = _vpos + 30;
    long slidersize = _v_scr->getProperty(WSNsliderSize);
    long max = _v_scr->getProperty(WSNmaximum);
    if (val > max - slidersize){
      val = max - slidersize;
    }
    setProperty(WSNvbarValue,val);
    return;
  }
 
  WSCform::onMousePress(pt);
}
