//
// 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 <WSCpulldownMenu.h>
#include <WSCclassInformation.h>
#include <WSCdevice.h>
#include <WSDdev.h>
#include <WSCimageSet.h>
#include <WSCpulldownMenuPopup.h>
#include <WSDmouse.h>
#include <WSCfontSet.h>
#include <WSCcolorSet.h>
#include <WSDfont.h>
#include <WSDappDev.h>
#include <string.h>
#include <WSCblink.h>
#include <WSCbaseList.h>
#include <ctype.h>

WSMFguiClassInitialize(WSCpulldownMenu, WSCvlabel);
WSMFversion(WSCpulldownMenu, WSCvlabel);

WSMFpropertyValueChange(WSCpulldownMenu,WSNforeColor,short,WS_DF_MENUFORECOLOR);
WSMFpropertyValueChange(WSCpulldownMenu,WSNbackColor,short,WS_DF_MENUBACKCOLOR);
WSMFpropertyValueChange(WSCpulldownMenu,WSNtopShadowColor,short,WS_DF_MENUTOPSHADOWCOLOR);
WSMFpropertyValueChange(WSCpulldownMenu,WSNbottomShadowColor,short,WS_DF_MENUBOTTOMSHADOWCOLOR);


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

  _register_focus_move();

  _menu  = NULL;
  _press_state = False;
  _mouse_x = -1;
  _mouse_y = -1;
  _grabed = 0;
  _sc_str = WSGFstrdup(""); 
  _menu_str = WSGFstrdup("item1(key1):ep1_name:key1:1,item2(key2):ep2_name:key2:2,SP,item3(key3):ep3_name:key3:3"); 
  _out_side_mouse_move = True;
//  _out_side_mouse_release = True;
  _shadow_type = WS_SHADOW_OUT;

  _fore_color = WS_DF_MENUFORECOLOR;
  _back_color = WS_DF_MENUBACKCOLOR;
  _ts_color = WS_DF_MENUTOPSHADOWCOLOR;
  _bs_color = WS_DF_MENUBOTTOMSHADOWCOLOR;
  _mouse_no_check = 0;
  _ld_name = WSGFstrdup("");
  _rd_name = WSGFstrdup("");

  WSGIappDev()->addMenu(this);
  WSGIappObjectList()->addEvent(this,WSEV_GUI_POLICY_CH);

  WSMFpropertyCreateStart
    WSMFparentCheckVerSrc(WSCpulldownMenu);

    WSMFpropertyCreate(WSNmenuItems, char*, _menu_str,WSSmenuItems);
    WSMFpropertyCreate(WSNshortcut, char*, _sc_str,WSSshortcut);
    WSMFpropertyCreate(WSNleftward,   char*,   _ld_name,WSSleftward);
    WSMFpropertyCreate(WSNrightward,  char*,   _rd_name,WSSrightward);

    WSMFpropertyDelete(WSNorientation);
    WSMFpropertyDelete(WSNalignmentV);
    WSMFpropertyDelete(WSNlabelPixmap);
    WSMFpropertyDelete(WSNblinkPixmap);
    WSMFpropertyDelete(WSNshadowType);
    WSMFpropertyDelete(WSNmaxLength);

    WSMFpropertyValueChangeDef(WSCpulldownMenu,WSNforeColor,short);
    WSMFpropertyValueChangeDef(WSCpulldownMenu,WSNbackColor,short);
    WSMFpropertyValueChangeDef(WSCpulldownMenu,WSNtopShadowColor,short);
    WSMFpropertyValueChangeDef(WSCpulldownMenu,WSNbottomShadowColor,short);

    WSMFaddTrigger(WSEV_ACTIVATE  );

    WSMFdelTrigger(WSEV_MOUSE_MOVE  );
    WSMFdelTrigger(WSEV_MOUSE_PRESS   );
    WSMFdelTrigger(WSEV_MOUSE_RELEASE );

  WSMFpropertyCreateEnd
}

WSMFproperty( WSCpulldownMenu, WSNshortcut, char*, _sc_str, WSGFstrdup("")); 
WSMFproperty( WSCpulldownMenu, WSNmenuItems, char*, _menu_str, WSGFstrdup("item1(key1):ep1_name:key1,item2(key2):ep2_name:key2,SP,item3(key3):ep3_name:key3")); 
WSMFproperty(WSCpulldownMenu, WSNleftward,   char*,   _ld_name, WSGFstrdup(""));
WSMFproperty(WSCpulldownMenu, WSNrightward,  char*,   _rd_name, WSGFstrdup(""));

void WSCpulldownMenu::setWorkWSNshadowThickness(WSCuchar data){
  if (data == 0){
    setPropertyV(WSNshadowThickness,(WSCuchar)1);
  }
}
void WSCpulldownMenu::setWorkWSNmenuItems(char* data){
  if (_menu != NULL){
    _menu->setPropertyV(WSNmenuItems, data);
  }
}

void WSCpulldownMenu::getWorkWSNmenuItems(char** ){}
void WSCpulldownMenu::setWorkWSNshortcut(char* ){}
void WSCpulldownMenu::getWorkWSNshortcut(char** ){}
void WSCpulldownMenu::setWorkWSNemboss(WSCbool fl){
  if (_menu != NULL){
    _menu->setEmboss(fl);
  }
}
void WSCpulldownMenu::setWorkWSNleftward(char*) {}
void WSCpulldownMenu::getWorkWSNleftward(char**) {}
void WSCpulldownMenu::setWorkWSNrightward(char*) {}
void WSCpulldownMenu::getWorkWSNrightward(char**) {}

WSCpulldownMenu::~WSCpulldownMenu(){
  WSGIappObjectList()->delEvent(this,WSEV_GUI_POLICY_CH);
  WSGIappDev()->delMenu(this);
  if (_ptarget == this){
      _ptarget = NULL;
  }
  getParent()->setUserData("PLD-PUSHED",(void*)0);

  if (_menu != NULL) {
    if (_menu->getVisible() != False){
      _menu_popdown();
    }
    delete _menu;
    _menu = NULL;
  }
  delete _sc_str;
  delete _menu_str;
  if (_ld_name != NULL){
    delete _ld_name;
  }
  if (_rd_name != NULL){
    delete _rd_name;
  }
}

long WSCpulldownMenu::initialize(){
  WSCstring name;
  name = (WSCstring)"pm-" + getInstanceName();
  _menu = new WSCpulldownMenuPopup(NULL, name);
  _menu->initialize();
  _menu->setInternalObject(True);
  _menu->setPropertyV(WSNx, (short)10);
  _menu->setPropertyV(WSNy, (short)10);
  _menu->setPropertyV(WSNwidth, (WSCushort)10);
  _menu->setPropertyV(WSNheight, (WSCushort)10);

  WSCvlabel::initialize();
  return WS_NO_ERR;
}

long WSCpulldownMenu::_device_initialize(){
  WSDdev* dev = getowndev();
  if (dev == NULL){
    return WS_ERR;
  }

  dev->setEnableEventBit( WSEV_MOUSE_MOVE_BIT | WSEV_MOUSE_OUT_BIT |
                          WSEV_MOUSE_PRESS_BIT  | WSEV_MOUSE_RELEASE_BIT );

  WSCvlabel::_device_initialize();
  return WS_NO_ERR;
}

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

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

//  short x, y;
//  WSCushort w, h;
//  getGeometry(&x, &y, &w, &h);
  short x = _x;
  short y = _y;
  WSCushort w = _w;
  WSCushort h = _h;

  WSCbool absolute = getAbsoluteDraw();
  if (absolute != False){
  }else if (dev->isExposed(x, y, w, h) == False){
    return WS_NO_ERR;
  }

//  WSCushort st = _shadow_thick;
  WSCbool blinkfore = WSGIappBlink()->getBlinkFore(_blink_rate);

  if (  _shadow_type == WS_SHADOW_NONE &&
        _bl_fl != False &&
        blinkfore != False &&
        _tw_fl == False){
    return WS_NO_ERR;
  }

  if (WSGIappDev()->getExtGuiPolicySelected() != False){
    if (_ext_draw_proc == NULL){
      _ext_draw_proc = (void(*)(void*))WSGIappDev()->
                               getExtGuiPolicyProc("WSCpulldownMenu::draw");
    }
    if (_ext_draw_proc != NULL){
      WSCpulldownMenu_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.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.emboss = _emboss;
      st.font = _font;
      st.reverse_flag = _rv_fl;
      _ext_draw_proc(&st);
      return WS_NO_ERR;
    }
  }


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

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

  WSCstring  str(_label_string);
  str.replaceString("\\n", "\n", 0);

  if (0 < w && 0 < h){
    if (_rv_fl != False) {
      if (_bl_type != WS_FORE &&
          _bl_fl != False &&
          blinkfore != False &&
          _tw_fl != False) {
        dev->setForeColor(_blink_color);
      } else {
        dev->setForeColor(_fore_color);
      }
    } else {
      if (_bl_type != WS_FORE &&
          _bl_fl != False &&
          blinkfore != False &&
          _tw_fl != False) {
        dev->setForeColor(_bg_blink_color);
      } else {
        dev->setForeColor(_back_color);
      }
    }
    dev->drawFillRect(0, 0, w, h);

    if (_press_state != False) {
      if (WSGIappDev()->getGuiPolicy() & WS_POLICY_ORIGINAL){
        WSGFdrawShadow(dev, _shadow_type, _shadow_thick, _fore_color, _ts_color, _bs_color, _back_color,0, 0, w, h);
      }
      if (WSGIappDev()->getGuiPolicy() & WS_POLICY_WINDOWS){
        dev->setForeColor(WSGIappColorSet()->getDefaultColorNo(WS_DF_MENUSELECTCOLOR));
        dev->drawFillRect(0, 0, w, h);
      }
    }
  }

  WSCushort margin_left   = _margin_left;
  WSCushort margin_right  = _margin_right;
  WSCushort margin_top    = _margin_top;
  WSCushort margin_bottom = _margin_bottom;
  short sx = margin_left;
  short sy = margin_top;
  short sw = 0;
  short sh = 0;
  if ( w > margin_left + margin_right){
    sw = w - margin_left - margin_right;
  }

  if ( h > margin_top + margin_bottom){
    sh = h - margin_top - margin_bottom;
  }

  if( getSensitive() == False ||
     (getPropertyEditMode() != False && (long)getUserData(WS_DET) == 0)){
    if (_emboss != False){
      if (_bl_fl != False &&
        blinkfore != False &&
        _bl_type != WS_BACK &&
        _tw_fl != False) {
        dev->setForeColor(_blink_color);
      } else {
        dev->setForeColor(_ts_color);
      }
      dev->setBackColor(_back_color);

      if (_bl_fl != False &&
        blinkfore == False &&
        _bl_type != WS_BACK &&
        _tw_fl == False){
        // 描画しない
      }else{
        // 表示文字列の描画
        if (_tw_fl == False || _bl_fl == False){
          dev->drawString(sx+1, sy+1, sw, sh, &str, _font, getAlignment(), -1, False);
        }
      }
    }else{
      dev->setHatchPattern(8); //網目模様
    }
  }else{
    dev->setHatchPattern(0); //ベタ塗
  }

  if (_rv_fl != False) {
    if (_bl_fl != False &&
        blinkfore != False &&
        _bl_type != WS_BACK &&
        _tw_fl != False) {
      dev->setForeColor(_bg_blink_color);
    } else {
      if ( _emboss != False && (getSensitive() == False ||
          (getPropertyEditMode() != False && (long)getUserData(WS_DET) == 0))){
        dev->setForeColor(_bs_color);
      } else {
        dev->setForeColor(_back_color);
      }
    }
    dev->setBackColor(_fore_color);
  } else {
    if (_bl_fl != False &&
        blinkfore != False &&
        _bl_type != WS_BACK &&
        _tw_fl != False) {
      dev->setForeColor(_blink_color);
    } else {
      if ( _emboss != False && (getSensitive() == False ||
          (getPropertyEditMode() != False && (long)getUserData(WS_DET) == 0))){
         dev->setForeColor(_bs_color);
      }else{
         dev->setForeColor(_fore_color);
      }
    }
    dev->setBackColor(_back_color);
  }

  if (_press_state != False) {
    if (WSGIappDev()->getGuiPolicy() & WS_POLICY_WINDOWS){
      dev->setForeColor(WSGIappColorSet()->getDefaultColorNo(WS_DF_MENUSELECTFORECOLOR));
    }
  }
  if (_bl_fl != False &&
      blinkfore == False &&
      _bl_type != WS_BACK &&
      _tw_fl == False){
     // 描画しない
  }else{
    // 表示文字列の描画
    dev->drawString(sx, sy, sw, sh, &str, _font, getAlignment(), -1, False);
  }

  dev->endDraw();

  return WS_NO_ERR;
}

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

void WSCpulldownMenu::onVisibleChange(WSCbool fl){
  if (fl == False){
    getParent()->setUserData("PLD-PUSHED",(void*)0);
    _menu_popdown();
    if (_grabed != 0){
      WSDdev* pdev = getParentDev();
      WSCbool fl = False;
      pdev->setValue(WSDEV_GRAB_POINTER,&fl);
      _grabed = 0;
      _mouse_grabed = 0;
//      _out_side_mouse_move = False;
      _out_side_mouse_release = False;
      _out_side_mouse_press = False;
    }
  }
  WSCvlabel::onVisibleChange(fl);
}

void WSCpulldownMenu::onParentVisibleChange(WSCbool fl){
  if (fl == False){
    getParent()->setUserData("PLD-PUSHED",(void*)0);
    _menu_popdown();
    if (_grabed != 0){
      WSDdev* pdev = getParentDev();
      WSCbool fl = False;
      pdev->setValue(WSDEV_GRAB_POINTER,&fl);
      _grabed = 0;
      _mouse_grabed = 0;
//      _out_side_mouse_move = False;
      _out_side_mouse_release = False;
      _out_side_mouse_press = False;
    }
  }
  WSCvlabel::onParentVisibleChange(fl);
}

WSCpulldownMenu* WSCpulldownMenu::_ptarget = NULL;

void WSCpulldownMenu::onMousePress(WSCpoint* point){
  if (getSensitive() == False) {
    WSCbase::onMousePress(point);
    return;
  }
  if (_press_state == False && (long)getUserData(WS_PM_POPUPED) == 0){
    if (getPropertyEditMode() == False ||
        (WSGIappMouse()->getTargetBtn() != WS_MOUSE_BTN3)){
      if (_ptarget != NULL){
        _ptarget->onMouseRelease(point);
      }
      getParent()->setUserData("PLD-PUSHED",(void*)this);
      _menu_popup(point);
      setAbsoluteDraw(True);
      redraw();
    }
  }
  WSCvlabel::onMousePress(point);
}

void WSCpulldownMenu::onMouseRelease(WSCpoint* point){
  getParent()->setUserData("PLD-PUSHED",(void*)0);
  if (getSensitive() == False) {
    return;
  }
  if (_press_state != False){
    if (getPropertyEditMode() == False ||
        (WSGIappMouse()->getTargetBtn() != WS_MOUSE_BTN3)){
      short px,py;
      getMouseAddr(&px,&py);
      if (_grabed == 0 &&
          -1 < px && px < (signed)_w && -1 < py && py < (signed)_h &&
          getPropertyEditMode() == False){
        WSDdev* pdev = getParentDev();
        WSCbool fl = True;
        pdev->setValue(WSDEV_GRAB_POINTER,&fl);
        _grabed = 1;
        _mouse_grabed = 1;
//        _out_side_mouse_move = True;
        _out_side_mouse_release = True;
        _out_side_mouse_press = True;
      }else if (_grabed == 0 && _mouse_no_check == True &&
          getPropertyEditMode() == False){
        WSDdev* pdev = getParentDev();
        WSCbool fl = True;
        pdev->setValue(WSDEV_GRAB_POINTER,&fl);
        _grabed = 1;
        _mouse_grabed = 1;
        _out_side_mouse_release = True;
        _out_side_mouse_press = True;
      }else{
        if (_grabed != 0){
          WSDdev* pdev = getParentDev();
          WSCbool fl = False;
          pdev->setValue(WSDEV_GRAB_POINTER,&fl);
          _grabed = 0;
          _out_side_mouse_press = False;
        }
        _menu_popdown();
        execProcedure(WSEV_VALUE_CH);

        setAbsoluteDraw(True);
        redraw();
  
        if (getSensitive() != False && _menu->getSelected() != False){
          onActivate();
          if ( strcmp(_menu->getProcName(),"") ){
            execProcedure(_menu->getProcName());
          }
        }
      }
    }
  }
  WSCvlabel::onMouseRelease(point);
}

void WSCpulldownMenu::onMouseMove(WSCpoint* pos){
  if (getSensitive() == False) {
    return;
  }
  if (_press_state != False){
    _menu_update();
  }else{
    WSCpulldownMenu* target = (WSCpulldownMenu*)getParent()->getUserData("PLD-PUSHED");
    if ( pos->x > 0 && pos->x < _w && pos->y > 0 && pos->y < _h &&
         target != NULL && target != this ){
      target->onMouseRelease(pos);
      onMousePress(pos);
    }
  }
}

long WSCpulldownMenu::addProcedure(WSCprocedure* ac){
  if (existTrigger(ac->getTrigger()) == False && ac->getInternal() == False){
WSMFtrace("WSCpulldownMenu::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 = getowndev();
    if (dev != NULL){
      dev->setEnableEventBit(_event_mask);
    }
    return WS_NO_ERR;
  }

  WSCnwbase::addProcedure(ac);
  return WS_NO_ERR;
}
long WSCpulldownMenu::beginCascade(char* lb){
  WSCstring str(_menu_str);
  str.delHeadSpace();
  str.delTailSpace();
  if (strcmp(str.getString(),"")){
    str += ",";
  }
  str = str + lb + ":{";
  setPropertyV(WSNmenuItems,str.getString());
  return WS_NO_ERR;
}
long WSCpulldownMenu::endCascade(){
  WSCstring str(_menu_str);
  str += "}";
  setPropertyV(WSNmenuItems,str.getString());
  return WS_NO_ERR;
}

void WSCpulldownMenu::_menu_popup(WSCpoint*){
  _out_side_mouse_press = True;
//  _out_side_mouse_move = True;
  _out_side_mouse_release = True;
  _mouse_grabed = True;
  _ptarget = this;
  _press_state = True;
  WSGIappMouse()->getMousePosition(&_mouse_x, &_mouse_y);

  WSDdev* dev = getowndev();
  if (dev == NULL){
    return;
  }
  short px, py;
  dev->getDispAddr(&px,&py);
  WSCbool do_cascade = False;

  WSCuchar st = _shadow_thick;
  if (WSGIappDev()->getGuiPolicy() & WS_POLICY_WINDOWS){
    st = 2;
  }
  WSCbase* spobj = getSpecialFocusInstance();
  if (spobj != NULL && spobj != this){
    spobj->setSpecialFocus(False);
  }
  spobj = getFocusInstance();
  if (spobj != NULL && spobj != this){
    spobj->setFocus(False);
  }

  WSGIappKeyboard()->setFocusInputWorkProc(_key_handler,NULL,this);

  if (_menu != NULL){
    WSCstring str(_menu_str);  
    long num = str.getWords(",");    

    short len = 0;
    short ww = 0;
    short hh = st*2;
    long i;
    WSDfont* fn = WSGIappFontSet()->getFont(_font);
    for (i=0; i<num; i++) {
      WSCstring sect = str.getWord(i, ",");
      WSCstring sect_str = sect.getWord(0, ":");
      WSCstring op_name = sect.getWord(1, ":");

      if (!strcmp(sect_str.getString(),"SP") ||
          !strcmp(sect_str.getString(),"SEPARATOR")){
        hh += st*2;
        if (WSGIappDev()->getGuiPolicy() & WS_POLICY_WINDOWS){
          hh += 4;
        }
      }else{
        if ( !strncmp(op_name.getString(),"{",1) ){
          do_cascade = True;
          long wpos = str.getWordCharPos(i, ",");
          WSCstring tmp(str.getString());
          tmp.deleteChars(0,wpos);
          wpos = tmp.getWordCharPos(1,"{");
          tmp.deleteChars(0,wpos);

          char* tstr = tmp.getString(WS_EN_UTF8);
          long len = strlen(tstr);
          long num_of_separator = 0;
          long j;
          long layers = 0;
          for(j=0; j< len; j++){
            if (tstr[j] == '}'){
              if (layers == 0){
                tstr[j] = 0;
                break;
              }else{
                layers--;
              }
            }
            if (tstr[j] == '{'){
              layers++;
            }
            if (tstr[j] == ','){
              num_of_separator++;
            }
          }
          i += num_of_separator;
        }
        hh += _h;
      }

      if (len < (short)strlen(sect_str.getString())) {
        len = (short)strlen(sect_str.getString());
        WSCstring space(" ");
        WSCushort smargin = WSGIappFontSet()->getStringWidth(_font,&space);
        ww = (short)fn->getStringWidth(&sect_str) + st * 2 + st * 2 + smargin;
      }
    }

    if (do_cascade != False){
      ww += 30;
    }

    if (px + ww > WSGIappDev()->getWidth()) {
      px -= (px + ww - WSGIappDev()->getWidth());
    }
    py += _h;
    if (py + hh > WSGIappDev()->getHeight()) {
      py -= (py + hh - WSGIappDev()->getHeight());
    }

    _menu->setPropertyV(WSNx, (short)(px));
    _menu->setPropertyV(WSNy, (short)(py));
    _menu->setPropertyV(WSNmenuItemHeight,  _h);
    _menu->setPropertyV(WSNfont, (WSCuchar)_font);
    _menu->setPropertyV(WSNforeColor, _fore_color);
    _menu->setPropertyV(WSNbackColor, _back_color);
    if (WSGIappDev()->getGuiPolicy() & WS_POLICY_ORIGINAL){
      _menu->setPropertyV(WSNshadowThickness, st);
    }else
    if (WSGIappDev()->getGuiPolicy() & WS_POLICY_WINDOWS){
      _menu->setProperty(WSNshadowThickness, 2);
    }
    _menu->setPropertyV(WSNshadowType, (char)_shadow_type);
    _menu->setPropertyV(WSNtopShadowColor, _ts_color);
    _menu->setPropertyV(WSNbottomShadowColor, _bs_color);
    _menu->setPropertyV(WSNmenuItems, _menu_str);
    _menu->setPropertyV(WSNheight, (WSCushort)(hh));
    _menu->setPropertyV(WSNwidth, (WSCushort)(ww));
    _menu->setPropertyV(WSNpixmapStyle, (WSCuchar)(WS_DYNAMIC_PIXMAP));
    _menu->setVisible(True);
//    WSGFstretchPopup(_menu);
  }
}


void WSCpulldownMenu::_menu_update(){
  short x, y;
  WSCbool ret = WSGIappMouse()->getMousePosition(&x, &y);
  if (ret != False){
    if (_menu->getNextPopup() != False) {
//DEVELOP///
//WSMFtrace("*** WSCpulldownMenu::menuPopup 次のポップアップを表示するはず\n");
    }
    if ( _mouse_x != x || _mouse_y != y){
      _mouse_x = x;
      _mouse_y = y;
      _menu->setAbsoluteDraw(True);
      _menu->draw();
    }
  }
}

void WSCpulldownMenu::_menu_popdown(){
  WSGIappKeyboard()->resetFocusInputWorkProc();

  _out_side_mouse_press = False;
//  _out_side_mouse_move = False;
  _out_side_mouse_release = False;
  _mouse_grabed = False;
  _ptarget = NULL;
  _press_state = False;
  _menu->setVisible(False);
//  WSGFstretchPopdown(_menu);
}

long WSCpulldownMenu::setValueSensitive(short id, WSCbool fl) {
  long ret = WS_ERR;
  if (_menu != NULL){
    ret = _menu->setValueSensitive(id,fl);
  }
  return ret;
}

long WSCpulldownMenu::setItemSensitive(short no, WSCbool fl) {
  if (no < 0){
    return WS_ERR;
  }
  if (_menu != NULL){
    return _menu->setItemSensitive(no,fl);
  }
  return WS_ERR;
}

WSCbool* WSCpulldownMenu::getItemSensitive() {
  if (_menu != NULL){
    return _menu->getItemSensitive();
  }
  return NULL;
}

long WSCpulldownMenu::getValue(){
  if (_menu != NULL){
    long ret = _menu->getValue();
    return ret;
  }
  return 0;
}

long WSCpulldownMenu::addItem(char* lb,char* op,char* sc,long id){
  WSCstring str(_menu_str);
  if (_menu_str[0] != 0 && _menu_str[strlen(_menu_str)-1] != '{'){
    str += ",";
  }
  str = str + lb + ":" + op + ":" + sc + ":" + WSGFltoa(id);
  setPropertyV(WSNmenuItems,str.getString());
  return WS_NO_ERR;
}

long WSCpulldownMenu::getItems(){
  if (_menu != NULL){
    return _menu->getItems();
  }
  return 0;
}
long WSCpulldownMenu::execEventProc(long ev,void* data){
  if (ev == WSEV_KEY_PRESS && getPropertyEditMode() == False &&
      getVisible() != False){
    long key = WSGIappKeyboard()->getKey();
    char* text = WSGIappKeyboard()->getText();
    if (key != 0 && text[0] != 0 && _sc_str != NULL){
      int val1 = toupper(text[0]);
      int val2 = toupper(_sc_str[0]);
      if (val1 == val2){
        WSCpoint pt;
        pt.x = 0;
        pt.y = 0;
        onMousePress(&pt);
        _mouse_no_check = 1;
        onMouseRelease(&pt);
        _mouse_no_check = 0;
        WSGIappKeyboard()->setText("");
        return WS_NO_ERR;
      }
    }
  }
  return WSCvlabel::execEventProc(ev,data);
}
void WSCpulldownMenu::_key_handler(void* ptr,WSDkeyboard* keyboard,WSCbool fl){
  WSCpulldownMenu* obj = (WSCpulldownMenu*)ptr;
  if (fl != False){
    long key = keyboard->getKey(); 
    char* text = keyboard->getText(); 
    if (obj->_menu != NULL && obj->_menu->getVisible() != False){
      char buf[2];
      buf[0] = (char)toupper(text[0]);
      buf[1] = 0;
      WSCstring pname = obj->_get_proc_name_by_sc(obj->_menu_str,buf);
      if (strcmp(buf,"") && strcmp(pname,"")){
        WSCpoint pt;
        pt.x = 0;
        pt.y = 0;
        obj->onMousePress(&pt);
        obj->onMouseRelease(&pt);
        obj->execProcedure((char*)pname);
      }else
      if (key == WSK_Up || key == WSK_Down || key == WSK_Left || key == WSK_Right){
        obj->_menu->setUserData("KEY_PROCESSED",(void*)0);
        obj->_menu->onKeyPress(keyboard,fl);
        if ( (key == WSK_Left || key == WSK_Right) &&
             obj->_menu->getUserData("KEY_PROCESSED") == (void*)0){
          WSCbase* target = NULL;
          if ( key == WSK_Left){
            target = obj->_get_focus_move_instance(WS_LEFT);
          }else
          if ( key == WSK_Right){
            target = obj->_get_focus_move_instance(WS_RIGHT);
          }
          if (target != NULL){
            obj->_menu->setSelected(False);
            WSCpoint pt;
            pt.x = 0;
            pt.y = 0;
            obj->onMousePress(&pt);
            obj->onMouseRelease(&pt);
            if (target->cast("WSCpulldownMenu") != NULL){
              WSCpulldownMenu* tt = (WSCpulldownMenu*)target->cast("WSCpulldownMenu");
              tt->onMousePress(&pt);
              tt->_mouse_no_check = 1;
              tt->onMouseRelease(&pt);
              tt->_mouse_no_check = 0;
            }else{
              target->setFocus(True);
            }
            return;
          }
        }
      }else
      if (key == WSK_Escape){
        obj->_menu->setSelected(False);
        WSCpoint pt;
        pt.x = 0;
        pt.y = 0;
        obj->onMousePress(&pt);
        obj->onMouseRelease(&pt);
        keyboard->setKey(0); 
      }
      if (key == WSK_Return){
        WSCpoint pt;
        pt.x = 0;
        pt.y = 0;
        obj->onMousePress(&pt);
        obj->onMouseRelease(&pt);
      }
    }
  }
}
WSCstring WSCpulldownMenu::_get_proc_name_by_sc(char* menustr,char* sc){
  if (menustr == NULL){
    WSCstring ret;
    return ret;
  }
  WSCstring str(menustr);
  long num = str.getWords(",");
  long i;
  for(i=0; i<num; i++){
    WSCstring tmp;
    tmp = str.getWord(i,",");
    WSCstring submenu;
    submenu = tmp.getWord(1,":"); 
    submenu.delHeadSpace();
    submenu.delTailSpace();
    char* submenu1 = submenu.getString(WS_EN_UTF8);
    long sblen = strlen(submenu1);
    if (submenu1[0] == '{' && submenu1[sblen-1] == '}'){
      submenu1[sblen-1] = 0;
      WSCstring t(&submenu1[1],WS_EN_UTF8);
      WSCstring procn = _get_proc_name_by_sc(t.getString(),sc);
      if (strcmp((char*)procn,"")){
        return procn;
      }
    }
    WSCstring scname;
    scname = tmp.getWord(2,":"); 
    scname.to_upper();
    if (!strcmp(scname,sc)){
      return submenu;
    }
  }
  WSCstring ret;
  return ret;
}
void(*WSCpulldownMenu::_ext_draw_proc)(void*) = NULL;
WSCstring WSCpulldownMenu::_policy_name;

void WSCpulldownMenu::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("WSCpulldownMenu::draw");
    }
  }
  if (getVisible() != False){
    needUpdate();
    setAbsoluteDraw(True);
    redraw();
  }
}

