/* CLASS: VPVIEWINFO
   Contains View Information for a viaraible in the Variable
   Browser & Presenter.

   REQUIRE: VPVARINFO.CLS
*/!!

inherit(Object, #VPviewInfo, #(var /* a VPvarInfo instance */
viewStartLine /* line # in view where this starts */
bufNum /* text buffer number */
bufText /* a TextCollection */
lastBuf? /* true if no buffer > bufNum for this var */), 2, nil)!!

now(class(VPviewInfo))!!

/* PUBLIC */
Def new(self, varInfo)
{
  ^initialize( new(self:ancestor), varInfo ) ;
}
!!

now(VPviewInfo)!!

/* PUBLIC */
Def bufNum(self)
{ ^bufNum }
!!

/* PUBLIC */
Def bufText(self)
{ ^bufText }
!!

/* PUBLIC
   Go to Variable Server for display text.
*/
Def initBufText(self, varSession, viewLine, bufNumRequested
            | bufAddr result)
{
  /* get buffer text for self from var -> bufText */
  if not(bufNumRequested) cor not(bufAddr := readVarAtNFromFrame( varSession, varID(var), bufNumRequested, frameNumber(var) )) then
   ^nil /* error! */
  endif ;

  /* set bufText, viewStartLine, bufNum, and lastBuf? */
  result := setBufTextFromAddr( self, bufAddr ) ; /* dealloc's C storage */
  setViewStartLine( self, viewLine ) ;
  /* cache line info in var */
  if not( linesVeracity(var) = #Exact ) cor lastBuf?(self)
  then
    if lastBuf?(self) 
      setLineNumInfo( var, 
                      ((bufNumRequested * 20) + size(bufText)),
                      #Exact) ;
    else
      setLineNumInfo( var, 
                      ((bufNumRequested * 20) + size(bufText)),
                      #Incomplete) ;
    endif ;
  endif ;

  ^result
}
!!

/* PRIVATE */
Def initialize(self, varInfo)
{
  var := varInfo ;
  bufNum := 0 ;
  viewStartLine := 0 ;
}!!

/* PUBLIC */
Def lastBuf?(self)
{ ^lastBuf? }
!!

/* PUBLIC
   Flush bufText & get new.
*/
Def newBufText(self, varSession, newViewStartLine)
{
  bufText := nil ;

  ^initBufText( self, varSession, newViewStartLine, bufNum(self) )
}
!!

/* PUBLIC */
Def offsetViewStartLine(self, offset)
{ ^viewStartLine := (viewStartLine + offset) }
!!

/* PRIVATE */
Def setBufNum(self, num)
{
  bufNum := num ;
}
!!

/* PRIVATE
   Take a "VS_DISPLAY_BUFFER_TYPE *" and grab its text.
   Use the low-level Struct prims for speed.
   Free C storage on completion.
   Returns nil on failure, else #ok.
*/
Def setBufTextFromAddr(self, longCAddress | aStruct, textLen, handle)
{
  if not(longCAddress) cor (longCAddress = 0L)
  then
    bufText := add( new(TextCollection, 1), "" ) ;
    ^nil
  endif ;

  /* struct less the text */
  aStruct := copyFromLong( new(Struct,12), longCAddress ) ;

  /* how much text did we get? -- # chars */
  textLen := longAt( aStruct, 8 ) ;
  bufNum  := longAt( aStruct, 4 );
   /* (continued? == 0) => (lastBuf? is true) */
  lastBuf? := (wordAt(aStruct, 2) = 0) ;

  /* make a new TextColletion and convert the string into it */
  add( (bufText := new(TextCollection, 1)), "" ) ;

  insertText( bufText, 
/*removeNulls(*/ physicalString(copyFromLong(new(Struct,textLen), 
                                                (longCAddress + 12) )),
              0, 0
            ) ;

  /* free the C storage */
  if ((handle := wordAt(aStruct, 0)) <> 0)
  then
    Call GlobalFree(handle) ;
  else
    cFree( MallocLibClass$Inst, longCAddress ) ;
  endif ;

  /* Whew! */
  ^#ok
}

!!

/* PUBLIC */
Def setViewStartLine(self, startLineNum)
{ ^viewStartLine := startLineNum }
!!

/* PUBLIC 
   The size of a VPviewInfo is the number of lines of text it contains.
*/
Def size(self)
{ 
  if bufText
  then ^size(bufText)
  else ^0
  endif ;
}
!!

/* PUBLIC - return the varInfo object */
Def var(self)
{ ^var }
!!
/* PUBLIC */
Def viewEndLine(self)
{ ^(viewStartLine + size(bufText) - 1) }
!!

/* PUBLIC -- return textStr based on view line # */
Def viewLineStr(self, lineNum)
{
  if (lineNum >= viewStartLine) cand 
     (lineNum < (viewStartLine + size(bufText)))
  then
    ^bufText[ (lineNum - viewStartLine) ]
  else
    ^nil
  endif ;
}
!!

/* PUBLIC */
Def viewStartLine(self)
{ ^viewStartLine }
!!
