//
// 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.

#ifdef TE
#include <tstring.h>
#include <btron/bsocket.h>
//extern "C" {
//#include "fileio.c"
//};
#endif

#include <basic.h>
#include <btron/tf.h>
#include <btron/WSDbtronAppDev.h>
#include <WSDfont.h>
#include <WSDdev.h>
#include <btron/WSDbtronMouse.h>
#include <btron/WSDbtronColor.h>
#include <btron/WSDbtronDraw.h>

#ifdef TE
extern "C" {
char* getcwd(char* buf,unsigned int len){
  strncpy(buf,"/SYS",len);
  return buf;
}
int chdir(const char* path){
  return 0;
}
int gettimeofday(struct timeval *__tv,
                  struct timezone *__tz){
  __tv->tv_sec = 0;
  __tv->tv_usec = 0;
  __tz->tz_minuteswest = 0;
  __tz->tz_dsttime = 0;
  return 0;
}
char* getenv(const char*){
  return NULL;
}
};
#endif

void WSGFsetRect(RECT* r,short x,short y,WSCushort w,WSCushort h){
  r->c.left = x;
  r->c.top = y;
  r->c.right = x+w;
  r->c.bottom = y+h;
}


TF_CTX tc_to_string_ctx = NULL;
TF_CTX string_to_tc_ctx = NULL;

char* WSGFbtronTcToString(TC* src){
//#ifndef TE
  if (tc_to_string_ctx == NULL){
    ERR ret = tf_open_ctx(&tc_to_string_ctx);
    if( ret != 0){
      return NULL;
    }
    tf_init_charset(tc_to_string_ctx);
    W id = tf_to_id( TF_ID_PROFSET_CONVERTTO,"UTF-8");
    if (id < 0){
//printf("here1 %d 0x%x\n",ret,ret);
      return NULL;
    }
    ret = tf_set_profile(tc_to_string_ctx, id);
    if (ret < 0){
//printf("here2 %d 0x%x\n",ret,ret);
      return NULL;
    }
  }
  if (tc_to_string_ctx == NULL){
    return NULL;
  }
  W len;
//  WERR ret = tf_tcstostr(tc_to_string_ctx,src,-1,TSC_UNI1,TF_ATTR_START,
  WERR ret = tf_tcstostr(tc_to_string_ctx,src,-1,TSC_SYS,TF_ATTR_START,
                         NULL,&len);
  if (ret < 0){
    return NULL;
  }
  UB* buffer = new UB[len+1];
  ret = tf_tcstostr(tc_to_string_ctx,src,-1,TSC_SYS,TF_ATTR_START,
//  ret = tf_tcstostr(tc_to_string_ctx,src,-1,TSC_UNI1,TF_ATTR_START,
                         buffer,&len);
  if (ret < 0){
    if (buffer != NULL){
      delete buffer;
    }
    return NULL;
  }
  buffer[len] = 0;
  return (char*)buffer;
//#endif
//  return NULL;
}

TC* WSGFbtronStringToTc(char* src,long* tlen){
//#ifdef TE
//  WSCstring str(src,WS_EN_UTF8);
//  long tclen = eucstotcs(NULL,(UB*)str.getString(WS_EN_EUCJP));
//  TC* tstr2 = new TC[tclen+8];
//  eucstotcs(tstr2,(UB*)str.getString(WS_EN_EUCJP));
//  *tlen = tclen;
//  return tstr2;
//#else
  if (string_to_tc_ctx == NULL){
    ERR ret = tf_open_ctx(&string_to_tc_ctx);
    if( ret != 0){
      return NULL;
    }
    tf_init_charset(string_to_tc_ctx);
    W id = tf_to_id( TF_ID_PROFSET_CONVERTFROM,"UTF-8");
//    W id = tf_to_id( TF_ID_PROFSET_CONVERTFROM,"US-ASCII");
    if (id < 0){
      return NULL;
    }
    ret = tf_set_profile(string_to_tc_ctx, id);
    if (ret < 0){
      return NULL;
    }
// 2 -> 2332 
#if 0
    id = tf_to_id( TF_ID_CHARSET,"UTF-8");
    if (id < 0){
      return NULL;
    }
    ret = tf_set_profile(string_to_tc_ctx, id);
#endif
#if 0
    id = tf_to_id( TF_ID_OPT_CONVERT,"CONV_SBCHAR_HAN");
    if (id < 0){
      return NULL;
    }
    ret = tf_set_options(string_to_tc_ctx,id,1);
#endif
  }
  if (string_to_tc_ctx == NULL){
    return NULL;
  }


  W len;
  WERR ret2 = tf_strtotcs(string_to_tc_ctx,(UB*)src,-1,TF_ATTR_START,NULL,&len);
//                          TF_ATTR_START|TF_ATTR_SUPPRESS_FUSEN,NULL,&len);

  if (ret2 < 0){
    return NULL;
  }
  TC* tcs = new TC[len+1];
  if (tcs == NULL){
    return NULL;
  }
  tcs[len] = 0;
  ret2 = tf_strtotcs(string_to_tc_ctx,(UB*)src,-1,TF_ATTR_START,tcs,&len);
//                          TF_ATTR_START|TF_ATTR_SUPPRESS_FUSEN,tcs,&len);
  if (ret2 < 0){
    if (tcs != NULL){
      delete tcs;
    }
    return NULL;
  }
//{
//printf("#%s# ",src);
//  long i;
//  for(i=0; i<len+1; i++){
//printf("0x%x ",tcs[i]);
//  }
//printf("\n");
//}
  *tlen = len;
  return tcs;
//#endif
}
TC* WSGFbtronStringToTc2(char* src,long* tlen){
  if (string_to_tc_ctx == NULL){
    ERR ret = tf_open_ctx(&string_to_tc_ctx);
    if( ret != 0){
      return NULL;
    }
    tf_init_charset(string_to_tc_ctx);
    W id = tf_to_id( TF_ID_PROFSET_CONVERTFROM,"UTF-8");
//    W id = tf_to_id( TF_ID_PROFSET_CONVERTFROM,"US-ASCII");
    if (id < 0){
      return NULL;
    }
    ret = tf_set_profile(string_to_tc_ctx, id);
    if (ret < 0){
      return NULL;
    }
  }
  if (string_to_tc_ctx == NULL){
    return NULL;
  }


  W len;
  WERR ret2 = tf_strtotcs(string_to_tc_ctx,(UB*)src,-1,
                          TF_ATTR_START|TF_ATTR_SUPPRESS_FUSEN,NULL,&len);

  if (ret2 < 0){
    return NULL;
  }
  TC* tcs = new TC[len+1];
  if (tcs == NULL){
    return NULL;
  }
  tcs[len] = 0;
  ret2 = tf_strtotcs(string_to_tc_ctx,(UB*)src,-1,
                          TF_ATTR_START|TF_ATTR_SUPPRESS_FUSEN,tcs,&len);
  if (ret2 < 0){
    if (tcs != NULL){
      delete tcs;
    }
    return NULL;
  }
  *tlen = len;
  return tcs;
}

TC begin_ascii[5] = { 0xffa2,0x6,0x300,0,0x102 };
TC begin_2byte[5] = { 0xffa2,0x6,0x300,0,0 };

void _btron_draw_string(TC* str,WSDfont* fn,GID gid,W fg,W bg,long op,long slen,
       long cur,WSCbool inter_cur,long lw,long scur1,long scur2,long x,long y){
  WSCbool onebyte = False;
  long sptr = 0;
  long ptr = 0;
  long bcur = -1;
  long icur = -1;
  FSSPEC* fnt = (FSSPEC*)fn->getValue1();
  FSSPEC* fnt_ascii = (FSSPEC*)fn->getValue3();
  long cnt = 0;
  if (inter_cur == 0 && cur > -1){
    bcur = cur;
  }
  if (inter_cur != 0 && cur > -1){
    icur = cur;
  }
  long diffx = 0;
  while(1){
//printf("> cnt=%d s1=%d s2=%d diffx=%d icur=%d\n",cnt,scur1,scur2,diffx,icur);
    if (str[ptr] == 0xffa2){
      if (!memcmp(begin_ascii,&str[ptr],sizeof(TC)*5)){
        long tclen = ptr - sptr;
        TC* buf = new TC[tclen+1];
        memcpy(buf,&str[sptr],sizeof(TC)*tclen);
        buf[tclen] = 0;

        if (onebyte == False){
          gset_fon(gid,fnt);
          diffx += (fnt->size.h * tclen);
        }else{
          gset_fon(gid,fnt_ascii);
          diffx += (fnt_ascii->size.h * tclen);
        }
        if (op == G_AND){
          if (WSGIbtronAppDev()->haveColorMap() == False){
            gset_chc(gid,0x10000000,0x10ffffff);
          }else{
            gset_chc(gid,0x10ffffff,0x10000000);
          }
          gdra_str(gid,buf,tclen,G_AND);
        }else{
          if ((scur1 < cnt && cnt <= scur2) || cnt == bcur){
            gset_chc(gid,bg,fg);
            gdra_str(gid,buf,tclen,G_STORE);
          }else{
            if (WSGIbtronAppDev()->haveColorMap() == False){
              gset_chc(gid,fg,0x10000000);
            }else{
              gset_chc(gid,fg,0x10ffffff);
            }
            gdra_str(gid,buf,tclen,G_OR);
          }
        }
        delete buf;
        ptr +=5;
        sptr = ptr;
        onebyte = True;
      }else
      if (!memcmp(begin_2byte,&str[ptr],sizeof(TC)*5)){
        long tclen = ptr - sptr;
        TC* buf = new TC[tclen+1];
        memcpy(buf,&str[sptr],sizeof(TC)*tclen);
        buf[tclen] = 0;

        if (onebyte == False){
          gset_fon(gid,fnt);
          diffx += (fnt->size.h * tclen);
        }else{
          gset_fon(gid,fnt_ascii);
          diffx += (fnt_ascii->size.h * tclen);
        }
        if (op == G_AND){
          if (WSGIbtronAppDev()->haveColorMap() == False){
            gset_chc(gid,0x10000000,0x10ffffff);
          }else{
            gset_chc(gid,0x10ffffff,0x10000000);
          }
          gdra_str(gid,buf,tclen,G_AND);
        }else{
//printf("cnt=%d s1=%d s2=%d\n",cnt,scur1,scur2);
          if ((scur1 < cnt && cnt <= scur2) || cnt == bcur){
            gset_chc(gid,bg,fg);
            gdra_str(gid,buf,tclen,G_STORE);
          }else{
            if (WSGIbtronAppDev()->haveColorMap() == False){
              gset_chc(gid,fg,0x10000000);
            }else{
              gset_chc(gid,fg,0x10ffffff);
            }
            gdra_str(gid,buf,tclen,G_OR);
          }
        }

        delete buf;
        ptr +=5;
        sptr = ptr;
        onebyte = False;
      }
    }
    if ( ((scur1 < scur2 ) && ((cnt == scur1) || (cnt == scur2)))||
         (cnt == icur && icur > 0) ||
         (cnt == bcur) ||
         (cnt+1 == bcur) ||
         (ptr == slen)){
//printf(" >> cnt=%d s1=%d s2=%d\n",cnt,scur1,scur2);
      long tclen = ptr - sptr;
      if (onebyte == False){
        gset_fon(gid,fnt);
        diffx += (fnt->size.h * tclen);
        if (op == G_AND){
          if (WSGIbtronAppDev()->haveColorMap() == False){
            gset_chc(gid,0x10000000,0x10ffffff);
          }else{
            gset_chc(gid,0x10ffffff,0x10000000);
          }
          gdra_str(gid,&str[sptr],tclen,G_AND);
        }else{
//printf("cnt=%d s1=%d s2=%d\n",cnt,scur1,scur2);
          if ((scur1 < cnt && cnt <= scur2) || cnt == bcur){
            gset_chc(gid,bg,fg);
            gdra_str(gid,&str[sptr],tclen,G_STORE);
          }else{
            if (WSGIbtronAppDev()->haveColorMap() == False){
              gset_chc(gid,fg,0x10000000);
            }else{
              gset_chc(gid,fg,0x10ffffff);
            }
            gdra_str(gid,&str[sptr],tclen,G_OR);
          }
        }

      }else{
        gset_fon(gid,fnt_ascii);
        diffx += (fnt_ascii->size.h * tclen);
        if (op == G_AND){
          if (WSGIbtronAppDev()->haveColorMap() == False){
            gset_chc(gid,0x10000000,0x10ffffff);
          }else{
            gset_chc(gid,0x10ffffff,0x10000000);
          }
          gdra_str(gid,&str[sptr],tclen,G_AND);
        }else{
//printf("cnt=%d s1=%d s2=%d\n",cnt,scur1,scur2);
          if ((scur1 < cnt && cnt <= scur2) || cnt == bcur){
            gset_chc(gid,bg,fg);
            gdra_str(gid,&str[sptr],tclen,G_STORE);
          }else{
            if (WSGIbtronAppDev()->haveColorMap() == False){
              gset_chc(gid,fg,0x10000000);
            }else{
              gset_chc(gid,fg,0x10ffffff);
            }
            gdra_str(gid,&str[sptr],tclen,G_OR);
          }
        }
      }
      sptr = ptr;
    }
//printf("op=%d icur=%d cnt=%d\n",op,icur,cnt);
    if (op == G_OR && icur == cnt){
      PAT pat; 
      pat.spat.kind = 0;
      pat.spat.hsize = 16;
      pat.spat.vsize = 16;
      pat.spat.fgcol = fg;
      pat.spat.bgcol = fg;
      pat.spat.mask = FILL100;
      RECT r;
      r.c.left = x + diffx;
      r.c.right = x + diffx + 3;
      r.c.top = y - fnt->size.v;
      r.c.bottom = y;
      gfil_rec(gid,r,&pat,0,G_STORE);
//printf("fill %d,%d,%d,%d\n",x,y - fnt->size.v,lw,fnt->size.v);
    }
    if (ptr == slen){
      break;
    }
    if (ptr > slen){
      break;
    }
    ptr++;
    cnt++;
  }

}


void WSGFbtronDrawString(TC* str,WSDfont* fn,GID gid,W fg,W bg,long len,short x,short y,long cur,WSCbool inter_cur,long lw,long scur1,long scur2){
  gset_chp(gid,x,y,(Bool)True);
  _btron_draw_string(str,fn,gid,fg,bg,G_AND,len,cur,inter_cur,lw,scur1,scur2,x,y);
  gset_chp(gid,x,y,(Bool)True);
  _btron_draw_string(str,fn,gid,fg,bg,G_OR,len,cur,inter_cur,lw,scur1,scur2,x,y);
}
short WSGFbtronGetStringWidth(TC* str,WSDfont* fn,long slen){
  WSCbool onebyte = False;
  long sptr = 0;
  long ptr = 0;
  FSSPEC* fnt = (FSSPEC*)fn->getValue1();
  FSSPEC* fnt_ascii = (FSSPEC*)fn->getValue3();
  W fdesc = fn->getValue2();
  GID fgid = WSGIbtronAppDev()->getFontGid();
  W ret = 0;
  while(1){
    if (str[ptr] == 0xffa2){
      if (!memcmp(begin_ascii,&str[ptr],sizeof(TC)*5)){
        long tclen = ptr - sptr;
        TC* buf = new TC[tclen+1];
        memcpy(buf,&str[sptr],sizeof(TC)*tclen);
        buf[tclen] = 0;
        if (onebyte == False){
          gset_fon(fgid,fnt);
        }else{
          gset_fon(fgid,fnt_ascii);
        }
        W width = gget_stw(fgid,buf,tclen,NULL,NULL);
        ret += width;

        delete buf;
        ptr +=5;
        sptr = ptr;
        onebyte = True;
      }else
      if (!memcmp(begin_2byte,&str[ptr],sizeof(TC)*5)){
        long tclen = ptr - sptr;
        TC* buf = new TC[tclen+1];
        memcpy(buf,&str[sptr],sizeof(TC)*tclen);
        buf[tclen] = 0;
        if (onebyte == False){
          gset_fon(fgid,fnt);
        }else{
          gset_fon(fgid,fnt_ascii);
        }

        W width = gget_stw(fgid,buf,tclen,NULL,NULL);
        ret += width;

        delete buf;
        ptr +=5;
        sptr = ptr;
        onebyte = False;
      }
    }
    if (ptr == slen){
      long tclen = ptr - sptr;
      if (onebyte == False){
        gset_fon(fgid,fnt);
      }else{
        gset_fon(fgid,fnt_ascii);
      }
      W width = gget_stw(fgid,&str[sptr],tclen,NULL,NULL);
      ret += width;
      break;
    }
    if (ptr > slen){
      break;
    }
    ptr++;
  }
  return ret;
}

int main1(int argc,char** argv){
#ifdef TDBG
dbprintf("main start:\n");
WSMFtrace("main start:\n");
WSGFsetTimePoint();
#endif

//    W er = opendbox(&lnk, USER_DATA, 0x2000);
//  chg_emk(EM_ALL);
  LINK    lnk;
  prc_inf(0, PI_LINK, (VP)&lnk, sizeof(LINK));
  dopn_dat(&lnk);


dbprintf("Main.cpp: main1() %s:%d stargetd.\n",__FILE__,__LINE__);
   WSDdev::setDraw(new WSDbtronDraw());

   WSDappDev* app = WSGIappDev();
   WSDbtronAppDev* btronApp = (WSDbtronAppDev*)app->cast("WSDbtronAppDev");
   if (argc != 0){
     btronApp->setInitPrm(argc,argv);
   }
   btronApp->initialize();
   WSGIbtronAppMouse()->initialize();

//   WSDbtronColor::restart_blink_server();

   extern void _btronFont_init();
   _btronFont_init();

#ifdef TDBG
dbprintf("main init done.:%d\n",WSGFdiffTimePoint());
WSMFtrace("main init done.:%d\n",WSGFdiffTimePoint());
#endif
dbprintf("Main.cpp: main1() %s:%d done.\n",__FILE__,__LINE__);
  return 0;
}

int WSGFwsInitialize(){
  main1(0,NULL);
  return 0;
}




