#ifndef _XTEXT
#define _XTEXT
#include "xfont.h"

enum  fontType
{
  CH_UNDEF,
  CH_ASCII,CH_ASCII_TINY,CH_ASCII_HOR,
  CH_KANJI,CH_KANJI_TINY
};

class xchar
{
  ulong                 Color;
  int                   ButtonID;
  fontType              FontType;
  short                 XY  [2];
  uchar                 Code[2];
public:
  inline                xchar   (void)
  {
    Color=0;ButtonID=0;
    FontType=CH_UNDEF;XY[0]=0;XY[1]=0;Code[0]='\0';Code[1]='\0';
  }
  inline                xchar   (const xchar& XChar)
  {
    Color   =XChar.Color; ButtonID=XChar.ButtonID;
    FontType=XChar.FontType;
    XY[0]   =XChar.XY  [0];XY  [1]=XChar.XY  [1];
    Code[0] =XChar.Code[0];Code[1]=XChar.Code[1];
  }
  inline  void          offsetXY(int X,int Y){ XY[0]+=X;XY[1]+=Y;}
  inline  void          set     (ulong   Clr,int BID,fontType FType,
				 int X,int Y,char  Byte1)
  { 
    Color=Clr;ButtonID=BID;
    FontType=FType;XY[0]=X;XY[1]=Y;Code[0]=(uchar)Byte1;Code[1]='\0';
  }
          void          set     (ulong   Clr,int BID,fontType FType,
				 int X,int Y,uchar Byte1,uchar Byte2);
  inline                xchar   (ulong   Clr,int BID,fontType FType,
				 int X,int Y,char  Byte1)
  { set(Clr,BID,FType,X,Y,Byte1);}
  inline                xchar   (ulong   Clr,int BID,fontType FType,
				 int X,int Y,uchar Byte1,uchar Byte2)
  { set(Clr,BID,FType,X,Y,Byte1,Byte2);}
  inline  xchar         operator=(xchar XChar)
  {
    Color   =XChar.Color; ButtonID=XChar.ButtonID;
    FontType=XChar.FontType;
    XY[0]   =XChar.XY  [0];XY  [1]=XChar.XY  [1];
    Code[0] =XChar.Code[0];Code[1]=XChar.Code[1];
    return *this;
  }
  inline  void          init    (void)
  {
    Color=0;ButtonID=0;
    FontType=CH_UNDEF;XY[0]=0;XY[1]=0;Code[0]='\0';Code[1]='\0';
  }
  inline  ulong         color   (void){ return      Color;}
  inline  int           buttonID(void){ return   ButtonID;}
  inline  fontType      type    (void){ return   FontType;}
  inline  int           x       (void){ return (int)XY[0];}
  inline  int           y       (void){ return (int)XY[1];}
  inline  uchar         byte1   (void){ return    Code[0];}
  inline  uchar         byte2   (void){ return    Code[1];}
};

const int               MaxNumberOfChars=8192;

class xTextWindow;
class textPage
{
  static xchar*         XCharListWork;
  int                   CharCnt;
  xchar*                XCharList;
  textPage*             Prior;
  textPage*             Next;
public:
  inline                textPage(void)
  {
    if(NULL==XCharListWork)XCharListWork=new xchar[MaxNumberOfChars];
    else for(int I=0;I<MaxNumberOfChars;++I) XCharListWork[I].init();
    XCharList=XCharListWork;CharCnt=0;Prior=Next=NULL;
  }
  inline  void          fix     (void)
  {
    XCharList=new xchar[CharCnt];
    for(int I=0;I<CharCnt;++I) XCharList[I]=XCharListWork[I];
  }
  inline  int           charCnt (void)        { return CharCnt;}
  inline  xchar&        list    (int I)       { return XCharList[I];}
  inline  int           addChar (xchar XChar)
  {
    if(CharCnt<MaxNumberOfChars-1){ XCharList[CharCnt++]=XChar;return 0;}
    else                          { return 1;}
  }
  inline  textPage*     prior   (void)        { return Prior;}
  inline  textPage*     next    (void)        { return Next;}
  inline  void          prior   (textPage* Pr){ Prior=Pr;}
  inline  void          next    (textPage* Ne){ Next =Ne;}
  inline  void          drawText(xTextWindow* XTWin);
          int           buttonID(xTextWindow* XTWin,int MX,int MY);
};

class xTextWindow       :public xwindow
{
protected:
  fontA*                FontA;
  fontA*                FontATiny;
  fontK*                FontK;
  fontK*                FontKTiny;
  int                   ShadowFlag;
  ulong                 ShadowColor;
  int                   DrawTextFlag;
  textPage*             TextPageFirst;
  textPage*             TextPageLast;
  textPage*             TextPageToWrite;
  textPage*             TextPageToShow;
public:
  int                   CharHeightASCII;
  int                   CharWidthASCII;
  int                   CharHeightASCIITINY;
  int                   CharWidthASCIITINY;
  int                   CharHeightASCIIHOR;
  int                   CharWidthASCIIHOR;
  int                   CharHeightKANJI;
  int                   CharWidthKANJI;
  int                   CharHeightKANJITINY;
  int                   CharWidthKANJITINY;
                        xTextWindow(int Width,int Height,
				    char*  FG,char*   SG,char* BG,
				    char* FNA,char* FNAT,char* FNK,char* FNKT);
	  void          drawChar   (xchar XChar);
          int           event      (void);
  inline  int           addChar    (xchar XChar)
  { drawChar(XChar); return TextPageToWrite->addChar(XChar);}
  inline  void          drawText   (Bool);
  inline  void          newTextPage(void)
  {
    clearScreen();TextPageLast->fix();
    TextPageToWrite=new textPage;
    TextPageToWrite->prior(TextPageLast);
    TextPageLast->next(TextPageToWrite);
    TextPageLast=TextPageToShow=TextPageToWrite;
  }
  inline  void          shadowON   (void){ ShadowFlag=1;}
  inline  void          shadowOFF  (void){ ShadowFlag=0;}
};

inline  void textPage   ::drawText(xTextWindow* XTWin)
{ for(int I=0;I<CharCnt;++I)XTWin->drawChar(XCharList[I]);}

inline  void xTextWindow::drawText(Bool f=True)
{ if(f)clearScreen();if(DrawTextFlag){TextPageToShow->drawText(this);}}

#endif
