/***** ru32un.c *****/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <malloc.h>
#include <string.h>

#include "ru32cp.h"
#include "ru32var.h"
#include "ru32lat.h"
#include "ru32fi.h"
#include "ru32au.h"
#include "ru32mau.h"

// message defines :
#ifndef __ru32verinfo
#define __ru32verinfo "0.1 (4.62 port)"
#endif

#ifndef __ru32datinfo
#define __ru32datinfo "Russian Anywhere v0.1, 1999-2000"
#endif

#ifndef __ru32autinfo
#define __ru32autinfo " http//tx-tx.da.ru, http//dll.da.ru"
#endif

#ifndef __ru32libinfo
#define __ru32libinfo  __ru32datinfo ", ver." __ru32verinfo "," __ru32autinfo
#endif

//---------------------------wrk attr buffer---------------- //

////Tattr Attr;   - temporary in ru32var.c, extern  :(

//--------------------------- RCL32 export :---------------- //

extern void InitLibrary(void);
extern char* ProcessString (char* src, char* dst);
extern int  ProcessFile (char* fn1, char* fn2);
  // returns: 0-success, 1-convertion error, 2-file operation error
extern void  ProcessFile0 (FILE* f1, FILE* f2);

extern int /*bool*/  CheckUnicodeFile (char*  FileSpec, char* FileNew);
 //returns: 0 if no Unicode, 1 if changed from Unicode as FileNew, 2 if failed.

extern int getDBFInfo (long *nrec, int *nfield, int *Linf, int* Lrec, char*date, FILE* f1);
// *Linf - header length (bytes number), *Lrec - record length (bytes number)
// *nrec - number of records, *nfield - number of fields,
// date - last modified (y m d - 3 bytes). 

extern void LoadUserAlph (char* myAlph);
extern void LoadUserAlphFile (char* fn);
extern void LoadAddCPI (char* fn);
extern void SaveAddCPI (char* fn);

//---(from strman:)---//

extern void  ConvertViaString (FILE* f1, FILE* f2);

extern char* Char2CharConvert (int cp1, int cp2, char* src);
extern void  ConvertFile (int SkipBytes, FILE* f1, FILE* f2);
extern void  ConvertDBF (FILE* f1, FILE* f2);


extern char* Pol2Win (char* LatinTable, char* src, char* dst);
extern char* Win2Pol (char* LatinTable, char* src, char* dst);

extern void  DecryptFile (char* fn1, char* fn2, char* pw);
extern void  EncryptFile (char* fn1, char* fn2, char* pw);


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

char wrkstr_un [270],  wrkstr_un2[270], wrkstr_un3[270];;
  /* temporary string buffers */

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

extern void InitLibrary(void)
{
  InitCPIconst();
  InitLatinTable();
  __latrules = both;
  SetDelHtmlTag(true);    
  binhextag = false;       
  mimestr = 80;
  SetisExtended(false);
  SetVerbose(true);
  SetisAddList(true);
  SetAuto2Cpi(GetCPIbyName("Koi"));
  SetDeepAuto(true);

  SetPh(phNo);
  SetDBF(false);
  Attr.Cp1 = WinCPI;
  Attr.Cp2 = WinCPI;
//    Fn1:='noname.txt';    --------REVISE for interface
//    Fn2:='noname.cvr';    --------REVISE for interface
  Attr.autocpi = false;
};



extern char* ProcessString (char* src, char* dst)
{
 char* trg;
 trg = wrkstr_un;
// printf("src: <%s>\n");
 if (Attr.Cp1 < 0 || Attr.Cp2 < 0 || Attr.Cp1 >= CPI_STANDcount+CPI_ADDcount
                                  || Attr.Cp2 >= CPI_STANDcount+CPI_ADDcount
    || no2this(Attr.Cp2) || ((Attr.Cp1==PolCPI)&&(Attr.Cp2==HtmCPI)) 
    || Attr.Cp1==Attr.Cp2  )
   strcpy(dst,src);
 else if (Attr.Cp1==ExpressCPI)  StringExpress (src,dst);
 else if (Attr.Cp1==MimeCPI)     StringDoMime64 (src,dst);
 else if (Attr.Cp1==UuCPI)      
   { mim = mimuu; skipbyte = 1;  StringDoMime64 (src,dst);
     mim = mim64; skipbyte = 0; 
   } 
 else if (Attr.Cp1==XxCPI) 
   { mim = mimxx; skipbyte = 1;  StringDoMime64 (src,dst);
     mim = mim64; skipbyte = 0; 
   }
 else if (Attr.Cp1==BinhexCPI)
   { mim = mimbin; skipbyte = 1; StringBinHex (src,dst);
     mim = mim64;  skipbyte = 0;
   } 
 else if (Attr.Cp1==Utf7CPI)    StringUtf7 (src,dst);
 else if (Attr.Cp1==OddCPI)       TakeOddsFromString (src,dst);
 else if (Attr.Cp1==HexCPI)       Hex2Win (src,dst);
 else if (Attr.Cp2==HexCPI)       Win2Hex (src,dst);
 else if (Attr.Cp1==GetCPIbyName("%hex"))
          { hexsmb = '%'; Hex2Win (src,dst); hexsmb = '='; }
 else if (Attr.Cp1==GetCPIbyName("\\hex"))
          { hexsmb= '\\'; Hex2Win (src,dst); hexsmb = '='; }
 else if (Attr.Cp1==PolCPI) 
  { 
   Pol2Win(LatinTable, src, dst);
   if (Attr.Cp2 != WinCPI)  Char2CharConvert (WinCPI, Attr.Cp2, dst);
  }
 else if (Attr.Cp2==PolCPI)
  {
   if (Attr.Cp1 != WinCPI)
     {  strcpy (trg, src);
        Char2CharConvert (Attr.Cp1, WinCPI, trg);
        Win2Pol (LatinTable, trg, dst);
     }   
   else  Win2Pol(LatinTable, src, dst);
  }
 else if (Attr.Cp1==HtmCPI)
  { 
   __latrules = nochars;
   if (delhtmltag)
     {  Pol2Win (HtmlTable, src, trg);  DeleteTag (trg, dst); }
   else   Pol2Win (HtmlTable, src, dst);
   __latrules = both;
  }
 else if (Attr.Cp2==HtmCPI)
  {
   __latrules = nochars;
   Win2Pol (HtmlTable, src, dst);
   __latrules = both;
  }
 else
  { strcpy (dst, src);
    Char2CharConvert (Attr.Cp1, Attr.Cp2, dst);
  }

 return dst;
};




extern int  ProcessFile (char* fn1, char* fn2)
  // returns: 0-success, 1-convertion error, 2-file operation error
{
FILE *f1=NULL, *f2=NULL;
int cp1,cp2;

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

if ( (f2=fopen(fn2,"wb")) == NULL )
  { 
    strcpy (wrkstr_un,"ProcessFile--can't open new file-to : ");
    strcat(wrkstr_un,fn2);
    re4ShowMessage (wrkstr_un);
    if (f1 != NULL) fclose(f1);
    return 2;
  }
// printf("ProcessFile: fn1=%s(%i),fn2=%s(%i)\n",fn1,Attr.Cp1,fn2,Attr.Cp2);
 ProcessFile0 (f1,f2);
 
fin:
 if (f2 != NULL) fclose(f2);
 if (f1 != NULL) fclose(f1);
 return 0;
}


extern void  ProcessFile0 (FILE* f1, FILE* f2)
{
  fseek(f1,0L,SEEK_SET);
  if (Attr.Cp1<0 || Attr.Cp2<0 || Attr.Cp1>=CPI_STANDcount+CPI_ADDcount
                               || Attr.Cp2>=CPI_STANDcount+CPI_ADDcount)
  {
   re4cpfile(f1,f2);  
   goto fin;; 
  };

  if ( no2this(Attr.Cp2) || ((Attr.Cp1==PolCPI)&&(Attr.Cp2==HtmCPI)) )
  {
    strcpy(wrkstr_un,"No convertion to ");
    strcat(wrkstr_un,GetCodepageByNumber(Attr.Cp2));
    re4ShowMessage(wrkstr_un);
    re4cpfile(f1,f2);
    goto fin;;
  };
//    printf ("ProcessFile0 start %i->%i\n",Attr.Cp1,Attr.Cp2);
  if (Attr.isDBF)  ConvertDBF (f1,f2);
  else if (Attr.Cp1==ExpressCPI)  DoExpress(f1,f2);
  else if (Attr.Cp1==MimeCPI)     DoMime64(f1,f2);
  else if (Attr.Cp1==BinhexCPI)   DoBinHex(f1,f2);
  else if (Attr.Cp1==UuCPI || Attr.Cp1==XxCPI || Attr.Cp1==Utf7CPI) 
     ConvertViaString (f1,f2);
  else if (Attr.Cp1==OddCPI)  TakeOddsFromFile (f1,f2);
  else if (Attr.Cp1==HexCPI)  ConvertHEX(f1,f2);
  else if (Attr.Cp2==HexCPI)  ConvertToHEX(f1,f2);
  else if (Attr.Cp1==GetCPIbyName("%hex")) 
          { hexsmb = '%'; ConvertHEX(f1,f2); hexsmb = '='; }
  else if (Attr.Cp1==GetCPIbyName("\\hex"))  ConvertViaString (f1,f2);
  else if (Attr.Cp1==PolCPI || Attr.Cp2==PolCPI)  ConvertViaString (f1,f2);
  else if (Attr.Cp1==HtmCPI)  ConvertViaString (f1,f2);
  else if (Attr.Cp2==HtmCPI) 
   { htmlbreak = true; ConvertViaString (f1,f2); htmlbreak = false; } 
  else ConvertFile(0,f1,f2);

fin :
 if (f2 != NULL) fflush(f2);
};


extern int /*bool*/  CheckUnicodeFile (char*  FileSpec, char* FileNew)
{
  FILE *f1=NULL, *f2=NULL;
  char cctag;
  int cc, ch, nn, nnbad;

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

  nn = 0;   nnbad = 0;
  while ( (ch=getc(f1)) != EOF  &&  nn++ < 100 )
  {
    if ( ch < 0x20 && ch != 0x0d && ch != 0x0a )  nnbad++;
//printf ("nn=%i  nnbad=%i  ch=%i(%c)\n", nn,nnbad,ch,ch);
  };
//printf ("nn=%i  nnbad=%i\n", nn,nnbad);
  if (nnbad < nn/3)   return 0 ;


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

  fseek (f1, 0L, SEEK_SET);
  
  while ( (ch=getc(f1)) != EOF )
  {
    cc = ch;

    if ( (ch=getc(f1)) != EOF ) cctag = ch;
    else  ungetc (ch, f1);
    if ( cctag == 4 && cc >= 0x10 && cc <= 0x4f )
       cc += (-0x10 +0xc0); // convert russ.letters from  Unicode to Win
    else if (cctag != 0)    // if cctag=0 - cc is Win already.
      {  // convert from Unicode to  Win according to table
       nnbad = true;
       for (nn = 0; nn < 64; nn++)
        { if ( uni_dead[nn*2]==cc && uni_dead[nn*2+1]==cctag )
            { cc = 0x80 +nn;   nnbad = false;   break;
            }
        }
        if (nnbad)  cc = 0x20; // clean bad symbols.
      };
    putc(cc,f2);
  };

 if (f2 != NULL) fclose(f2);
 if (f1 != NULL) fclose(f1);
 return 1;
};




extern int getDBFInfo (long *nrec, int *nfield, int *Linf, int* Lrec, char*date, FILE* f1)
// *Linf - header length (bytes number), *Lrec - record length (bytes number)
// *nrec - number of records, *nfield - number of fields,
// date - last modified (y m d  - 3 bytes). 
{ 
  int ch, ret;
  short wrd;
  long headend;

  fseek (f1, 0L, SEEK_SET);
  ch = getc (f1);
//  if ( (ch != 0x03) && (ch != 0x83) && (ch != 'F') )   return (1);

  fread ( date, 3, 1, f1);  // date[4] ='\0'; nothing for.. - isn't string 
  fread ( nrec, 4, 1, f1);
  fread ( &wrd, 2, 1, f1);
  *Linf = wrd;
  *nfield = ( (*Linf) - 33 ) / 32;
  fread ( &wrd, 2, 1, f1);
  *Lrec = wrd;

/* 
 printf("sizeint=%i,sizelong=%i,sizeshort=%i\n",
   sizeof(int),sizeof(long),sizeof(short));
 printf("Linf=%i \n",*Linf); 
 printf("date=%i %i %i \n",date[0],date[1],date[2]); 
 printf("nrec=%i \n",*nrec); 
 printf("nfield=%i \n",*nfield); 
*/   

  if ((*Linf) < 33) return 1;
  headend = (*Linf)-1L;
  fseek (f1, headend, SEEK_SET);
  ret = 0; ch = 0;
  if ((ch = getc (f1)) != 0x0d) ret = 1;
//  printf ("ch=%i(%c) headend=%i\n",ch,ch,headend);

  fseek (f1, 0L, SEEK_SET);
  return  ret;
};


extern void LoadUserAlphFile (char* fn)
{
 FILE * fi;
 char myAlph[270];
 int cc, ch;

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

  cc = 0;
  while ( (ch=getc(fi)) != EOF  &&  cc < 256)
  { 
    myAlph[cc++] = (char)ch;
  }
  myAlph[cc] = '\0';

 if (fi != NULL)  fclose (fi);
 LoadUserAlph (myAlph);

}


extern void LoadUserAlph (char* myAlph)
{
 char * s;
 int  i,j,n,n0,kk;

 s = wrkstr_un;
 n = strlen(myAlph);
 n0=n;
 for (i = 0; i < n; i++)
  if ( myAlph[i] < '\32'  &&  myAlph[i] >='\0' )  
    { // printf("clean%i %i %i\n ",i,n,n0);
      for (j = i; j < n; j++)   myAlph[j]=myAlph[j+1]; n0--; }
 myAlph[n0]='\0';
// printf ("\n***tiny myAlf len old=%i new=%i\n",n,n0);

 strncpy (s,myAlph,64);// 64 - length of standart russian alphabet table
 n = strlen(s);  kk = 64;
 if (n < kk)  { for (i = n; i < kk; i++) s[i] = '.';  s[kk] = '\0'; }
 strncpy (CPI[UserCPI][CPIbody], s, kk);
// for (i=0; i<64; i++) printf("%c-%i\n",CPI[PolCPI][CPIbody][i],CPI[UserCPI][CPIbody][i]);

 if (n0>64) strncpy (s, myAlph+64, ExtCPIwin);
 else strcpy(s,"");
 n = strlen(s);  kk = ExtCPIwin;
 if (n < kk)  { for (i = n; i < kk; i++) s[i] = '.';  s[kk] = '\0'; }
 strncpy (CPI[UserCPI][CPIBodyWin], s, kk);

 if (n0>64+ExtCPIwin) strncpy (s, myAlph+64+ExtCPIwin, ExtCPIdos);
 else strcpy(s,"");
 n = strlen(s);  kk = ExtCPIdos;
 if (n < kk)  { for (i = n; i < kk; i++) s[i] = '.';  s[kk] = '\0'; }
 strncpy (CPI[UserCPI][CPIBodyDos], s, kk);

};

extern void LoadAddCPI (char* fn)
{
 char *myAlf,*s,*s1,slet[100];
 int  i,j,nn,n0,n,np,cadd,c,ch,kk;
 FILE * fi;
 char divid;

 divid = ':';
 myAlf = wrkstr_un;
 s = wrkstr_un2;
 s1 = wrkstr_un3;   
 
 if ( (fi=fopen(fn,"rb")) == NULL )
  { 
    strcpy (wrkstr_un,"can't open UserAlph-file: ");
    strcat(wrkstr_un,fn);
    re4ShowMessage (wrkstr_un);
    return;
  }

 c = CPI_STANDcount+CPIaddNoChange;
 strncpy (slet, CPILetter, c);

 cadd = CPIaddNoChange;
 while ( (ch = getc(fi) ) != EOF )
 {
  ungetc (ch, fi);
  if (c>=CPImax) break;
  getline (myAlf, fi);
  nn = strlen(myAlf);
  n0=nn;
// printf("get lenAlf=%i\n",nn);
  for (i = 0; i < nn; i++)
   if ( myAlf[i] < '\32'  &&  myAlf[i] >='\0' )  
     { // printf("clean%i %i %i\n ",i,nn,n0);
       for (j = i; j < nn; j++)   myAlf[j]=myAlf[j+1]; n0--; }
  myAlf[n0]='\0';
// printf ("\n***tiny myAlf len old=%i new=%i\n",nn,n0);

  np = re4pos (divid ,myAlf);
  if (np<1) continue; // Cpi name not found
  if (myAlf[1]==macrodivlet) continue;
                      //1st symbol in  Cpi name is system reserved symbol.
  strncpy (s1, myAlf, np-1);
// printf ("new: %s\n",s1);
  if (re4pos (s1[0], slet) >= 0) continue; // Cpi name is already used

  for (i = np+1; i <= n0; i++)  myAlf[i-(np+1)] = myAlf[i]; // with str-end
  n0 = strlen(myAlf);  //i.e. myAlf:=copy(myAlf,np+1,nn); 
//printf ("div1 s1=%s\n lenAlf=%i\n",s1,n0);
  np = re4pos (divid, myAlf);
  if (np <0) {  myAlf[n0] = divid; myAlf[n0+1]='\0'; n0++; np = n0;
             }
//    If np<2 then continue; // Cpi russian alphabeth table not found 
  if (np <1) strcpy(s, "");  else  strncpy(s, myAlf,np-1);
// for (i=0; i<strlen(s); i++) printf("%c-%i\n",CPI[PolCPI][CPIbody][i],CPI[c][CPIbody][i]);

  // adding new Cpi:
  cadd++;
  c++;
  strncpy (CPI[c][CPIname], s1,10);
                       //cat Cpi name length -for avoid too long one
  i=strlen(slet);  slet[i]=s1[0];   slet[i+1]='\0';

  if (np <1) strcpy(s, "");  else  strncpy(s, myAlf,np-1);
  for (i = np+1; i <= n0; i++)  myAlf[i-(np+1)] = myAlf[i]; // with str-end
  n0 = strlen(myAlf);  //i.e. myAlf:=copy(myAlf,np+1,nn); 
  n = strlen(s);  kk = 64;
                // 64 - length of standart russian alphabeth russian table
  if (n < kk)  { for (i = n; i < kk; i++) s[i] = '.';  s[kk] = '\0'; }
  strncpy (CPI[c][CPIbody], s, kk);
// for (i=0; i<kk; i++) printf("%c-%i\n",CPI[PolCPI][CPIbody][i],CPI[c][CPIbody][i]);

  np = re4pos (divid, myAlf);
  if (np <0) {  myAlf[n0] = divid; myAlf[n0+1]='\0'; n0++; np = n0;
             }
  if (np <1) strcpy(s, "");  else  strncpy(s, myAlf,np-1);
  for (i = np+1; i <= n0; i++)  myAlf[i-(np+1)] = myAlf[i]; // with str-end
  n0 = strlen(myAlf);  //i.e. myAlf:=copy(myAlf,np+1,nn); 
  n = strlen(s);  kk = ExtCPIwin;
  if (n < kk)  { for (i = n; i < kk; i++) s[i] = '.';  s[kk] = '\0'; }
  strncpy (CPI[c][CPIBodyWin], s, kk);

  np = re4pos (divid, myAlf);
  if (np <0) {  myAlf[n0] = divid; myAlf[n0+1]='\0'; n0++; np = n0;
             }
  if (np <1) strcpy(s, "");  else  strncpy(s, myAlf,np-1);
  n = strlen(s);  kk = 64;
  if (n < kk)  { for (i = n; i < kk; i++) s[i] = '.';  s[kk] = '\0'; }
  strncpy (CPI[c][CPIBodyDos], s, kk);
 };
 if (fi != NULL)  fclose (fi);

 if (cadd >0)
 {
  CPI_ADDcount = cadd;
  c = CPI_STANDcount+CPI_ADDcount;
  for (i=0; i < c; i++)
    {
    CPILetter[i]=(char)toupper((CPI[i][CPIname])[0]);
    }
  CPILetter[c] = '\0';

  // InitCPIdefines;
  SetisAddList (isAddList);
      // without changing AddList setting, recalculate  CPIcount
 };
};


extern void SaveAddCPI (char* fn)
{
 char *myAlf, *s, divid [2];
 int  i,c,cc,k;
 FILE  *fo;

 divid[0] = ':';  divid[1] = '\0';
 myAlf = wrkstr_un;
 s = wrkstr_un2;

 if ( (fo=fopen(fn,"wb")) == NULL )
  { 
    strcpy (wrkstr_un,"can't open new UserAlph-file: ");
    strcat(wrkstr_un,fn);
    re4ShowMessage (wrkstr_un);
    return;
  }

 cc = CPI_STANDcount+CPI_ADDcount;
 for (c = CPI_STANDcount /*+CPIaddNoChange*/; c < cc; c++)
  {
    strcpy (myAlf, CPI[c][CPIname]);
    strcat (myAlf, divid);
    strcat (myAlf, CPI[c][CPIbody]);
    strcat (myAlf, divid);

    strcpy (s, CPI[c][CPIBodyWin]);
    k = 0; for (i = 0; i <  ExtCPIwin; i++) { if (s[i]!='.')  k++; }
    if (k==0) strcpy(s, ""); //for don't write strings consisting of points only
    strcat (myAlf, s);
    strcat (myAlf, divid);

    strcpy (s, CPI[c][CPIBodyDos]);
    k = 0; for (i = 0; i < ExtCPIdos; i++) { if (s[i]!='.')  k++; }
    if (k==0) strcpy(s, ""); //for don't write strings consisting of points only
    strcat (myAlf, s);
    
    putline (myAlf, fo);
  };

 if (fo != NULL)  fclose (fo);
};


//--------------------------- STRMAN :---------------- //


extern void  ConvertViaString (FILE* f1, FILE* f2)
{
  int ch, nbytes;

  nbytes = (htmlbreak) ? 14 : 120;

  while ( (ch = getc(f1) ) != EOF )
    {
    ungetc (ch, f1);
    getnline (wrkstr_un, f1, nbytes);
    ProcessString (wrkstr_un, wrkstr_un2);

    putline (wrkstr_un2, f2);
    }
  fflush (f2); 
};



extern char* Char2CharConvert (int cp1, int cp2, char* src)
{
 char *ss, cc1;
 int k;

 for (ss = src; *ss != '\0'; ss++)
 {
    k = re4pos(*ss, CPI[cp1][CPIbody]);
    if (k>-1)
    { 
      *ss = CPI[cp2][CPIbody][k];
      if (Attr.PH == phRE)
      { if (k=pLocation)  *ss = 'p';
        if (k=HLocation)  *ss = 'H';
      };
    }

    else if ( isExtended && (*ss != '.') )
    {
      k = re4pos(*ss, CPI[cp1][CPIBodyWin]);
      if (k>-1)
      {
        cc1 = (CPI[cp2][CPIBodyWin])[k];
        if (cc1 != '.')  *ss = cc1;
      }
      else
      {
        k = re4pos(*ss, CPI[cp1][CPIBodyDos]);
        if (k>-1)
        {
          cc1 = (CPI[cp2][CPIBodyDos])[k];
          if (cc1 != '.')  *ss = cc1;
        }
      }
    };

    if (Attr.PH == phER)
    { if (*ss == 'p')
          *ss = CPI[cp2][CPIbody][pLocation];
      if (*ss == 'H')
          *ss = CPI[cp2][CPIbody][HLocation];
    };
 };

  return src;
};


extern void  ConvertFile (int SkipBytes, FILE* f1, FILE* f2)
{
  int k,ch;
  char cc,cc1;
  long offs;

  offs = SkipBytes;

  while ( offs-- > 0 )
  { 
    if ( (ch=getc(f1)) == EOF )  break;
    cc = (char)ch;  putc(cc,f2);
  }

  fseek(f1, (long)SkipBytes, 0L);
  while ( (ch=getc(f1)) != EOF )
  {
    cc = (char)ch;
    k = re4pos(cc, CPI[Attr.Cp1][CPIbody]);
//printf("\nConvertFile:cc=%x Body-k=%i",cc,k);
    if (k>-1)
    { 
      cc = CPI[Attr.Cp2][CPIbody][k];
      if (Attr.PH == phRE)
      { if (k=pLocation)  cc = 'p';
        if (k=HLocation)  cc = 'H';
      };
          
    }
    else if ( isExtended && (cc != '.') )
    {
      k = re4pos(cc, CPI[Attr.Cp1][CPIBodyWin]);
//printf("  cc=%x BodyWin-k=%i",cc,k);
      if (k>-1)
      {
        cc1 = (CPI[Attr.Cp2][CPIBodyWin])[k];
        if (cc1 != '.')  cc = cc1;
      }
      else
      {
        k = re4pos(cc, CPI[Attr.Cp1][CPIBodyDos]);
//printf("  cc=%x BodyDos-k=%i",cc,k);
        if (k>-1)
        {
          cc1 = (CPI[Attr.Cp2][CPIBodyDos])[k];
          if (cc1 != '.')  cc = cc1;
        }
      }
    };

    if (Attr.PH == phER)
    { if (cc == 'p')
          cc = CPI[Attr.Cp2][CPIbody][pLocation];
      if (cc == 'H')
          cc = CPI[Attr.Cp2][CPIbody][HLocation];
    };

   putc(cc,f2);
  }
};


extern void  ConvertDBF (FILE* f1, FILE* f2)
{
  long nrec;
  int nfield, Linf, Lrec;
  char date[4];

  if (getDBFInfo (&nrec, &nfield, &Linf, &Lrec, date, f1) != 0)
//       printf("in ConvertDBF Linf=%i\n",Linf);
       re4ShowMessage("file-from  not a DBFfile");
  else ConvertFile(Linf, f1, f2);
};



extern char* Pol2Win (char* LatinTable, char* src, char* dst)
{
// standart vars as in Win2Pol + additional variations: ju,ja etc

  strcpy (dst, src);
  if (__latrules != norules) SubstFromLat (LatinTable, dst);
  if (__latrules != nochars) Char2CharConvert (PolCPI, WinCPI, dst);
 return dst;
};

extern char* Win2Pol (char* LatinTable, char* src, char* dst)
{
// standart vars, except additional variations of Pol2Win: ju,ja etc

  strcpy (dst, src);
//printf ("src: %s\n",src);
  if (__latrules != norules) SubstToLat(LatinTable, dst);
//printf ("dst: %s\n",dst);
  if (__latrules != nochars) Char2CharConvert (WinCPI, PolCPI, dst);
 return dst;
};


char* GenerateKey (const char* pwd)
{
 char* dst;

 dst = (char*) malloc(3* strlen(pwd) +30);
 strcpy(dst,pwd); strcat(dst,"6751266784");
 strcat(dst,pwd); strcat(dst,"78907896784567");
 strcat(dst,pwd);
 return (dst);
};


extern int/*bool*/ WhatDecFile (FILE* f1, long xt)
{
 char *xx,cc;
 int ch, istry, i, xxlen;
 

 xx = wrkstr_un;
 strcpy(xx,"&**0773721166770226780037827889*00932**@");
 xxlen = strlen(xx);
 istry = false; i = 0;

 fseek (f1, 0L, SEEK_SET);

 while ( (ch=getc(f1)) != EOF )
 { cc = ch;
   if (!istry)
    { if (cc != '&') continue;
      else { i = 1; istry = true; continue; }
    }
   else
    { if (cc == '&')
        { i = 1; istry = true; continue; }
      else 
        if (cc != xx[i]) {istry = false; i = 0; continue; }   
        else
         { i++; if (i>=xxlen) break;
         }
    }       
//  printf ("istry=%i,cc=%c,i=%i,xx[i]=%c\n",istry,cc,i,xx[i]); 
 }
 return (i >= xxlen);
}


extern void  DecryptFile1 (char* fn1, char* fn2, char* pw)
{
  FILE *f1=NULL, *f2=NULL;

  char cc;
  int i, j, nj, ch, ix, ipwd, cc1;
  char *pww, *xx, *yy;
  long xt;


  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;;
  }

  fseek (f1, 0L, SEEK_END);  xt = ftell(f1);

  if (! WhatDecFile(f1,xt) ) goto fin;

  pww = GenerateKey(pw);
  xx = "&**0773721166770226780037827889*00932**@";
  yy = wrkstr_un;
  nj = strlen(pww);  j = 0;
  
  fseek (f1, 0L, SEEK_SET);

  while ( (ch=getc(f1)) != EOF )
  {
    cc = ch;
// printf("%c",cc);
    if (cc == '@') break;
  }
  
  i = 0;   strcpy (yy,"");
  while ( (ch=getc(f1)) != EOF )
  {
    cc = ch;
// printf("%c--",cc);
    if (cc == '*') break;
    if (cc != '\\' && cc != 0x0d && cc != 0x0a) 
      { yy[i++] = cc;  yy[i]='\0';
      }
    else if (cc == '\\' || cc == '*') 
      {
        ix = atoi (yy);  ipwd = pww[j]; if (ipwd <0) ipwd +=256;
        cc1 = ( ix ) ^ ( ipwd );
//printf("j=%i pww[j]=%c ix(yy)=%i(%s) cc1(ipwd)=%i(%i)\n",j,pww[j],ix,yy,cc1,ipwd);
        putc (cc1, f2);
        i = 0;  strcpy (yy, "");
        j++;  j %= nj;
      };
  };

fin :
 if (f2 != NULL) fclose(f2);
 if (f1 != NULL) fclose(f1);
};



extern void EncryptFile1 (char* fn1, char* fn2, char* pw)
{
  FILE *f1=NULL, *f2=NULL;

  
  int i, j, nj, ch, ix, ipwd, cc1;
  char *pww, *xx, *yy;
  long xt;

  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;;
  }

  fseek (f1, 0L, SEEK_END);  xt = ftell(f1);

  fseek (f1, 0L, SEEK_SET);
  pww = GenerateKey(pw);
  yy = wrkstr_un;   xx = wrkstr_un2;
  nj = strlen(pww);  j = 0;
  strcpy (yy, "EEXB");
  fwrite (yy, 4, 1, f2);
//    xx:='&**0773721166770226780037827889*00932**@';

  i = int( sin(xt)*100000 );
  srandom(i);
  xt = random();
  sprintf (xx, "%li", xt);
  strcpy(yy, "&**");   strcat(yy, xx);   strcat(yy, "**@");
//        printf ("yy: <%s>\n",yy);
  i = strlen(yy);
  fwrite (yy, i, 1, f2);

  while ( (ch=getc(f1)) != EOF )
  {
   ix = (ch <0)? ch+256 : ch; 
   ipwd = pww[j]; if (ipwd <0) ipwd +=256;
   cc1 = ( ix ) ^ ( ipwd );
   sprintf (xx, "%i", cc1);   strcat(xx,"\\");
   i = strlen(xx);
   fwrite (xx, i, 1, f2);
   j++;  j %= nj;
  };
  strcpy (xx,"*");
  strcat (xx, "&**0773721166770226780037827889*00932**@");
  i = strlen(xx);
  fwrite (xx, i, 1, f2);

fin :
 if (f2 != NULL) fclose(f2);
 if (f1 != NULL) fclose(f1);
};


extern void DecryptFile (char* fn1, char* fn2, char* pw)
{
 DecryptFile1 (fn1, fn2, pw);
 DecryptFile1 (fn1, "__tempredf", pw);
 DecryptFile1 ("__tempredf", fn2, pw);
 remove ("__tempredf");  
}

extern void EncryptFile (char* fn1, char* fn2, char* pw)
{
// EncryptFile1 (fn1, fn2, pw);
 EncryptFile1 (fn1, "__tempredf", pw);
 EncryptFile1 ("__tempredf", fn2, pw);
 remove ("__tempredf");  
}
