/***** ru32fi.c *****/

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

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


extern char* Hex2Win (char* src, char* dst);
extern char* Win2Hex (char* src, char *dst);

extern void  ConvertHEX (FILE* f1, FILE* f2);
extern void  ConvertToHEX (FILE* f1, FILE* f2);

extern void TakeOddsFromFile (FILE* f1, FILE* f2);
extern void DoMime64 (FILE* f1, FILE* f2);
extern void DoBinHex (FILE* f1, FILE* f2);
extern void DoExpress (FILE* f1, FILE* f2);

extern char* TakeOddsFromString (char* src, char* dst);
extern char* StringDoMime64 (char* src, char* dst);
extern char* StringBinHex(char* src, char* dst);
extern char* StringUtf7(char* src, char* dst);
extern char* StringExpress (char* src, char* dst);
extern char* DeleteTag (char* src, char* dst);

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

char wrkstr_fi [270],  wrkstr_fi2[270];
  /* temporary string buffers */

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

extern void  ConvertHEX (FILE* f1, FILE* f2)
{
 char  w,d,n1,n2,n0,w1,ordhex;
 int ch;

 ordhex = hexsmb;
 n1 = 99; n2 = 99;  // don't wait for code pair
 n0 = 0; // no 'still waiting' ,i.e. 'have read n0=0 additional start symbols'

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

  if (w==10 || w==13)  goto WRT;
  if (n2==99)  //if not waiting for code pair
    {
      if (w==ordhex)
      { n1 = 88; n2 = 88; n0 = 0; continue;
      }  // start waiting for code pair
      else goto WRT;
    }

  if (n2==88 && hexsmb=='\\' && n0==0 && w==39)   //chr(39)
    { //still waiting, have read n0=1 additional start symbol
      n0 = 1;
      continue;
    }

    if (n2==88)  //if waiting for code pair
    {
    if ( (hexsmb!='\\' || (hexsmb=='\\' && n0==1)) && 
     (w>=0x41 && w<=0x46) || (w>=0x61 && w<=0x66) || (w>=0x30 && w<=0x39))
      {
       if ((w>=0x41 && w<=0x46)) d = 10+w-0x41;
       else if ((w>=0x61 && w<=0x66))  d = 10+w-0x61;
       else d = w-0x30;
       if (n1==88)  // if wait for first code from pair
          { n1 = d; w1 = w; continue; }
       else            //  if wait for 2nd code from pair
          { n2 = d; w = n1*16 +n2;
                n1 = 99; n2 = 99; //skip waiting for code pair
                goto WRT;
          }
      }
      else // it turned out to be not a code pair !
      {
       if (hexsmb!='\\')
        {
          d = ordhex;  putc(d,f2);           // we return '='
          if (n1<88) putc(w1,f2); // and the first code if any
        };
       if (w==ordhex) 
         { n1 = 88; n2 = 88; n0 = 0; continue;
         }  // start waiting for new code pair
       else if (hexsmb=='\\') continue;
       else
         { n1 = 99; n2 = 99; goto WRT;
         }
      }
    }
    WRT:  putc(w,f2);
  }
  if (n2==88) // if file finished when we wait for code pair
  {
    d = ordhex; putc(d,f2);           // we return '='
    if (hexsmb=='\\')  { d = 39; putc(d,f2); } // chr(#39)
    if (n1<88)  putc(w1,f2); // and the first code if any
  }

  fflush(f2);
};


extern char* Hex2Win (char* src, char* dst)
{
 char *m1,*m2;
 char w,d,n1,n2,n0,w1,ordhex;
 int  j, lensrc, ads;


 ordhex = hexsmb;
 ads = 0;
 m1 = src;
 m2 = dst; strcpy(dst, "");

 n1 = 99; n2 = 99;  // don't wait for code pair
 n0 = 0; // no 'still waiting' ,i.e. 'have read n0=0 additional start symbols'
 w1 = 13; // for no use, only to calm delphi on "may not be initialized" ;)

 lensrc = strlen(m1);
 for (j = 0; j < lensrc; j++) 
 {
   w = m1[j];
   if (w==10 || w==13) goto WRT;
   if (n2==99)  //if not waiting for code pair
   {
     if (w==ordhex) 
     { n1 = 88; n2 = 88; n0 = 0; continue;
     }  // start waiting for code pair
     else goto WRT;
   }

   if (n2==88 && hexsmb=='\\' && n0==0 && w==39)  // chr(39)
   { //still waiting, have read n0=1 additional start symbol
     n0 = 1;
     continue;
   }

   if (n2==88)   //if waiting for code pair
   {
     if ( (hexsmb!='\\' || (hexsmb=='\\' && n0==1)) && 
      (w>=0x41 && w<=0x46) || (w>=0x61 && w<=0x66) || (w>=0x30 && w<=0x39) )
     {
       if (w>=0x41 && w<=0x46)  d = 10+w-0x41;
       else if (w>=0x61 && w<=0x66)  d = 10+w-0x61;
       else d = w-0x30;
       if (n1==88)  // if wait for first code from pair
         { n1 = d; w1 = w; continue; }
       else            //  if wait for 2nd code from pair
         { n2 = d; w = n1*16 +n2;
           n1 = 99; n2 = 99; //skip waiting for code pair
           goto WRT;
         }
     }
     else // it turned out to be not a code pair !
     {
       if (hexsmb!='\\')
       {
         m2[ads++] = hexsmb;         // we return '='
         if (n1<88) 
              m2[ads++] = w1; // and the first code if any
       }
       if (w==ordhex)
          { n1 = 88; n2 = 88; n0 = 0; continue;
          }  // start waiting for new code pair
       else if (hexsmb=='\\') continue;
       else
          { n1 = 99; n2 = 99; goto WRT;
          }
     }
   }

 WRT:  m2[ads++] = w; 
 }

 if (n2==88)  // if string finished when we wait for code pair
 {
   m2[ads++] = hexsmb;           // we return '='
   if (hexsmb=='\\')   m2[ads++] = 39; 
   if (n1<88) m2[ads++] = w1;  // and the first code if any
 }

 m2[ads++] = '\0';
 return dst;
};

extern void  ConvertToHEX (FILE* f1, FILE* f2)
{
 char d,ordhex;
 int ch, w;

 ordhex = hexsmb;
 
 while ( (ch=getc(f1)) != EOF )
  {
  w = ch;
  if (w<0) w+= 256;
//printf("w=%i, w/16=%i, w mod 16=%i\n", w,w/16,w%16);
  if ( w==10 || w==13 ||
       (w>=0x30 && w<=0x39) ||
       (w>=0x41 && w<=0x5a) || w==0x5f ||
       (w>=0x61 && w<=0x7a) )
     putc (w,f2);
  else
    {
     d = ordhex; putc(d,f2);
     d = w / 16; if (d<10) d = 0x30+d;  else d = 0x37+d;
     putc(d,f2);
     d = w % 16; if (d<10) d = 0x30+d;  else d = 0x37+d;
     putc(d,f2);
    }
  }

  fflush(f2);
};


extern char* Win2Hex (char* src, char *dst)
{
 char *m1,*m2;
 int  w,d,ordhex,j, lensrc;
 int ads;

 ads = 0;
 m1 = src;
 m2 = dst; strcpy(m2,"");
 ordhex = hexsmb;

 lensrc = strlen(m1);
 for (j=0; j<lensrc; j++)
 {
   w = m1[j];  if (w<0) w +=256;
   if ( w==10 || w==13 ||
       (w>=0x30 && w<=0x39) ||
       (w>=0x41 && w<=0x5a) || w==0x5f ||
       (w>=0x61 && w<=0x7a) ) 
     m2[ads++] = w;
   else
    {
     d = ordhex; m2[ads++] = d;  
     d = (w / 16); if (d<10)  d = 0x30+d;   else d = 0x37+d;
      m2[ads++] = d;   
     d = (w % 16); if (d<10)  d = 0x30+d;   else d = 0x37+d;
      m2[ads++] = d;  
    }
 }

 m2[ads++] = '\0';
 return dst;
};


extern void TakeOddsFromFile (FILE* f1, FILE* f2)
{
 int  cc, ch;
 int /*bool*/yesno,lowpart;

// {C3 D0 D1}
 yesno = false;

 while ( (ch=getc(f1)) != EOF )
  {
  cc = ch;
  if (cc<0) cc +=256;

  lowpart = (cc<128);
  yesno = (yesno || lowpart);
  if (yesno)
    { putc(cc,f2);
    }
//printf("cc=%i yesno=%i lowpart=%i\n",cc,yesno,lowpart);
  yesno = ! yesno;
  }

 fflush(f2);
};


extern char* TakeOddsFromString (char* src, char* dst)
{
 int  i, cc;
 int /*bool*/ yesno,lowpart;
 int ads, lensrc;

 ads = 0;  strcpy(dst,"");

// {C3 D0 D1}
 yesno = false;

 lensrc = strlen(src);
 for (i=1; i< lensrc; i++)
 {
   cc = src[i];   if(cc<0) cc +=256;
   lowpart = (cc<128);
   yesno = (yesno || lowpart);
   if (yesno)  dst[ads++] = src[i];
   yesno = ! yesno;
 }

 dst[ads++] = '\0';
 return dst;
};


extern void DoMime64 (FILE* f1, FILE* f2)
{
 int cc,ch,ads,lentrg;
 char *src,*trg;
 long lenf1;

 src = wrkstr_fi;   ads = 0;   strcpy(src,"");
 trg = wrkstr_fi2;
 fseek(f1, 0L, SEEK_END);
 lenf1 = ftell(f1) -1L;
 fseek(f1, 0L, SEEK_SET);
//printf("lenf1=%li",lenf1);

 while ( (ch=getc(f1)) != EOF )
 {
   cc = ch;
   if (cc<0) cc +=256;

   if (binhextag && (cc==':'))  skipbyte = 0;
   if ( (re4pos((char)cc,mim) <0) && (ftell(f1)<lenf1) )  continue;
   if (binhextag && (skipbyte==1)) 
      { skipbyte = 0; continue; }
//      if not(begout and begstr)

   src[ads++] = cc;   /*otl printf("%c",cc); */
   if ( (ads==mimestr) || (ftell(f1)==lenf1) )
   {  /*otl  printf("\n\n"); */
     src[ads++] = '\0';
//re4ShowMessage(src);
     if (binhextag)  StringBinHex(src, trg);
     else StringDoMime64(src, trg);
//re4ShowMessage(trg);
     lentrg = strlen(trg);
         // printf("lentrg=%i, ..trg=%i\n",lentrg,trg[lentrg-1]);
     fwrite (trg,1,lentrg,f2);
//        m2.write(crlf,1);
//        m2.write(crlf1,1);
     strcpy(src,"");  ads = 0;
   }
 }
 
 fflush(f2); 
};


extern void DoBinHex (FILE* f1, FILE* f2)
{
 mimestr = 64;
 binhextag = true;
 mim = mimbin;
 skipbyte = 1;

 DoMime64(f1,f2);

 skipbyte = 0;
 mim = mim64;
 binhextag = false;
 mimestr = 80;

};


extern char* StringDoMime64 (char* src, char* dst)
{
  int i,j,jsmb, lensrc, ads;
  char cc;

  lensrc = strlen(src);
// printf("Mime- lensrc,src: %i %s\n",lensrc,src);
  strcpy(dst, "");  ads = 0;

  jsmb = 0; j = 0;
  for (i = skipbyte; i<lensrc; i++)
  {
    cc = re4pos((char)(src[i]),mim);
//printf ("src[i],cc:%c %i",src[i],cc);    
    if (cc<0)  continue;
    jsmb = (jsmb)*64+cc;
    if (++j == 4)
    {
      // $100 = 256
      dst[ads++] = jsmb / 0x10000;
      dst[ads++] = (jsmb / 0x100) % 0x100;
      dst[ads++] = jsmb % 0x100;
      jsmb = 0; j = 0;
//printf ("dst: %i %i %i\n", dst[ads-3],dst[ads-2],dst[ads-1]);
    }
  }

  dst[ads++] = '\0';
  return dst;
};


extern char* StringBinHex(char* src, char* dst)
{
  int  i, j, jsmb, N, Nobuf, press2, ads, cc;
  char press1;
  int  obuf[48];

  strcpy(dst, "");  ads = 0;
  jsmb = 0; j = 0;
  N = strlen(src); if (N>64) N = 64;    /*otl printf("%s\n",src); */
//  src[N]:=' ';  //  zap out the newline
  Nobuf = 0;
  for (i = 0; i< N; i++)
  {
    cc = re4pos(src[i],mim);
    if (cc<0) continue;

    if (i<skipbyte) continue;

    j++;
    jsmb = (jsmb)*64+cc;
    
    if (j == 4)
    {
      // $100 = 256
      obuf[Nobuf]   = jsmb / 0x10000;
      obuf[Nobuf+1] = (jsmb / 0x100) % 0x100;
      obuf[Nobuf+2] = jsmb % 0x100;
/*      if (Nobuf==0)    // restore lost spaces
       {
         Ncrc=((obuf[0] / 3) + 1) * 4;
         for (j= N+1 to Ncrc)   src:=src+' ';
       } */
      jsmb = 0; j = 0; Nobuf = Nobuf+3;
    }
  }

  press1 = ' ';
  press2 = 0;  
  for (i=0; i< Nobuf; i++)
  {
    cc = obuf[i];  if(cc<0) cc +=256;
    if (press2==1)
      {
        if (cc==0)  dst[ads++] = 0x90;
        else  for (j = 0; j< cc; j++) dst[ads++] = press1;
             press2 = 0;
      }
    else if (cc==0x90) press2 = 1;
    else
      {
      if (cc<0x20 && cc!=0x0d && cc!=0x0a)  cc = 0x20;
       press1 = cc;
       dst[ads++] = press1;
      }
  }

  dst[ads++]='\0';
  return dst;
};


extern char* StringUtf7(char* src, char* dst)
{
 char *src1,*src2;
 int kk,nn,nnbad,i1,i2,i0;
 int cc,cctag, ads;

// printf ("src beg: %s\n",src);
 src1 = wrkstr_fi;   src2 = wrkstr_fi2;
 skipbyte = 0;
 strcpy(dst, "");  ads = 0;
 kk = strlen(src);
 while (kk > 0)
 {
// printf ("src kk=%i: %s\n",kk,src);

   i1 = re4pos('+',src);
   if (i1>=1)  { strncat(dst,src,i1);  ads = strlen(dst); }
// printf ("dst len=%i: <%s>\n",ads,dst);
   if (i1>=0)
    {
      strncpy (src1, src+i1+1,kk);
      i0 = strlen(src1);
      i2 = -1;
      for (i1=0; i1 <i0; i1++) if (re4pos(src1[i1],mim64)<0)
      {
        i2 = i1; break;
      }
      if (i2>=0)
      {
        if (src1[i2] != '-')  strcpy (src, src1+i2);
        else  strcpy (src, src1+i2+1);
        src1[i2] = '\0';
      } else strcpy(src,"");

      i0 = strlen(src1);
      i1 = i0 % 4;  if (i1>0) i1 = 4-i1;
// printf("lensrc1,dlen,newlen:%i %i %i\n",i0,i1,i0+i1);
      for (i2=0; i2 < i1; i2++)  src1[i0+i2]='A';
      i0 += i1;  src1[i0] = '\0';

// printf("src1 len>mim64: %i <%s>\n, src tail: <%s>\n",i0,src1,src);
      StringDoMime64(src1, src2);
// printf("1st lensrc2,i1:%i,%i\n",strlen(src2),i1);
      i0 = i0 *3 /4  -i1;
      src2[i0] = '\0';
           // " src2 [strlen(src2)-i1]='\0'; "

      i1 = i0 / 2;
//printf("lensrc2,i1:%i,%i\n",i0,i1);
      for (i2 = 0; i2< i1; i2++)
      {
        cctag = src2[i2*2];
        cc = src2[i2*2+1];
//printf("cctag,cc:%i %i+",cctag,cc);
        if (cctag==4 && cc>=0x10 && cc<=0x4f)
          cc += (-0x10+0xc0); 
        else if (cctag!=0) 
        {
         nnbad = 1;
         for (nn=0; nn< 64; nn++)
          if (uni_dead[nn*2]==cc  && uni_dead[nn*2+1]==cctag)
          { cc = 0x80+nn; nnbad = 0; break;
          };
          if (nnbad==1)  cc=0x20;
        }
        ads = strlen(dst);  dst[ads++] = cc;  dst[ads] = '\0';
      }
    }
   else
    { strcat(dst, src);  strcpy(src,"");
    };
    kk = strlen(src);
 } //while

  return dst;
};


extern void DoExpress (FILE* f1, FILE* f2)
{
 int cc, ch;
 char *src,*trg;
 int lensrc;
 long lenf1;

 src=wrkstr_fi;  strcpy(src,"");
 trg=wrkstr_fi2;

 fseek(f1, 0L, SEEK_END);
 lenf1 = ftell(f1) -1L;
 fseek(f1, 0L, SEEK_SET);

 while ( (ch=getc(f1)) != EOF )
  {
    cc = ch;
    if (cc<0) cc +=256;

    lensrc = strlen(src);
    if ( (cc==0x0d || cc==0x0a) && (ftell(f1)<lenf1)
         && lensrc>0 ) 
     {
      if ( re4pos(src[lensrc-1],"&#0123456789") >=0 )  continue;
     }
    src[lensrc++]=cc;  src[lensrc]='\0';
    if ( (lensrc>210 && cc==';')
        || (ftell(f1)>=lenf1)
        || (cc==0x0a) ) 
     {
      StringExpress(src, trg);
      fwrite(trg,1,strlen(trg),f2);
      strcpy(src,""); 
     }
  } // end while
};


extern char* StringExpress (char* src, char* dst)
{
  int p,ii,it, i, lenss, ads;
  char *ss,si[20], *ppos;
  
  ss = wrkstr_fi;
  strcpy(ss, src);
  strcpy(dst, "");
  while ( strlen(ss) > 0 )
  {
    ppos = strstr(ss,"&#");  p = (ppos==NULL) ? -1 : ppos-ss;
    if (p<0) { strcat(dst,ss); strcpy(ss,"");
             }
    else
    {
      if (p>=1)
      {
        strncat(dst,ss,p);
        lenss=strlen(ss); for(i=p; i<=lenss; i++) ss[i-p]=ss[i];
                    //ss:=copy(ss,p,length(ss))
      };
      p = re4pos(';',ss);
      if (p<3) { strcat(dst,ss); strcpy(ss,"");
               }
      else
      {
         strncpy (si,ss+2,p-2);
         ii = atoi(si);
         if (ii>1)
           { ii = 128+(ii % 128);
             it = 48+ii;  
             ads=strlen(dst); dst[ads++]=it; dst[ads]='\0';
           }
        else  // no digital
         { strcat(dst,"&#");
           strcat(dst,si);
           strcat(dst,";");
         }

        lenss = strlen(ss);
        if (p<lenss) 
                for (i=p+1; i<=lenss; i++) ss[i-p-1]=ss[i];
                                 //ss:=copy(ss,p+1,length(ss))
        else  strcpy(ss,"");
      } //';' found after '&#'

    } // '&#' found

  } //while-loop

  return dst;
};


extern char* DeleteTag (char* src, char* dst)
{
  int p, i, lenss;
  char ss[270];

  strcpy(ss,src);
  ReplaceSubWord("&nbsp;",  "",ss);

  strcpy(dst,"");
  while (strlen(ss)>0)
  {
    p = re4pos('<',ss);
    if (p<0) { strcat(dst,ss); strcpy(ss,"");
             }
    else
    {
      if (p>=1)
      {
        strncat(dst,ss,p-1);
        lenss=strlen(ss); for(i=p; i<=lenss; i++) ss[i-p]=ss[i];
                    //ss:=copy(ss,p,length(ss))
      }
      p = re4pos('>',ss);
      if (p<0) { strcat(dst,ss); strcpy(ss,"");
               }
      else
       {
        lenss = strlen(ss);
        if (p<lenss) 
                for (i=p+1; i<=lenss; i++) ss[i-p-1]=ss[i];
                                 //ss:=copy(ss,p+1,length(ss))
        else strcpy(ss,"");
       } //'>' found after '<'

    } // '<' found

  } //while-loop

  return dst;
};


