/******  ru32mau.c ******/

#include <stdio.h>

#include "ru32cp.h"
#include "ru32var.h"
#include "ru32fi.h"
#include "ru32au.h"
#include "ru32un.h"



#define  N_try2    60
#define  N_try3a  118
        //114+4 : 'kkkk','KKKK','MimD','iiDI'
#define  N_try3   152
        //118+34+4 : 'kkkk','KKKK','MimD','iiDI'
#define  N_try4a  286
#define  N_try4   366

int  N_try;

char *m_try [N_try4]  =
  { //"KDKIK",
   "D","K","I","M","F","k","C","Y","Z",
   "~DK","~DK~DW~IW",
   "KD","kD","KI","kI","KM","kM",
   "DK","Dk","IK","Ik","MK","Mk","cF",  //{'fC'-íå íóæíà, ýòî CF+ñìåíà ðåãèñòðà}
   "KY","KZ","kY","kZ","YK","ZK","CK","Yk","Zk","Ck",
   "iD","ID","dI","IM","iC","DI","mD","kk","KK",
   "KDKIK","KIKDK","dMiCdiiiDI",
   "iY","iZ","YM","ZM","MZ"
   ,
   "ImD","imD","kkk","KKK","iDI",
   "kkkk","KKKK","MimD","iiDI"
   ,
   "KDK","KIK","KMK","kDK","kIK","kMK",
   "KDk","KIk","KMk","kDk","kIk","kMk",
   "KKD","KKI","KKM","DKK","IKK","MKK",
   "kkD","kkI","kkM","Dkk","Ikk","Mkk",
   "kiD","kID","kdI","kIM","kiC","kDI","kmD",
   "KiD","KID","KdI","KIM","KiC","KDI","KmD",
   "iDk","IDk","dIk","IMk","iCk","DIk","mDk",
   "iDK","IDK","dIK","IMK","iCK","DIK","mDK",
   "ikD","IkD","IkM","iKD","IKD","IKM",
   "KKY","KKZ","kkY","kkZ","YKK","ZKK","CKK","Ykk","Zkk","Ckk",
   "KiY","KiZ","KYM","KZM","KMZ","kiY","kiZ","kYM","kZM","kMZ",
   "iYK","iZK","YMK","ZMK","MZK","iYk","iZk","YMk","ZMk","MZk",
   "ZKM","MKZ","ZkM","MkZ"
   ,
   "KKDK","KKIK","KKMK","KKDk","KKIk","KKMk",
   "kkDK","kkIK","kkMK","kkDk","kkIk","kkMk",
   "KDKK","KIKK","KMKK","KDkk","KIkk","KMkk",
   "kDKK","kIKK","kMKK","kDkk","kIkk","kMkk",

   "KDKK","KIKK","KMKK","KDKK","KIKK","KMKK",
   "KDkk","KIkk","KMkk","KDkk","KIkk","KMkk",
   "kDKK","kIKK","kMKK","kDKK","kIKK","kMKK",
   "kDkk","kIkk","kMkk","kDkk","kIkk","kMkk",

   "kkiD","kkID","kkdI","kkIM","kkiC","kkDI","kkmD",
   "KKiD","KKID","KKdI","KKIM","KKiC","KKDI","KKmD",
   "iDkk","IDkk","dIkk","IMkk","iCkk","DIkk","mDkk",
   "iDKK","IDKK","dIKK","IMKK","iCKK","DIKK","mDKK",

   "kiDk","kIDk","kdIk","kIMk","kiCk","kDIk","kmDk",
   "KiDk","KIDk","KdIk","KIMk","KiCk","KDIk","KmDk",
   "kiDK","kIDK","kdIK","kIMK","kiCK","kDIK","kmDK",
   "KiDK","KIDK","KdIK","KIMK","KiCK","KDIK","KmDK",

   "kikD","kIkD","kIkM","kiKD","kIKD","kIKM",
   "KikD","KIkD","KIkM","KiKD","KIKD","KIKM",
   "ikDk","IkDk","IkMk","iKDk","IKDk","IKMk",
   "ikDK","IkDK","IkMK","iKDK","IKDK","IKMK",

   "ikkD","IkkD","IkkM","iKKD","IKKD","IKKM",

   "KKKY","KKKZ","KKKI","KKKD","KKKM",
   "kkkY","kkkZ","kkkI","kkkD","kkkM",
   "YKKK","ZKKK","IKKK","DKKK","MKKK","CKKK",
   "Ykkk","Zkkk","Ikkk","Dkkk","Mkkk","Ckkk",
   "KKiY","KKiZ","KKYM","KKZM","KKMZ","kkiY","kkiZ","kkYM","kkZM","kkMZ",
   "iYKK","iZKK","YMKK","ZMKK","MZKK","iYkk","iZkk","YMkk","ZMkk","MZkk",
   "KiYK","KiZK","KYMK","KZMK","KMZK","KiYk","KiZk","KYMk","KZMk","KMZk",
   "kiYK","kiZK","kYMK","kZMK","kMZK","kiYk","kiZk","kYMk","kZMk","kMZk",
   "ZKKM","YKKM","MKKZ","ZkkM","YkkM","MkkZ",
   "KZKM","KZkM","kZKM","kZkM","ZKMK","ZkMK","ZKMk","ZkMk",
   "MKZK","MkZK","MKZk","MkZk" 
  };


 char CpiTry [256]; //i: 0-255

 int ffreq0 [256];  //i: 0-255
 int freqblock0 [16];
 int bestblock0 [4];
 int uppeset0,loweset0,freqmax0;
 int myauto2cpi;  //, myDeepAuto;
 int CpimTo, CpimFrom; char SelMac[50];  // for display


extern void  AutoProcessFile (char* fn1, char* fn2);
extern int/*bool*/  Try_File (FILE* f1, FILE* fn2);
extern int   TestXX (int qcpi);
extern int/*bool*/  TryByMacros (char* m_string);
extern int/*bool*/  TestWin (void);
extern int/*bool*/  TestWinPlainTxt (void);
extern int/*bool*/  ConvertByBaseMacros (FILE *f1, FILE *f2, char *m_string);

extern void GetAutoCpi (int *Cp1, int *Cp2);
extern char* GetSelMac (void);

// ---------------------------- //

char wrkstr_mau [270], wrkstr_mau2[270]; 
  /* temporary string buffers */

// ---------------------------- //



extern void  AutoProcessFile (char* fn1, char* fn2)
{
int /*bool*/ winOK =false;
FILE *f1=NULL, *f2=NULL;
int cp1,cp2;

if ( (f1=fopen(fn1,"rb")) == NULL )
  { 
    strcpy (wrkstr_un,"can't open file-from : ");
    strcat(wrkstr_un,fn1);
    re4ShowMessage (wrkstr_un);
    return;
  }

if ( (f2=fopen(fn2,"wb")) == NULL )
  { 
    strcpy (wrkstr_un,"can't open new file-to : ");
    strcat(wrkstr_un,fn2);
    re4ShowMessage (wrkstr_un);
    goto fin;;
  }


//  ShowMessage ('f1='+f1+#10+'f2='+f2);
  SetAuto (true);

  winOK = Try_File(f1,f2);
  GetAutoCpi(&cp1,&cp2);
  Attr.Cp1 = cp1;  Attr.Cp2 = cp2;
  if (!winOK) // not yeat converted
     ProcessFile0 (f1,f2);
 
fin:
 if (f2 != NULL) fclose(f2);
 if (f1 != NULL) fclose(f1);
}



extern int/*bool*/  Try_File (FILE* f1, FILE* f2)
{
 int /*bool*/ winOK =false;
 char m_res[50];
 int i,j,jr,j0;
 int /*bool*/ res_add,extold,istmp = false;
 char m_s, cc;
 int rexx[3];

 if (GetDeepAuto())  N_try = N_try4;
 else N_try = N_try3;

 winOK  = false;
 CpimFrom = -1; CpimTo = -1; 
 extold = GetisExtended();
 myauto2cpi = GetAuto2Cpi();


 istmp = SymbolDistribution(f1);
/*     // if istmp -
     // successful created  '_$tmpspc.tmp' - 1-st 500 chars
 if (isLatin())
  {  winOK = TestAutoLatin(istmp);
     if (winOK)
      { GetTestRes (m_res, &CpimFrom, &CpimTo);
        SetCp1(CpimFrom);  SetCp2(CpimTo);
        ProcessFile0 (f1,f2);
      }
  }
 else if ( isOdd() )  
  {
   CpimFrom = GetCPIbyName("Odd");  CpimTo = WinCPI;
   m_res[0] = 'O' /*letter Odd*/;  m_res[1] = '\0';   
   SetCp1(CpimFrom);  SetCp2(CpimTo);
   ProcessFile0 (f1,f2);
   WinOK = true;
  }
 else  // try base macrolist 
  { 
//   CopyFreqs ("to_freq0");
   GetFreqs (ffreq0, freqblock0,
             &uppeset0, &loweset0, &freqmax0);


//   SetisExtended (false);   // in ver.4.62 - operator is turned on !
   for (i = 0; i< N_try; i++)
    {
     winOK = TryByMacros (m_try[i]); 
     if (winOK)
       {
         strcpy(m_res,m_try[i]);
         break;
       }
    }

//   CopyFreqs ("from_freq0");
   PutFreqs (ffreq0, freqblock0,
             uppeset0, loweset0, freqmax0);

   SetisExtended (extold);

   if (winOK) // successful try base macrolist
   {
    winOK = ConvertByBaseMacros (f1,f2,m_res);

    m_s = m_res[0];
    if (m_s == macrodivlet)
      {
        if (strlen(m_res)>=3)
         {  CpimFrom = GetCPIbyName(m_res+1);
            CpimTo   = GetCPIbyName(m_res+2);
         }
      } else
      {
       CpimFrom = GetCPIbyName( m_res);  //m_s
       i = m_s;
       if (toupperANSI(i)==i)  CpimTo = WinCPI;
       else { CpimTo = CpimFrom; CpimFrom = WinCPI;
            };
      }
    } // end successful try base

    else 
    {  winOK = TestText();
       if (winOK)
        { GetTestRes (m_res, &CpimFrom, &CpimTo);
          SetCp1(CpimFrom);  SetCp2(CpimTo);
          ProcessFile0 (f1,f2);
        }
     }
   } // end try base macrolist
*/

 SetisExtended (extold);

 if ( (! GetDeepAuto())  &&  (! winOK) )
   re4ShowMessage("Autocovertion failed. Try to set DeepAuto.");


 if (winOK)  strcpy (SelMac, m_res);
 else if (CpimFrom==-1) strcpy (SelMac, "Autoconvertion failed");
 else if (CpimTo==WinCPI)
   strcpy(SelMac, GetCodepageByNumber(CpimFrom));
 else  { cc = (GetCodepageByNumber(CpimTo))[0];
         SelMac[0] = tolowerANSI(cc); SelMac[1] = '\0';
       }

 if ( winOK && (SelMac==m_res) && ( ! GetisAddList() ) ) 
 { 
   res_add = false;
   for (i = strlen(m_res)-1; i>-1; i--)
    if ( GetCPIbyName(m_res+i) >= CPI_STANDcount )
       res_add = true;
   if (res_add)  strcat (SelMac, " (Add)");
 }

 return winOK;
};


extern int/*bool*/ TestAutoLatin (int/*bool*/ istmp)
{
 int /*bool*/ winOK =false;

 winOK = TestLatin();
 if (winOK)
  {
   GetTestRes (m_res, &CpimFrom, &CpimTo);

   if ( istmp  &&   ( CpimFrom==MimeCPI || CpimFrom==XxCPI) )
    {
     mim = mim64; skipbyte = 0;
     rexx[0] = TestXX(MimeCPI);
     rexx[1] = TestXX(Utf7CPI);
     mim = mimxx; skipbyte = 1;
     rexx[2] = TestXX(XxCPI);

     j0 = 0;
     for (i = 1; i<= 4; i++)
     {
       for (j = 1; j<= 3; j++)
        {
// find among results of TestXX for j-th Cpi-from (j=1..3):
// first of all (when i=0) - rexx=0 // full success,
// if not found - then  rexx without flags  1000 and 100,
// if not found - then  rexx without flag  10,
// at last (when i=4) -  rexx without flag 1000.
         jr = rexx[j-1]; if (i==2) jr = jr / 100;
         else if (i==3)  jr = (jr % 100) / 10;
         else if (i==4)  jr = jr / 1000;
         if (jr==0) {  j0 = j; break;
                    };
        } // end j-loop of Cpi groop
       if (j0>0) break;

     } // end i-loop of sucsess degrees

    if (j0==0)  CpimFrom = MimeCPI;
    else if (j0==1)  CpimFrom = Utf7CPI;
    else if (j0==2)  CpimFrom = XxCPI;
    else CpimFrom = MimeCPI;
       // maybe better here {CpiFrom = -1, winOK=false} ?
       // no!! zB we have Iso+Mime  - then we have a chance in double auto

    mim = mim64; skipbyte = 0;
    remove ("_$tmpspc.tmp");
    } // end of istmp testing

 return winOK;
}


extern int  TestXX (int qcpi)
{
 int  i,ns,cc;
 char *s1,*s2;
 int/*bool*/ begstr;
 int nlo,nwin,nmic,nbad,nbad0,result,ch;
 FILE *f1=NULL;

 result = 1111;
 s1 = wrkstr_mau;   s2 = wrkstr_mau2;

 nlo = 0; nwin = 0; nmic = 0; nbad = 0;

 if ( (f1=fopen("_$tmpspc.tmp","rb")) == NULL )
  { 
   return result;
  }

 while ( (ch = getc(f1) ) != EOF )
  {
   ungetc (ch, f1);
   getnline (s1, f1, 128);

   if (qcpi==Utf7CPI)  StringUtf7(s1,s2);
   else StringDoMime64(s1,s2);

   // tests2: 
   ns = strlen(s2);
   for (i = 0; i< ns; i++)
     {
      cc = s2[i]; if(cc<0) cc+=256;
      if (cc==0x0a || cc==0x0d)  continue;
      if (cc<=0x0d) nbad0++;
      else if (cc<32) nbad++;
      else if (cc<128) nlo++;
      else if (cc<192) nmic++;
      else nwin++ ;
     }
  // end tests2
  }
  
//printf ("nn=%i  nnbad=%i  ch=%i(%c)\n", nn,nnbad,ch,ch);
   if (nwin>4*nbad)  result-=1000;
   if (nwin>4*nmic)  result-=100;
   if ( (nwin+nmic)>10*nbad )  result-=10;
   if ( (nwin+nmic+nlo+nbad+nbad0)>40 || (nbad0+nbad)==0 ) result-=1;
 return result;
};


extern int/*bool*/  TryByMacros (char* m_string)
{
 int/*bool*/ winOK =false;

 int  n,j,i,k,Cp1,Cp2;
 char  cc,cc1,m_s;
 char *scp1, *scp2, *scp1w, *scp2w, *scp1d, *scp2d;
 int  macmac,mc1,mc2;
 int/*bool*/ extold,extnew;

 n = strlen(m_string);

// macmac = 0; mc1 = 0;
 extold = GetisExtended();
 extnew = extold;

 for (j = 0; j< 256; j++)  CpiTry[j]=j;

 macmac = 0; mc1 = 0;
 for (i = 0; i< n; i++)
  {
   m_s = m_string[i];
   if (m_s==macrodivlet)
     { macmac = 1; continue;
     }

   Cp1 = re4pos(toupperANSI(m_s),CPILetter);
   if (macmac==1)
     { macmac=2; mc1=Cp1; extnew=(toupperANSI(m_s)==m_s); continue;
     }

   if (macmac==2)
     { macmac=0; mc2=Cp1;
       Cp1=mc1; Cp2=mc2; SetisExtended (extnew);
     } 
   else if (toupperANSI(m_s)==m_s)  Cp2=1;
   else { Cp2=Cp1; Cp1=1;
        }
   scp1  = CPI[Cp1][CPIbody];
   scp2  = CPI[Cp2][CPIbody];
   scp1w = CPI[Cp1][CPIBodyWin];
   scp2w = CPI[Cp2][CPIBodyWin];
   scp1d = CPI[Cp1][CPIBodyDos];
   scp2d = CPI[Cp2][CPIBodyDos];

   for (j=0; j< 256; j++)
    {
     cc = CpiTry[j];
     k = re4pos(cc,scp1);
     if (k>-1)
       cc = scp2[k];
     else if (GetisExtended() && (cc!='.'))
      {
       k = re4pos(cc,scp1w);
       if (k>-1)//and(k<=ExtCPIAutoLength)
        {
         cc1 = scp2w[k];
         if (cc1!='.')  cc=cc1;
        }
       else
         { k = re4pos(cc,scp1d);
           if (k>-1) {cc1 = scp2d[k];
           if (cc1!='.') cc=cc1;}
         }
      }; // end extended processing
    }; // end j loop

   CpiTry[j] = cc;
  }; // end i loop
 SetisExtended (extold);

 winOK=TestWin();

 return winOK;
};


extern int/*bool*/  TestWin (void)
{

 int i;
 int /*bool*/ resOK =false;

 SymbolDistribution_for_Try(ffreq0, freqblock0, CpiTry) ;
//printf("ÎÀÅÈÒÍ: mean- %f\n",SampleMean("ÎÀÅÈÒÍ"));
//printf(" : min- %i\n",SampleMin("ÎÀÅÈÒÍ"));
//printf("ÞÔÚÜÝÉ: max- %i\n",SampleMax("ÞÔÚÜÝÉ"));


 SelectBestBlocks (8);
 if (isLatin())  resOK = false;
 else if ( nInBest(8,4) && nInBest(9,4) && nInBest(10,4) && nInBest(11,4) )
     resOK = TestWinPlainTxt();
 else  resOK = false;

 return resOK;
};


extern int/*bool*/  TestWinPlainTxt (void)
{
 int aGood,aBad ;
 int/*bool*/ resOK =false;
// float s;

  aGood =SampleMin("ÎÀÅÈÒÍ");
//  s   =SampleMean("ÎÀÅÈÒÍ");
  aBad  =SampleMax("ÞÔÚÜÝÉ");

//  printf ("TestWinPlainText- min %s=%i max %s=%i \n",
//          "ÎÀÅÈÒÍ",aGood,"ÞÔÚÜÝÉ",aBad);
  resOK = (aGood > aBad*1.1);

  return resOK;
};


extern int/*bool*/  ConvertByBaseMacros (FILE *f1, FILE *f2, char *m_string)
{
 int i, n, Cp1, Cp2, k, ch;
 char cc, cc1, m_s;
 int macmac, mc1, mc2;
 int /*bool*/  extold, extnew;

 n = strlen(m_string);

 macmac = 0; mc1 = 0;
 extold = GetisExtended();
 extnew = extold;

 fseek (f1, 0L, SEEK_SET);

 while ( (ch=getc(f1)) != EOF )
  {
   cc = (char)ch;

   for (i=0; i< n; i++)
    {
     m_s = m_string[i];
     if (m_s==macrodivlet)
       { macmac = 1; continue;
       }

     Cp1 = GetCPIbyName(m_string+i); //m_s
     if (macmac==1) 
       { macmac=2; mc1=Cp1; extnew=(toupperANSI(m_s)==m_s); continue;
       }

     if (macmac==2)
       { macmac = 0; mc2 = Cp1;
         Cp1 = mc1; Cp2 = mc2; SetisExtended(extnew);
       } 

     else if (toupperANSI(m_s)==m_s)  Cp2=1;
     else { Cp2=Cp1; Cp1=1;
          }

//if (ftell(f1)<1L)
//printf("%s: %i -> %i\n",m_string[i],Cp1,Cp2);

     k = re4pos(cc,CPI[Cp1][CPIbody]);
     if (k>-1)
       cc = CPI[Cp2][CPIbody][k];
     else if ( GetisExtended() && (cc!='.') )
      {
        k = re4pos(cc,CPI[Cp1][CPIBodyWin]);
        if (k>-1) //and(k<ExtCPIAutoLength)
          {
           cc1=(CPI[Cp2][CPIBodyWin])[k];
           if (cc1!='.') cc=cc1;
          }
        else
          {
           k = re4pos(cc,CPI[Cp1][CPIBodyDos]);
           if (k>-1)//and(k<ExtCPIAutoLength)
            {
             cc1=(CPI[Cp2][CPIBodyDos])[k];
             if (cc1!='.') cc=cc1;
            }
          }
      };  // end extended processing

     SetisExtended (extold);
    };  // end i-loop - macroconvert for current symbol

//printf("%c ",cc);

   putc(cc,f2);
 }; // end of file

 return 0;
};



extern void GetAutoCpi (int *Cp1, int *Cp2)
{
 (*Cp1)=CpimFrom;
 (*Cp2)=CpimTo;
};


extern char* GetSelMac (void) { return SelMac; }

