/**********************************************************************

DispalyFilter1

 This is all the code specificly for translating raw text data into
  a monocolour 2d text area. 

 Dont use tab characters in this source
  Dont use tab characters in this source
   Dont use tab characters in this source
    Dont use tab characters in this source
     Dont use tab characters in this source
      Dont use tab characters in this source
       Dont use tab characters in this source
        Dont use tab characters in this source
         Dont use tab characters in this source
          Thanks.

  changelog:
    ??? created. dan.
    jul 6  2002: rewrote redraw to use a contentfilter. dan.
    jan 1  2003: finished trim, needed in new redraw. dan.
    Apr 13 2003: trying to work out colourization
    Apr 15 2003: Adding method for setting prop filter
    Nov 21 2003: Cleanup of redraw method
    Dec 13 2003: Fixed for gcc 3.3 dan 

**********************************************************************/

#include "vif.h"         // visual interface. console, Xwindow, win32win, emacs,  whatever...
#include "accumulator2.h"  // the source buffer
#include "cestypes.h"      // Point, int64_t, etc&whateva

#include "displayfilter.h" // us
#include "propfilter.h" // attributes... !!!???!!! this should just be a filter base class

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


/*****************************************************

Methods:
  
   DisplayFilter1     ( VIF * display = NULL ,  Accumulator * source = NULL, int64_t X = 0, int64_t Y = 0 );

   void    SetDisplay ( VIF * display = NULL);
   int     SetSource  ( Accumulator * source = NULL );
   void    SetScroll  ( int64_t X, int64_t Y );		
   void    ReDraw     ( void );


*****************************************************/



//DisplayFilter1::DisplayFilter1 ( VIF * display = NULL, Accumulator * source = NULL, int64_t X = 0, int64_t Y = 0 ) {
DisplayFilter1::DisplayFilter1 ( VIF * display, Accumulator * source, int64_t X, int64_t Y) {

  SetSource  ( source  );
  SetScroll  ( X, Y    );
  SetDisplay ( display );
}

//void DisplayFilter1::SetDisplay ( VIF * display = NULL) {
void DisplayFilter1::SetDisplay ( VIF * display ) {
  Display = display;
}

//int DisplayFilter1::SetSource (  Accumulator * source = NULL ) {
int DisplayFilter1::SetSource (  Accumulator * source ) {
  
  SourceData = source;     // dont ask why its here...
  Editor.SetAccumulator(source);
  Scout.SetAccumulator(source);

  return 0;
}

/**********************************
*
* This method shouldn't exist, because all the 
*  redraw filters are supposed to derive off a base
*  class that we just call on a list of.
*  but for now its here.
*
**********************************/

CESError_t DisplayFilter1::SetPropFilter ( PropFilter * Props ) {

  PropFil = Props;
  
  return NoError;

}


/*******************************
*
*  This sets the offset for the redraw
*  can anyone say inline?
*
*******************************/
ChrOffset DisplayFilter1::Scroll ( void ) {

  return DrawStart ;

}


/*******************************
*
*  This sets the offset for the redraw
*  can anyone say inline?
*
*******************************/
CESError_t DisplayFilter1::Scroll ( ChrOffset newstart ) {

  DrawStart = newstart; //!!!???!!!
  
  return NoError;

}


/*******************************
*
*  This needs to figure out the offset for the redraw
*  Its an absolute position
*
*
*******************************/
//CESError_t DisplayFilter1::SetScroll ( int64_t X = 0, int64_t Y = 0 ) {
CESError_t DisplayFilter1::SetScroll ( int64_t X , int64_t Y  ) {

  ChrOffset tpos;
  int y; // y it is an int :-)

  ScrollLoc.X = MAX ( X, 0 );
  ScrollLoc.Y = MAX ( Y, 0 );
  
  if ( SourceData == NULL ) { return NoData; } 
  
  Editor.Seek(0, SEEK_SET); // rewind the data

  // select the line
//  contentfilter->SelectStart(contentfilter->seekline( ScrollLoc.Y ));

/*
    This gets interesting...
    to find the line, we have to trudge though a bunch of Nextline methods,
    and we have to be open to the possibility that the line were looking for 
    may not exist at all...
    I expect that within the next few years this will be replaced with
    a bookmark to hold our position, by then the accumulator will likley
    be streamable too...
*/
  tpos = 0; //preset
  for (y = ScrollLoc.Y; y != 0; y--) {
     if ((tpos = Scout.NextLine(tpos)) != (-1)) {
       Editor.SelectionStart(tpos);    
     }
   }
  
   DrawStart = Editor.SelectionStart(); //!!!???!!!
   
   return NoError;
   
} 

/***************************************************
The task of this fellow is to trim a buffer containing a 
  whole line to whatever will fit on teh screen.

  The result should be atleast ChronLength long, providing BuffSize allows
  
       // VVVV                txtbuff,  txtBuffLen,    startCrop  , CropLen(minSize)   , auxbuff );
     Trim   ( LineBuff, LINEBUFF_SIZE, ScrollLoc.X, (Display->Width -1), PropBuff ); // Trim to width 

 this cheap itteration of what I need is ok if, inbuff == outbuff....

***************************************************/
int DisplayFilter1::Trim   ( char * inBuff, long inSize, char * outBuff, long outSize, long start, char pad ) {

   if (start > inSize ) {              // the output is past the end of the buffer, return spaces.
     memset(outBuff, pad, outSize);
     outBuff[outSize] = '\0'; 
   } else {                            // copy some conetent.
     memmove(outBuff, &inBuff[start], MIN((inSize-start), outSize ));  // memmove is supposed to be ok with overlaps. 
     if ((inSize-start) < outSize) {   // we have to pad the end of it.
       memset( &outBuff[(inSize-start)], pad, (outSize - (inSize-start)));
     }
     outBuff[outSize] = '\0';
   }
 return 1;

}

/***************************************************
All references to width are adjusted to width-1, this 
  is to prevent the bumping of the cursor to the next line,
  which causes ugly shifting effects. this could also be 
  done by leaving an extra row for the cursor to end up on,
  but rows are more valuble than columns.
 
***************************************************/
void DisplayFilter1::ReDraw ( void ) {

  int64_t LineCounter;
  char * LineBuff;
  char * PropBuff;
  int y, i;
  
  ChrOffset tpos;
  
  #define LINEBUFF_SIZE  512  // dynamic adjustment of this would be good....
  //Dataf is a data Filter (ContentFilter)

  if (( LineBuff = new char[LINEBUFF_SIZE] ) == NULL ) {
    printf("cannot allocate scroll buffer.\n");
    exit ( 0 ); // !!!???!!!  CHANGE THIS
  }

  if (( PropBuff = new char[LINEBUFF_SIZE] ) == NULL ) {
    delete[] LineBuff;
    printf("cannot allocate prop buffer.\n");
    exit ( 0 ); // !!!???!!!  CHANGE THIS
  }


  // Editor.Seek(0, SEEK_SET); // rewind the data

  // select the line
//  contentfilter->SelectStart(contentfilter->seekline( ScrollLoc.Y ));

/*
    This gets interesting...
    to find the line, we have to trudge though a bunch of Nextline methods,
    and we have to be open to the possibility that the line were looking for 
    may not exist at all...
    I expect that within the next few years this will be replaced with
    a bookmark to hold our position, by then the accumulator will likley
    be streamable too...
*/
/*
  tpos = 0; //preset
  for (y = ScrollLoc.Y; y != 0; y--) {
     if ((tpos = Scout.NextLine(tpos)) != (-1)) {
       Editor.SelectionStart(tpos);    
     } else {
       //printf("displayfilter:redraw  oops, sorry...\n");
     }
   }
 */  
   Editor.SelectionStart(DrawStart);  //!!!???!!!
   Editor.SelectionEnd(Scout.LineEnd(Editor.SelectionStart()));
   //tpos = Scout.LinePos(DrawStart)-1; // this shoudl reflect ScrollLoc.X
  
   for (LineCounter = 0;  LineCounter < Display->Height; LineCounter++ ) {    
     Editor.Read           ( LineBuff, LINEBUFF_SIZE );
     
     // Next we change the colours of things, er go cursors or syntax hilighting
     //  It is important to do this while the data still syncs with the primary buffer positions
     //  this is not where a hilighter should go! (it should be another process that 
     //    creates props for its colours)
     //  this needs the LineBuff because its possable for a prop to have a content override!
     
        memset( PropBuff, 7, LINEBUFF_SIZE - 1);   
        PropFil->Colourize( LineBuff, PropBuff, LINEBUFF_SIZE, Editor.SelectionStart() );      // Hilight Props      
        
     // We then process control characters, like tabs
     //   due to a lack of unification this needs to make corresponding prop buffer changes
     //   There may be problems with this approach, cursors on tabs will look long, while 
     //     cursors on hidden characters will be gone.... hmmmm....
//!     Translator.Translate ( LineBuff, LINEBUFF_SIZE, PropBuff );                      // Translate control characters
     // We then trim the data according to x scroll and display width

     // VVVV                txtbuff,  txtBuffLen,    startCrop  , CropLen(minSize)   , auxbuff );
//!     Trim   ( LineBuff, LINEBUFF_SIZE, ScrollLoc.X, (Display->Width -1), PropBuff ); // Trim to width  

     // Trim   ( char * inbuff, long inSize, char * outbuff, long outSize, long start );     
        Trim   ( LineBuff, MIN(LINEBUFF_SIZE, Editor.SelectionSize()), LineBuff, (Display->Width - 1 ), ScrollLoc.X, ' ' );
        Trim   ( PropBuff, MIN(LINEBUFF_SIZE, Editor.SelectionSize()), PropBuff, (Display->Width - 1 ), ScrollLoc.X, 7 );
     // Were done, post the result.
#define buffered

#ifdef buffered     
     Display->BufferPos   (0, LineCounter + 1);      // Write to display, direct is faster?
//     Display->BufferText  ( LineBuff, PropBuff ); 
     Display->BufferText  ( LineBuff, PropBuff ); 
  
#else

     Display->CursorPos( 0, LineCounter + 1);
     Display->WriteText( LineBuff, PropBuff);
     
#endif

      // First we get data from the buffer to be processed
            
      //   !!!???!!! THIS ASSUMES THAT THERE IS ONLY 1 LINEFEED CHARACTER !!!!!!!!!!!!!!!!!!!
     Editor.SelectionStart ( Editor.SelectionEnd() + 2 );                     // Get a line
     
     
     
     //    We want the end to be the end of the start....
     Editor.SelectionEnd   ( Scout.LineEnd(Editor.SelectionStart()) ); 
    
   } // end of for

// !!!???!!!! set the screen draw end tag
 
#ifdef buffered  
  Display->ReDraw();  
#endif
 delete[] LineBuff;
 delete[] PropBuff;

}



DisplayFilter1::~DisplayFilter1 ( void ) {
 return;
}

