/* CLASS: ChunkManager
   An ordered collection of tuples: < chunk#, vStartLine#, #lines >
   Use first, last, and size from parent, otherwise consider methods as
   private. 
   Used by the CachingBrowser.

   REQUIRE: CACHINGB.CLS and all VirtDataObjects classes.
*/!!

inherit(OrderedCollection, #ChunkManager, nil, 2, 0)!!

now(class(ChunkManager))!!

now(ChunkManager)!!

/* 06/20/92 - PUBLIC */
Def recalcChunks(self, dataObject)
{  
   do(over (0,lastElement),
     {using(element)
        /* chunkInfo->(chunk#, virtStartLineOfChunk, NumLinesInChunk) */
        self[element][1] := getChunkStartLine(dataObject, at(self, element)[0]);
        self[element][2] := getChunkSize(dataObject, at(self, element)[0]);
     });
  ^0;
}
!!

/* 06/20/92 - PUBLIC
   Add new chunk entry at end/bottom.
   ChunkInfo -> #(chunk#, VirtualStartLine of Chunk, NumLines in Chunk)
*/
Def addAtBottom(self, chunkNum, vStartLine, numLines)
{ 
  add(self, tuple(chunkNum, vStartLine, numLines))
}
!!

/* 06/20/92 - PUBLIC
   Add new chunk entry at top
*/
Def addAtTop(self, chunkNum, vStartLine, numLines)
{ 
  insert(self, tuple(chunkNum, vStartLine, numLines), 0)
}
!!

/* 06/20/92 - PRIVATE */
Def getChunkNumber(self, index)
{ 
  /* chunkInfo->(chunk#, virtStartLineOfChunk, NumLinesInChunk) */
  ^(at(self, index)[0])
}
!!

/* 06/20/92 - PRIVATE */
Def getChunkSize(self, index)
{ 
  /* chunkInfo->(chunk#, virtStartLineOfChunk, NumLinesInChunk) */
  ^(at(self, index)[2]);
}
!!

/* 06/20/92 - PRIVATE */
Def getChunkStartLine(self, index)
{  
  /* chunkInfo->(chunk#, virtStartLineOfChunk, NumLinesInChunk) */
  ^(at(self, index)[1]);
}
!!

/* 06/20/92 - PUBLIC 
   Return the number of the first chunk in self
*/
Def getFirstChunkNumber(self)
{ 
  ^getChunkNumber( self, 0 ) ;
}
!!

/* 06/20/92 - PUBLIC 
   Get 1st virtual data line number
*/
Def getFirstLineNumber(self)
{ 
  if (size(self) > 0) then 
    ^getChunkStartLine( self, firstElement );
  endif;
  ^0;
}
!!

/* 06/20/92 - PUBLIC 
   Return the number of the last chunk in self
*/
Def getLastChunkNumber(self)
{ 
  ^getChunkNumber( self, lastElement - 1 );
}
!!

/* 06/20/92 - PUBLIC 
   Get last virtual data line number
   (startLine + # lines - 1) of last chunk
*/
Def getLastLineNumber(self)
{
  if (size(self) > 0) then
    ^(getChunkStartLine( self, lastElement-1 ) + getChunkSize( self, lastElement-1 ) - 1) ;
  endif ;
  ^0;
}
!!

/* 06/20/92 - PUBLIC
   remove entry from bottom/end
*/
Def removeFromBottom(self)
{
  removeLast(self);
  ^nil
}
!!

/* 06/20/92 - PUBLIC
   remove entry from top
*/
Def removeFromTop(self)
{ 
  removeFirst(self);
  ^nil
}
!!

/* 06/20/92 - PUBLIC 
   Return a new TextCollection with any superfluous text trimmed off.
   Trimming must occur in units of Chunk.
*/
Def trimChunks(self, vStartLine, vEndLine, direction, aTextCollection
                   | lineNum, trimNeeded, origStart, origEnd)
{ 
  trimNeeded := nil ;
  origStart  := getFirstLineNumber(self);
  origEnd    := getLastLineNumber(self);

  if (direction = #up) /* toward the beginning; trim off end */
  then
    loop
    while ((lineNum := getChunkStartLine(self, lastElement-1)) > vEndLine)
    begin
      removeFromBottom(self);
      trimNeeded := #true ;
    endLoop ;

    /* trim text collection (trim lines off end) */
    if trimNeeded then
      do(over( 0, asInt(origEnd - getLastLineNumber(self)) ), 
        {using(dummy) removeLast(aTextCollection); } 
       );
/* DEBUG        
      if (size(aTextCollection) <> 
          (getLastLineNumber(self) - getFirstLineNumber(self) + 1))
      then 
        errorBox("Fatal Error", "Cached Buffer corrupted. Please close Source window."); 
      endif;
*/      
    endif ;
    
  else /* (direction = #down) => toward the end; trim off beginning */
    loop
    while ((lineNum := getFirstLineNumber(self) + getChunkSize(self,0) - 1)
          < vStartLine)
    begin
      removeFromTop( self ) ;
      trimNeeded := #true ;
    endLoop ;

    /* trim text collection (trim lines off beginning) */
    if trimNeeded
    then
      do(over( 0, asInt(getFirstLineNumber(self) - origStart) ), 
        {using(dummy) removeFirst(aTextCollection); } 
       ) ;
/* DEBUG 
      if (size(aTextCollection) <> 
        (getLastLineNumber(self) - getFirstLineNumber(self) + 1))
      then 
        errorBox("Fatal Error", "Cached Buffer corrupted. Please close Source window."); 
      endif;
*/      
    endif;
  endif ;
/* DEBUG 
  printLine("Cache: "+asString(size(aTextCollection)));
  printLine("lines: "+asString(getFirstLineNumber(self))+"-"+
      asString(getLastLineNumber(self))); 
*/  
  ^aTextCollection
}
!!
