//
// 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 <WSCvlabel.h>
#include <WSCclassInformation.h>
#include <WSDdev.h>
#include <WSClist.h>
#include <WSCfontSet.h>
#include <WSCsform.h>
#include <WSCscrFrame.h>
#include <WSCvbtn.h>
#include <WSCbaseList.h>
#include <WSDmouse.h>
#include <WSDkeyboard.h>
#include <WSCvscrBar.h>

//#define TDBG

#define SELECT_STATUS "ls-selected"
WSMFguiClassInitialize(WSClist,WSCscrForm);
WSMFpropertyValueChange( WSClist, WSNhbarVisible , WSCbool,False);
WSMFpropertyValueChange( WSClist, WSNscrollHeight , WSCushort,20);

WSClist::WSClist(WSCbase* base,char* objname):
                WSCscrForm(base,objname){

  _lb_height = 20;
  _scroll_height = 20;
  _lb_height_bk = 20;
  _lb_class.setString("WSCvklabel");
  _font = WSGIappFontSet()->getDefaultFontNo();
  _select_color = WS_DF_MENUSELECTCOLOR;
  _select_fore_color = WS_DF_MENUSELECTFORECOLOR;
  _disp_type = WS_NORMAL;
  _mselect = False;
  _select_item_changed = 0;
  _activate = 1;
  _reverse_select = True;
  _absolute_select_change = 0;
  _btn_area = NULL;
  _bar_pos = WSGFstrdup("20");
  _padding = 0;
  _title_string = WSGFstrdup("title");
  _use_icon = False;
  _icon_pixmap = -1;
  _icon_pixmap_old = -1;
//  _virtual_scr = 1;
  _need_update = 0;
  _data = WSGFstrdup("");
  _data_source_name = WSGFstrdup("");
  _data_source_type = WS_DATA_SOURCE_NONE;
  _hbar_visible = False;
  _lb_width = 1024;
  _work_height_bk = 0;
  _enable_input = 0;
  _input_instance = NULL;
  _separator = WSGFstrdup(",");
  _need_ds_update = False;
  _need_scr_redraw = True;
  _wy_pos_bak = 0;
  _pre_select = -1;

  WSMFpropertyCreateStart
    WSMFpropertyCreate(WSNitemHeight,  WSCuchar, _lb_height, WSSitemHeight );
    WSMFpropertyCreate(WSNiconPixmap,  short, _icon_pixmap, WSSiconPixmap );
    WSMFpropertyCreate(WSNuseIcon,  WSCbool, _use_icon, WSSuseIcon );
      WSMFpropertySetSelection(WSRbool1,WSRbool1D);
    WSMFpropertyCreate(WSNfont,  WSCuchar, _font, WSSfont );
    WSMFpropertyCreate(WSNselectColor,short, _select_color, WSSselectColor );
    WSMFpropertyCreate(WSNselectForeColor,short, _select_fore_color, WSSselectForeColor );
    WSMFpropertyCreate(WSNtype,  WSCuchar, _disp_type, WSStype );
      WSMFpropertySetSelection(WSRtype,WSRtypeD);
    WSMFpropertyCreate(WSNmultiSelect,  WSCbool, _mselect, WSSmultiSelect );
      WSMFpropertySetSelection(WSRbool1,WSRbool1D);
    WSMFpropertyCreate(WSNreverseSelect,  WSCbool, _reverse_select, WSSreverseSelect );
      WSMFpropertySetSelection(WSRbool3,WSRbool3D);
    WSMFpropertyCreate(WSNtitleHeight, WSCuchar, _padding,WSStitleHeight );
    WSMFpropertyCreate(WSNtitleString, char*, _title_string,WSStitleString );
    WSMFpropertyCreate(WSNbarValue, char*, _bar_pos,WSSbarValue );
    WSMFpropertyCreate(WSNdata, char*, _data,WSSdata );
    WSMFpropertyCreate(WSNdataSource, WSCuchar, _data_source_type,WSSdataSource );
      WSMFpropertySetSelection(WSRdataSource,WSRdataSourceD);
    WSMFpropertyCreate(WSNdataSourceName, char*, _data_source_name,WSSdataSourceName );
    WSMFpropertyCreate(WSNenableInput,  WSCbool, _enable_input, WSSenableInput );
      WSMFpropertySetSelection(WSRbool3,WSRbool3D);

//    WSMFpropertyDelete(WSNvirtualScroll);
    WSMFpropertyCreate(WSNseparator,  char*, _separator, WSSseparator );
    WSMFpropertyVisibleOff(WSNscrollHeight);
    WSMFpropertyValueChangeDef( WSClist,WSNscrollHeight ,WSCushort);
    WSMFpropertyValueChangeDef( WSClist,WSNhbarVisible ,WSCbool);

    WSMFaddTrigger(WSEV_KEY_PRESS);
    WSMFaddTrigger(WSEV_KEY_RELEASE);
    WSMFaddExtTrigger(WSEV_SORT,"SORT");
    WSMFaddExtTrigger(WSEV_ITEM_SELECTED,"ITEM-SELECTED");
    WSMFaddExtTrigger(WSEV_INPUT_FIXED,"INPUT-FIXED");
    WSMFaddExtTrigger(WSEV_ITEM_DOUBLE_CLICKED,"ITEM-DOUBLE-CLICKED");

  WSMFpropertyCreateEnd

}

WSMFproperty( WSClist, WSNitemHeight, WSCuchar, _lb_height,  20);
WSMFproperty( WSClist, WSNiconPixmap, short, _icon_pixmap,  -1);
WSMFproperty( WSClist, WSNuseIcon, WSCbool,   _use_icon,   False);
WSMFproperty( WSClist, WSNfont, WSCuchar,   _font,   (char)WSGIappFontSet()->getDefaultFontNo());
WSMFproperty( WSClist, WSNselectColor, short,_select_color,WS_DF_MENUSELECTCOLOR);
WSMFproperty( WSClist, WSNselectColor, short,_select_fore_color,WS_DF_MENUSELECTFORECOLOR);
WSMFproperty( WSClist, WSNtype, WSCuchar,_disp_type,WS_NORMAL);
WSMFproperty( WSClist, WSNmultiSelect, WSCbool,_mselect,False);
WSMFproperty( WSClist, WSNreverseSelect, WSCbool,_reverse_select,True);
WSMFproperty( WSClist, WSNtitleHeight,  WSCuchar, _padding, 0);
WSMFproperty( WSClist, WSNtitleString,  char*, _title_string,WSGFstrdup("title"));
WSMFproperty( WSClist, WSNbarValue,  char*, _bar_pos,WSGFstrdup("20"));
WSMFproperty( WSClist, WSNdata,  char*, _data,WSGFstrdup(""));
WSMFproperty( WSClist, WSNdataSource,  WSCuchar, _data_source_type,WS_DATA_SOURCE_NONE);
WSMFproperty( WSClist, WSNdataSourceName,  char*, _data_source_name,WSGFstrdup(""));
WSMFproperty( WSClist, WSNenableInput,  WSCbool, _enable_input,False);
WSMFproperty( WSClist, WSNseparator,  char*, _separator,WSGFstrdup(","));

void WSClist::setWorkWSNitemHeight(WSCuchar){}
void WSClist::getWorkWSNitemHeight(WSCuchar*){}

void WSClist::setWorkWSNiconPixmap(short){
  if (_use_icon == False){
    return;
  }
  long i;
  long num = _lb_list.getNum();
  for(i=0; i<num; i++){
    WSCbase* lb = (WSCbase*)_lb_list[i];
    short icon;
    lb->getPropertyV(WSNlabelPixmap,&icon);
    if (icon == -1){
      lb->setPropertyV(WSNlabelPixmap,_icon_pixmap);
    }else
    if (icon == _icon_pixmap_old){
      lb->setPropertyV(WSNlabelPixmap,_icon_pixmap);
    }
  }
  _icon_pixmap_old = _icon_pixmap;
}
void WSClist::getWorkWSNiconPixmap(short*){}

void WSClist::setWorkWSNuseIcon(WSCbool){
  long i;
  long num = _lb_list.getNum();
  if (_use_icon == False){
    for(i=0; i<num; i++){
      WSCbase* lb = (WSCbase*)_lb_list[i];
      lb->setPropertyV(WSNlabelPixmap,(short)-1);
    }
  }else{
    for(i=0; i<num; i++){
      WSCbase* lb = (WSCbase*)_lb_list[i];
      short icon;
      lb->getPropertyV(WSNlabelPixmap,&icon);
      if (icon == -1){
        lb->setPropertyV(WSNlabelPixmap,_icon_pixmap);
      }else
      if (icon == _icon_pixmap_old){
        lb->setPropertyV(WSNlabelPixmap,_icon_pixmap);
      }
    }
  }
}
void WSClist::getWorkWSNuseIcon(WSCbool*){}

void WSClist::setWorkWSNbarValue(char* val){
  if(_btn_area != NULL){
    _btn_area->setProperty(WSNbarValue,val);
  }
}
void WSClist::getWorkWSNbarValue(char** val){
  WSCstring tmp;
  if (_btn_area != NULL){
    if (_bar_pos != NULL){
      delete _bar_pos;
      _bar_pos = NULL;
    }
    tmp = _btn_area->getProperty(WSNbarValue);
    _bar_pos = WSGFstrdup((char*)tmp);
    *val = _bar_pos;
  }
}

void WSClist::setWorkWSNtitleString(char*){
  _adjust();
}
void WSClist::getWorkWSNtitleString(char**){}
void WSClist::setWorkWSNtitleHeight(WSCuchar){
  if (_disp_type == WS_VERBOSE){
    _v_scr_x_bk = 0;
    _h_scr_y_bk = 0;
    _scr_area->setPropertyV(WSNx,(short)_shadow_thick);
    _scr_area->setPropertyV(WSNy,(short)(_shadow_thick + _padding));
    if(_padding != 0 && _btn_area != NULL){
      _btn_area->setVisible(True);
    }
    _adjust();
  }else{
    _scr_area->setPropertyV(WSNx,(short)_shadow_thick);
    _scr_area->setPropertyV(WSNy,(short)_shadow_thick);
    _v_scr_x_bk = 0;
    _h_scr_y_bk = 0;
    _padding = 0;

    _adjust();
  }
}
void WSClist::getWorkWSNtitleHeight(WSCuchar*){}

void WSClist::setWorkWSNbackColor(short val){
  WSCscrForm::setWorkWSNbackColor(val);
  _adjust();
}
void WSClist::setWorkWSNforeColor(short val){
  WSCscrForm::setWorkWSNforeColor(val);
  _adjust();
}
void WSClist::setWorkWSNtopShadowColor(short val){
  WSCscrForm::setWorkWSNtopShadowColor(val);
  _adjust();
}
void WSClist::setWorkWSNbottomShadowColor(short val){
  WSCscrForm::setWorkWSNbottomShadowColor(val);
  _adjust();
}
void WSClist::setWorkWSNfont(WSCuchar){}
void WSClist::getWorkWSNfont(WSCuchar*){}
void WSClist::setWorkWSNselectColor(short){}
void WSClist::getWorkWSNselectColor(short*){}
void WSClist::setWorkWSNselectForeColor(short){}
void WSClist::getWorkWSNselectForeColor(short*){}
void WSClist::setWorkWSNtype(WSCuchar fl){
  if (fl == WS_NORMAL || fl == WS_TREE){
    if (_btn_area != NULL){
      _btn_area->setVisible(False);
      _padding = 0;
    }
  }else if (fl == WS_VERBOSE){
    if (_btn_area == NULL){
      WSCstring name;
      name = (WSCstring)"sf-" + getInstanceName();
      _btn_area = new WSCsform(this,name);
      _btn_area->setInternalObject(True);
      _btn_area->setUseParentBaseDev(True);
      _btn_area->initialize();
      _btn_area->setPropertyV(WSNshadowThickness,(WSCuchar)0);
      _btn_area->setPropertyV(WSNbarThickness,(WSCushort)0);
      _btn_area->setPropertyV(WSNpixmapStyle,(WSCuchar)WS_DYNAMIC_PIXMAP);
      _btn_area->setProperty(WSNx,(long)_shadow_thick-_wx_pos);
      _btn_area->setProperty(WSNwidth,_work_width);
      _btn_area->setAdjustChildren(False);
      WSGFsetMargin(_btn_area,0);
      _adjust();
      if(_padding != 0){
        _btn_area->setVisible(True);
      }
      _btn_area->setUserData("p-list",(void*)this);
      WSCprocedure* op = new WSCprocedure("value-ch",WSEV_VALUE_CH);
      op->setInternal(True);
      op->setFunction(_btn_area_valuech,"_btn_area_valuech");
      _btn_area->addProcedure(op);
    } 
  }
}
void WSClist::_btn_area_valuech(WSCbase* ptr){
  WSClist* obj = (WSClist*)ptr->getUserData("p-list");
  if (obj->_bar_pos != NULL){
    delete obj->_bar_pos;
    obj->_bar_pos = NULL;
  }
  WSCstring tmp;
  tmp = ptr->getProperty(WSNbarValue);
  obj->_bar_pos = WSGFstrdup((char*)tmp);
  obj->_redraw_scr();
//  obj->_scr_area->cdraw(); 
  obj->redraw(); 
}
void WSClist::getWorkWSNtype(WSCuchar*){
}
void WSClist::setWorkWSNmultiSelect(WSCbool){}
void WSClist::getWorkWSNmultiSelect(WSCbool*){}
void WSClist::setWorkWSNreverseSelect(WSCbool){}
void WSClist::getWorkWSNreverseSelect(WSCbool*){}
void WSClist::setWorkWSNenableInput(WSCbool){}
void WSClist::getWorkWSNenableInput(WSCbool*){}

void WSClist::setWorkWSNwidth(WSCushort data){
  WSCscrForm::setWorkWSNwidth(data);
  if (_work_width < data){
    setPropertyV(WSNworkWidth,data);
  }else{
    if (_disp_type == WS_VERBOSE){
      if ( _scr_area != NULL &&
           _btn_area != NULL){
        if (_bar_pos != NULL){
          delete _bar_pos;
          _bar_pos = NULL;
        }
        WSCstring tmp;
        tmp = _btn_area->getProperty(WSNbarValue);
        _bar_pos = WSGFstrdup(tmp);
//printf("WSClist::setWorkWSNwidth barpos=%s\n",(char*)tmp);
        if ( _scr_area->getVisible() ){
//printf("WSClist::setWorkWSNwidth exec cdraw..\n");
          _scr_area->cdraw();
        }
      }
    }
  }
}
void WSClist::setWorkWSNheight(WSCushort data){
  WSCscrForm::setWorkWSNheight(data);
  if (_no_scroll != False){
    _adjust();
    _adjust_scr_area();
    _lb_adjust();
  }
}
void WSClist::setWorkWSNworkWidth(WSCushort data){
  WSCscrForm::setWorkWSNworkWidth(data);
  long i;
  long num=_lb_list.getNum();
  for(i=0; i<num; i++){
    WSCbase* lb = (WSCbase*)_lb_list[i];
    lb->setPropertyV(WSNwidth,data);
  }
  if (_btn_area != NULL){
    _btn_area->setProperty(WSNwidth,data);
  }
//  if (_disp_type == WS_TREE && _scr_area->getVisible()){
//  }
}
void WSClist::setWorkWSNworkHeight(WSCushort data){
  if (_scr_area != NULL){
    WSCulong slsize;
    _v_scr->getPropertyV(WSNsliderSize,&slsize);
    WSCulong pos;
    _v_scr->getPropertyV(WSNvalue,&pos);

    if (data < pos + slsize){
      if ((long)data - (long)slsize-1 > 0){
        setPropertyV(WSNvbarValue,(WSCushort)(data -slsize-1));
      }else{
        setPropertyV(WSNvbarValue,(WSCushort)0);
      }
    }

    if (_virtual_scr == 0){
      _scr_area->setPropertyV(WSNworkHeight,data);
      _scr_area->setAbsoluteDraw(False); //set work height clear bug fix
    }else{
      WSCushort wh_org;
      _scr_area->getPropertyV(WSNworkHeight,&wh_org);
      if (wh_org > _h){
        if (wh_org > _h + 256){
          _scr_area->setPropertyV(WSNworkHeight,_h);
        }
      }else if (wh_org < _h){
        if (wh_org > _h + 256){
          _scr_area->setProperty(WSNworkHeight,(_h+256));
        }

      }
    }
    if (data <_v_scr_slider_sz){
      _v_scr->setPropertyV(WSNsliderSize,(WSCulong)_v_scr_slider_sz);
    }
    _v_scr->setPropertyV(WSNmaximum,(WSCulong)data);
    _adjust();
  }
}

void WSClist::setData(WSCvariant* val,long code){
  if (code == WS_EN_DEFAULT){
    WSCstring str;
    str.setString(val->getCharPtr(),code);
    _set_data(str.getString());
  }else{
    _set_data(val->getCharPtr());
  }
}
void WSClist::setData(const WSCvariant& val,long code){
  WSCvariant tmp = val;
  if (code == WS_EN_DEFAULT){
    WSCstring str;
    str.setString(tmp.getCharPtr(),code);
    _set_data(str.getString());
  }else{
    _set_data(tmp.getCharPtr());
  }
}



long WSClist::getDataSourceType(){
  return _data_source_type;
}
char* WSClist::getDataSourcePropertyName(){
  return WSNdata;
}

void WSClist::_set_data(char* data){
//printf("WSClist::_set_data #%s#\n",data);
  WSCstring str;
  str.setString(data);
  delAll();
  if (_data != NULL){
    delete _data;
  }
  _data = WSGFstrdup((char*)str);
  while(!str.eof()){
    WSCstring line = str.gets();
    WSCstring word1 = line.getWord(0,_separator);
    long words = line.getWords(_separator);
    long len = strlen((char*)word1);
    word1.delHeadSpace();
    word1.delTailSpace();
    if (_disp_type == WS_TREE ){
      WSCstring itemstr;
      if (_use_icon != False){
        if (words > 1){
          char* line1 = line.getString();
          itemstr = &line1[len+strlen(_separator)];
        }
      }else{
        itemstr = line;
      }
      WSCstring levelstr;
      WSCstring statusstr;
      WSCstring labelstr;
      levelstr = itemstr.getWord(0,_separator);
      statusstr = itemstr.getWord(1,_separator);
      labelstr = itemstr.getWord(2,_separator);
      addItem(labelstr);
      WSCbase* item = getLabel(-1);
      item->setUserData(WS_LIST_INDENT_LEVEL,(void*)atoi(levelstr));
      item->setUserData(WS_LIST_TREE_OPEN,(void*)atoi(statusstr));
      if (_use_icon != False){
        if (strcmp((char*)word1,"")){
          item->setProperty(WSNlabelPixmap,word1);
        }
      }
    }else
    if (_use_icon != False){
      if (words > 1){
        char* line1 = line.getString();
        addItem(&line1[len+strlen(_separator)]);
        if (strcmp((char*)word1,"")){
          WSCbase* item = getLabel(-1);
          char* pix = word1.getString();
          item->setProperty(WSNlabelPixmap,pix);
        }
      }else{
        addItem((char*)line);
      }
    }else{
      addItem((char*)line);
    }
  }
  _adjust();
  updateList();
}

void WSClist::setWorkWSNdata(char* data){
  _clear_ds_instance();
//  if (_data_source_type == WS_DATA_SOURCE_NONE){
    WSCstring tmp;
    tmp.setString(_data);
    tmp.replaceString("\\n","\n",0);
    _set_data(tmp);
//  }
}
void WSClist::_clear_ds_instance(){
  if ( getDataSourceServer() != NULL){
    getDataSourceServer()->delDataSourceClient(this);
    setDataSourceServer(NULL);
  }
}
void WSClist::_set_ds_instance(){
  WSCbase* serv = WSGIappObjectList()->searchInstance("WSCbase", _data_source_name);
  if (serv != NULL){
    setDataSourceServer(serv);
    serv->addDataSourceClient(this);
    WSCstring val;
    val = serv->getProperty(serv->getDefaultProperty());
    _set_data(val);
  }else{
    _need_ds_update = True;
    delAll();
  }
}
WSCstring WSClist::_get_data(){
  WSCstring ret;
  long num = _lb_list.getNum();
  long i;
  for(i=0; i<num; i++){
    WSCbase* lb = (WSCbase*)_lb_list[i];
    WSCstring tmp;
    tmp = lb->getProperty(WSNlabelString);
    if (_use_icon != False){
      WSCstring iconame;
      iconame = lb->getProperty(WSNlabelPixmap);
      ret << iconame << _separator;
    }
    if (_disp_type == WS_TREE ){
      long ilevel = (long)lb->getUserData(WS_LIST_INDENT_LEVEL);
      long topen = (long)lb->getUserData(WS_LIST_TREE_OPEN);
      ret << ilevel << _separator;
      ret << topen << _separator;
    }
    if (i+1 != num){
      ret << tmp << "\n";
    }else{
      ret << tmp;
    }
  }
  return ret;
}
void WSClist::getWorkWSNdata(char** ptr){
  if (getPropertyEditMode() != False &&
      _data_source_type != WS_DATA_SOURCE_NONE){
    *ptr = "";
    return;
  }else{
    WSCstring tmp = _get_data();
    if (_data != NULL && strcmp(_data,tmp.getString())){
      delete _data;
      _data = WSGFstrdup(tmp.getString());
      *ptr = _data;
      return;
    }
    if (_data == NULL){
      _data = WSGFstrdup(tmp.getString());
      *ptr = _data;
    }
  }
}
void WSClist::setWorkWSNdataSource(WSCuchar){
  if (_data_source_name != NULL && _data_source_name[0] != 0){
    if (_data_source_type == WS_DATA_SOURCE_FILE){
      _data_from_file(_data_source_name);
    }else
    if (_data_source_type == WS_DATA_SOURCE_INSTANCE){
      _set_ds_instance();
    }
    if (_data_source_type != WS_DATA_SOURCE_INSTANCE){
      WSCbase* ds = getDataSourceServer();
      if (ds != NULL){
        ds->delDataSourceClient(this);
        setDataSourceServer(NULL);
      }
    }
  }
}
void WSClist::getWorkWSNdataSource(WSCuchar*){}

void WSClist::setWorkWSNdataSourceName(char*){
  if (_data_source_type == WS_DATA_SOURCE_INSTANCE){
    _set_ds_instance();
  }else
  if (_data_source_type == WS_DATA_SOURCE_FILE){
    _data_from_file(_data_source_name);
  }
}
void WSClist::getWorkWSNdataSourceName(char**){}
void WSClist::setWorkWSNseparator(char* data){
//printf("WSClist::setWorkWSNseparator sep=#%s#\n",data);
  if (_btn_area != NULL){
    _btn_area->setProperty(WSNseparator,data);
  }
  _adjust();
  if (_data != NULL){
    _set_data(_data);
  }
}
void WSClist::getWorkWSNseparator(char**){}

void WSClist::_data_from_file(char* fname){
  WSCstring* str = WSGFreadTextFile(fname);
  if (str != NULL){
    delAll();
    _set_data(str->getString());
    delete str;
  }
}

WSClist::~WSClist(){
  if (_bar_pos != NULL){
    delete _bar_pos;
    _bar_pos = NULL;
  }
  if (_title_string != NULL){
    delete _title_string;
    _title_string = NULL;
  }
  if (_data != NULL){
    delete _data;
    _data = NULL;
  }
  if (_data_source_name != NULL){
    delete _data_source_name;
    _data_source_name = NULL;
  }
  if (_separator != NULL){
    delete _separator;
    _separator = NULL;
  }
}
#if 0
void WSClist::_mouse_press_work(WSCbase* scr){
    WSClist* p =(WSClist*)scr->getUserData("scrparent");
    short x=0,y=0;
    WSGIappMouse()->getMousePosition(&x,&y,scr);
    WSCpoint pt;
    pt.x = x;
    pt.y = y;
    p->onScrMousePress(&pt);
}
void WSClist::_mouse_release_work(WSCbase* scr){
    WSClist* p =(WSClist*)scr->getUserData("scrparent");
    short x=0,y=0;
    WSGIappMouse()->getMousePosition(&x,&y,scr);
    WSCpoint pt;
    pt.x = x;
    pt.y = y;
    p->onScrMouseRelease(&pt);
}
#endif
void WSClist::onScrMousePress(WSCpoint* pt){
  int i;
  long num = _lb_list.getNum();
  long tpos = getTopPos();
  WSCbase* target = NULL;
  long pos = -1;
  for(i=tpos; i<num; i++){
    WSCbase* item = (WSCbase*)_lb_list[i];
    if (item == NULL){
      continue;
    }
    if (item->getVisible() == False){
      continue;
    }
    short posy;
    item->getPropertyV(WSNy,&posy); 
    if (posy <= pt->y && pt->y <= posy + _lb_height){
      target = item;
      pos = i;
      break;
    }
  }
  if (pos != -1){
    long clk = WSGFclocktime();
    long clkbk = (long)getUserData("ctime");
    if (clk - clkbk < 250){
      setUserData("onfire",(void*)1);
      setUserData("target",(void*)target);
      setUserData("pos",(void*)pos);
    }else{
      setUserData("ctime",(void*)clk);
      setUserData("onfire",(void*)0);
    }
  }
  WSCscrForm::onScrMousePress(pt);
}
void WSClist::onScrMouseRelease(WSCpoint* pt){
  int i;
  long num = _lb_list.getNum();
  long tpos = getTopPos();
  WSCbase* target = NULL;
  long pos = -1;
  for(i=tpos; i<num; i++){
    WSCbase* item = (WSCbase*)_lb_list[i];
    if (item == NULL){
      continue;
    }
    if (item->getVisible() == False){
      continue;
    }
    short posy;
    item->getPropertyV(WSNy,&posy); 
    if (posy <= pt->y && pt->y <= posy + _lb_height){
      target = item;
      pos = i;
      break;
    }
  }
  if (pos != -1){
    if ((long)getUserData("onfire")){
      WSCbase* target2 = (WSCbase*)getUserData("target");
      long pos2 = (long)getUserData("pos");
      if (pos2 == pos){
        _adjust_input(target2,pos2,True,pt->x,pt->y);
      }
      setUserData("onfire",(void*)0);
      setUserData("ctime",(void*)0);
    }
  }else{
    setUserData("onfire",(void*)0);
    setUserData("ctime",(void*)0);
  }
  WSCscrForm::onScrMouseRelease(pt);
}
WSCstring WSClist::getInputString(){
  WSCstring str;
  if (_input_instance != NULL){
    str = _input_instance->getProperty(WSNlabelString);
  }
  return str;
}
void WSClist::replaceItem(char* item,long pos,long column){

  WSCstring str2(item);
  if (_disp_type == WS_VERBOSE){
    WSCstring str;
    str = getItem(pos);
    long num = str.getWords(_separator);
    long i;
    WSCstring newstr;
    for(i=0; i<num; i++){
      if (i != 0){
        newstr << _separator;
      }
      if (i == column){
        newstr << str2;
      }else{
        WSCstring tmp = str.getWord(i,_separator);
        newstr << tmp;
      }
    }
    replaceItem(newstr,pos);
  }else{
    replaceItem(str2,pos);
  } 
}
void WSClist::onInputFixed(WSCstring str,long pos,long column){
  execProcedure(WSEV_INPUT_FIXED);
  if (_disp_type == WS_VERBOSE){
    replaceItem(str,pos,column);
  }else{
    replaceItem(str,pos);
  }
}
void WSClist::_input_fix_work(WSCbase* ifield){
  long key = WSGIappKeyboard()->getKey();
  if (key == WSK_Return){
    WSCbase* target = (WSCbase*)ifield->getUserData("selected-target");
    if (target == NULL){
      return;
    }
    WSClist* list = (WSClist*)ifield->getUserData("plist");
    WSCstring str;
    str = ifield->getProperty(WSNlabelString);
    long pos = (long)ifield->getUserData("No.");
    if (list->_disp_type != WS_VERBOSE){
      list->onInputFixed(str,pos,0);
    }else{
      long bno = (long)ifield->getUserData("bno");
      list->onInputFixed(str,pos,bno);
    }
    list->_adjust_input(target,pos,False,0,0);
  }
}
void WSClist::_input_focus_lose(WSCbase* ifield){
  if (ifield->getFocus() == False){
    WSCbase* target = (WSCbase*)ifield->getUserData("selected-target");
    if (target == NULL){
      return;
    }
    WSClist* list = (WSClist*)ifield->getUserData("plist");
    WSCstring str;
    str = ifield->getProperty(WSNlabelString);
    long pos = (long)ifield->getUserData("No.");
    if (list->_disp_type != WS_VERBOSE){
      list->onInputFixed(str,pos,0);
    }else{
      long bno = (long)ifield->getUserData("bno");
      list->onInputFixed(str,pos,bno);
    }
    list->_adjust_input(target,pos,False,0,0);
  }else{
    ifield->setSpecialFocus(True);
  }
}
void WSClist::_adjust_input(WSCbase* target,long pos,WSCbool vis,short x,short y){
  if (_input_instance == NULL){
    return;
  }
  if (target == NULL){
    _input_instance->setVisible(False);
    return;
  }
  short x1 = target->getProperty(WSNx);
  short y1 = target->getProperty(WSNy);
  WSCushort w = target->getProperty(WSNwidth);
  WSCushort h = target->getProperty(WSNheight);
  if (vis != False){
    WSCstring str;
    str = target->getProperty(WSNlabelString);
    long bno = 0;

    WSCushort st = target->getProperty(WSNshadowThickness);
    WSCushort hh = h -st*2;
    if (_disp_type == WS_NORMAL){
      if (_use_icon != False){
        x1 += hh + hh/4;
        w -= (hh + hh/4);
      }
    }else
    if (_disp_type == WS_TREE){
      long indent_level = (long)target->getUserData(WS_LIST_INDENT_LEVEL);
      if (_use_icon != False){
        x1 += (hh*2 + hh/4 + hh * indent_level);
        w -= (hh*2 + hh/4 + hh * indent_level);
      }else{
        x1 += (hh + hh/4 + hh * indent_level);
        w -= (hh + hh/4 + hh * indent_level);
      }
    }else
    if (_disp_type == WS_VERBOSE){
      WSCstring barlist(_bar_pos);
      long num = barlist.getWords(_separator);
      long bpos = w;
      long bpos2 = 0;
      long i;
      for(i=0; i<num;i++){
        WSCstring val = barlist.getWord(i,_separator);
        long bv = atoi((char*)val);
        if (x < bv){
          bpos = bv;
          bno = i;
          break;
        }
        bpos2 =  bv;
      }
      if (i == num){
        bno = num;
        bpos = w;
      }
      if (_use_icon != False){
        str = str.getWord(bno,_separator);
        if (bno == 0){
          x1 += hh + hh/4;
          w = bpos - (hh + hh/4) - bpos2;
        }else{
          x1 += bpos2;
          w = bpos - bpos2;
        }
      }else{
        str = str.getWord(bno,_separator);
        x1 = bpos2;
        w = bpos - bpos2;
      }
    }

    if (_input_instance->getVisible() != False){
      if (_disp_type != WS_VERBOSE){
        if (pos == (long)_input_instance->getUserData("No.")){
          return;
        }
      }else{
        if (bno == (long)_input_instance->getUserData("bno") &&
            pos == (long)_input_instance->getUserData("No.")){
          return;
        }
      }
    }
    if (_input_instance->getVisible() != False){
      WSCbase* target = (WSCbase*)_input_instance->getUserData("selected-target");
      if (target != NULL){
        WSCstring str;
        str = _input_instance->getProperty(WSNlabelString);
        long pos = (long)_input_instance->getUserData("No.");
        if (_disp_type != WS_VERBOSE){
          onInputFixed(str,pos,0);
        }else{
          long bno = (long)_input_instance->getUserData("bno");
          onInputFixed(str,pos,bno);
        }
        _input_instance->setUserData("selected-target",NULL);
        _input_instance->setVisible(False);
        target->redraw();
      }
    }
    _input_instance->setProperty(WSNx,x1);
    _input_instance->setProperty(WSNy,y1);
    _input_instance->setProperty(WSNwidth,w);
    _input_instance->setProperty(WSNheight,h);
    _input_instance->setProperty(WSNmarginRight,0);
    _input_instance->setProperty(WSNmarginLeft,0);
    _input_instance->setProperty(WSNmarginTop,0);
    _input_instance->setProperty(WSNmarginBottom,0);
    _input_instance->setVisible(True);
    _input_instance->setSpecialFocus(True);
    _input_instance->setFocus(True);
    _input_instance->setProperty(WSNlabelString,(char*)str);
    _input_instance->setUserData("No.",(void*)pos);
    WSCprocedure* op = new WSCprocedure("focus-lose",WSEV_FOCUS_CH);
    op->setInternal(True);
    op->setFunction(_input_focus_lose,"_input_focus_lose");
    _input_instance->addProcedure(op);
    WSCprocedure* op2 = new WSCprocedure("focus-lose",WSEV_KEY_HOOK);
    op2->setInternal(True);
    op2->setFunction(_input_fix_work,"_input_fix_work");
    _input_instance->addProcedure(op2);
    _input_instance->setUserData("plist",(void*)this);
    _input_instance->setUserData("selected-target",(void*)target);
    target->setSensitive(False);
//    target->setVisible(False);
    if (_disp_type == WS_VERBOSE){
      _input_instance->setUserData("bno",(void*)bno);
    }
  }else{
    _input_instance->setVisible(False);
    _input_instance->setUserData("selected-target",NULL);
    target->setSensitive(True);
//    target->setVisible(True);
    target->redraw();
  }
}
void WSClist::_adjust(){
//  cancelInput();
  if (_enable_input != False&& _input_instance == NULL){
    WSCbase* scr = getScrFrame();
    scr->setUserData("scrparent",(void*)this);
#if 0
    WSCprocedure* op = new WSCprocedure("mouse-press",WSEV_MOUSE_PRESS);
    op->setInternal(True);
    op->setFunction(_mouse_press_work,"_mouse_press_work");
    scr->addProcedure(op);

    WSCprocedure* op2 = new WSCprocedure("mouse-release",WSEV_MOUSE_RELEASE);
    op2->setInternal(True);
    op2->setFunction(_mouse_release_work,"_mouse_release_work");
    scr->addProcedure(op2);
#endif
    _input_instance = WSCbase::getNewInstance("WSCvifield",this,"list-in");
    _input_instance->initialize();
    _input_instance->setInternalObject(True);
  }
  if (_disp_type != WS_VERBOSE){
    _padding = 0;
  }
  WSCscrForm::_adjust();
  WSCscrForm::_adjust_scr_area();
  if (_btn_area == NULL){
    return;
  }
  if (_disp_type != WS_VERBOSE){
    _btn_area->setVisible(False);
    _padding = 0;
    return;
  }
  _btn_area->setPropertyV(WSNx,(short)_shadow_thick);
  _btn_area->setPropertyV(WSNy,(short)_shadow_thick);
  if (_scr_area_w == 0){
    _adjust_scr_area();
  }
//printf("WSClist::_adjust scr_w=%d\n",_scr_area_w);
  _btn_area->setPropertyV(WSNwidth,(WSCushort)_scr_area_w);
  _btn_area->setPropertyV(WSNheight,(WSCushort)_padding);

  _btn_area->setPropertyV(WSNbackColor,(short)_back_color);
  _btn_area->setPropertyV(WSNforeColor,(short)_fore_color);
  _btn_area->setPropertyV(WSNtopShadowColor,(short)_ts_color);
  _btn_area->setPropertyV(WSNbottomShadowColor,(short)_bs_color);

  WSClistData children = _btn_area->getChildren();
  long num = children.getNum();
  WSCstring bar_pos(_bar_pos);
  long btnnum = bar_pos.getWords(_separator) +1;
  long cnt = 0;
  long i;
  WSCstring title(_title_string);
//printf("WSClist::_adjust btnnum=%d\n",btnnum);
  for(i=0; i<num; i++){
    WSCbase* item = (WSCbase*)children[i];
    if (item->cast("WSCgripHand") != NULL){
      continue;
    }else if (i < btnnum){
      WSCstring tmp = title.getWord(cnt,_separator);
      item->setPropertyV(WSNlabelString,(char*)tmp);
      item->setPropertyV(WSNbackColor,(short)_back_color);
      item->setPropertyV(WSNforeColor,(short)_fore_color);
      item->setPropertyV(WSNtopShadowColor,(short)_ts_color);
      item->setPropertyV(WSNbottomShadowColor,(short)_bs_color);
      item->setPropertyV(WSNshadowThickness,(WSCuchar)_shadow_thick);
      item->setVisible(True);
//printf("WSClist::_adjust %d=#%s# %s\n",i,(char*)tmp,_separator);
      cnt++;
    }else{
      item->setVisible(False);
    }
  }
  if (cnt < btnnum){
    long i;
    for(i=cnt; i<btnnum; i++){
      WSCstring name;
      name = (WSCstring)"bt-" + getInstanceName();
      WSCvbtn* item = new WSCvbtn(_btn_area,name);
      item->setInternalObject(True);
      item->initialize();
      item->setPropertyV(WSNalignmentH,(WSCuchar)WS_LEFT);
      item->setPropertyV(WSNbackColor,(short)_back_color);
      item->setPropertyV(WSNforeColor,(short)_fore_color);
      item->setPropertyV(WSNtopShadowColor,(short)_ts_color);
      item->setPropertyV(WSNbottomShadowColor,(short)_bs_color);
      item->setPropertyV(WSNshadowThickness,(WSCuchar)_shadow_thick);
      item->setPropertyV(WSNusePixmap,(WSCbool)True);
      item->setProperty(WSNenableFocusMove,False);
      item->setDrawFocusBorder(False);
      WSCstring tmp = title.getWord(i,_separator);
      item->setPropertyV(WSNlabelString,(char*)tmp);
      item->setVisible(True);
      item->setUserData("p-list",(void*)this);
      item->setUserData("btn-pos",(void*)i);
      
      WSCprocedure* op = new WSCprocedure("value-ch",WSEV_ACTIVATE);
      op->setInternal(True);
      op->setFunction(_btn_activate,"_btn_activate");
      item->addProcedure(op);
    }
  }
  _btn_area->needUpdate();
  _btn_area->update();
#if 0
  WSCscrForm::_adjust();
  WSCscrForm::_adjust_scr_area();
#endif
}
void WSClist::_btn_activate(WSCbase* btn){
  WSClist* obj = (WSClist*)btn->getUserData("p-list");
  obj->_sort_pos = (long)btn->getUserData("btn-pos");
  obj->onSort();
}
void WSClist::onSort(){
  long sort_pos = getSortPos(); 

  long num = _lb_list.getNum();
  WSClistData list;
  long i;
  for(i=0; i<num; i++){
    WSCbase* item = (WSCbase*)_lb_list[i];
    WSCstring str(item->getProperty(WSNlabelString));
    WSCstring sortstr = str.getWord(sort_pos,_separator);
    item->setUserData("SORT-STR",(void*)WSGFstrdup((char*)sortstr));

    long inum = list.getNum();
    long j;
    long added = 0;
    for(j=0; j<inum; j++){
      WSCbase* lb = (WSCbase*)list[j];
      char* istr = (char*)lb->getUserData("SORT-STR");
      if (strcmp(istr,(char*)sortstr)>0){
        list.add((void*)item,j);
        added = 1;
        break;
      }
    }
    if (added == 0){
      list.add((void*)item);
    }
  }
  num = list.getNum();
  _lb_list.clear();
  for(i=0; i<num; i++){
    WSCbase* lb = (WSCbase*)list[i];
    char* istr = (char*)lb->getUserData("SORT-STR");
    delete istr;
    _lb_list.add(lb);
  }
  _lb_adjust();


//  execEventProc(WSEV_SORT,NULL);
  execProcedure(WSEV_SORT);
}
long WSClist::getSortPos(){
  return _sort_pos;
}
void WSClist::setLabelClass(char* cname){
  _lb_class.setString(cname);
}

void WSClist::setLabelHeight(WSCushort h){
  _scroll_height = h;
  _lb_height = h;
  _lb_height_bk = h;
  updateList();
}

long WSClist::getNum(){
  return _lb_list.getNum();
}

WSCbase* WSClist::getLabel(long pos){
  if (pos == -1){
    pos = _lb_list.getNum()-1;
    if (pos < 0){
      pos = 0;
    }
  }
  return (WSCbase*)_lb_list.getData(pos);
}

void WSClist::addItem(char* str,long pos){
  cancelInput();
//   WSCushort sw;
//   getPropertyV(WSNworkWidth,&sw);
   WSCbase* lb = WSCbase::getNewInstance(_lb_class.getString(),
                                     this,"lblist-l");
   if (lb == NULL){
WSMFtrace("WSClist::addItem Error. Can not create %s class instance.\n",(char*)_lb_class);
     return;
   }
   short y = (short)( _lb_list.getNum() * _lb_height );
   lb->setInternalObject(True);
   lb->initialize();
   lb->setPropertyV(WSNx,(short)0);
   if (_no_scroll != False){
     lb->setPropertyV(WSNy,(short)(y - _wy_pos));
   }else{
     lb->setPropertyV(WSNy,y);
   }
   lb->setPropertyV(WSNwidth,_lb_width);
   lb->setPropertyV(WSNheight,(WSCushort)_lb_height);
   lb->setPropertyV(WSNshadowThickness,(WSCuchar)0);
   lb->setPropertyV(WSNfont,(WSCuchar)_font);
   lb->setPropertyV(WSNalignmentH,(WSCuchar)WS_LEFT);
   lb->setPropertyV(WSNbackColor,(short)_work_back_color);
   lb->setPropertyV(WSNlabelString,str);
   lb->setPropertyV(WSNusePixmap,(WSCbool)True);
   WSGFsetMargin(lb,0);
   if (_use_icon != False && _icon_pixmap != -1){
     short fl;
     lb->getPropertyV(WSNlabelPixmap,&fl);
     if (fl == -1){
       lb->setPropertyV(WSNlabelPixmap,_icon_pixmap);
     }
   }
   lb->setVisible(True);
   _lb_list.add((void*)lb,pos);
//  _lb_adjust();
   needUpdate();
   _need_update = 1;
}
void WSClist::update(){
  if ( _need_ds_update != False){
    _need_ds_update = False;
    _set_ds_instance();
  }
  if ( _need_update != 0){
    updateList();
    if (_pixmap_style == WS_DYNAMIC_PIXMAP){
      WSDdev* dev = _scr_area->getdev();
      if (dev != NULL){
        char fl = WS_DIRECT_WINDOW;
        dev->setValue(WSDEV_PIXMAP_STYLE,&fl);
        fl = WS_DYNAMIC_PIXMAP;
        dev->setValue(WSDEV_PIXMAP_STYLE,&fl);
      }
      _redraw_scr();
      _need_scr_redraw = False;
    }
    if (_need_scr_redraw != False){
      _redraw_scr();
      _need_scr_redraw = False;
    }
  }
  WSCscrForm::update();
}
void WSClist::updateList(){
//  cancelInput(); ->NG
   _need_update = 0;
  long num = _lb_list.getNum();
  long i;
  WSCushort width;
  getPropertyV(WSNworkWidth,&width);

  if (width != _w_bk){
    _w_bk = width;
    if (_lb_width < width){
      _lb_width = width + 256;
      for(i=0; i< num; i++){
        WSCbase* label = (WSCbase*)_lb_list[i];
        label->setPropertyV(WSNwidth,_lb_width);
        label->update();
      }
    }
  }
  _lb_adjust();
  if (getDataSourceServer() == NULL&&
      _data_source_type == WS_DATA_SOURCE_INSTANCE){
    _set_ds_instance();
  }
  num = _lb_list.getNum();
  for(i=0; i< num; i++){
    WSCbase* label = (WSCbase*)_lb_list[i];
    label->setUserData(WS_LIST_TREE_OPEN_CH,(void*)0);
  }

//  setAbsoluteDraw(True);
//  _scr_area->redraw();
//  cdraw();
}

void WSClist::delAll(){
//  cancelInput(); ->NG.
  long num = _lb_list.getNum();
  long i;
  for(i=0; i< num; i++){
    WSCbase* label = (WSCbase*)_lb_list[i];
    delete label;
  }
  _lb_list.clear();
  needUpdate();
  _scr_area->setAbsoluteDraw(True);// for clearing area.
  if (_pixmap_style == WS_DYNAMIC_PIXMAP){
    WSDdev* dev = _scr_area->getdev();
    if (dev != NULL){
      char fl = WS_DIRECT_WINDOW;
      dev->setValue(WSDEV_PIXMAP_STYLE,&fl);
      fl = WS_DYNAMIC_PIXMAP;
      dev->setValue(WSDEV_PIXMAP_STYLE,&fl);
    }
  }
  if (_data != NULL){
    delete _data;
  }
  _data = NULL;
  _need_update = 1;
  _need_scr_redraw = 1;
}

void WSClist::setLabelProperty(char* pr,char* vl){
  long num = _lb_list.getNum();
  long i;
  for(i=0; i< num; i++){
    WSCbase* label = (WSCbase*)_lb_list[i];
    label->setProperty(pr,vl);
  }
}
WSCstring WSClist::getItem(long pos,long col){
  if (col <0){
    WSCbase* label = (WSCbase*)_lb_list.getData(pos);
    WSCstring tmp;
    if (label != NULL){
      tmp = label->getProperty(WSNlabelString);
      return tmp;
    }  
    return tmp;
  }else{
    WSCstring tmp = getItem(pos);
    WSCstring ret = tmp.getWord(col,_separator);
    return ret;
  }
}
void WSClist::replaceItem(char* item,long pos){
//  cancelInput(); ->NG.
  WSCbase* label = (WSCbase*)_lb_list.getData(pos);
  if (label != NULL){
    label->setProperty(WSNlabelString,item);
  }
  needUpdate();  
  _need_update = 1;
}
void WSClist::cancelInput(){
  if (_input_instance != NULL){
    if (_input_instance->getVisible() != False){
      _input_instance->setUserData("selected-target",NULL);
    }
  }
}
void WSClist::delPos(long pos){
  cancelInput();
  if (pos == -1){
    pos = _lb_list.getNum()-1;
    if (pos < 0){
      pos = 0;
    }
  }
  WSCbase* label = (WSCbase*)_lb_list.getData(pos);
  if (label != NULL){
    _lb_list.delPos(pos);
    delete label;
  }  
  needUpdate();
  _need_update = 1;
  _need_scr_redraw = 1;
}
long WSClist::getSelectedPos(){
  long i;
  long num = _lb_list.getNum();
  for(i=0; i<num; i++){
    WSCbase* lb = (WSCbase*)_lb_list[i];
    long status =(long)lb->getUserData(SELECT_STATUS);
    if (status != 0){
      return i;
    }
  }
  return -1;
}
long WSClist::getPreSelectedPos(){
  return _pre_select;
}

WSCstring WSClist::getSelectedItem(){
  long i;
  long num = _lb_list.getNum();
  WSCstring tmp;
  for(i=0; i<num; i++){
    WSCbase* lb = (WSCbase*)_lb_list[i];
    long status =(long)lb->getUserData(SELECT_STATUS);
    if (status != 0){
      tmp = lb->getProperty(WSNlabelString);
      return tmp;
    }
  }
  return tmp;
}
long WSClist::getTopPos(){
//  long hnum = _v_scr_slider_sz / _lb_height;
  long topbase = _wy_pos / _lb_height;
  long num = _lb_list.getNum();
  long i;
  long cnt =0;
  for(i=0; i<num; i++){
    WSCbase* item = (WSCbase*)_lb_list[i];
    if (cnt == topbase){
      return i;
    }
    if (item->getVisible() != False){
      cnt++;
    }
  }
  return 0;
}

void WSClist::setTopPos(long pos){
  if (pos == -1){
    pos = _lb_list.getNum();
  }
  long num = _lb_list.getNum();
  long i;
  long cnt =0;
  for(i=0; i<num; i++){
    WSCbase* item = (WSCbase*)_lb_list[i];
    if (cnt == pos){
      setProperty(WSNvbarValue,_lb_height*i);
      return;
    }
    if (item->getVisible() != False){
      cnt++;
    }
  }
  setProperty(WSNvbarValue,_lb_height*i);
}

long WSClist::getBottomPos(){
  long pos = getTopPos();
  long hnum = _v_scr_slider_sz / _lb_height;
  long pos2 = pos + hnum -1;
  long max = _lb_list.getNum();
  if (pos2 < max){
    return pos2;
  }
  if (max > 0){
    return max-1;
  }
  return 0;
}

void WSClist::setBottomPos(long pos){
  if (pos == -1){
    pos = _lb_list.getNum();
  }
  long hnum = _v_scr_slider_sz / _lb_height;
  long pos2 = pos - hnum +1;
  if (pos2 <0){
    pos2 = 0;
  }
  setTopPos(pos2);
}

long WSClist::setPreSelectPos(long pos){
  long num =  _lb_list.getNum();
  if (pos > num -1){
    return WS_ERR;
  }
  if (pos <0){
    pos = num -1;
  }
  _pre_select = pos;
  return WS_NO_ERR;
}
long WSClist::setSelectPos(long pos){
  long num =  _lb_list.getNum();
  if (pos > num -1){
    return WS_ERR;
  }
  if (pos <0){
    pos = num -1;
  }
  _pre_select = pos;
  if (_mselect == False){
    long i;
    long num = _lb_list.getNum();
    for(i=0;i<num;i++){
      WSCbase* lb = (WSCbase*)_lb_list[i];
      if (i==pos){
        if (_reverse_select == 1){
          long fl = (long)lb->getUserData(SELECT_STATUS);
          if (fl == 0){
            lb->setPropertyV(WSNselectColor,(short)_select_color);
            lb->setPropertyV(WSNselectForeColor,(short)_select_fore_color);
            lb->setUserData(SELECT_STATUS,(void*)1);
          }else{
            lb->setPropertyV(WSNselectColor,(short)0);
            lb->setPropertyV(WSNselectForeColor,(short)0);
            lb->setUserData(SELECT_STATUS,(void*)0);
          }
          _select_item_changed = 1;
        }else{
          lb->setPropertyV(WSNselectColor,(short)_select_color);
          lb->setPropertyV(WSNselectForeColor,(short)_select_fore_color);
          if ((long)lb->getUserData(SELECT_STATUS) == 0 ||
               _absolute_select_change){
            _select_item_changed = 1;
          }
          lb->setUserData(SELECT_STATUS,(void*)1);
        }
      }else{
        lb->setPropertyV(WSNselectColor,(short)0);
        lb->setPropertyV(WSNselectForeColor,(short)0);
        if ((long)lb->getUserData(SELECT_STATUS) != 0){
          _select_item_changed = 1;
        }
        lb->setUserData(SELECT_STATUS,(void*)0);
      }
    }
  }else{
    WSCbase* lb = (WSCbase*)_lb_list.getData(pos);
    if (_reverse_select == 1){
      long fl = (long)lb->getUserData(SELECT_STATUS);
      if (fl == 0){
        lb->setPropertyV(WSNselectColor,(short)_select_color);
        lb->setPropertyV(WSNselectForeColor,(short)_select_fore_color);
        lb->setUserData(SELECT_STATUS,(void*)1);
      }else{
        lb->setPropertyV(WSNselectColor,(short)0);
        lb->setPropertyV(WSNselectForeColor,(short)0);
        lb->setUserData(SELECT_STATUS,(void*)0);
      }
      _select_item_changed = 1;
    }else{
      lb->setPropertyV(WSNselectColor,(short)_select_color);
      lb->setPropertyV(WSNselectForeColor,(short)_select_fore_color);
      if ((long)lb->getUserData(SELECT_STATUS) == 0 ||
          _absolute_select_change ){
        _select_item_changed = 1;
      }
      lb->setUserData(SELECT_STATUS,(void*)1);
    }
  }
  if (_activate){
    onActivate();
  }
  onItemSelected();
  needUpdate();
  _need_update = 1;
  return WS_NO_ERR;
}
WSCbool WSClist::getSelectItemChanged(){
  return _select_item_changed;
}
void WSClist::setSelectItemChanged(WSCbool fl){
  _select_item_changed = fl;
}
//void WSClist::onActivate(){
//  execProcedure(WSEV_ACTIVATE);
//}
void WSClist::onItemSelected(){
  execProcedure(WSEV_ITEM_SELECTED);
}
void WSClist::onItemDoubleClicked(){
  execProcedure(WSEV_ITEM_DOUBLE_CLICKED);
}
WSClistData* WSClist::getLabels(){
  return &_lb_list;
}
void WSClist::setEnableActivate(WSCbool fl){
  _activate = fl;
}
WSCbool WSClist::getEnableActivate(){
  return _activate;
}
void WSClist::setAbsoluteChangeSelectFlag(WSCbool fl){
  _absolute_select_change = fl;
}
WSCbool WSClist::getAbsoluteChangeSelectFlag(){
  return _absolute_select_change;
}

long WSClist::draw(){
//  if (_get_hbar_visible() != False){
//    setPropertyV(WSNhbarVisible,(WSCbool)False);
//  }
  if (_lb_height != _lb_height_bk){
    _need_update = True;
  }
  if (_need_update != 0){
    updateList();
//    _redraw_scr();
  }
  return WSCscrForm::draw();
}

long WSClist::setItemVisible(long pos,WSCbool fl){
  long num = _lb_list.getNum();
  if (num <1){
    return WS_ERR;
  }
  if (pos < 0){
    pos = num -1;
  }
  WSCbase* item = (WSCbase*)_lb_list.getData(pos);
  item->setVisible(fl);
//  _lb_adjust();
  needUpdate();
  _need_update = 1;
  return WS_NO_ERR;
}
long WSClist::setItemValue(long pos,long kind,long val){
  long num = _lb_list.getNum();
  if (pos <0){
    pos = num -1;
  }
  if (pos <0){
    return WS_ERR;
  }
  if (pos > num -1){
    pos = num -1;
  }
  WSCbase* item = (WSCbase*)_lb_list.getData(pos);
  if (kind == WS_OPEN){
    _need_update = 1;
    if (val == 0){
      item->setUserData(WS_LIST_TREE_OPEN,(void*)0);
    }else{
      item->setUserData(WS_LIST_TREE_OPEN,(void*)1);
    }
  }else
  if (kind == WS_ABSOLUTE_OPEN){
    if (val == 0){
//      item->setUserData(WS_LIST_TREE_OPEN,(void*)0);
    }else{
//      item->setUserData(WS_LIST_TREE_OPEN,(void*)1);
      long level = (long)item->getUserData(WS_LIST_INDENT_LEVEL);
      long pos2 = pos;
//printf("pos=%d\n",pos);
      while(level > 0){
        pos2--;
        WSCbase* item2 = (WSCbase*)_lb_list.getData(pos2);
        long level2 = (long)item2->getUserData(WS_LIST_INDENT_LEVEL);
        if (level2 < level){
//printf("set pos=%d \n",pos2);
          _need_update = 1;
          item2->setUserData(WS_LIST_TREE_OPEN,(void*)1);
          level = level2;
        }
        if (pos2 == 0){
          return WS_NO_ERR;
        }
      }
    }
  }else
  if (kind == WS_INDENT_LEVEL){
    item->setUserData(WS_LIST_INDENT_LEVEL,(void*)val);
  }else
  if (kind == WS_ICON && _use_icon != False){
    item->setProperty(WSNlabelPixmap,(char*)val);
  }
  return WS_NO_ERR;
}

long WSClist::getItemValue(long pos,long kind,long* val){
  long num = _lb_list.getNum();
  if (pos <0){
    pos = num -1;
  }
  if (pos <0){
    return WS_ERR;
  }
  WSCbase* item = (WSCbase*)_lb_list.getData(pos);
  if (kind == WS_OPEN){
    *val = (long)item->getUserData(WS_LIST_TREE_OPEN);
    return WS_NO_ERR;
  }else
  if (kind == WS_INDENT_LEVEL){
    *val = (long)item->getUserData(WS_LIST_INDENT_LEVEL);
    return WS_NO_ERR;
  }
  return WS_ERR;
}
void WSClist::_lb_adjust_work(long& pos,long indent,WSCbool vis,long& cnt){
//printf("_lb_adjust_work...\n");
#ifdef TDBG
  printf("WSClist::_lb_adjust_work pos=%d  start %d \n",pos,WSGFclocktime());
#endif

  long num = _lb_list.getNum();
  WSCbool pvis = 0;
  WSCbase* pre = NULL;
  while(1){
#ifdef TDBG
  printf("WSClist::_lb_adjust_work here-1 pos=%d %d\n",pos,WSGFclocktime());
#endif

    if (pos > num -1){
      return;
    }
    WSCbase* item = (WSCbase*)_lb_list.getData(pos);
    if (pos == 0){
      item->setUserData(WS_LIST_TOP,(void*)1);
    }else{
      item->setUserData(WS_LIST_TOP,(void*)0);
    }
    long level = (long)item->getUserData(WS_LIST_INDENT_LEVEL);
    if (level <indent){
#ifdef TDBG
  printf("WSClist::_lb_adjust_work here-2 pos=%d %d\n",pos,WSGFclocktime());
#endif
      return;
    }
#ifdef TDBG
  printf("WSClist::_lb_adjust_work here-3 pos=%d %d\n",pos,WSGFclocktime());
#endif
    item->setUserData(WS_LIST_INDENT_STATUS,(void*)0);
    item->setUserData(WS_LIST_LABEL_LIST,(void*)&_lb_list);
    if (level > indent){
      level = indent+1;
      item->setUserData(WS_LIST_INDENT_LEVEL,(void*)level);
#ifdef TDBG
  printf("WSClist::_lb_adjust_work here-4 pos=%d %d\n",pos,WSGFclocktime());
#endif
      if (pre != NULL){
        long val;
        val = (long)pre->getUserData(WS_LIST_INDENT_STATUS);
        pre->setUserData(WS_LIST_INDENT_STATUS,(void*)(val | WS_HAVE_CHILD));
      }
#ifdef TDBG
  printf("WSClist::_lb_adjust_work here-5 pos=%d %d\n",pos,WSGFclocktime());
#endif
      _lb_adjust_work(pos,level,pvis,cnt);
    }else{
#ifdef TDBG
  printf("WSClist::_lb_adjust_work here-6 pos=%d %d\n",pos,WSGFclocktime());
#endif
      if (vis == 0){
        if ((WSCbool)item->getProperty(WSNvis) != False){
#if 0 //deleted..
          short ybk;
          item->getPropertyV(WSNy,&ybk);
          if (ybk > (short)( cnt * _lb_height )){
            if (_no_scroll != False){
              if (ybk > _wy_pos + _v_scr_slider_sz ){
              }else if (ybk + _lb_height > _wy_pos ){
                item->clear();
              }else{
              }
            }else{
              if (ybk + _lb_height > _wy_pos &&
                  ybk < _wy_pos + _v_scr_slider_sz ){
                item->clear();
              }
            }
          }
#endif //deleted..
          item->setNoClearFlag(True);
          item->setVisible(False);
          item->setNoClearFlag(False);
        }
        pvis = 0;
#ifdef TDBG
  printf("WSClist::_lb_adjust_work here-7 pos=%d %d\n",pos,WSGFclocktime());
#endif
      }else{
        if (pre != NULL){
          long val;
          val = (long)pre->getUserData(WS_LIST_INDENT_STATUS);
          pre->setUserData(WS_LIST_INDENT_STATUS,(void*)(val | WS_HAVE_BROS));
        }
        long val = (long)item->getUserData(WS_LIST_TREE_OPEN);
        if (val == 0){
          pvis =0;
        }else{
          pvis =1;
        }
#if 0 //deleted..
        short ybk;
        item->getPropertyV(WSNy,&ybk);
        if (ybk > (short)( cnt * _lb_height )){
          if (_no_scroll != False){
            if (ybk > _wy_pos + _v_scr_slider_sz ){
            }else if (ybk + _lb_height > _wy_pos ){
              item->clear();
            }else{
            }
          }else{
            if (ybk + _lb_height > _wy_pos &&
                ybk < _wy_pos + _v_scr_slider_sz ){
              item->clear();
            }
          }
        }
#endif //deleted..
#ifdef TDBG
  printf("WSClist::_lb_adjust_work here-8 pos=%d %d\n",pos,WSGFclocktime());
#endif
        if (_no_scroll != False){
          if (_lb_height * cnt > _wy_pos + _v_scr_slider_sz ){
            item->setPropertyV(WSNy, (short)( -_lb_height*2 ));
            item->WSCbase::update();
          }else if (_lb_height * cnt + _lb_height > _wy_pos ){
            item->setPropertyV(WSNy, (short)( cnt * _lb_height - _wy_pos));
          }else{
            item->setPropertyV(WSNy, (short)( -_lb_height*2 ));
            item->WSCbase::update();
          }
        }else{
          item->setPropertyV(WSNy, (short)( cnt * _lb_height ));
        }
        if (item->getVisible() == False){
          item->setVisible(True);
        }
        cnt++;
      }
      pos++;
      pre = item;
#ifdef TDBG
  printf("WSClist::_lb_adjust_work here-9 pos=%d %d\n",pos,WSGFclocktime());
#endif
    }
  }
}
void WSClist::_lb_adjust(){
//printf("_lb_adjust\n");
  long num = _lb_list.getNum();
  if (num <1){
//    setPropertyV(WSNworkHeight,(WSCushort)1);
    setPropertyV(WSNworkHeight,(WSCushort)_scr_area_h);
    _work_height_bk = _scr_area_h;
    if (getVisible() != False){
      _redraw_scr();
    }
    return;
  }
  long cnt = 0;
  if (_disp_type != WS_TREE){
    long i;
    for(i=0; i<num; i++){
      WSCbool fl;
      WSCbase* item = (WSCbase*)_lb_list[i];
      item->getPropertyV(WSNvis,&fl);
      if (fl != False){
        if (_no_scroll != False){
          if (_lb_height * cnt > _wy_pos + _v_scr_slider_sz ){
            item->setPropertyV(WSNy, (short)( -_lb_height *2));
            item->WSCbase::update();
          }else if (_lb_height * cnt + _lb_height > _wy_pos ){
            item->setPropertyV(WSNy, (short)( cnt * _lb_height - _wy_pos));
          }else{
            item->setPropertyV(WSNy, (short)( -_lb_height *2));
            item->WSCbase::update();
          }
        }else{
          item->setPropertyV(WSNy, (short)( cnt * _lb_height ));
        }
        cnt++;
      }
    }
//printf("WSClist::_lb_adjust %s cnt=%d wh=%d\n",getInstanceName(),cnt,cnt*_lb_height);
    WSCulong lbh = cnt*_lb_height;
    if (lbh > 0xffff){
      lbh = 0xffff;
    }
    if (_scr_area_h > lbh){
      lbh = _scr_area_h;
    }
    if (lbh != _work_height_bk){
      setProperty(WSNworkHeight,lbh);
      setAbsoluteDraw(False);
      _work_height_bk = lbh;
    }
  }else{
    long pos = 0;
    _lb_adjust_work(pos,0,1,cnt);
    WSCulong lbh = cnt*_lb_height;
    if (_scr_area_h > lbh){
      //This makes the tree no refresh when the tree status is changed..
      lbh = _scr_area_h;
    }
//    long wh = getProperty(WSNworkHeight);
//    if (wh == lbh){
//      setProperty(WSNworkHeight,lbh-1);
//    }
    if (lbh != _work_height_bk){
      _work_height = 1;
      setProperty(WSNworkHeight,lbh);
      setAbsoluteDraw(False);
      _scr_area->setProperty(WSNworkHeight,lbh);
      _scr_area->setAbsoluteDraw(False);
      _work_height_bk = lbh;
    }
//    if (cnt < num){
//      WSCrect area;
//      area.x = 0;
//      area.y = cnt*_lb_height;
//      area.width = _work_width;
//      area.height = _scr_area_h - area.y+1000;
//      _scr_area->execEventProc(WSEV_EXPOSE,&area);
//printf("WSClist::_lb_adjust exposed %d %d %d %d\n",area.x,area.y,area.width,area.height);
//    }
//    setPropertyV(WSNworkHeight,(WSCushort)(cnt*_lb_height));
    if (_pixmap_style == WS_DYNAMIC_PIXMAP){
      _scr_area->redraw();
    }
  }
  if ( cnt*_lb_height > 32760 ){
    if (_no_scroll == False){
      _set_no_scroll(True);
      _adjust_no_scroll();
    }
    if (cnt*_lb_height < _wy_pos + _v_scr_slider_sz){
      WSDdev* dev = _scr_area->getowndev();
      if (dev != NULL){
        dev->exposeArea(0,cnt*_lb_height - _wy_pos,
                        _work_width, _v_scr_slider_sz);
      }
    }
  }else{
    _set_no_scroll(False);
    if (cnt*_lb_height < _wy_pos + _v_scr_slider_sz){
      WSDdev* dev = _scr_area->getowndev();
      if (dev != NULL){
        dev->exposeArea(0,cnt*_lb_height,_work_width,_v_scr_slider_sz);
      }
    }
  }
}
void WSClist::getSelectedLabels(WSClistData& list){
  list.clear();
  long i;
  long num = _lb_list.getNum();
  for(i=0; i<num; i++){
    WSCbase* lb = (WSCbase*)_lb_list[i];
    long status =(long)lb->getUserData(SELECT_STATUS);
    if (status != 0){
      list.add((void*)lb);
    }
  }
}

void WSClist::onKey(WSDkeyboard* key,WSCbool fl){
  if (fl == False){
    execProcedure(WSEV_KEY_RELEASE);
  }else{
    execProcedure(WSEV_KEY_PRESS);
  }
}
char* WSClist::getSeparator(){
  return _separator;
}
void WSClist::_adjust_no_scroll(){
  long num = _lb_list.getNum();
  if (num <1){
    setPropertyV(WSNworkHeight,(WSCushort)_scr_area_h);
    if (getVisible() != False){
      _redraw_scr();
    }
    return;
  }

  long i;
  long cnt=0;
  for(i=0; i<num; i++){
    WSCbase* item = (WSCbase*)_lb_list[i];
    WSCbool fl = item->getVisible();
    if (fl != False){
      if (_lb_height * cnt > _wy_pos + _v_scr_slider_sz ){
        short val;
        item->getPropertyV(WSNy,&val);
        if (val != (short)( -_lb_height *2)){
          item->setPropertyV(WSNy, (short)( -_lb_height *2));
          item->WSCbase::update();
        }
      }else if (_lb_height * cnt + _lb_height > _wy_pos ){
        item->setPropertyV(WSNy, (short)( cnt * _lb_height - _wy_pos));
//        item->WSCbase::update(); 
      }else{
        short val;
        item->getPropertyV(WSNy,&val);
        if (val != (short)( -_lb_height *2)){
          item->setPropertyV(WSNy, (short)( -_lb_height *2));
          item->WSCbase::update();
        }
      }
      cnt++;
    }
  }
#if 0
  if (_wy_pos > _wy_pos_bak){
    if (_wy_pos < _wy_pos_bak + _v_scr_slider_sz){
      WSDdev* dev = _scr_area->getowndev();
      if (dev != NULL){
        dev->copyArea( 0,_wy_pos - _wy_pos_bak,
                    _work_height,_v_scr_slider_sz - _wy_pos + _wy_pos_bak,
                    0,0);
        dev->exposeArea(0,  _v_scr_slider_sz - _wy_pos + _wy_pos_bak,
                        _work_height, _wy_pos - _wy_pos_bak);
      }
    }else{
      _redraw_scr();
    }
  }else
  if (_wy_pos < _wy_pos_bak){
    if (_wy_pos_bak < _wy_pos + _v_scr_slider_sz){
      WSDdev* dev = _scr_area->getowndev();
      if (dev != NULL){
        dev->copyArea( 0,0,
                    _work_height,_wy_pos_bak - _wy_pos,
                    0,_v_scr_slider_sz - _wy_pos_bak + _wy_pos);
        dev->exposeArea(0,0,_work_height,_wy_pos_bak - _wy_pos);
      }
    }else{
      _redraw_scr();
    }
  }
  _wy_pos_bak = _wy_pos;
#endif
}
void WSClist::onValueChange(){
  WSCscrForm::onValueChange();
  if (_v_scr_x_bk != _wx_pos){
    if (_btn_area != NULL){
      _btn_area->setProperty(WSNx,(long)_shadow_thick-(_wx_pos));
      _btn_area->setProperty(WSNwidth,_h_scr_slider_sz + _wx_pos);
    }
  }
}

long WSClist::getSelectedNextPos(long pos){
  long i;
  long num = _lb_list.getNum();
  for(i=pos+1; i< num; i++){
    WSCbase* lb = (WSCbase*)_lb_list[i];
    long status = (long)lb->getUserData(SELECT_STATUS);
    if (status != 0){
      return i;
    }
  }
  return -1;
}
WSCbool WSClist::setSelected(long pos,WSCbool fl){
  long i;
  long num = _lb_list.getNum();
  if (pos < 0){
    pos = num-1;
  }
  if (pos <num){
    WSCbase* lb = (WSCbase*)_lb_list[pos];
    long ret = (long)lb->getUserData(SELECT_STATUS);
    if (fl == False){
      lb->setUserData(SELECT_STATUS,(void*)0);
      lb->setPropertyV(WSNselectColor,(short)0);
      lb->setPropertyV(WSNselectForeColor,(short)0);
      if ((long)lb->getUserData(SELECT_STATUS) == 0){
        lb->setUserData(SELECT_STATUS,(void*)0);
        _select_item_changed = 1;
        if (_activate){
          onActivate();
        }
        onItemSelected();
        needUpdate();
        _need_update = 1;
      }
    }else{
      WSCbool sl = getSelected(pos);
      if (sl == False){
        setSelectPos(pos);
      }
    }
    return (WSCbool)ret;
  }
  return False;
}
WSCbool WSClist::getSelected(long pos){
  long i;
  long num = _lb_list.getNum();
  if (pos < 0){
    pos = num-1;
  }
  if (pos <num){
    WSCbase* lb = (WSCbase*)_lb_list[pos];
    long ret = (long)lb->getUserData(SELECT_STATUS);
    return (WSCbool)ret;
  }
  return False;
}
WSCstring WSClist::getSelectedNextItem(long pos){
  long next_pos = getSelectedNextPos(pos);
  if (next_pos != -1){
    return getItem(next_pos);
  }
  WSCstring ret;
  return ret;
}
char* WSClist::getDefaultProperty(){
  return WSNdata;
}



