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

 This is a 'navigator' its job is to provide basic content
    specific navigation, things like nextLine, prevline, 
    line begin and lineend pointers
 
 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.
 
 mothods:
  // setup classes
  int       SetAccumulator  ( Accumulator * accum = NULL );
 
  // content search
  ChrOffset LinePos         ( void ) ;
  ChrOffset LineEnd         ( ChrOffset ) ;
  ChrOffset NextLine        ( ChrOffset ) ;
  ChrOffset PrevLine        ( ChrOffset ) ;
  
 --================| change log ==============--
 
 Feb 17 2002  Dan Williams, Created. note: NOT CONCURRENT
 [bunch of stuff missing here]
 mar 10 2002  dan, Added prevline method.
 mar 10 2002  dan, Added range checking to seek.
 mar 10 2002  dan, added lineEnd
 nov 29 2002  dan, stripped down contentfilter to become navigator
 Dec 13 2003: Fixed for gcc 3.3 dan 

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

#include <stdlib.h>
#include <string.h> // strchr
#include "navigator.h"
#include "accumulator2.h"
#include "cestypes.h" // MIN


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

  Initialize the thing.

************************************/
Navigator::Navigator( void ) {

 accumulator= NULL;

}

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

  Clean up.

************************************/
Navigator::~Navigator() {

}

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

  Set the accumulator

*************************************/
//int Navigator::SetAccumulator ( Accumulator * accum = NULL ) {
int Navigator::SetAccumulator ( Accumulator * accum  ) {

    accumulator = accum;
    return 0;

}


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

Report the cursor position in a line that the cursor 
  is currently on.

  notes:
  
   - error handling would be a good thing...
   
   \nlsfjdllkfdldsflkjasfjk\n
    ^        ^          
    0        9

***********************************************/
long    Navigator::LinePos    ( ChrOffset position ) {
 
  // this is slow, but using the new-legal methods
  
  char buffer[2] = "";
  //ChrOffset position;
  ChrOffset retval = 0;
  
  //position = blockStart; // start at current position
  
  accumulator->ReadN ( position, buffer, 1 ); // read "1" character
  
  // position >= 0 causes the beggining of file to report the same as \n
  
  while (( buffer[0] != '\n' ) && ( position >= 0 )) { // count back to linefeed or BOF
    retval ++;
    position --;
    accumulator->ReadN ( position, buffer, 1 );
  } // end of while
  
 return( retval );
 
}

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

  Return the position of the last character 
    of the current line. This is measured 
    from blockstart.
    
    \nlsafdlsfjlkfhksg\nfksfiewoiutrkjnsciou\n
         ^           ^
       start      result

*******************************************/
ChrOffset Navigator::LineEnd( ChrOffset position ) {

 //ChrOffset position;
 int found = 0; 
 ChrOffset dataEnd;
 char buffer[2] = "";

 dataEnd  = accumulator->GetSize();
 //position = blockStart + 1;  // first character dosn't count
 position++;

 while (found == 0) { 
 
   if (position > dataEnd)     // return EOF
     return ( position - 1);
 
   accumulator->ReadN ( position, buffer, 1 ); // read a byte
 
   if ( buffer[0] == '\n' ) 
     found = 1;
   else 
     position++;            // next byte
 
 } // end while

 return ( position - 1) ;

}

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

  Return the position of the first character 
    of the next line.
    
    \nlsafdlsfjlkfhksg\nfksfiewoiutrkjnsciou\n
         ^              ^
       start         result

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

ChrOffset Navigator::NextLine( ChrOffset position ) {

 //ChrOffset position;
 int found = 0; 
 ChrOffset dataEnd;
 char buffer[2] = "";

 dataEnd  = accumulator->GetSize();
 //position = blockStart + 1;  // first character dosn't count
 position++;

 while (found == 0) { 
 
   if (position > dataEnd) // die if EOF
     return -1;
 
   accumulator->ReadN ( position, buffer, 1 ); // read a byte
 
   if ( buffer[0] == '\n') 
     found = 1;

     position++;            // next byte
 
 } // end while

 return position ;

}

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

  Return the position of the first character 
    of the previous line.
    
    \nlsafdlsfjlkfhksg\nfksfiewoiutrkjnsciou\n
      ^                             ^
     result                        start               

    asdaf\nlsafdlsfjlkfhksg\nfksfiewoiutrkjnsciou\n
    ^             ^
   result         start
   
    \nlsafdlsfjlkfhksg\nfksfiewoiutrkjnsciou\n
    ^             ^  
    result      start

  works by stopping on 2n'd \n or BOF
  
*******************************************/

ChrOffset Navigator::PrevLine( ChrOffset position ) {
 // this is slow, but using the new-legal methods
  
  char buffer[2] = "";
  //ChrOffset position;
  char lineCount = 0;
  
  //position = blockStart + 1; // start at current position (with compensation)
  position++;
  
  do {
 
    position --;

    accumulator->ReadN ( position, buffer, 1 );
    
    if (buffer[0] == '\n') {
      lineCount++;
    }
    
   } while (( lineCount < 2 ) && ( position != 0 ));  // count back to linefeed or BOF
  
   if (lineCount == 2) { // if we stoped because we found a normal begginig, 
      position++;        //  adjust to first character of that line.
   }
  
 return( position );

}






