//
// Copyright (C) 1999-2002 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 <WSCstring.h>
#include <WSCbase.h>
#include <WSCmessageDialog.h>
#include <advance/WSadcom.h>
#include <WSCclassInformation.h>
#include <WSCbaseList.h>

static WSCbase*  _get_parent_base(WSCbase* win,char* pname){
  if (!strcmp(pname,win->getInstanceName())){
    return win;
  }
  WSClistData children = win->getChildren();
  long num = children.getNum();
  long i;
  for(i=0; i<num; i++){
    WSCbase* child = (WSCbase*)children[i];

    if ( !strcmp(pname,child->getInstanceName()) ){
      return child;
    }else{
      WSCbase* ret = _get_parent_base(child,pname);
      if (ret != NULL){
        return ret;
      }
    }
  }
  return NULL;
}
static WSCbase*  _get_parent_base2(WSCbase* win,char* pname){
  char* tname = (char*)win->getUserData("tname-");
  if (tname != NULL && !strcmp(pname,tname)){
    return win;
  }
  WSClistData children = win->getChildren();
  long num = children.getNum();
  long i;
  for(i=0; i<num; i++){
    WSCbase* child = (WSCbase*)children[i];

    char* tname = (char*)child->getUserData("tname-");
    if ( tname != NULL && !strcmp(pname,tname) ){
      return child;
    }else{
      WSCbase* ret = _get_parent_base2(child,pname);
      if (ret != NULL){
        return ret;
      }
    }
  }
  return NULL;
}
extern void _get_2_words(char* src,char* word1,char* word2);
#if 0
void _get_2_words(char* src,char* word1,char* word2){
   word1[0] = 0;
   word2[0] = 0;
   long ptr=0;
   while(1){
     if (src[ptr] == 0){
       return;
     }
     if (src[ptr] == ' ' || src[ptr] == '\t'){
       ptr++;
     }else{
       break;
     }
   }

   long i=0;
   while(1){
     if (src[ptr] == 0){
       word1[i] = 0;
       return;
     }
     if (src[ptr] == ' ' || src[ptr] == '\t'){
       word1[i] = 0;
       break;
     }
     word1[i] = src[ptr];
     i++;
     ptr++;
   }

   while(1){
     if (src[ptr] == 0){
       return;
     }
     if (src[ptr] == ' ' || src[ptr] == '\t'){
       ptr++;
     }else{
       break;
     }

   }

   i=0;
   while(1){
     if (src[ptr] == 0){
       word2[i] = 0;
       return;
     }
     if (src[ptr] == ' ' || src[ptr] == '\t'){
       word2[i] = 0;
       return;
     }
     word2[i] = src[ptr];
     i++;
     ptr++;
   }
}
#endif
static void _op_dummy(WSCbase*){
}
void _clean_tname_(WSCbase* base){
  if (base != NULL){
    char* tname = (char*)base->getUserData("tname-");
    if (tname != NULL){
      delete tname;
      base->setUserData("tname-",NULL);
    }
    WSClistData children = base->getChildren();
    long num = children.getNum();
    long i;
    for(i=0; i<num; i++){
      WSCbase* child = (WSCbase*)children[i];
      _clean_tname_(child);
    }
  }
}
WSCbase* _WSGFreadWinSrc(WSCstring& src,WSCbool edit,WSCbool spec_name,char* topname);

WSCbase* WSGFreadWinSrc(WSCstring& src,WSCbool edit){
  WSCbase* ret = _WSGFreadWinSrc(src,edit,False,NULL);
  _clean_tname_(ret);
  return ret;
}
WSCbase* WSGFreadWinSrc2(WSCstring& src,WSCbool edit,char* topname){
  return _WSGFreadWinSrc(src,edit,True,topname);
}
long (*_create_proc_handler)(char*,char*) = NULL;
void WSGFreadWinSrcSetCreateProcHandler(long(*hd)(char*,char*)){
  _create_proc_handler = hd;
}

char* get_type_name(long num){
extern char* WSGFvalueToType(long);
  return WSGFvalueToType(num);
#if 0
  switch(num){
    case 0: return "long";
    case 1: return "WSCulong";
    case 2: return "short";
    case 3: return "WSCushort";
    case 4: return "char";
    case 5: return "WSCuchar";
    case 6: return "float";
    case 7: return "double";
    case 9: return "char*";
    case 11: return "WSCbool";
    case 12: return "int";
    case 13: return "WSCuint";
    case 14: return "void";
  }
  return "long";
#endif
}
long get_type_value(char* typen){
extern long WSGFtypeToValue(char*);
  return WSGFtypeToValue(typen);
#if 0
  if (!strcmp(typen,"long")){
    return 0;
  }else
  if (!strcmp(typen,"WSCulong")){
    return 1;
  }else
  if (!strcmp(typen,"short")){
    return 2;
  }else
  if (!strcmp(typen,"WSCushort")){
    return 3;
  }else
  if (!strcmp(typen,"char")){
    return 4;
  }else
  if (!strcmp(typen,"WSCuchar")){
    return 5;
  }else
  if (!strcmp(typen,"float")){
    return 6;
  }else
  if (!strcmp(typen,"double")){
    return 7;
  }else
  if (!strcmp(typen,"char*")){
    return 9;
  }else
  if (!strcmp(typen,"void")){
    return 10;
  }else
  if (!strcmp(typen,"WSCbool")){
    return 11;
  }else
  if (!strcmp(typen,"int")){
    return 12;
  }else
  if (!strcmp(typen,"WSCuint")){
    return 13;
  }
  return 0;
#endif
}
char* get_type_name2(char* typen){
  if (!strcmp(typen,"long")){
    return "Long";
  }else
  if (!strcmp(typen,"WSCulong")){
    return "ULong";
  }else
  if (!strcmp(typen,"short")){
    return "Short";
  }else
  if (!strcmp(typen,"WSCushort")){
    return "UShort";
  }else
  if (!strcmp(typen,"char")){
    return "Char";
  }else
  if (!strcmp(typen,"WSCuchar")){
    return "UChar";
  }else
  if (!strcmp(typen,"float")){
    return "Float";
  }else
  if (!strcmp(typen,"double")){
    return "Double";
  }else
  if (!strcmp(typen,"char*")){
    return "String";
  }else
  if (!strcmp(typen,"void")){
    return "void";
  }else
  if (!strcmp(typen,"WSCbool")){
    return "Char";
  }else
  if (!strcmp(typen,"int")){
    return "Int";
  }else
  if (!strcmp(typen,"WSCuint")){
    return "UInt";
  }
  return "Long";
}




WSCbase* _WSGFreadWinSrc(WSCstring& src,WSCbool edit,WSCbool spec_name,char* topname){
   WSCbase* ret = NULL;
   WSCbase* obj = NULL;
   WSCbase* obj2 = NULL;
   WSCbool top = True;
//   char buffer[1024];
   char buf1[1024];
   char buf2[1024];
   char buf3[1024];
   char buf4[1024];
   WSCstring classname;

   src.seek(0);
   WSCstring str = src.gets();
   while(src.eof() == False){
     buf1[0] = 0;
     buf2[0] = 0;
     _get_2_words((char*)str,buf1,buf2);
    if(strcmp("#OBJ", buf1) && strcmp("#obj", buf1) &&
        strcmp("#cobj",buf1) && strcmp("#sobj",buf1) &&
        strcmp("#cobjr",buf1) ){
      break;
    }
    WSCbool ext = False;
    WSCbool classwin = False;
    WSCbool storewin = False;
    WSCbool rclass = False;
    if (!strcmp("#OBJ",buf1)){
      ext = True;
    }
    if (!strcmp("#cobj",buf1)){
      classwin = True;
      rclass = False;
    }
    if (!strcmp("#cobjr",buf1)){
      classwin = True;
      rclass = True;
    }
    if (!strcmp("#sobj",buf1)){
      storewin = True;
    }
    char dummy[2048];
    long ano;
    WSCbool is_array = WSGFcheckArrayName(buf2,&ano,dummy);
    if (is_array != False){
      ext = True;
    }

    if (src.eof() != False){
      break;
    }
    str = src.gets();

    buf1[0] = 0;
    buf3[0] = 0;

    _get_2_words(str,buf1,buf3);
    if (classwin != False){
      classname = buf3;
    }
    if (strcmp("#TYPE",buf1)){
      break;
    }
    if (src.eof() != False){
      break;
    }
    str = src.gets();

    buf1[0] = 0;
    buf4[0] = 0;

    _get_2_words(str,buf1,buf4);

    if (strcmp("#PARENT",buf1)){
      break;
    }

    WSCbase* parent = NULL;
    if ( strcmp(buf4,"NULL") && buf4[0] != 0 ){
      if (spec_name == False){
        if (obj != NULL && !strcmp(obj->getInstanceName(),buf4)){
          parent = obj;
        }else
        if (obj2 != NULL && !strcmp(obj2->getInstanceName(),buf4)){
          parent = obj2;
        }else if (ret != NULL){
          parent = _get_parent_base(ret,buf4);
        }
        obj2 = parent; //親になったものをキャッシュする
      }else{
        if (obj != NULL){
          char* tname = (char*)obj->getUserData("tname-");
          if (tname != NULL && !strcmp(tname,buf4)){
            parent = obj;
          }
        }
        if (parent == NULL && obj2 != NULL){
          char* tname2 = (char*)obj2->getUserData("tname-");
          if (tname2 != NULL && !strcmp(tname2,buf4)){
            parent = obj2;
          }
        }
        if (parent == NULL && ret != NULL){
          parent = _get_parent_base2(ret,buf4);
        }
        obj2 = parent; //親になったものをキャッシュする
      }
    }

    obj = WSCbase::getNewInstance(buf3,parent,"--NO NAME--");
    if (obj == NULL){
      WSCmessageDialog* msg = WSGIappMessageDialog();
      msg->setPropertyV(WSNdefaultPosition,(WSCbool)True);
      msg->setPropertyV(WSNwidth,(WSCushort)450);
      msg->setPropertyV(WSNheight,(WSCushort)120);
      char buffer[1024];
      sprintf(buffer,WSGFgettext("A3:WSSTR Can not create class: %s.\nPlease check the import library is right."),buf3);
      msg->setPropertyV(WSNlabelString,buffer);
      msg->popup();
      if (ret != NULL){
        delete ret;
      }
      return NULL;
    }
//printf("WSadcom::readWinSrc cname=%s name=%s\n",buf3,buf2);
    long st_name = 0;
    if (spec_name == False){
      st_name = WSGFexistName(buf2,obj);
    }else if (top != False){
      st_name = WSGFexistName(topname,obj);
    }
    if (ext == True && ((st_name != 0 && is_array == False) ||
                       ((st_name == WS_PROCEDURE_NAME ||
                         st_name == WS_OBJECT_NAME ) && is_array != False ))){
      if (spec_name == False){
        WSCmessageDialog* msg = WSGIappMessageDialog();
        msg->setPropertyV(WSNwidth,(WSCushort)450);
        msg->setPropertyV(WSNheight,(WSCushort)120);
        char buffer[1024];
        sprintf(buffer,
           WSGFgettext("B3:WSSTR The name %s is already used by another instance."),
           buf2);
        msg->setPropertyV(WSNlabelString,buffer);
        msg->popup();
      }
    }
    if (spec_name == False){
      obj->setInstanceName(buf2);
    }else{
      obj->setUserData("tname-",WSGFstrdup(buf2));
      if (ret != NULL){
        obj->setInstanceName(WSGFcreateName(ret->getInstanceName(),
                             obj->getClassName()));
      }else{
        obj->setInstanceName(topname);
      }
    }

    obj->initialize();
    obj->setPropertyEditMode(edit);

    WSGFexecCreateHandler(obj);

    void (*delete_handler)(WSCbase*) = WSGFgetDeleteHandler();
    if (delete_handler != NULL){
      WSCprocedure* ac = new WSCprocedure("delete-handler",WSEV_DELETE);
      ac->setFunction(delete_handler,"delete_handler");
      ac->setInternal(True);
      obj->addProcedure(ac);
    }

    if (ext == True){
      obj->setUserData(WS_EXT_VAR,(void*)1);
    }
    if (classwin == True){
      obj->setUserData(WS_WIN_CLASS,(void*)1);
    }
    if (rclass == True){
      obj->setUserData(WS_RCLASS_GENERATE,(void*)1);
    }
    if (storewin == True){
      obj->setUserData(WS_WIN_STORE,(void*)1);
    }
    if (src.eof() != False){
      break;
    }
    str = src.gets();

    while(1){
      buf1[0]=0;
      buf2[0]=0;
      _get_2_words(str,buf1,buf2);

      if (strcmp("#PROC",buf1)){
        break;
      }

      if (src.eof() != False){
        return ret;
      }
      str = src.gets();

      long trig;
      buf1[0]=0;
      buf3[0]=0;
      sscanf(str,"%s %d",buf1,&trig);

      if (src.eof() != False){
        return ret;
      }
      str = src.gets();

      _get_2_words(str,buf1,buf3);

      WSCstring prog(buf3);

      WSCprocedure* ac = new WSCprocedure(buf2,trig);
      if (prog.isExist(".cpp") == -1 && prog.isExist(".C") == -1){
        ac->setUseFile(False);
      }else{
        ac->setUseFile(True);
        if (spec_name != False && _create_proc_handler != NULL){
          if (classwin == False){
            _create_proc_handler((char*)prog,NULL);
          }else{
            _create_proc_handler((char*)prog,(char*)classname);
          }
        }
      }

      prog.replaceString(".cpp","",0);
      prog.replaceString(".C","",0);
      ac->setFunction(_op_dummy,prog.getString());
      obj->addProcedure(ac);

      if (src.eof() != False){
        return ret;
      }
      str = src.gets();
      if (src.eof() != False){
        return ret;
      }
      str = src.gets();
    }

    while(1){
      buf1[0]=0;
      buf2[0]=0;
      _get_2_words(str,buf1,buf2);

      if (strcmp("#RES",buf1)){
        break;
      }
      if (src.eof() != False){
        return ret;
      }
      str = src.gets();
      obj->setProperty(buf2,(char*)str);

      if (src.eof() != False){
        return ret;
      }
      str = src.gets();
    }

    while(1){
      buf1[0]=0;
      buf2[0]=0;
      char tbuf1[1024];
      char bbuf1[1024];
      tbuf1[0] = 0;
      bbuf1[0] = 0;
      long att = 0;
      long type;
      long use_file;

      sscanf(str,"%s %s %s %d %d %d %s",buf1,buf2,tbuf1,&type,&use_file,&att,bbuf1);
      if (strncmp("#res",buf1,4)){
        break;
      }
      if (src.eof() != False){
        return ret;
      }
      str = src.gets();

      WSClistData* prprc_list = (WSClistData*)obj->getUserData(WS_PROP_LIST);
      if (prprc_list == NULL){
        prprc_list = new WSClistData();
        obj->setUserData(WS_PROP_LIST,(void*)prprc_list);
      }
      char values[1024];
      values[0] = 0;
      if (buf1[4] == '#'){
        strcpy(values,&(buf1[5]));
      }
      prop_data* propdata = new prop_data;
      propdata->name.setString(buf2);
      propdata->vname.setString(tbuf1);
      propdata->value.setString(str);
      propdata->bname.setString(bbuf1);
      propdata->type = type;
      propdata->att = att;
      propdata->use_file = use_file;
      propdata->values.setString(values);
      propdata->values.replaceString("\\S"," ",0);
      prprc_list->add((void*)propdata);
      if (src.eof() != False){
        return ret;
      }
      str = src.gets();
    }

    while(1){
      buf1[0]=0;
      buf2[0]=0;
      char bbuf1[1024];
      long value;
      long value2;

      sscanf(str,"%s %s %s %d",buf1,buf2,bbuf1,&value2);
      if (strncmp("#utrg",buf1,4)){
        break;
      }
      if (src.eof() != False){
        return ret;
      }
      str = src.gets();
      value = atoi(str);

      WSClistData* prprc_list = (WSClistData*)obj->getUserData(WS_UTRG_LIST);
      if (prprc_list == NULL){
        prprc_list = new WSClistData();
        obj->setUserData(WS_UTRG_LIST,(void*)prprc_list);
      }
      utrg_data* utrgdata = new utrg_data;
      utrgdata->name.setString(buf2);
      utrgdata->vname.setString(bbuf1);
      utrgdata->value = value;
      utrgdata->type = value2;
      prprc_list->add((void*)utrgdata);
      if (src.eof() != False){
        return ret;
      }
      str = src.gets();
    }


    while(1){
      buf1[0]=0;
      long trg;

      sscanf(str,"%s %d",buf1,&trg);
      if (strcmp("#trg",buf1)){
        break; //
      }

      WSClistData* tlist = (WSClistData*)obj->getUserData(WS_TRG_LIST);
      if (tlist == NULL){
        tlist = new WSClistData();
        obj->setUserData(WS_TRG_LIST,(void*)tlist);
      }
      tlist->add((void*)trg);

      if (src.eof() != False){
        return ret;
      }
      str = src.gets();
    }

    while(1){
      buf1[0]=0;
      buf2[0]=0;
      _get_2_words(str,buf1,buf2);

      if (strcmp("#icon",buf1)){
        break; //
      }

      char* icon = (char*)obj->getUserData(WS_CLASS_ICON);
      if (icon != NULL){
        delete icon;
      }

      obj->setUserData(WS_CLASS_ICON,(void*)WSGFstrdup(buf2));
      if (src.eof() != False){
        return ret;
      }
      str = src.gets();
    }

    while(1){
      buf1[0]=0;
      buf2[0]=0;

//      sscanf(str,"%s %s",buf1,buf2);
      _get_2_words(str,buf1,buf2);

      if (strcmp("#com",buf1)){
        break; //
      }

      char* ccom = (char*)obj->getUserData(WS_CLASS_COMMENT);
      if (ccom != NULL){
        delete ccom;
      }
      obj->setUserData(WS_CLASS_COMMENT,(void*)WSGFstrdup(buf2));
      if (src.eof() != False){
        return ret;
      }
      str = src.gets();
 
    }

    while(1){
      buf1[0]=0;
      buf2[0]=0;

      _get_2_words(str,buf1,buf2);

      if (strcmp("#cbase",buf1)){
        break;
      }

      char* cbase = (char*)obj->getUserData(WS_WIN_CLASS_BASE);
      if (cbase != NULL){
        delete cbase;
      }

      obj->setUserData(WS_WIN_CLASS_BASE,(void*)WSGFstrdup(buf2));
      if (src.eof() != False){
        return ret;
      }
      str = src.gets();
    }

    while(1){
      buf1[0]=0;
      buf2[0]=0;

      _get_2_words(str,buf1,buf2);

      if (strcmp("#rmethod",buf1)){
        break;
      }

      WSClistData* rmlist = (WSClistData*)obj->getUserData(WS_RMETHOD_LIST);
      if (rmlist == NULL){
        rmlist = new WSClistData();
        obj->setUserData(WS_RMETHOD_LIST,(void*)rmlist);
      }
      WSCstring rstr(buf2);

      rmethod_data* rmdata = new rmethod_data;
      rmdata->name = rstr.getWord(1,",");
//      rmdata->type =  get_type_value(rstr.getWord(0,","));
      rmdata->type_name =  rstr.getWord(0,",");

      if (src.eof() != False){
        return ret;
      }
      rstr = src.gets();
      rmdata->params = rstr;
      rmlist->add((void*)rmdata);

      if (src.eof() != False){
        return ret;
      }
      str = src.gets();
    }

    while(1){
      buf1[0]=0;
      buf2[0]=0;

      _get_2_words(str,buf1,buf2);

      if (strcmp("#rcname",buf1)){
        break;
      }
      obj->setUserData(WS_RCLASS_NAME,WSGFstrdup(buf2));

      if (src.eof() != False){
        return ret;
      }
      str = src.gets();
    }

    while(1){
      buf1[0]=0;
      buf2[0]=0;

      _get_2_words(str,buf1,buf2);

      if (strcmp("#brcname",buf1)){
        break;
      }
      obj->setUserData(WS_RCLASS_BNAME,WSGFstrdup(buf2));

      if (src.eof() != False){
        return ret;
      }
      str = src.gets();
    }

    if (top != False){
      ret = obj;
      obj->setUserData(WS_EXT_VAR,(void*)1);
      top = False;
    }
    str = src.gets();
  }
  return ret;
}
static void  _append(WSClistData* list,WSCstring* str){
  long num = list->getNum();
  long i;
  if (num > 2){
    WSClistData list1;
    WSClistData list2;
    for(i=0; i<num; i++){
      if (i < num/2){
        list1.add( (*list)[i]);
      }else{
        list2.add( (*list)[i]);
      }
    }
    WSCstring str1;
    WSCstring str2;
    _append(&list1,&str1);
    _append(&list2,&str2);
    str->addString(str1.getString());;
    str->addString(str2.getString());;
    return;
  }else{
    if (num == 2){
      WSCstring* str1 = (WSCstring*)(*list)[0];
      WSCstring* str2 = (WSCstring*)(*list)[1];
      str->addString(str1->getString());
      str->addString(str2->getString());
    }else if (num == 1){
      WSCstring* str1 = (WSCstring*)(*list)[0];
      str->addString(str1->getString());
    }
    return;
  }
}

void WSGFcreateWinData(WSCstring* str,WSCbase* parent,WSCbase* base){
   WSClistData children = base->getChildren();
   char buffer[2048];
   WSCstring str2;
   if ((long)base->getUserData(WS_WIN_STORE) == 1){
     sprintf(buffer,"#sobj      %s\n",base->getInstanceName());
   }else if ((long)base->getUserData(WS_WIN_CLASS) == 1){
     if ((long)base->getUserData(WS_RCLASS_GENERATE) == 1){
       sprintf(buffer,"#cobjr      %s\n",base->getInstanceName());
     }else{
       sprintf(buffer,"#cobj      %s\n",base->getInstanceName());
     }
   }else if ((long)base->getUserData(WS_EXT_VAR) == 1){
     sprintf(buffer,"#OBJ       %s\n",base->getInstanceName());
   }else{
     sprintf(buffer,"#obj       %s\n",base->getInstanceName());
   }
   str2.addString(buffer);
   sprintf(buffer," #TYPE       %s\n",base->getClassName());
   str2.addString(buffer);

   if (parent == NULL){
     sprintf(buffer," #PARENT   NULL\n");
   }else{
     sprintf(buffer," #PARENT   %s\n",parent->getInstanceName());
   }
   str2.addString(buffer);


   WSClistData* prc_list = base->getProcedureList();
   long num = prc_list->getNum();
   long i;
   for(i=0; i< num; i++){
     WSCprocedure* ac = (WSCprocedure*)(*prc_list)[i];
     if (ac->getInternal() != False){
       continue;
     }
     sprintf(buffer," #PROC  %s\n",ac->getProcName());
     str2.addString(buffer);
     sprintf(buffer,"  #TRIG    %d\n",ac->getTrigger());
     str2.addString(buffer);
     if (ac->getUseFile() == False){
       sprintf(buffer,"  #PRO   %s\n\n",ac->getFunctionName());
     }else{
       sprintf(buffer,"  #PRO   %s.cpp\n\n",ac->getFunctionName());
     }
     str2.addString(buffer);

   }

   WSClistData props;
   WSGFgetAllPropertyList(base,&props);
//   WSClistData* props = base->getClassInformation()->getAllPropertyList();
   WSCproperty* prop;
   num = props.getNum();
   for(i=0; i< num; i++){
     prop = (WSCproperty*)props[i];
//     WSCbool def = prop->isDefaultValue(base);
     WSCbool def = True;
     base->isDefaultValue(prop->getPropObjName(),&def);
     if (def != False){
       continue;
     }
     if (!strcmp("name",prop->getPropObjName())){
       continue;
     }
     if (base->getDataSourceType() != WS_DATA_SOURCE_NONE &&
        !strcmp(prop->getPropObjName(),base->getDataSourcePropertyName())){
       continue;
     }

     sprintf(buffer," #RES      %s\n",prop->getPropObjName());
     str2.addString(buffer);

     sprintf(buffer,"%s",(char*)base->getProperty(prop->getPropObjName()));
     WSCstring sdata;
     sdata.setString(buffer);
     sdata.replaceString("\n","\\n",0);
     str2.addString(sdata.getString());
     str2.addString("\n");
   }

   WSClistData* prprc_list = (WSClistData*)base->getUserData(WS_PROP_LIST);
   if (prprc_list != NULL){
     num = prprc_list->getNum();
     for(i=0; i<num; i++){
       prop_data* propdata = (prop_data*)(*prprc_list)[i];
       if( !strcmp(propdata->vname.getString(),"")){
          propdata->vname.setString("dummy");
       }
       if (!strcmp(propdata->values.getString(),"")){
         sprintf(buffer," #res\t%s\t%s\t%d\t%d\t%d\t%s\n",propdata->name.getString(),
                       propdata->vname.getString(),
                       propdata->type,
                       propdata->use_file,
                       propdata->att,
                       propdata->bname.getString());
       }else{
         sprintf(buffer," #res#%s\t%s\t%s\t%d\t%d\t%d\t%s\n",propdata->values.getString(),
                       propdata->name.getString(),
                       propdata->vname.getString(),
                       propdata->type,
                       propdata->use_file,
                       propdata->att,
                       propdata->bname.getString());
       }
       str2.addString(buffer);
       sprintf(buffer,"%s",propdata->value.getString());
       WSCstring sdata;
       sdata.setString(buffer);
       sdata.replaceString("\n","\\n",0);
       str2.addString(sdata.getString());
       str2.addString("\n");
     }
   }
   WSClistData* prut_list = (WSClistData*)base->getUserData(WS_UTRG_LIST);
   if (prut_list != NULL){
     num = prut_list->getNum();
     for(i=0; i<num; i++){
       utrg_data* utrgdata = (utrg_data*)(*prut_list)[i];
       sprintf(buffer," #utrg\t%s\t%s\t%d\n",utrgdata->name.getString(),
                       utrgdata->vname.getString(),utrgdata->type);
       str2.addString(buffer);
       sprintf(buffer,"%d",utrgdata->value);
       WSCstring sdata;
       sdata.setString(buffer);
       sdata.replaceString("\n","\\n",0);
       str2.addString(sdata.getString());
       str2.addString("\n");
     }
   }
   WSClistData* tlist = (WSClistData*)base->getUserData(WS_TRG_LIST);
   if (tlist != NULL){
     num = tlist->getNum();
     for(i=0; i<num; i++){
       long trg = (long)(*tlist)[i];
       sprintf(buffer," #trg\t%d\n",trg);
       str2.addString(buffer);
     }
   }

   if ((char*)base->getUserData(WS_CLASS_ICON) != NULL){
       sprintf(buffer," #icon\t%s\n",(char*)base->getUserData(WS_CLASS_ICON));
       str2.addString(buffer);
   }

   if ((char*)base->getUserData(WS_CLASS_COMMENT) != NULL){
       sprintf(buffer," #com\t%s\n",(char*)base->getUserData(WS_CLASS_COMMENT));
       str2.addString(buffer);
   }

   if ((char*)base->getUserData(WS_WIN_CLASS_BASE) != NULL){
       sprintf(buffer," #cbase\t%s\n",(char*)base->getUserData(WS_WIN_CLASS_BASE));
       str2.addString(buffer);
   }

   WSClistData* rmlist = (WSClistData*)base->getUserData(WS_RMETHOD_LIST);
   if (rmlist != NULL){
     num = rmlist->getNum();
     for(i=0; i<num; i++){
       rmethod_data* rmdata = (rmethod_data*)(*rmlist)[i];
       sprintf(buffer," #rmethod\t%s,%s\n%s\n",
           (char*)rmdata->type_name,(char*)rmdata->name,
           (char*)rmdata->params);
       str2.addString(buffer);
     }
   }
   char* rcname = (char*)base->getUserData(WS_RCLASS_NAME);
   if (rcname != NULL){
     WSCstring tmp;
     tmp << " #rcname " << rcname <<"\n";
     str2 << tmp;
   }
   char* brcname = (char*)base->getUserData(WS_RCLASS_BNAME);
   if (brcname != NULL){
     WSCstring tmp;
     tmp << " #brcname " << brcname <<"\n";
     str2 << tmp;
   }



   str2.addString("\n");

   str->addString(str2.getString());

   num = children.getNum();
   WSClistData clist;
   for(i=0; i<num; i++){
      WSCbase* child = (WSCbase*)children[i];
      if (child->getInternalObject() == False){
        WSCstring* cdata = new WSCstring;
        WSGFcreateWinData(cdata,base,child);
        clist.add((void*)cdata);
      }
   }

   WSCstring str3;
   _append(&clist,&str3);
   str->addString(str3.getString());

   num = clist.getNum();
   for(i=0; i<num; i++){
     WSCstring* cdata = (WSCstring*)clist[i];
     delete cdata;
   }
}

WSCstring WSGFcreateWinSrc(WSCbase* win){
  WSCstring str;
  WSGFcreateWinData(&str,NULL,win);
  return str;
}

char* WSGFcreateName(char* winname,char* classname){
static char buffer[32];
static int  num=0;
char tmp[16];
   strcpy(buffer,"___________");
   if (!strncmp(winname,"WSC",3) || !strncmp(winname,"WSD",3)){
     strncpy(tmp,&winname[3],3);
   }else{
     strncpy(tmp,winname,3);
   }
   tmp[3]=0;
   memcpy(buffer,tmp,strlen(tmp));
   if (strlen(classname) < 4){
     strcpy(tmp,"AAAAA");
   }else{
     strncpy(tmp,&(classname[3]),5);
   }
   tmp[4]=0;
   memcpy(&(buffer[3]),tmp,strlen(tmp));
   sprintf(tmp,"%03d",num);
   tmp[3]=0;
   memcpy(&(buffer[11-strlen(tmp)]),tmp,strlen(tmp));
   buffer[11]=0;
   num++;
   WSCbase* base = WSGIappObjectList()->getInstance("WSCbase",buffer);
   if ( base != NULL){
     return WSGFcreateName(winname,classname);
   }
//printf("WSGFcreateName ret=%s\n",buffer);
   return buffer;
}

WSCbool WSGFneedGenerateRemoteClass(WSCbase* inst){
  WSCbase* cbase = (WSCbase*)inst->getUserData(WS_WIN_CLASS_BASE);
  if (cbase != NULL){
    if (cbase->getUserData(WS_RCLASS_GENERATE)){
      return True;
    }else{
      return False;
    }
  }else{
    if (inst->getUserData(WS_RCLASS_GENERATE)){
      return True;
    }else{
      return False;
    }
  }
  return False;
}

WSCstring WSGFcreateVirtualRemoteClassHeader(WSCbase* inst){
  WSClistData* rdata = (WSClistData*)inst->getUserData(WS_RMETHOD_LIST);
  WSCstring cname = inst->getInstanceName();
  WSCstring ret;
  char* rcname = (char*)inst->getUserData(WS_RCLASS_NAME);
  if (rcname == NULL){
    WSCstring tmp;
    tmp = inst->getInstanceName();
    if (!strncmp((char*)tmp,"WSC",3)){
      tmp.replaceString("WSC","WSCR",1);
    }else{
      WSCstring tmp2;
      tmp2 << "WSCR" << tmp;
      tmp = tmp2;
    }
    rcname = WSGFstrdup((char*)tmp);
  }

  char* rbcname = (char*)inst->getUserData(WS_RCLASS_BNAME);
  if (rcname == NULL){
    WSCstring tmp;
    tmp = inst->getClassName();
    if (!strncmp((char*)tmp,"WSC",3)){
      tmp.replaceString("WSC","WSCR",1);
    }else{
      WSCstring tmp2;
      tmp2 << "WSCR" << tmp;
      tmp = tmp2;
    }
    rbcname = WSGFstrdup((char*)tmp);
  }

  ret =  "//----------------------------------------------------//\n";
  ret << "// Wide Studio Application C++ Source File            //\n";
  ret << "//            created by Wide Studio source generator //\n";
  ret << "//----------------------------------------------------//\n";
  ret << "#ifndef " << rcname << "_H\n";
  ret << "#define " << rcname << "_H\n\n";
  ret << "#include <WScom.h>\n";
  ret << "#include <" << rbcname << ".h>\n";

  ret << "class ";
  ret << rcname << " :public ";
  ret << rbcname << " {\n\n";
  ret << " public:\n";
  ret << "  " << rcname << "();\n";
  ret << "  ~" << rcname << "();\n\n";

  if (rdata != NULL){

    long i;
    long num = rdata->getNum();

    for(i=0; i<num; i++){
      rmethod_data* rmdata =(rmethod_data*)(*rdata)[i];
      if (rmdata != NULL){
        ret << "  " << rmdata->type_name << " "
            << rmdata->name << "(";
        WSCstring params;
        params = rmdata->params;
        long j;
        long pnum = params.getWords(",");
        for(j=0; j<pnum; j++){
          WSCstring tname;
          WSCstring pname;
          tname = params.getWord(j,",");
          j++;
          pname = params.getWord(j,",");
          ret << tname << " " << pname;
          if (j+1 < pnum){
            ret << ",";
          }
        }
        ret << ");\n";
      }
    }

  }
  ret << "  WSMFclassDef(" << rcname << "," <<
          rbcname << ");\n";
  ret << "};\n";
  ret << "#endif\n";
  return ret;
}

WSCstring WSGFcreateVirtualRemoteClassSrc(WSCbase* inst){
  WSClistData* rdata = (WSClistData*)inst->getUserData(WS_RMETHOD_LIST);
  WSCstring cname = inst->getInstanceName();
  WSCstring ret;
  char* rcname = (char*)inst->getUserData(WS_RCLASS_NAME);
  if (rcname == NULL){
    WSCstring tmp;
    tmp = inst->getInstanceName();
    if (!strncmp((char*)tmp,"WSC",3)){
      tmp.replaceString("WSC","WSCR",1);
    }else{
      WSCstring tmp2;
      tmp2 << "WSCR" << tmp;
      tmp = tmp2;
    }
    rcname = WSGFstrdup((char*)tmp);
  }

  char* rbcname = (char*)inst->getUserData(WS_RCLASS_BNAME);
  if (rcname == NULL){
    WSCstring tmp;
    tmp = inst->getClassName();
    if (!strncmp((char*)tmp,"WSC",3)){
      tmp.replaceString("WSC","WSCR",1);
    }else{
      WSCstring tmp2;
      tmp2 << "WSCR" << tmp;
      tmp = tmp2;
    }
    rbcname = WSGFstrdup((char*)tmp);
  }

  ret =  "//----------------------------------------------------//\n";
  ret << "// Wide Studio Application C++ Source File            //\n";
  ret << "//            created by Wide Studio source generator //\n";
  ret << "//----------------------------------------------------//\n";

  ret << "#include <WScom.h>\n";
  ret << "#include <" << rcname << ".h>\n";
  ret << "#include <" << inst->getInstanceName() << ".h>\n";
  ret << "#include <WSCbase.h>\n";
  ret << "#include <WSCbaseList.h>\n\n";
  ret << "WSMFclassInit(" << rcname << "," << rbcname << ");\n";
  ret << "WSMFremoteClassInit(" << rcname << "," << inst->getInstanceName() << ");\n\n";

  ret << rcname << "::" << rcname << "(){\n}\n\n";
  ret << rcname << "::~" << rcname << "(){\n}\n\n";

  if (rdata != NULL){

    long i;
    long num = rdata->getNum();

    for(i=0; i<num; i++){
      rmethod_data* rmdata =(rmethod_data*)(*rdata)[i];
      if (rmdata != NULL){
        ret << rmdata->type_name << " " << rcname << "::"
            << rmdata->name << "(";
        WSCstring params;
        params = rmdata->params;
        long j;
        long pnum = params.getWords(",");
        for(j=0; j<pnum; j++){
          WSCstring tname;
          WSCstring pname;
          if (!strcmp(pname,"")){
            pname << "p"<< j;
          }
          tname = params.getWord(j,","); j++;
          pname = params.getWord(j,",");
          ret << tname << " " << pname;
          if (j+1 < pnum){
            ret << ",";
          }
        }
        ret << "){\n";
        ret << "  if (_local != NULL){\n";
        ret << "    " << inst->getInstanceName() << "* item = (";
        ret << inst->getInstanceName() << "*)_local->cast(\"";
        ret << inst->getInstanceName() << "\");\n";
        ret << "    if (item != NULL){\n";
        if (strcmp((char*)rmdata->type_name,"void")){
          ret << "      return item->" << rmdata->name << "(";
        }else{
          ret << "      item->" << rmdata->name << "(";
        }
        for(j=0; j<pnum; j++){
          WSCstring pname;
          j++;
          pname = params.getWord(j,",");
          if (!strcmp(pname,"")){
            pname << "p"<< j;
          }
          ret << pname;

          if (j+1 < pnum){
            ret << ",";
          }
        }
        ret << ");\n";
        if (!strcmp((char*)rmdata->type_name,"void")){
          ret << "      return;\n";
        }
        ret << "    }\n";
        ret << "  }\n";
        ret << "  WSCremoteCall rc;\n";
        ret << "  rc.setClassName(\"" << inst->getInstanceName() << "\");\n";
        ret << "  rc.setOperationName(\"" << rmdata->name << "\");\n";
        ret << "  beginRemoteCall(&rc);\n";
        ret << "  if (_db == NULL){\n";
        if (!strcmp((char*)rmdata->type_name,"void")){
          ret << "    return;\n";
        }else
        if (!strcmp((char*)rmdata->type_name,"char*")){
          ret << "    return "";\n";
        }else{
          ret << "    return 0;\n";
        }
        ret << "  }\n";

        for(j=0; j<pnum; j++){
          WSCstring tname;
          WSCstring pname;
          if (!strcmp(pname,"")){
            pname << "p"<< j;
          }

          tname = params.getWord(j,",");
          j++;
          pname = params.getWord(j,",");
          if (!strcmp( get_type_name2((char*)tname) ,"String")){
            ret << "  _db->save(WS_DcRString,\""
                << pname << "\",(void*)" << pname << ");\n";
          }else{
            ret << "  _db->save(WS_DcR" << get_type_name2((char*)tname) 
                << ",\"" << pname << "\",(void*)&" << pname << ");\n";
          }

        }
        if (!strcmp((char*)rmdata->type_name,"void")){
        }else
        if (!strcmp((char*)rmdata->type_name,"char*")){
          ret << " char* ret;";
          ret << " _db->loadAlloc(WS_DcRString,\"ret\",(void**)&ret,NULL);\n";
        }else{
          ret << "  " << rmdata->type_name << " ret;\n";
          ret << " _db->load(WS_DcR"
                << get_type_name2((char*)rmdata->type_name) 
                << ",\"ret\",(void**)&ret);\n";
        }
        ret << "  endRemoteCall();\n";
        if (!strcmp((char*)rmdata->type_name,"void")){
          ret << "  return;\n";
        }else{
          ret << "  return ret;\n";
        }
      }
      ret << "}\n";
    }
  }
  ret << "void _" << inst->getInstanceName()
      << "_remote_call(WSDserialize* db,WSCremoteCall* rc){\n";
  long i;
  long num = rdata->getNum();
  for(i=0; i<num; i++){
    rmethod_data* rmdata =(rmethod_data*)(*rdata)[i];
    if (rmdata != NULL){
      ret << "  if (!strcmp(rc->_op,\"" << rmdata->name << "\")){\n";
      ret << "    WSCbase* inst ="
          << " WSGIappObjectList()->getInstance(rc->_class,rc->_instance);\n";

      if (!strcmp((char*)rmdata->type_name,"void")){
      }else
      if (!strcmp( (char*)rmdata->type_name ,"char*")){
        ret << "    WSCstring ret;\n";
      }else{
        ret << "    " << rmdata->type_name << " ret = 0;\n";
      }

      ret << "    if (inst != NULL){\n";
      ret << "      " << inst->getInstanceName() << "* target = ("
          << inst->getInstanceName() << "*)inst->cast(\""
          << inst->getInstanceName() << "\");\n";
      WSCstring params;
      params = rmdata->params;
      long j;
      long pnum = params.getWords(",");
      for(j=0; j<pnum; j++){
        WSCstring tname;
        WSCstring pname;
        if (!strcmp(pname,"")){
          pname << "p"<< j;
        }
        tname = params.getWord(j,","); j++;
        pname = params.getWord(j,",");

        if (!strcmp( get_type_name2((char*)tname) ,"String")){
          ret << "      char* " << pname << ";\n";
          ret << "      db->loadAlloc(WS_DcRString,\""
              << pname << "\",(void**)&" << pname << ",NULL);\n";
          ret << "      WSCstring " << pname << "_tmp;\n";
          ret << "      " << pname << "_tmp.setString(" << pname
              << ",WS_EN_UTF8);\n";
        }else{
          ret << "      " << tname << " " << pname << ";\n";
          ret << "      db->load(WS_DcR" << get_type_name2((char*)tname) 
              << ",\"" << pname << "\",(void*)&" << pname << ");\n";
        }
      }
      ret << "      if (target != NULL){\n";
      if (!strcmp(rmdata->type_name,"void")){
        ret << "        target->" << rmdata->name << "(";
      }else
      if (!strcmp( (char*)rmdata->type_name ,"char*")){
        ret << "        ret.setString( target->" << rmdata->name << "(";
      }else{
        ret << "        ret = target->" << rmdata->name << "(";
      }
      for(j=0; j<pnum; j++){
        WSCstring tname;
        WSCstring pname;
        if (!strcmp(pname,"")){
          pname << "p"<< j;
        }
        tname = params.getWord(j,","); j++;
        pname = params.getWord(j,",");

        if (!strcmp( get_type_name2((char*)tname) ,"String")){
          ret << pname << "_tmp";
        }else{
          ret << pname;
        }
        if (j+1 < pnum){
          ret << ",";
        }
      }
      ret << ")";
      if (!strcmp((char*)rmdata->type_name,"void")){
        ret << ";\n";
        ret << "        return;\n";
        ret << "      }\n";
        ret << "    }\n";
        ret << "    return;\n";
      }else
      if (!strcmp( (char*)rmdata->type_name ,"char*")){
        ret << ",WSGIappLocaleSet()->getDefaultEncoding());\n";
        ret << "      }\n";
        ret << "    }\n";
        ret << "    db->save(WS_DcR"
            << get_type_name2((char*)rmdata->type_name)
            << ",\"ret\",(void*)ret.getString(WS_EN_UTF8));\n";
        ret << "    return;\n";
      }else{
        ret << ";\n";
        ret << "      }\n";
        ret << "    }\n";
        ret << "    db->save(WS_DcR"
            << get_type_name2((char*)rmdata->type_name)
            << ",\"ret\",(void*)&ret);\n";
        ret << "    return;\n";
      }
      if (i+1<num){
        ret << "  }else\n";
      }else{
        ret << "  }\n";
      }
    }
  }
//XXZZ
  ret << "extern void _" << inst->getClassName()
      << "_remote_call(WSDserialize* db,WSCremoteCall* rc);\n";
  ret << "  _" << inst->getClassName() << "_remote_call(db,rc);\n}\n\n";

  ret << "WSMFdefineDrNetServer(" << inst->getInstanceName()
      << ",_" << inst->getInstanceName() << "_remote_call);\n\n";
  return ret;
}




