/*ProfiPacket - packet radio terminal program
  Copyright (C) 1999  Alexander Feigl

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  Author:

  Alexander Feigl
  Burachstraße 51

  D-88250 Weingarten

  Mail : Alexander.Feigl@gmx.de
*/


#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "Editor.h"


#define ANSI_State_No_ANSI     0
#define ANSI_State_Read_ESC    1
#define ANSI_State_Read_InSEQ  3

#define FALSE 0
#define TRUE 1



unsigned long Stream_StreamToANSI(struct ANSIStream *ansi)
{
 unsigned char *SourceChar,*DestBuffer;
 struct StyleInfo *SourceStyle;
 unsigned long scl,ssl;
 ansi->TextLength=0;
 DestBuffer=ansi->TextBuffer;

 SourceChar=ansi->CharBuffer;
 SourceStyle=ansi->Styles;
 scl=ansi->CharLength;
 ssl=ansi->UsedStyles;

 while (ssl!=0)
  {
   if (SourceStyle->StartColumn>=ansi->CurrentColumn) break;
   ssl--;
   SourceStyle++;
  }  

 if (ansi->CurrentColumn>scl)
  {
   ansi->CurrentColumn=scl;
   return (MUIV_Editor_Return_OK);
  }
 SourceChar+=ansi->CurrentColumn;
 scl-=ansi->CurrentColumn;

 if (ansi->TextBufferSize<20)
  {

   return (MUIV_Editor_Return_ANSI_BufferTooSmall);
  }
 while (ansi->TextBufferSize>=(ansi->TextLength+16))
  {
   if ( (ssl!=0) && (SourceStyle->StartColumn==ansi->CurrentColumn) )
    {
     if ( (SourceStyle->ForegroundColor==ansi->ForegroundColor) &&
          (SourceStyle->BackgroundColor==ansi->BackgroundColor) &&
          (SourceStyle->TextStyle==ansi->TextStyle) )
      {
       ssl--;
       SourceStyle++;
       continue;
      }
     *(DestBuffer++)='\033';
     *(DestBuffer++)='[';

     if ( (ansi->TextStyle&7)!=(SourceStyle->TextStyle&7) )
       {        
        if (              
             ((ansi->TextStyle & 7) &
             ( ( SourceStyle->TextStyle & 7) ^ 7) )
            !=0)
         {
          *(DestBuffer++)='0';
          *(DestBuffer++)=';';
          ansi->TextLength+=2;
          ansi->TextStyle=0;
          ansi->ForegroundColor=1;
          ansi->BackgroundColor=0;        
         }
        if ( (SourceStyle->TextStyle & 1) != (ansi->TextStyle & 1) )
         {
          *(DestBuffer++)='4';
          *(DestBuffer++)=';';
          ansi->TextLength+=2;
          ansi->TextStyle|=1;
         }
        if ( (SourceStyle->TextStyle & 2) != (ansi->TextStyle & 2) )
         {
          *(DestBuffer++)='1';
          *(DestBuffer++)=';';
          ansi->TextLength+=2;
          ansi->TextStyle|=2;
         }
        if ( (SourceStyle->TextStyle & 4) != (ansi->TextStyle & 4) )
         {
          *(DestBuffer++)='3';
          *(DestBuffer++)=';';
          ansi->TextLength+=2;
          ansi->TextStyle|=4;
         }
       }

     if (ansi->ForegroundColor!=SourceStyle->ForegroundColor)
      {
       *(DestBuffer++)='3';
       *(DestBuffer++)='0'+SourceStyle->ForegroundColor;
       *(DestBuffer++)=';';
       ansi->TextLength+=3;
       ansi->ForegroundColor=SourceStyle->ForegroundColor;
      }

     if (ansi->BackgroundColor!=SourceStyle->BackgroundColor)
      {
       *(DestBuffer++)='4';
       *(DestBuffer++)='0'+SourceStyle->BackgroundColor;
       *(DestBuffer++)=';';
       ansi->TextLength+=3;
       ansi->BackgroundColor=SourceStyle->BackgroundColor;
      }

 
   if ( *(DestBuffer-1) == ';' )
      {
       DestBuffer--;
       ansi->TextLength--;
      }
     *(DestBuffer++)='m';
     ansi->TextLength+=3;
     ++SourceStyle; 
     --ssl;
    }
   
   if (scl!=0) 
    {
     *(DestBuffer++)=*(SourceChar++);
     scl--;
     ansi->TextLength++;
     ansi->CurrentColumn++;
    }
    else
    {
     if (ansi->StreamCR!=FALSE)
      {
       *(DestBuffer++)='\012';
       ansi->TextLength++;
      }

     return (MUIV_Editor_Return_OK);

    }
  }
 return (MUIV_Editor_Return_ANSI_NotFinished);
}

unsigned long Stream_ANSIToStream(struct ANSIStream *ansi)
{

 unsigned char *ParseString,*DestBuffer;
 unsigned long ParseLength;
 struct StyleInfo *DestStyle;

 ParseString=ansi->TextBuffer;
 ParseLength=ansi->TextLength;
 DestBuffer=ansi->CharBuffer;
 DestStyle=ansi->Styles;

 ansi->CharLength=0;
 ansi->UsedStyles=0;
 ansi->StreamCR=FALSE;

 if (ansi->CurrentColumn==0)
  {
   if (ansi->UsedStyles==ansi->StyleSize)
    {
     return (MUIV_Editor_Return_ANSI_StreamTooSmall);
    }
   ansi->UsedStyles++;
   DestStyle->ForegroundColor=ansi->ForegroundColor;
   DestStyle->BackgroundColor=ansi->BackgroundColor;
   DestStyle->TextStyle=ansi->TextStyle;
   DestStyle->Pad1=0;
   DestStyle->StartColumn=ansi->CurrentColumn;
   ++DestStyle;
  }

 while (ParseLength!=0)
  {
   switch (ansi->ANSICmdState)
    {
     case ANSI_State_No_ANSI:
      {
       if ( (*ParseString)=='\012')
        {
         ansi->StreamCR=TRUE;
         return (MUIV_Editor_Return_OK);
        }
       if (*(ParseString)!='\033')
        {
         if (ansi->CharBufferSize==ansi->CharLength)
          {
           return (MUIV_Editor_Return_ANSI_StreamTooSmall);
          }
         *(DestBuffer++)=*(ParseString++);
         ParseLength--;
         ansi->CharLength++;
         ansi->CurrentColumn++;
        }
        else
        {
         ansi->ANSICmdState=ANSI_State_Read_ESC;
         ParseLength--;
         ParseString++;
        }
       break;
      }
     case ANSI_State_Read_ESC:
      {
       if ( *(ParseString)=='[')
        {
         ansi->ANSICmdState=ANSI_State_Read_InSEQ;
         ParseLength--;
         ParseString++;
         ansi->ANSICommand[0]='\0';
        }
        else
        {
         ansi->ANSICmdState=ANSI_State_No_ANSI;
         if (ansi->CharBufferSize==ansi->CharLength)
          {
           return (MUIV_Editor_Return_ANSI_StreamTooSmall);
          }
         *(DestBuffer++)='\033';
         ansi->CharLength++;
         ansi->CurrentColumn++;
         break;
        }
      }
     case ANSI_State_Read_InSEQ:
      {
       unsigned char pchar;
       
       pchar=*(ParseString);
       if ( pchar=='m')
        {
         unsigned char *CurrentParse,*Parser;
         unsigned long ParseLen;
         unsigned long oldfore,oldback,oldstyle;

         /* close down sequence */
      
         oldfore=ansi->ForegroundColor;
         oldback=ansi->BackgroundColor;
         oldstyle=ansi->TextStyle;
         
         CurrentParse=ansi->ANSICommand;
          
         while (*(CurrentParse)!='\0')
          {
           Parser=CurrentParse;
           ParseLen=0;
           while ( (*(Parser)!=';') && (*(Parser)!='\0' ) )
            {
             ++Parser;
             ++ParseLen;
            }
           Parser=CurrentParse;
           CurrentParse+=ParseLen;
           if (*(CurrentParse)!='\0') CurrentParse++;
           if ( (ParseLen==0) || (ParseLen>2) ) continue;
           if (ParseLen==1)
            {
             switch (*(Parser))
              {
               case '0':
                {
                 ansi->ForegroundColor=1;
                 ansi->BackgroundColor=0;
                 ansi->TextStyle=0;
                 break;                 
                }
               case '1':
                {
                 ansi->TextStyle|=2;
                 break;
                }
               case '2':
                {
                 ansi->ForegroundColor=2;
                 break;
                }
               case '3':
                {
                 ansi->TextStyle|=4;
                 break;
                }
               case '4':
                {
                 ansi->TextStyle|=1;
                 break;
                }
               case '7':
                {
                 unsigned char t; 
                 t=ansi->ForegroundColor;
                 ansi->ForegroundColor=ansi->BackgroundColor;
                 ansi->BackgroundColor=t;
                 break;
                }
               case '8':
                {
                 ansi->ForegroundColor=ansi->BackgroundColor;
                }
              }
            }
            else
            {
             signed char c1,c2;
             c1=*(Parser)-'0';
             c2=*(Parser+1)-'0';
             if ( ( c2<0)  || (c2>7) ) continue;
             if (c1==3) ansi->ForegroundColor=c2;
             if (c1==4) ansi->BackgroundColor=c2;
            }
          }         

         ansi->ANSICmdState=ANSI_State_No_ANSI;
         ParseLength--;
         ParseString++;                  

         if ( (ansi->ForegroundColor==oldfore) &&
              (ansi->BackgroundColor==oldback) &&
              (ansi->TextStyle==oldstyle) ) break;

         if ( (ansi->CurrentColumn==0) ||
              ( (ansi->UsedStyles>1) &&
                ((DestStyle-1)->StartColumn==ansi->CurrentColumn)))
          {
           ansi->UsedStyles--;
           DestStyle--;
          }

         if (ansi->UsedStyles==ansi->StyleSize)
          {
           return (MUIV_Editor_Return_ANSI_StreamTooSmall);
          }
         ansi->UsedStyles++;
         DestStyle->ForegroundColor=ansi->ForegroundColor;
         DestStyle->BackgroundColor=ansi->BackgroundColor;
         DestStyle->TextStyle=ansi->TextStyle;
         DestStyle->Pad1=0;
         DestStyle->StartColumn=ansi->CurrentColumn;
         ++DestStyle;         
         break;
        }
       if ( (pchar==';') || ( (pchar>='0') && (pchar<='9')  ) )
        {
         unsigned char *ANSIAppend;
         unsigned long ANSISize;
         ANSISize=0;
         ANSIAppend=ansi->ANSICommand;
         while ( (ANSISize<32) && ( *(ANSIAppend)!='\0') )
          {
           ++ANSIAppend;
           ++ANSISize;
          }
         if (ANSISize==32)
          {
           return (MUIV_Editor_Return_ANSI_BufferTooSmall);
          }
         *(ANSIAppend++)=*(ParseString++);
         *(ANSIAppend)='\0';
         --ParseLength;         
        }
        else
        {
         ansi->ANSICmdState=ANSI_State_No_ANSI;
         ParseLength--;
         ParseString++;         
        }
       break;
      }
    }   
  } 
 return (MUIV_Editor_Return_OK);
}
