/* View Information for Trace Browser */!!

inherit(Object, #TRviewInfo, #(viewStartLine /* line # in view where this starts */
firstFrameNum, lastFrameNum,
bufText /* a TextCollection */), 2, nil)!!

now(class(TRviewInfo))!!

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

/* PUBLIC */
Def newNextFrameGroup(self, trace, dq, startFrame, numFrames)
{
  ^initFrameGroup( new(self:ancestor), trace, dq, startFrame, numFrames, #Next ) ;
}
!!

/* PUBLIC */
Def newPrevFrameGroup(self, trace, dq, startFrame, numFrames)
{
  ^initFrameGroup( new(self:ancestor), 
                   trace, dq, startFrame, numFrames, #Previous ) ;
}
!!

now(TRviewInfo)!!

/* 3/17/1992 8:02 
  This routine searches through the buffer of trace frames and tries to
  center the trigger frame in the display.  It searches back from the 
  bottom of the buffer and counts out half the display size once it finds
  a frame that is numerically smaller than the trigger frame.
 */
Def scanForTrigger(self, triggerFrame visLines| members frame line loopy temp){
  loopy := size(bufText)-1;
  loop
  while loopy > 0
  begin 
    members := words(bufText[loopy]);
    if( (members[0][0] >= '0') cand (members[0][0] <= '9')
        cor (members[0][0] = '-') ) 
      frame := asLong(asInt(members[0],10));
    endif;
    
    if (frame < triggerFrame) 
      temp := loopy-(visLines/2);
      if (temp <0) ^0;
      else
        ^(0-temp);
      endif;
    endif;

    loopy := loopy - 1;
  endLoop;
  ^0;
}
!!

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

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

/* PRIVATE -- return  */
Def initFrameGroup(self, trace, dq, startFrame, numFrames, nextOrPrevious
| bufStr /*@@ deltaT @@*/
      realStartRef realEndRef textAddrRef textLenRef textColl retCode bufInfo)
{
/*@@{
  printNewLine("-----------------VVVVVVVVVVVVV-----------------");
}@@*/
  showWaitCurs();
  /* set startFrame position in trace */
  retCode := prim_trcReadFrameSet(trace, startFrame) ;
  if (retCode <> 0)
  then 
   showOldCurs();
   ^retCode
  endif ;
  if( numFrames < 20 )
    numFrames := 20;    /* force min. amount requested to 30 frames */
  endif;

  /* do the frame search */
  realStartRef  := new( Struct, 4 ) ;
  realEndRef    := new( Struct, 4 ) ;
  textAddrRef   := new( Struct, 4 ) ;
  textLenRef    := new( Struct, 2 ) ;
/*@@{
deltaT := time( 
  {
}@@*/
    if (nextOrPrevious = #Next)
    then
    retCode := forwardRead( trace, numFrames, realStartRef, realEndRef, 
                            textAddrRef, textLenRef ) ;
    else 
    retCode := backwardRead( trace, numFrames, realStartRef, realEndRef,
                             textAddrRef, textLenRef ) ;
    endif ;
/*@@{
  } ); /* end time() *|
printNewLine("(for|back)wardRead took " + asString(deltaT) + " milliSeconds") ;
}@@*/
  if( (retCode <> 0) cand (retCode <> ERR_ABORT_FROM_ESC) )
    showOldCurs();
    ^retCode 
  endif ;
/* we didn't get any frames (i.e.: no text) */
  if( wordAt(textLenRef,0) = 0 )
    cFree( MallocLibClass$Inst, longAt(textAddrRef, 0) ) ;
    showOldCurs();
    ^retCode 
  endif; 

  /* get the text into a textCollection */
  add( textColl := new( TextCollection, 1), "" ) ;
  
/*@@{
deltaT := 
  time( {
}@@*/
    bufStr := physicalString(
                  copyFromLong( new(Struct, wordAt(textLenRef,0)),
                                longAt(textAddrRef, 0) ) 
                             ) ;
/*@@{
    } ) ;
printNewLine("Text conversion took " + asString(deltaT) + " milliSeconds") ;
}@@*/

  insertText( textColl, bufStr, 0, 0 ) ; 
  cFree( MallocLibClass$Inst, longAt(textAddrRef, 0) ) ;
  removeLast( textColl ) ;
  showOldCurs();

  ^initialize( self, 
               longAt(realStartRef, 0), longAt(realEndRef, 0), textColl )
}
!!

/* PRIVATE */
Def initialize(self, startFrame, endFrame, textColl)
{
  firstFrameNum := startFrame ;
  lastFrameNum  := endFrame ;
  bufText       := textColl ;
}!!

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

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

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

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

/* PUBLIC */
Def viewEndLine(self)
{ ^(viewStartLine + size(bufText) - 1) }
!!

/* 3/17/1992 8:02 
  This routine returns the closest frame number to the indicated display
  line.  If no frame number is found then we try the next five lines.
  This routine is used to sync up the trace frame numbers when the user
  switches between viewing modes (i.e.: bus, clock and instruction).
  This could also be used by the linked cursor support to link frame
  numbers.
 */
Def viewLineFrameNumber(self, lineNum | members frame line){
  line := lineNum;
  loop
  while not(frame)
  begin 
    members := words(bufText[line-viewStartLine]);
    if( (members[0][0] >= '0') cand (members[0][0] <= '9')
        cor (members[0][0] = '-') ) 
      frame := asLong(asInt(members[0],10));
    endif;
    if( line > (lineNum+5) )
      ^nil;
    endif;
    line := line + 1;
  endLoop;
  ^frame;
}
!!

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

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