//
// 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 <X11/Xlib.h>
#include <WScom.h>
#include <WSCfontSet.h>
#include <x11/WSDxfont.h>
#include <x11/WSDxappDev.h>
#include <WSClocaleSet.h>
#include <xunicode.h>


#define DEFAULT_FONT_SET  "14 iso8859 * * * r * "
char* dfnames[] = { 
"0 14 iso8859 * * * r * ", //No. size rgstry fmly wght fndry slant not-use
"1 16 iso8859 * * * r * ",
"2 18 iso8859 * * * r * ",
"3 20 iso8859 * * * r * ",
"4 22 iso8859 * * * r * ",
"5 24 iso8859 * * * r * ",
"6 26 iso8859 * * * r * ",
"7 30 iso8859 * * * r * ",
"8 14 iso8859 * * * r * ",
NULL
};

#define DEFAULT_FONT_SET_J "14  jisx0201.1976  jisx0208.1983  *   misc misc * "
char* dfnames_j[] = { 
"0 14 jisx0201.1976 jisx0208.1983 *  misc misc misc ",
"1 16 jisx0201.1976 jisx0208.1983 *  *    *    *    ",
"2 24 jisx0201.1976 jisx0208.1983 *  *    jis  *    ",
"3 24 jisx0201.1976 jisx0208.1983 *  *    jis  *    ",
"4 24 jisx0201.1976 jisx0208.1983 *  *    jis  *    ",
"5 24 jisx0201.1976 jisx0208.1983 *  *    jis  *    ",
"6 24 jisx0201.1976 jisx0208.1983 *  *    jis  *    ",
"7 24 jisx0201.1976 jisx0208.1983 *  *    jis  *    ",
"8 14 jisx0201.1976 jisx0208.1983 *  misc misc misc ",
NULL
};


WSMFclassInit(WSDxfont,WSDfont);
WSDfont* _xfont_chandler(){
  WSDfont* font = new WSDxfont();
  return font;
};
long _xfont_setup_handler(WSDfont* font,char* str){
  char str1[128];
  char str2[128];
  char str3[128];
  char str4[128];
  char str5[128];
  char str6[128];
  char str7[128];
  char fname[256];
  str1[0] = 0;
  str2[0] = 0;
  str3[0] = 0;
  str4[0] = 0;
  str5[0] = 0;
  str6[0] = 0;
  str7[0] = 0;
  long no;
  sscanf(str,"%d %s %s %s %s %s %s %s",&no,str1,str2,str3,str4,str5,str6,str7);
  sprintf(fname,"%s %s %s %s %s %s %s",str1,str2,str3,str4,str5,str6,str7);
  font->setFontName(fname);
  font->setId((short)no);
  return WS_NO_ERR;
};

long _xfont_default_init_handler(WSCfontSet* fontset){
  long i=0;
  char** _dfnames = dfnames;
//  if (!strcmp(WSGIappLocaleSet()->getDefaultLocaleName(),WS_LOCALE_JAPANESE)){
//    _dfnames = dfnames_j;
//  } 
 
  while(_dfnames[i]){
    WSDfont* font = new WSDxfont();
    _xfont_setup_handler(font,_dfnames[i]);
    fontset->addFont(font);
    i++;
  }
  return WS_NO_ERR;
};

void _xfont_init(){
  WSGIappFontSet()->setCreateHandler(_xfont_chandler);
  WSGIappFontSet()->setSetupHandler(_xfont_setup_handler);
  WSGIappFontSet()->setDefaultInitializeHandler(_xfont_default_init_handler);
  WSGIappFontSet()->initializeDefault();
};



WSDxfont::WSDxfont(){
  _xfont_set = 0;
  _ergs.setString("jisx0201.1976");
  _krgs.setString("jisx0208.1983");
  _grgs.setString("jisx0208.1983");

  _efnd.setString("misc");
  _kfnd.setString("misc");
  _gfnd.setString("*");

//  if (strcmp(WSGIappLocaleSet()->getDefaultLocaleName(),WS_LOCALE_JAPANESE)){
    //lang C
    _fmly.setString("*");
    _wght.setString("*");
    _slant.setString("*");
//  }else{
//    //lang Japanese
//    //do nothing
//  }

}

WSDxfont::~WSDxfont(){
  destroy();
}

static Display* disp = NULL;

long WSDxfont::initialize(){
  char* fname = getSrc();
  if (fname == NULL || !strcmp(fname,"") ){
    fname = DEFAULT_FONT_SET;
//    if (!strcmp(WSGIappLocaleSet()->getDefaultLocaleName(),WS_LOCALE_JAPANESE)){
//      fname = DEFAULT_FONT_SET_J;
//    }
  }
  char efontr[128];
  char kfontr[128];
  char gfontr[128];
  char efontf[128];
  char kfontf[128];
  char gfontf[128];
  char fmly[128];
  char wght[128];
  char slant[128];
  long japanese = False;
//  if (strcmp(WSGIappLocaleSet()->getDefaultLocaleName(),WS_LOCALE_JAPANESE)){
    //C
    strcpy(kfontr,"*");
    strcpy(gfontr,"*");
    strcpy(kfontf,"*");
    strcpy(gfontf,"*");
    sscanf(fname,"%d %s %s %s %s %s %s",&_font_height,efontr,
     fmly,wght,efontf,slant,gfontf);
    _fmly.setString(fmly);
    _wght.setString(wght);
    _slant.setString(slant);
//  }else{
//    //Japanese
//    japanese = True;
//    sscanf(fname,"%d %s %s %s %s %s %s",&_font_height,efontr,
//     kfontr,gfontr,efontf,kfontf,gfontf);
//  }

  _ergs.setString(efontr);
  _krgs.setString(kfontr);
  _grgs.setString(gfontr);

  _efnd.setString(efontf);
  _kfnd.setString(kfontf);
  _gfnd.setString(gfontf);

  if (_font_height < -1 || _font_height > 60){
WSMFtrace("WSDxfont::initialize() font size invalid. font_size=%d.\n",_font_height);
    _font_height = 14;
  }

  char efname[256];
  char kfname[256];
  char gfname[256];

  if (japanese == False){
    sprintf(efname,"-%s-%s-%s-%s-*-*-%d-*-*-*-*-*-%s-*",_efnd.getString(),(char*)_fmly,(char*)_wght,(char*)_slant,_font_height,_ergs.getString());
    sprintf(kfname,"-%s-*-medium-r-*-*-%d-*-*-*-*-*-%s-*",_kfnd.getString(),_font_height,_krgs.getString());
    sprintf(gfname,"-%s-*-medium-r-*-*-%d-*-*-*-*-*-%s-*",_gfnd.getString(),_font_height,_grgs.getString());
  }else{
    sprintf(efname,"-%s-*-medium-r-*-*-%d-*-*-*-*-*-%s-*",_efnd.getString(),_font_height,_ergs.getString());
    sprintf(kfname,"-%s-*-medium-r-*-*-%d-*-*-*-*-*-%s-*",_kfnd.getString(),_font_height,_krgs.getString());
    sprintf(gfname,"-%s-*-medium-r-*-*-%d-*-*-*-*-*-%s-*",_gfnd.getString(),_font_height,_grgs.getString());
  }

  if (disp == NULL){
    WSDxappDev* app = WSGIxwinAppDev(); 
    disp = app->display();
  }
  if (disp == NULL){
WSMFtrace("WSDxfont::initialize() ERROR. display=NULL!\n");
    return WS_ERR;
  }

  if (efname[0] != 0){
    XFontStruct* xfs1 = XLoadQueryFont(disp,efname);
    if (xfs1 == NULL){
      setSrc( DEFAULT_FONT_SET );
      strcpy(efname, "-*-*-*-r-*-*-14-*-*-*-*-*-iso8859-*");
      xfs1 = XLoadQueryFont(disp,efname);

      if (xfs1 == NULL){
fprintf(stderr,WSGFgettext("A2:WSSTR Invalid font name: %s\n"),fname);
      }
    }
    setValue1((long)xfs1);
  }else{
    fprintf(stderr,WSGFgettext("A2:WSSTR Invalid font name: %s\n"),fname);
    setValue1(-1);
  }
  if (kfname[0] != 0){
    XFontStruct* xfs2 = XLoadQueryFont(disp,kfname);
    setValue2((long)xfs2);
  }else{
    setValue2(0);
  }
  if (gfname[0] != 0){
    XFontStruct* xfs3 = XLoadQueryFont(disp,gfname);
    setValue3((long)xfs3);
  }else{
    setValue3(0);
  }
  return WS_NO_ERR;
}

long WSDxfont::getXFontSet(){
  if (_xfont_set == 0){
    char **miss_font;
    int  miss_cnt;
    if (disp == NULL){
      WSDxappDev* app   = WSGIxwinAppDev(); 
      disp = app->display();
    }
    char fname[256];
    sprintf(fname,"-*-*-medium-r-*-*-%d-*-*-*-*-*-*-*",_font_height);
    _xfont_set = (long)XCreateFontSet(disp,fname,&miss_font,&miss_cnt,NULL);

    if (miss_cnt != 0){
WSMFtrace("WSDxfont::getXFontSet  miss=%d \n",miss_cnt);
      long i;
      for(i=0; i < miss_cnt;i++){
WSMFtrace("   ----> miss font=%s \n",miss_font[i]);
      }
    }
  }
  return _xfont_set;
}

long WSDxfont::destroy(){
  XFontStruct* xfs1 = (XFontStruct*)getValue1();
  if ( xfs1 != (XFontStruct*)-1 && xfs1 != NULL){
    XFreeFont(disp,xfs1);
    setValue1(-1);
  }
  XFontStruct* xfs2 = (XFontStruct*)getValue2();
  if ( xfs2 != (XFontStruct*)-1 && xfs2 != NULL){
    XFreeFont(disp,xfs2);
    setValue2(-1);
  }
  XFontStruct* xfs3 = (XFontStruct*)getValue3();
  if ( xfs3 != (XFontStruct*)-1 && xfs3 != NULL){
    XFreeFont(disp,xfs3);
    setValue3(-1);
  }
  return WS_NO_ERR;
}
long WSDxfont::getStringWidthUCS2(WSCushort* str){
  if (disp == NULL){
    WSDxappDev* app   = WSGIxwinAppDev(); 
    disp = app->display();
  }
  XFontStruct* xfs1 = (XFontStruct*)getValue1();
  return XUTextWidth(disp, xfs1, str,-1);
}
long WSDxfont::getStringHeightUCS2(WSCushort* str){
  getValue1();
  return  _font_height;
}
long WSDxfont::getStringWidth(WSCstring* str){
  if (disp == NULL){
    WSDxappDev* app   = WSGIxwinAppDev(); 
    disp = app->display();
  }
  XFontStruct* xfs1 = (XFontStruct*)getValue1();
  char* str1 = str->getString(WS_EN_UTF8);
  return XUutf8TextWidth(disp, xfs1,str1,-1);

#if 0
  long dx = 0;
  char* ptr = str->getString();
  XFontStruct* xfs1 = (XFontStruct*)getValue1();
  XFontStruct* xfs2 = (XFontStruct*)getValue2();
  XFontStruct* xfs3 = (XFontStruct*)getValue3();

extern char* EUCToJIS(char*);
extern int WSGFpickupString(WSCuchar*,WSCuchar*,int*);
  char*  work = new char[strlen(ptr) *2 +1];
  while(1){
    char* buffer;
    int pick;
    int ret = WSGFpickupString((WSCuchar*)work,(WSCuchar*)ptr,(int*)&pick);
    
    if (ret == 1){
      break;
    }
    buffer =  EUCToJIS(work);
    if (pick > 0){ //ASCII
      if (xfs1 != (XFontStruct*)-1 && xfs1 != NULL){
        dx+= XTextWidth(xfs1,buffer,strlen(buffer));
      }
    }else if (ret == -1){ //GAIJI
      if (xfs3 != (XFontStruct*)-1 && xfs3 != NULL){
        dx+= XTextWidth16(xfs3,(XChar2b*)buffer,strlen(buffer)/2);
      }

    }else{ //KANJI
      if (xfs2 != (XFontStruct*)-1 && xfs2 != NULL){
        dx+= XTextWidth16(xfs2,(XChar2b*)buffer,strlen(buffer)/2);
      }
    }
    if (pick < 0){
      pick = -pick;
    }
    ptr += pick;
  }
  delete work;
  return dx;
#endif
}
long WSDxfont::getStringHeight(WSCstring*){
  getValue1();
  return  _font_height;
}
