//
// 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 <WSCvbtn.h>
#include <WSCclassInformation.h>
#include <WSCdevice.h>
#include <WSDdev.h>
#include <WSCimageSet.h>
#include <WSDkeyboard.h>
#include <WSkeysym.h>
#include <WSDfont.h>
#include <WSCfontSet.h>
#include <WSCbaseList.h>
#include <WSCblink.h>
#include <WSDappDev.h>
#include <WSDmwindowDev.h>

WSMFguiClassInitialize(WSCvbtn, WSCvlabel);
WSMFversion(WSCvbtn, WSCvlabel);

WSMFpropertyValueChange(WSCvbtn,WSNemboss,WSCbool,True);


WSCvbtn::WSCvbtn(WSCbase* base, char* objname):
			WSCvlabel(base, objname) {

  _register_focus_move();

  _push_pixmap = -1;
  _ef_move = True;
  _td_name = WSGFstrdup("");
  _bd_name = WSGFstrdup("");
  _ld_name = WSGFstrdup("");
  _rd_name = WSGFstrdup("");
  _tb_name = WSGFstrdup("");
  _btb_name = WSGFstrdup("");
  _emboss = True;
  _focus_border = True;
  _mask_images = NULL;
  _ext_draw_proc = NULL;
  _no_background = False;
  WSGIappObjectList()->addEvent(this,WSEV_GUI_POLICY_CH);

  WSMFpropertyCreateStart
    WSMFparentCheckVerSrc(WSCvbtn);

    WSMFpropertyCreate(WSNpushPixmap,      short,   _push_pixmap,WSSpushPixmap);
    WSMFpropertyCreate(WSNenableFocusMove, WSCbool, _ef_move,WSSenableFocusMove);
    WSMFpropertySetSelection(WSRbool4, WSRbool4D);
    WSMFpropertyCreate(WSNupward,    char*,   _td_name,WSSupward);
    WSMFpropertyCreate(WSNdownward, char*,   _bd_name,WSSdownward);
    WSMFpropertyCreate(WSNleftward,   char*,   _ld_name,WSSleftward);
    WSMFpropertyCreate(WSNrightward,  char*,   _rd_name,WSSrightward);
    WSMFpropertyCreate(WSNtab,  char*,   _tb_name,WSStab);
    WSMFpropertyCreate(WSNbacktab,  char*,   _btb_name,WSSbacktab);
//    WSMFpropertyCreate(WSNreturn,  char*,  _rt_name,WSSreturn);
    WSMFpropertyValueChangeDef(WSCvbtn,WSNemboss,WSCbool);

    WSMFpropertyDelete(WSNshadowType);

    WSMFaddTrigger(WSEV_ACTIVATE   );
    WSMFaddTrigger(WSEV_KEY_PRESS  );
    WSMFaddTrigger(WSEV_KEY_RELEASE);
    WSMFaddTrigger(WSEV_FOCUS_CH   );

  WSMFpropertyCreateEnd

  _press_state = False;

}

WSMFproperty(WSCvbtn, WSNpushPixmap,      short,   _push_pixmap, -1);
WSMFproperty(WSCvbtn, WSNenableFocusMove, WSCbool, _ef_move, True);
WSMFproperty(WSCvbtn, WSNupward,    char*,   _td_name, WSGFstrdup(""));
WSMFproperty(WSCvbtn, WSNdownward, char*,   _bd_name, WSGFstrdup(""));
WSMFproperty(WSCvbtn, WSNleftward,   char*,   _ld_name, WSGFstrdup(""));
WSMFproperty(WSCvbtn, WSNrightward,  char*,   _rd_name, WSGFstrdup(""));
WSMFproperty(WSCvbtn, WSNtab,  char*,   _tb_name, WSGFstrdup(""));
WSMFproperty(WSCvbtn, WSNbacktab,  char*,   _btb_name, WSGFstrdup(""));
//WSMFproperty(WSCvbtn, WSNreturn, char*,   _rt_name, WSGFstrdup(""));

void WSCvbtn::setWorkWSNpushPixmap(short) {}
void WSCvbtn::getWorkWSNpushPixmap(short*) {}
void WSCvbtn::setWorkWSNenableFocusMove(WSCbool) {}
void WSCvbtn::getWorkWSNenableFocusMove(WSCbool*) {}
void WSCvbtn::setWorkWSNupward(char*) {}
void WSCvbtn::getWorkWSNupward(char**) {}
void WSCvbtn::setWorkWSNdownward(char*) {}
void WSCvbtn::getWorkWSNdownward(char**) {}
void WSCvbtn::setWorkWSNleftward(char*) {}
void WSCvbtn::getWorkWSNleftward(char**) {}
void WSCvbtn::setWorkWSNrightward(char*) {}
void WSCvbtn::getWorkWSNrightward(char**) {}
void WSCvbtn::setWorkWSNtab(char*) {}
void WSCvbtn::getWorkWSNtab(char**) {}
void WSCvbtn::setWorkWSNbacktab(char*) {}
void WSCvbtn::getWorkWSNbacktab(char**) {}

WSCvbtn::~WSCvbtn() {
  WSGIappObjectList()->delEvent(this,WSEV_GUI_POLICY_CH);

  if (getFocus() != False){
    WSGIappKeyboard()->resetFocusInputWorkProc();
  }
  if (_td_name != NULL){
    delete _td_name;
    _td_name = NULL;
  }
  if (_bd_name != NULL){
    delete _bd_name;
    _bd_name = NULL;
  }
  if (_ld_name != NULL){
    delete _ld_name;
    _ld_name = NULL;
  }
  if (_rd_name != NULL){
    delete _rd_name;
    _rd_name = NULL;
  }
  if (_tb_name != NULL){
    delete _tb_name;
    _tb_name = NULL;
  }
  if (_btb_name != NULL){
    delete _btb_name;
    _btb_name = NULL;
  }
  if (_mask_images != NULL){
    if (_mask_images[0] != NULL){
      delete _mask_images[0];
    }
    if (_mask_images[1] != NULL){
      delete _mask_images[1];
    }
    if (_mask_images[2] != NULL){
      delete _mask_images[2];
    }
    if (_mask_images[3] != NULL){
      delete _mask_images[3];
    }
    delete _mask_images;
  }
}
WSCbool WSCvbtn::_special_key_handler(void* ptr, WSDkeyboard* keyboard, WSCbool fl) {
  WSCvbtn* obj = (WSCvbtn*)ptr;
  WSCulong key = keyboard->getKey(); 

  if (obj->getVisible() == False || obj->getSensitive() == False) {
    return True;
  }
  if (fl == True && key == WSK_Return) {
    if (obj->_press_state == False) {
      obj->_press_state = True;
      obj->setAbsoluteDraw(True);
      obj->redraw();
    }
    return False;
  } else
  if (fl == False && key == WSK_Return) {
    if (obj->_press_state == True) {
      obj->_press_state = False;
      obj->setAbsoluteDraw(True);
      obj->redraw();
      if (obj->getSensitive() == True) {
        obj->onActivate();
      }
    }
    return False;
  }
  return True;
}

void WSCvbtn::_key_handler(void* ptr, WSDkeyboard* keyboard, WSCbool fl) {
  WSCvbtn* obj = (WSCvbtn*)ptr;
  WSCulong key = keyboard->getKey(); 

  if (obj->getVisible() == False || obj->getSensitive() == False) {
    return;
  }

  if (fl == True && key == WSK_Return) {
    if (obj->_press_state == False) {
      obj->_press_state = True;
      obj->setAbsoluteDraw(True);
      obj->redraw();
    }
  } else
  if (fl == False && key == WSK_Return) {
    if (obj->_press_state == True) {
      obj->_press_state = False;
      obj->setAbsoluteDraw(True);
      obj->redraw();
      if (obj->getSensitive() == True) {
//        obj->execEventProc(WSEV_ACTIVATE, NULL);
        obj->onActivate();
      }
    }

#if 0
    WSCbool fm;
    obj->getPropertyV(WSNenableFocusMove, &fm);
    if (fm == True){
       WSCbase* target;
       char* dest;
       WSCbool fl = obj->getPropertyV(WSNreturn,&dest);
       if ( fl != False && dest != 0 && dest[0] != 0){
          target = WSGIappObjectList()->getInstance("WSCbase",dest);
          if (target != NULL){
            target->setFocus();
            target->draw();
          }
       }
    }
#endif
  } else
  if (fl == True && key == WSK_Left) {
    WSCbool fm;
    obj->getPropertyV(WSNenableFocusMove, &fm);
    if (fm == True) {
      WSCbase*	target = obj->getFocusMoveInstance(WS_LEFT);
      if (target != NULL) {
        target->setFocus();
        target->redraw();
      }
    }
  } else
  if (fl == True && (key == WSK_Tab && keyboard->withShift() == False)) {
    WSCbool fm;
    obj->getPropertyV(WSNenableFocusMove, &fm);
    if (fm == True) {
      WSCbase*	target = obj->getFocusMoveInstance(WS_TAB);
      if (target != NULL) {
        target->setFocus();
        target->redraw();
      }
    }
  } else
  if (fl == True && (key == WSK_Tab && keyboard->withShift())) {
    WSCbool fm;
    obj->getPropertyV(WSNenableFocusMove, &fm);
    if (fm == True) {
      WSCbase*	target = obj->getFocusMoveInstance(WS_STAB);
      if (target != NULL) {
        target->setFocus();
        target->redraw();
      }
    }
  } else

  if (fl == True && key == WSK_Right ) {
    WSCbool fm;
    obj->getPropertyV(WSNenableFocusMove, &fm);
    if (fm == True) {
      WSCbase*	target = obj->getFocusMoveInstance(WS_RIGHT);
      if (target != NULL) {
        target->setFocus();
        target->redraw();
      }
    }
  } else
  if (fl == True && key == WSK_Up) {
    WSCbool fm;
    obj->getPropertyV(WSNenableFocusMove, &fm);
    if (fm == True) {
      WSCbase* target = obj->getFocusMoveInstance(WS_UP);
      if (target != NULL) {
        target->setFocus();
        target->redraw();
      }
    }
  } else
  if (fl == True && key == WSK_Down) {
    WSCbool fm;
    obj->getPropertyV(WSNenableFocusMove, &fm);
    if (fm == True) {
      WSCbase* target = obj->getFocusMoveInstance(WS_DOWN);
      if (target != NULL) {
        target->setFocus();
        target->redraw();
      }
    }
  }

  if (fl == True) {
    obj->execEventProc(WSEV_KEY_PRESS, keyboard);
  } else {
    obj->execEventProc(WSEV_KEY_RELEASE, keyboard);
  }
}

void WSCvbtn::onKey(WSDkeyboard* ,WSCbool) {}
//void WSCvbtn::onKeyRelease(WSDkeyboard*) {}
#if 0
long WSCvbtn::execEventProc(long ev, void* data) {

  if (ev == WSEV_KEY_PRESS) {
//    onKeyPress((WSDkeyboard*)data);
    onKey((WSDkeyboard*)data,True);
  }else
  if (ev == WSEV_KEY_RELEASE) {
//    onKeyRelease((WSDkeyboard*)data);
    onKey((WSDkeyboard*)data,False);
//  }else
//  if (ev == WSEV_ACTIVATE) {
//    onActivate();
  }

  return WSCvlabel::execEventProc(ev, data);
}
#endif
long WSCvbtn::_device_initialize() {
  WSDdev* dev = getowndev();
  if (dev == NULL) {
    return WS_ERR;
  }
  _event_mask |= (WSEV_MOUSE_MOVE_BIT | WSEV_MOUSE_OUT_BIT |
            WSEV_MOUSE_PRESS_BIT | WSEV_MOUSE_RELEASE_BIT);

  WSCvlabel::_device_initialize();

  return WS_NO_ERR;
}

void WSCvbtn::onFocusChange(WSCbool fl){
//WSMFtrace("WSCvbtn::onFocusChange(%d)\n",fl);
  if (getSensitive() == False && fl != False){
    return;
  }
  if (fl != False){
    WSGIappKeyboard()->setFocusInputWorkProc(_key_handler, NULL, this);
    if (getowndev() != NULL) {
      WSGIappKeyboard()->resetFep(getowndev());
    }
    setSpecialFocus(True);
  }else{
    WSGIappKeyboard()->resetFocusInputWorkProc();
  }
  execEventProc(WSEV_FOCUS_CH, NULL);
  setAbsoluteDraw(True);
  draw();
}
void WSCvbtn::onSpecialFocusChange(WSCbool fl){
//WSMFtrace("WSCvbtn::onFocusChange(%d)\n",fl);
  if (getSensitive() == False && fl != False){
    return;
  }
  if (fl != False){
    WSGIappKeyboard()->setSpecialInputWorkProc(_special_key_handler, this);
    if (getowndev() != NULL) {
      WSGIappKeyboard()->resetFep(getowndev());
    }
  }else{
    WSGIappKeyboard()->resetSpecialInputWorkProc();
  }
//  execEventProc(WSEV_FOCUS_CH, NULL);
  setAbsoluteDraw(True);
  draw();
  WSCvlabel::onSpecialFocusChange(fl);
}

long WSCvbtn::draw(){
  if (getVisible() == False) {
    return WS_NO_ERR;
  }

  WSDdev* dev = getowndev();
  if (dev == NULL) {
    return WS_ERR;
  }

  if (WSGIappDev()->getExtGuiPolicySelected() != False){
    if (_ext_draw_proc == NULL){
      _ext_draw_proc = (void(*)(void*))WSGIappDev()->
                               getExtGuiPolicyProc("WSCvbtn::draw");
    }
    if (_ext_draw_proc != NULL){
      WSCvbtn_draw_struct st;
      st._this = this;
      st.dev = dev;
      st.x = _x;
      st.y = _y;
      st.width = _w;
      st.height = _h;
      st.shadow_thickness = _shadow_thick;
      st.blinking = _bl_fl;
      st.blink_fore = WSGIappBlink()->getBlinkFore(_blink_rate);
      st.shadow_type = _shadow_type;
      st.blink_type  = _bl_type;
      st.twin_blink   = _tw_fl;
      st.fore_color   = _fore_color;
      st.back_color   = _back_color;
      st.blink_color  = _blink_color;
      st.back_blink_color = _bg_blink_color;
      st.top_shadow_color = _ts_color;
      st.bottom_shadow_color = _bs_color;
      st.label_string = _label_string;
      st.label_pixmap = _label_pixmap;
      st.blink_pixmap = _blink_pixmap;
      st.push_pixmap = _push_pixmap;
      st.press_state = _press_state;
      st.orientation = _orientation;
      st.gradation = _grad_no;
      st.gradation_margin = _grad_margin;
      st.margin_left = _margin_left;
      st.margin_right = _margin_right;
      st.margin_top = _margin_top;
      st.margin_bottom = _margin_bottom;
      st.focus_border = _focus_border;
      st.emboss = _emboss;
      st.font = _font;
      st.reverse_flag = _rv_fl;
      st.enable_focus_move = _ef_move;
      st.no_background = _no_background;
      _ext_draw_proc(&st);
      return WS_NO_ERR;
    }
  }

  short x = _x;
  short y = _y;
  WSCushort w = _w;
  WSCushort h = _h;
  long policy = WSGIappDev()->getGuiPolicy();


  WSCbool absolute = getAbsoluteDraw();
  if (absolute == False && dev->isExposed(x, y, w, h) == False) {
    return WS_NO_ERR;
  }
  WSCushort st       = _shadow_thick;
  long blinking      = _bl_fl;
  long blinkfore     = WSGIappBlink()->getBlinkFore(_blink_rate);
  long shadowtype    = _shadow_type;
  long blinktype     = _bl_type;
  long twinblink     = _tw_fl;
  short fgno         = _fore_color;
  short bgno         = _back_color;
  short blinkcolorno = _blink_color;
  short backblinkno  = _bg_blink_color;
  short tsno         = _ts_color;
  short bsno         = _bs_color;

  if (policy & WS_POLICY_AQUA){
//    WSDimage* image = WSGIappImageSet()->getImage(WS_AQUA_BTN_IMAGE);
//    WSDimage* mask = WSGIappImageSet()->getImage(WS_AQUA_BTN_MASK_IMAGE);
//    WSCushort pw = image->getImageWidth();
//    WSCushort ph = image->getImageHeight();
    if (_mask_images != NULL){
      WSCulong val = (WSCulong)((WSCulong)w << 16 + h);
      WSCulong val2 = (WSCulong)_mask_images[4];
      if (val != val2){
//printf("WSCvbtn::draw size changed...%d %d \n",val,val2);
        delete _mask_images[0];
        delete _mask_images[1];
        delete _mask_images[2];
        delete _mask_images[3];
        delete _mask_images;
        _mask_images = NULL;
      }
    }
    if (_mask_images == NULL){
//printf("WSCvbtn::draw images allocated...\n");
      _mask_images = new WSDmwindowDev*[5];
      _mask_images[0] = WSGFgetAquaImage(tsno,w,h,1);
      _mask_images[1] = WSGFgetAquaImage(WS_DF_AQUAFORECOLOR,w,h,1);
      _mask_images[2] = WSGFgetAquaImage(WS_DF_AQUAHIGHLIGHTCOLOR,w,h,1);
      _mask_images[3] = WSGFgetAquaMaskImage(w,h,1);
      _mask_images[4] = (WSDmwindowDev*)((WSCulong)((WSCulong)w << 16 + h));
    }
  }


  if ( shadowtype == WS_SHADOW_NONE &&
        blinking  != False &&
        blinkfore != False &&
        twinblink == False){
    return WS_NO_ERR;
  }

  WSCstring str;
  str.setString(_label_string);
  if (_orientation == WS_VERTICAL) {
    WSGFcreateVerticalString(&str);
  } else {
    str.replaceString("\\n", "\n", 0);
  }

  long err = dev->beginDraw(x, y, w, h, absolute);
  if (err != WS_NO_ERR){
    return WS_NO_ERR;
  }

  WSCbase::update();
  setAbsoluteDraw(False);

  if (_rv_fl == True){
    if (blinking  != False &&
        blinkfore != False &&
        blinktype != WS_FORE ){
      dev->setForeColor(blinkcolorno);
    }else{
      dev->setForeColor(fgno);
    }
  }else{
    if (blinking  != False &&
        blinkfore != False &&
        blinktype != WS_FORE ){
      dev->setForeColor(backblinkno);
    }else{
      dev->setForeColor(bgno);
    }
  }
  if (_grad_no == 0){
    if (!(policy & WS_POLICY_AQUA) || _label_pixmap != -1||
     _push_pixmap != -1 || _blink_pixmap != -1){
      dev->drawFillRect(0, 0, w, h);
    }else{
      if (_press_state != False) {
        _mask_images[2]->copyToWindowWithMask(dev,0,0,w,h,1,1,_mask_images[3]);
      }else if (_mouse_in != False){
        _mask_images[2]->copyToWindowWithMask(dev,0,0,w,h,0,0,_mask_images[3]);
      }else if (getFocus() != False){
        _mask_images[1]->copyToWindowWithMask(dev,0,0,w,h,0,0,_mask_images[3]);
      }else{
        _mask_images[0]->copyToWindowWithMask(dev,0,0,w,h,0,0,_mask_images[3]);
      }
    }
  }else{
    if (_press_state == True) {
      dev->drawGradation(_grad_no,tsno,bgno,bsno,0, 1, w, h,_grad_margin);
    }else{
      dev->drawGradation(_grad_no,tsno,bgno,bsno,0, 0, w, h,_grad_margin);
    }
  }

  short          xx = st + _margin_left;
  short          yy = st + _margin_top;
  WSCushort ww = w - st*2;
  WSCushort hh = h - st*2;
  WSCushort h_m = _margin_left + _margin_right;
  WSCushort v_m = _margin_top + _margin_bottom;

  if (ww < h_m){
    ww = 1;
  }else{
    ww = ww - h_m;
  }
  if (hh < v_m){
    hh = 1;
  }else{
    hh = hh - v_m;
  }

  WSDimage* image = NULL;
  if (!(policy & WS_POLICY_AQUA) || _label_pixmap != -1||
     _push_pixmap != -1 || _blink_pixmap != -1){
    if (blinking  != False &&
        blinktype != WS_BACK &&
        blinkfore != False ){
      if (_blink_pixmap != -1 && twinblink != False){
        image = WSGIappImageSet()->getImage(_blink_pixmap);
        short dy = yy;
        if (_press_state == True){
          dy++;
        }
        dev->drawImage (xx, dy, ww, hh, image, getAlignment());
      }
    }else{
      short dy=yy;
      WSCbool drawfl = False;
      if (_press_state != False) {
        dy++;
        if (_push_pixmap != -1) {
          image = WSGIappImageSet()->getImage(_push_pixmap);
          drawfl = True;
        } else if (_label_pixmap != -1){
          image = WSGIappImageSet()->getImage(_label_pixmap);
          drawfl = True;
        }
      }else{
        if (_label_pixmap != -1){
          image = WSGIappImageSet()->getImage(_label_pixmap);
          drawfl = True;
        }
      }
      if (drawfl != False){
        dev->drawImage (xx, dy, ww, hh, image, getAlignment());
      }
    }
  }
  WSCbool specialfocus= getSpecialFocus(); 
  if ((!(policy & WS_POLICY_AQUA) || _label_pixmap != -1||
     _push_pixmap != -1 || _blink_pixmap != -1) && st > 0){
    char	type = WS_SHADOW_OUT;
    if (getSensitive() == False ||
        (getPropertyEditMode() != False && getUserData(WS_DET) == 0)) {
      type = WS_SHADOW_OUT;
    }else if (_press_state == True) {
      type = WS_SHADOW_IN;
    }
    if (specialfocus == False){
      WSGFdrawBtnShadow(dev, type, st, tsno, tsno, bsno, bgno,0, 0, w, h);
    }else if (WSGIappDev()->getGuiPolicy() & WS_POLICY_ORIGINAL){
      WSGFdrawBtnShadow(dev, type, st, tsno, tsno, bsno, bgno,0, 0, w, h);
    }else if (_focus_border == False) {
      WSGFdrawBtnShadow(dev, type, st, tsno, tsno, bsno, bgno,0, 0, w, h);
    }else{
      WSGFdrawBtnShadow(dev, type, st, tsno, tsno, bsno, bgno,1, 1, w-2, h-2);
    }
    if (specialfocus != False && _focus_border != False ){
      dev->setForeColor(WS_DF_DARKBOTTOMSHADOWCOLOR);
      dev->setLineDashType(0);
      dev->setLineWidth(1);
      dev->drawRect(0,0,w,h);
    }    
  }

  if (getSensitive() == False ||
      (getPropertyEditMode() != False && (long)getUserData(WS_DET) == 0)){
    if (_emboss != False){

      if (blinking  != False &&
          blinkfore != False &&
          blinktype != WS_BACK &&
          twinblink == False){
        // do nothing...
      }else{
        if (twinblink == False || blinking == False){
          if (blinking  != False &&
              blinkfore != False &&
              blinktype != WS_BACK &&
              twinblink != False) {
            dev->setForeColor(blinkcolorno);
          } else {
            dev->setForeColor(tsno);
          }
          dev->drawString(xx+1, yy+1, ww, hh, &str, _font, getAlignment(), -1, False);
        }
      }
    }else{
      dev->setHatchPattern(8);
    }
  }
#if 0
  if (specialfocus != False && _focus_border != False && 
      (WSGIappDev()->getGuiPolicy() & WS_POLICY_ORIGINAL)){
    if (_press_state == True) {
      dev->setLineWidth(1);
      dev->setLineDashType(0);
      dev->setForeColor(bsno);
      dev->drawLine(st + 4, 1 + h -st -5, w - st*2 -4, 1 + h -st -5);
      dev->setForeColor(tsno);
      dev->drawLine(st + 4, 2 + h -st -5, w - st*2 -4, 2 + h -st -5);
    }else{
      dev->setLineWidth(1);
      dev->setLineDashType(0);
      dev->setForeColor(bsno);
      dev->drawLine(st + 4, 0 + h -st -5, w - st*2 -4, 0 + h -st -5);
      dev->setForeColor(tsno);
      dev->drawLine(st + 4, 1 + h -st -5, w - st*2 -4, 1 + h -st -5);
    }
  }
#endif
  if (_rv_fl == True) {
    if (blinking  != False &&
        blinkfore != False &&
        blinktype != WS_BACK &&
        twinblink != False) {
      dev->setForeColor(backblinkno);
    } else {
      if( _emboss != False && (getSensitive() == False ||
          (getPropertyEditMode() != False && (long)getUserData(WS_DET) == 0))){
        dev->setForeColor(bsno);
      }else{
        dev->setForeColor(bgno);
      }
    }
  }else{
    if (blinking  != False &&
        blinkfore != False &&
        blinktype != WS_BACK &&
        twinblink != False) {
      dev->setForeColor(blinkcolorno);
    }else{
      if ( _emboss != False && (getSensitive() == False ||
        (getPropertyEditMode() != False && (long)getUserData(WS_DET) == 0))){
        dev->setForeColor(bsno);
      }else{
        dev->setForeColor(fgno);
      }
    }
  }

  if (blinking  != False &&
      blinkfore != False &&
      blinktype != WS_BACK &&
      twinblink == False ){
      //do nothing...
  }else{
    if (_press_state == True) {
      dev->drawString(xx, yy+1, ww, hh, &str,  _font, getAlignment(), -1, False);
    }else{
      dev->drawString(xx, yy, ww, hh, &str, _font, getAlignment(), -1, False);

    }
    if (!(policy & WS_POLICY_AQUA)){
      // draw dashed focused line...
      if (getFocus() != False && _ef_move != False) {
        if (w > 4 + st*2 && h > 4 + st*2) {
          // 描画する線幅は０に固定
          dev->setLineWidth(0);
          // 描画する線種は点線に固定
          dev->setLineDashType(8);
          if (_press_state == True) {
            //1 dot below
            dev->drawRect(st + 2, st + 3, w - st * 2 - 4, h - st * 2 - 4);
          } else {
            dev->drawRect(st + 2, st + 2, w - st * 2 - 4, h - st * 2 - 4);
          }
        }
      }
    }
  }

  dev->endDraw();
  return WS_NO_ERR;
}

void WSCvbtn::onActivate() {
  execProcedure(WSEV_ACTIVATE);
}

void WSCvbtn::onVisibleChange(WSCbool fl) {
  if (fl == False){
    _press_state = False;
  }
  WSCvlabel::onVisibleChange(fl);
}

void WSCvbtn::onParentVisibleChange(WSCbool fl) {
  if (fl == False){
    _press_state = False;
  }
  WSCvlabel::onParentVisibleChange(fl);
}

void WSCvbtn::onMousePress(WSCpoint* point){
//printf("WSCvbtn::onMousePress %s\n",getInstanceName());
  if (getSensitive() == False) {
    WSCbase::onMousePress(point);
    return;
  }
  setFocus(True);
  setSpecialFocus(True);
  if (_press_state == False) {
    _press_state = True;
    setAbsoluteDraw(True);
    redraw();
  }
  WSCvlabel::onMousePress(point);
}

void WSCvbtn::onMouseRelease(WSCpoint* point){
  if (getSensitive() == False) {
    return;
  }
  WSCvlabel::onMouseRelease(point);

  if (_press_state == True) {
    _press_state = False;
    setAbsoluteDraw(True);
    redraw();
    if (getSensitive() == True) {
//      execEventProc(WSEV_ACTIVATE, NULL);
      onActivate();
//      execProcedure(WSEV_ACTIVATE);
    }
  }
}

void WSCvbtn::onMouseIn(WSCpoint* pt){
  _mouse_in = True;
  if (WSGIappDev()->getGuiPolicy() & WS_POLICY_AQUA){
    setAbsoluteDraw(True);
    redraw();
  }
  WSCvlabel::onMouseIn(pt);
}
void WSCvbtn::onMouseOut(){
  _mouse_in = False;
  if (_press_state == True){
    _press_state = False;
    setAbsoluteDraw(True);
    redraw();
  }else if (WSGIappDev()->getGuiPolicy() & WS_POLICY_AQUA){
    setAbsoluteDraw(True);
    redraw();
  }
  WSCvlabel::onMouseOut();
}

long WSCvbtn::addProcedure(WSCprocedure* ac) {
  if (existTrigger(ac->getTrigger()) == False && ac->getInternal() == False) {
WSMFtrace("WSCvbtn::addProcedure trigger=%d not supported.\n", ac->getTrigger());
    return WS_ERR;
  }

  if (ac->getTrigger() == WSEV_ACTIVATE) {
    ac->setEffectiveTriggerMask( WSEV_MOUSE_MOVE_BIT | WSEV_MOUSE_PRESS_BIT |
                                 WSEV_MOUSE_RELEASE_BIT | WSEV_MOUSE_OUT_BIT );

    _event_mask |= ac->getEffectiveTriggerMask();
    _add_prcs(&_prc_list, ac);

    WSDdev* dev = _dev;
    if (dev != NULL){
      dev->setEnableEventBit( _event_mask );
    }
    return WS_NO_ERR;
  }

  WSCnwbase::addProcedure(ac);

  return WS_NO_ERR;
}
void WSCvbtn::setDrawFocusBorder(WSCbool fl){
  if (fl == False){
    _focus_border = False;
  }else{
    _focus_border = True;
  }
}

void WSCvbtn::setNoBackground(WSCbool fl){
  _no_background = fl;
}
void(*WSCvbtn::_ext_draw_proc)(void*) = NULL;
WSCstring WSCvbtn::_policy_name;

void WSCvbtn::onGuiPolicyChange(long policy){
  WSCvlabel::onGuiPolicyChange(policy);
  if (WSGIappDev()->getExtGuiPolicySelected() == False){
    _ext_draw_proc = NULL;
  }else{
    if (!strcmp((char*)_policy_name,(char*)WSGIappDev()->getExtGuiPolicyName())){
    }else{
      _ext_draw_proc = (void(*)(void*))WSGIappDev()->getExtGuiPolicyProc("WSCvbtn::draw");
    }
  }
  if (getVisible() != False){
    needUpdate();
    setAbsoluteDraw(True);
    redraw();
  }
}
