/****** ru32au.c ******/

#include <stdio.h>

#include "ru32cp.h"
#include "ru32var.h"

 int ffreq[256];  //i: 0-255
 int freqblock[16];
 int bestblock[4];
 int __CpiFrom,__CpiTo;
 int uppeset,loweset,freqmax;

//(-------------)//

//char wrkstr_au [270]; 
  /* temporary string buffers */

//(-------------)//


extern int/*bool*/ TestText(void);
extern int/*bool*/ isLatin(void);
extern int/*bool*/ isOdd(void);
extern int/*bool*/ nInBest(int iblock, int count);

extern int/*bool*/ GetTestRes(char* m_res, int *CpimFrom, int * CpimTo);

extern int/*bool*/ TestKoi8(void);
extern int/*bool*/ TestLatin(void);
extern float SampleMean (char* src);
extern int SampleMin (char* src);
extern int SampleMax (char* src);
extern void SelectBestBlocks (int BaseBlock); // BaseBlock: 0 - 8
extern int SymbolDistribution (FILE *f1);

extern void  GetFreqs (int* tofreqs, int* tofreqblock,
             int *uppeset0, int *loweset0, int *freqmax0);

extern void  PutFreqs (int* fromfreqs, int* fromfreqblock,
             int uppeset0, int loweset0, int freqmax0);

extern void  SymbolDistribution_for_Try (int *ffreq0, int* freqblock0,
         char* CpiTry);

//--------------------------- AUTODEC :---------------- //



extern int/*bool*/ TestText(void)
{
 int i, t =true;

 SelectBestBlocks (8);

//  printf("TestText:loweset=%i,uppeset=%i\n",loweset,uppeset);

 if (isLatin()) t =TestLatin();
 else if (nInBest(8,4) && nInBest(9,4) && nInBest(10,4) && nInBest(11,4))
    t =TestKoi8();
 else if (nInBest(12,4) && nInBest(13,4) && nInBest(14,4) && nInBest(15,4))
    {
     __CpiFrom = GetCPIbyName("F_Utf-part");
     __CpiTo = WinCPI;
    }
 else if (nInBest(11,4) && nInBest(12,4) && nInBest(13,4) && nInBest(15,4))
    {
    __CpiFrom = GetCPIbyName("Dos");
    __CpiTo = WinCPI;
    }
 else if (nInBest(8,4) && nInBest(9,4) && nInBest(10,4) && nInBest(15,4))
    {
    __CpiFrom = GetCPIbyName("Iso");  //
    __CpiTo = WinCPI;
    }
 else if ( nInBest(10,4) && nInBest(11,4) && nInBest(12,4) &&
           ( nInBest(8,4) || nInBest(9,4) ) )
    {
    __CpiFrom = GetCPIbyName("Mac");
    __CpiTo = WinCPI;
    }
 else if ( isOdd () )
    {
    __CpiFrom = OddCPI;
    __CpiTo = WinCPI;
    }
 else
    {
    __CpiFrom = 0;
    __CpiTo = 0;
    t = false;
    }
//printf ("TestText:from=%i to=%i\n",__CpiFrom,__CpiTo);
 return t;
};



extern int/*bool*/ nInBest(int iblock, int count)
{ int i, t =true;
  for (i=0; i< count; i++) if (iblock==bestblock[i]) t =false;
//  printf("nInBest %i %i = %c\n",iblock,count,t?'t':'f');
  return t; 
}


extern int/*bool*/ isOdd(void)
{ //printf("isOdd %c\n",( ffreq[freqmax]>uppeset/3 )?'t':'f');
  return ( ffreq[freqmax]>uppeset/3 );
}

extern int/*bool*/ isLatin(void)
{ //printf("isLatin %c\n",( loweset>5*uppeset )?'t':'f');
  return ( loweset>5*uppeset );
}



extern int/*bool*/ GetTestRes(char* m_res, int *CpimFrom, int *CpimTo)
{  m_res[0] = GetCodepageByNumber(__CpiFrom)[0];
   if (__CpiTo == WinCPI) m_res[1] = '\0';
   else { m_res[1] = tolowerANSI(GetCodepageByNumber(__CpiTo)[0]);
          m_res[2] = '\0';
        }
   (*CpimFrom) = __CpiFrom;
   (*CpimTo) = __CpiTo;
}

extern int/*bool*/ TestKoi8(void)
{
  float aKoi,aMKoi,aWin;
  int t =true;

  aKoi  = SampleMean("ÁÔÏÉ");
  aMKoi = SampleMean("ÞÕÍ");
  aWin  = SampleMean("ÀÈÎÒ");

//printf("aKoi=%f, aMKoi=%f, aWin=%f\n",aKoi,aMKoi,aWin);

  if (aKoi>aMKoi && aKoi>aWin) 
    {
    __CpiFrom = GetCPIbyName("Koi");
    __CpiTo = WinCPI;
    }
  else if (aMKoi>aWin)
    {
    __CpiFrom = WinCPI;
    __CpiTo = GetCPIbyName("Koi");
    }
  else
    {
    __CpiFrom = 0;
    __CpiTo = 0;
    t =false;
    };
  return t;
};


extern int/*bool*/ TestLatin(void)
{
  int imim64, imimuu, imimbin, iexpress, iall, i ;
  int t =true;

  iall = 0;
  for (i = 0; i< 256; i++) iall += ffreq[i];
  imim64 = 0;
  for (i = 0; i< 64; i++)  imim64 +=ffreq[mim64[i]];
  imimuu = 0;
  for (i = 0; i< 64; i++)  imimuu +=ffreq[mimuu[i]];
  imimbin =0;
  for (i = 0; i< 64; i++)  imimbin +=ffreq[mimbin[i]];
  iexpress = ffreq['&']+ffreq['#']+ffreq[';'];
//printf("TestLatin: iall=%i imimuu=%i imimbin=%i iexpress=%i\n",
//         iall, imimuu, imimbin, iexpress);
  if (ffreq['='] >iall/5)
    {
    __CpiFrom = HexCPI;
    __CpiTo = WinCPI;
    } 
  else if (ffreq['%'] >iall/5)
    {
    __CpiFrom = GetCPIbyName("%Hex");
    __CpiTo = WinCPI;
    }
  else if (ffreq['\\']+ffreq[39]+ffreq['{']+ffreq['}'] >iall/5)
    {
    __CpiFrom = GetCPIbyName("\\Hex");
    __CpiTo = WinCPI;
    }
  else if ( imim64 > (iall-imim64) *5 )
    {
     if (ffreq['-'] >ffreq['/'])
          __CpiFrom = XxCPI;
     else __CpiFrom = MimeCPI;
     __CpiTo = WinCPI;
    }
  else if ( iexpress >iall/4 && (ffreq['#']*2)>SampleMean("&;") )
    {
    __CpiFrom = ExpressCPI;
    __CpiTo = WinCPI;
    }
  else if ( SampleMin("&;") > SampleMean("0123456789")*5 )
    {
    __CpiFrom = HtmCPI;
    __CpiTo = WinCPI;
    }
  else if ( imimuu > (iall-imimuu)*4 )
    {
    __CpiFrom = UuCPI;
    __CpiTo = WinCPI;
    }
  else if ( imimbin > (iall-imimbin)*4 )
    {
    __CpiFrom = BinhexCPI;
    __CpiTo = WinCPI;
    }
  else if ( SampleMean("`hqb") > SampleMean("~}zt")*3 )
    {
    __CpiFrom = GetCPIbyName("AFF");
    __CpiTo = WinCPI;
    }
  else if ( SampleMean("AO") > 2*SampleMean("QWF") )
    {
    __CpiFrom = PolCPI;
    __CpiTo = WinCPI;
    }
  else if ( SampleMean("[FJ") > 3*SampleMean("]A") )
    {
    __CpiFrom = GetCPIbyName("Shift");
    __CpiTo = WinCPI;
    }
  else
    {
    __CpiFrom = 0;
    __CpiTo = 0;
    t =false;
    };
  return t;
};



extern float SampleMean (char* src)
{
 int  i,n,cc; float s;

 n = strlen(src);
 if (n<1) return 0.0;
 s = 0.0;

 for (i = 0; i< n; i++)
  {
  cc = (src[i]+0x100) % 0x100; 
  s +=  ( ffreq[(tolowerANSI(cc)+0x100) %0x100] 
         +ffreq[(toupperANSI(cc)+0x100) %0x100] );
  }
 return (s/n);
};


extern int SampleMin (char* src)
{
 int  i,n,s,fr,cc;

 n = strlen(src);
 if (n<1) return 0;
 s = uppeset+loweset+10;

 for (i = 0; i< n; i++)
  {
  cc = (src[i]+0x100) % 0x100; 
  fr =  ( ffreq[(tolowerANSI(cc)+0x100) %0x100] 
         +ffreq[(toupperANSI(cc)+0x100) %0x100] );
  if (s > fr)  s = fr;
//printf("cc=%i adr1=%i adr2=%i fr %i\n",cc,(tolowerANSI(cc)+0x100) %0x100, 
//         (toupperANSI(cc)+0x100) %0x100, fr );
  }
//printf ("SampleMin:res=%i\n",s);
  return s;
};


extern int SampleMax (char* src)
{
 int  i,n,s,fr,cc;

 n = strlen(src);
 if (n<1) return 0;
 s = 0;

 for (i = 0; i< n; i++)
  {
  cc = (src[i]+0x100) % 0x100; 
  fr =  ( ffreq[(tolowerANSI(cc)+0x100) %0x100] 
         +ffreq[(toupperANSI(cc)+0x100) %0x100] );
  if (s < fr)  s = fr;
  }
//printf ("SampleMax:res=%i\n",s);
  return s;
};


extern void SelectBestBlocks (int BaseBlock) // BaseBlock: 0 - 8
{
 int  i, m, k;
 int  bb [16];

// printf("SelectBest freqbl 8: %i\n",freqblock[8]);
 for (i=0; i <16; i++)  bb[i] = freqblock[i];
 for (i=0; i<  4; i++)
  {
    m = 0; 
    for (k=BaseBlock; k< 16; k++)
//         { printf("k=%i m=%i bbk=%i bbm=%i\n",k,m,bb[k],bb[m]);
             if (bb[k]>bb[m])  m = k;  
//         }
    bestblock[i] = m;
    bb[m] = 0;
  };
//printf ("SelectBest: %i %i %i %i\n", bestblock[0], bestblock[1], bestblock[2], bestblock[3]);
};


extern int/*bool*/ SymbolDistribution ( FILE *f1)
  // returns true  if tmp-file of first 500 chars is created
{
 int ch, cc, i, i_b;
 int/*bool*/ istmp;
 FILE *ftmp;

 istmp = ( (ftmp=fopen("_$tmpspc.tmp","wb")) != NULL );

// printf("SymbolDistr: istmp=%c\n",(istmp)?'t':'f');
 if (istmp)
 { cc = 0;
   fseek (f1, 0L, SEEK_SET);
   while ( (ch=getc(f1)) != EOF   &&  cc++ < 500 )
     fputc(ch, ftmp);
   /*if (ftmp !=NULL)*/ fclose (ftmp);
 }

 fseek (f1, 0L, SEEK_SET);
  
 for (i=0; i< 256; i++) ffreq[i] = 0;
 for (i=0; i< 16;  i++) freqblock[i] = 0;
 uppeset = 0;
 loweset = 0;

 while ( (ch=getc(f1)) != EOF )
  {
   cc = ch; // otl: if(cc<0) cc+=256;
   ffreq[cc] +=1;
//printf ("f1:cc=%i ",cc);

   if (cc >= 0x10)
    {
     i_b = (cc / 16);
     freqblock[i_b] +=1;
     if (cc>=0x80)  uppeset++;
     else if (cc>=0x20) loweset++;
    }
  }

 freqmax = 0;
 for (i=128; i< 256; i++)  if (ffreq[i] > ffreq[freqmax])  freqmax=i;

//printf("SymbDistr: uppeset=%i,loweset=%i,freqmax=%i\nfreqbl0,8-15=%i %i %i %i %i %i %i %i %i :\n ",
// uppeset, loweset, freqmax,
// freqblock[0], freqblock[8], freqblock[9], freqblock[10], freqblock[11],
// freqblock[12], freqblock[13], freqblock[14], freqblock[15]);
 return istmp;
};


extern void  GetFreqs (int* toffreq, int* tofreqblock,
             int *uppeset0, int *loweset0, int *freqmax0)
{
 int i;

 for (i=0; i< 256; i++)  *(toffreq+i) = ffreq[i];
 for (i=0; i< 16;  i++)  *(tofreqblock) = freqblock[i];
 *uppeset0 = uppeset;
 *loweset0 = loweset;
 *freqmax0 = freqmax;
}


extern void  PutFreqs (int* fromffreq, int* fromfreqblock,
             int uppeset0, int loweset0, int freqmax0)
{
 int i;

 for (i=0; i< 256; i++)  ffreq[i] = *(fromffreq+i);
 for (i=0; i< 16;  i++)  freqblock[i] = *(fromfreqblock+i);
 uppeset = uppeset0;
 loweset = loweset0;
 freqmax = freqmax0;
};


extern void  SymbolDistribution_for_Try (int *ffreq0, int* freqblock0,
       char* CpiTry)
{
 int  i, i_count, i_b;
 int  cc;

 for (i=0; i< 256; i++) ffreq[i]=0;
 for (i=0; i< 16;  i++) freqblock[i]=0;
 uppeset =0;
 loweset =0;

 for (i=0; i< 256; i++)
  {
   i_count = ffreq0[i];  // number of symbol i  in source file
   cc = CpiTry[i];       // cc -to what is symbol i transferred after macros
   if (cc<0) cc +=256;
   ffreq[cc] += i_count;
// printf ("%i-> %i(%i) \n",i,cc,i_count);

   if ( cc>=0x10 )
    { 
      i_b = (cc / 16);
      freqblock[i_b] += i_count;
      if ( cc>= 0x80 ) uppeset += i_count;
      else if ( cc>= 0x20 )  loweset += i_count;
    };
  };

 freqmax = 0;
 for (i=128; i< 256; i++)  if (ffreq[i]>ffreq[freqmax])  freqmax =i;

//printf("SymbDistr_forTry: uppeset=%i,loweset=%i,freqmax=%i\nfreqbl 0,8-15=%i %i %i %i %i %i %i %i %i :\n ",
// uppeset, loweset, freqmax,
// freqblock[0], freqblock[8], freqblock[9], freqblock[10], freqblock[11],
// freqblock[12], freqblock[13], freqblock[14], freqblock[15]);

};


