/******  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","KK","kk",
   "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",
   "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[100];  // for display
 int plaintest =0;

extern int  AutoProcessFile (char* fn1, char* fn2);
extern int  Try_File (char* fn1, char* fn2);
extern int/*bool*/  Try_File0 (FILE* f1, FILE* fn2);
extern int/*bool*/ TestAutoLatin (int/*bool*/ istmp, char* m_res);
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 int  MacroProcess (char* fn1, char* fn2, char* m_string, char isString);
  // isString: 's' or 'f', default: f
  // returns: 0-success, 1-convertion error, 2-file operation error

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

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

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

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



extern int  AutoProcessFile (char* fn1, char* fn2)
// 0 -success, 1 -autocpi not detected, 2 -file operations failed
{
int /*bool*/ resAuto0 =2, need_double =false;
int cp1,cp2, cp2user, i, cp1first, cp2first;
char doublcpi[33], SelMac1st[100];

 SetAuto (true);
 cp2user = GetAuto2Cpi();
 strncpy(doublcpi, GetDublAuto(),32); 

 resAuto0 = Try_File (fn1,fn2);
// 0 -success, 1 -autocpi not detected, 2 -file operations failed
 cp1first=GetCp1();  cp2first=GetCp2();

//printf ("after 1st :SelMac=%s(res %i) getcp1,getcp2=%i %i\n",
//   SelMac,resAuto0,GetCp1(),GetCp2());
 if (resAuto0==0) 
 {
  // see if need double auto and do it:

  if  ( re4pos(SelMac[0], doublcpi) > -1 )
   {
    strncpy(SelMac1st, GetCodepageByNumber(GetCPIbyName(SelMac)),4);
    SelMac1st[4]='\0';
    remove ("__tempre2dub.__");
    rename (fn2,"__tempre2dub.__");

    resAuto0 = Try_File("__tempre2dub.__",fn2);
//printf ("after 2nd :SelMac=%s(res %i) getcp1,getcp2=%i %i\n",
//   SelMac,resAuto0,GetCp1(),GetCp2());
    if (resAuto0==0)
         strncat(SelMac1st, SelMac,45);
    else { remove (fn2); rename("__tempre2dub.__",fn2); }

    strncpy(SelMac,SelMac1st,100);
    remove ("__tempre2dub.__");
    resAuto0 =0;
  }
 }
else  remove(fn2);  

 if (resAuto0==0) 
 {
  // see if need convertion to another Cpi and do it:
   if (cp2user != WinCPI)
   { SetCp1(WinCPI);  SetCp2(cp2user);
    remove ("__tempre2us.__");
    rename (fn2,"__tempre2us.__");

    resAuto0 =ProcessFile ("__tempre2us.__",fn2);
//printf ("after 3rd :SelMac=%s(res %i) getcp1,getcp2=%i %i\n",
//    SelMac,resAuto0,GetCp1(),GetCp2());
    if (resAuto0!=0)
      { remove (fn2); rename("__tempre2us.__",fn2); }
    remove ("__tempre2us.__");
    resAuto0 =0;
   }
 }
 
 if (resAuto0==0) { SetCp1(cp1first); SetCp2(cp2first); }
 SetAuto(false);
 
 return resAuto0;
}


extern int  Try_File (char* fn1, char* fn2)
// 0 -success, 1 -autocpi not detected, 2 -file operations failed
{
int /*bool*/ winOK =false;
FILE *f1=NULL, *f2=NULL;
int cp1,cp2;
//    printf("Try_File <%s> -> <%s>\n",fn1,fn2);
if ( (f1=fopen(fn1,"rb")) == NULL )
  { 
    strcpy (wrkstr_mau,"can't open file-from : ");
    strcat(wrkstr_mau,fn1);
    re4ShowMessage (wrkstr_mau);
    return 2;
  }

if ( (f2=fopen(fn2,"wb")) == NULL )
  { 
    strcpy (wrkstr_mau,"can't open new file-to : ");
    strcat(wrkstr_mau,fn2);
    re4ShowMessage (wrkstr_mau);
    if (f1 != NULL) fclose(f1);
    return 2;
  }


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

  winOK = Try_File0(f1,f2);

  SetAuto(false);

  GetAutoCpi(&cp1,&cp2);

  SetCp1(cp1);  SetCp2(cp2);
 
fin:
 if (f2 != NULL) fclose(f2);
 if (f1 != NULL) fclose(f1);
 
 return (winOK) ? 0 : 1;
}



extern int/*bool*/  Try_File0 (FILE* f1, FILE* f2)
{
 int /*bool*/ winOK =false;
 char m_res[50];
 int /*bool*/ res_add,extold,istmp = false;
 int i;
 char m_s, cc;

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

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


 istmp = SymbolDistribution(f1);
     // if istmp -
     // successful created  '_$tmpspc.tmp' - 1-st 500 chars
 if (isLatin())
  {  winOK = TestAutoLatin(istmp, m_res);
     if (winOK)
      { // GetTestRes (m_res, &CpimFrom, &CpimTo);
        SetCp1(CpimFrom);  SetCp2(CpimTo);
//printf("in LatProcessing %i-> %i,istmp=%c\n",GetCp1(),GetCp2(),(istmp)?'T':'F');
        ProcessFile0 (f1,f2);
      }
  }
 else if ( isOdd() )  
  {
   CpimFrom = GetCPIbyName("Odd");  CpimTo = WinCPI;
   m_res[0] = 'O';  m_res[1] = '\0';   // letter Odd
   SetCp1(CpimFrom);  SetCp2(CpimTo);
   ProcessFile0 (f1,f2);
   winOK = true;
  }
 else  // try base macrolist 
  {
//   CopyFreqs ("to_freq0");
   GetFreqs (ffreq0, freqblock0,
             &uppeset0, &loweset0, &freqmax0);
//printf("start macrolist\n");

//   SetisExtended (false);   // in ver.4.62 - operator is turned on !
   plaintest=1;
   for (i = 0; i< N_try; i++)
    {
// printf("trying %s\n",m_try[i]);
     winOK = TryByMacros (m_try[i]);
     if (winOK)
       {
// printf("finding %s\n",m_try[i]);
         strcpy(m_res,m_try[i]);
         break;
       }
    }
   plaintest=0;

//   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");

 if ( winOK && ( ! 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, char* m_res)
{
 int rexx[3];
 int i,j,jr,j0;
 int /*bool*/ winOK =false;
 long iexpress, iall;
 FILE *f1;
 
 winOK = TestLatin();
 if (winOK)
  {
   GetTestRes (m_res, &CpimFrom, &CpimTo);
//printf("in AutoLat Processing, CpiFrom:%s\n", GetCodepageByNumber(CpimFrom));
   if ( istmp  &&   ( CpimFrom==UuCPI || CpimFrom==PolCPI) )
    { if ( (f1=fopen("_$tmpspc.tmp","rb")) == NULL )  return winOK;
      iexpress = filterfile("&#",f1);
      fseek (f1, 1L, SEEK_SET);
      iall = ftell(f1);
      if (f1 != NULL) fclose (f1);
      if (iexpress*14 > iall) CpimFrom = ExpressCPI;
      m_res[0]=GetCodepageByNumber(ExpressCPI)[0];
      return winOK;
    }
   
   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 = -1;
     for (i = 1; i<= 4; i++)
     {
       for (j = 0; j<= 2; 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]; 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

    m_res[0]=GetCodepageByNumber(CpimFrom)[0];
    mim = mim64; skipbyte = 0;
    remove ("_$tmpspc.tmp");
    } // end of istmp Mime/XX 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
  }
  
   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;
//printf ("nwin=%i nbad=%i nmic=%i nlo=%i result=%i\n",nwin,nbad,nmic,nlo,result);

 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]=(char)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=0;
   else { Cp2=Cp1; Cp1=0;
        }
   scp1  = CPI[Cp1][CPIbody];
   scp2  = CPI[Cp2][CPIbody];
   scp1w = CPI[Cp1][CPIBodyWin];
   scp2w = CPI[Cp2][CPIBodyWin];
   scp1d = CPI[Cp1][CPIBodyDos];
   scp2d = CPI[Cp2][CPIBodyDos];
//printf("TryByMacros: Cp1=%i,Cp2=%i,scp1=%li,scp2=%li",Cp1,Cp2,scp1,scp2);
   for (j=0; j< 256; j++)
    {
     cc = CpiTry[j];
     k = re4pos(cc,scp1);
//printf("m_string %s : j=%i cc=%i k=%i scp2k=%i\n",m_string,j,cc,k,scp2[k]);
//if (m_string[0]!='D') exit(0);
     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

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

// if (strcmp(m_string,"kkk")==0 || strcmp(m_string,"kkkk")==0)
//   for (j=190; j<256; j++)
//  { printf("%i ",CpiTry[j]); if(j%16==0)printf("\n");} printf("\n");
     
//printf("TryByMacros:\n %s\n",m_string);
 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)
{/*
 good:     "OAENITSVR:"
 KK :     "ÐÂÅÏÊÆ ÕÞÔ"   // RVEPKZh XYuF
 KKK:    "Ò×ÅÐËÖ ÈÀÆ"   // TChERLTs IAZh
 KKKK: "ÔÞÅÒÌÃ ÉÁÖ"   // FYuETMG JBTs

 bad:   "ÔÕÖ×ÙÜÚÝÞÆ"   // FXTsChShch'^EhYhZh
*/

 char *sGood="ÎÀÅÈÒÍ" , *sBad0="ÞÔÚÜÝÉ" , *sBad1="ÔÕÖ×ÙÜÚÝÞÆ" , *sBad;
 float minGood,maxBad ;
 float mGood,mBad;
 float aGoodBad,bGoodBad;
 int/*bool*/ resOK =false;

 switch (plaintest)
   { case 0: aGoodBad=1.1; bGoodBad=0.0; sBad=sBad0; break;
     case 1: aGoodBad=1.6; bGoodBad=2.0; sBad=sBad0; break;
    default: aGoodBad=1.3; bGoodBad=2.0; sBad=sBad0;
   }
  minGood =(float)SampleMin(sGood);
  maxBad  =(float)SampleMax(sBad);

  mGood =SampleMean(sGood);
  mBad  =SampleMean(sBad);

//  printf ("TestWinPlainText- minGood=%f maxBad=%f aG %f, mB*aG %f\n",
//         minGood,maxBad,aGoodBad,maxBad*aGoodBad);
//  printf ("TestWinPlainText- mGood=%f mBad=%f\n",
//          mGood,mBad);
  resOK = (minGood > maxBad*aGoodBad) ;// && (mGood > mBad*bGoodBad);

  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;
//printf("start ConvByBaseMacros %s\n",m_string);
 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=0;
     else { Cp2=Cp1; Cp1=0;
          }

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

     k = re4pos(cc,CPI[Cp1][CPIbody]);
//printf("k=%i,cc=%i,cc1=%i\n",k,cc,(k>-1)?CPI[Cp2][CPIBodyWin][k]:cc);        
     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("%i ",cc);

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

 fflush(f2);

 return (true);
};


extern int  MacroProcess (char* fn1, char* fn2, char* m_string, char isString)
  // isString: 's' or 'f', default: f
  // returns: 0-success, 1-convertion error, 2-file operation error
{
 int/*bool*/ resOK =2;
 
 int  n,i,Cp1,Cp2;
 char m_s;
 int  macmac,mc1,mc2;
 int /*bool*/  extold, extnew, isfirst =true;
 char *fn1cur, *fn1wrk ="__tempre2mac.__", str1wrk[270];

 n = strlen(m_string);
 if (n<1) return 0;

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

// printf("start MacroProcess: =%s=\n",m_string);

 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);
// printf ("m_s=%i, upp m_s=%i, extnew=%c\n",m_s,toupperANSI(m_s),
//           (extnew)?'T':'F');
       continue;
     }

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


// start process macro current step:
   SetCp1(Cp1); SetCp2(Cp2);

   if (isString=='s')
    {
     if (isfirst) fn1cur=fn1;
     else
      { strcpy (str1wrk,fn2);
        fn1cur=str1wrk;
      }
     ProcessString(fn1cur,fn2);
    }
   else // if isFile
    {
     if (isfirst) fn1cur=fn1;
     else
      { remove (fn1wrk);
        rename (fn2,fn1wrk);
        fn1cur=fn1wrk;
      }
     isfirst=false;
// printf("MacroProcess: Cp1=%i,Cp2=%i,fn1cur=%s->fn2=%s\n",Cp1,Cp2,fn1cur,fn2);
     resOK = ProcessFile(fn1cur,fn2);
// printf ("after step :resOK=%i\n", resOK);
     if (resOK != 0)
      { remove (fn2); break;
      }
    } // end if isFile
 
   SetisExtended (extold);
//   printf ("extold=%c\n", (extold)?'T':'F');
  }; // end i loop

 remove (fn1wrk);

 return resOK; 
};


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


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

