/* 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), 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)!!
/* 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)
{
  retCode := prim_trcTracingGet(TraceLibClass$Inst);
  /* if error or tracing just leave */
  if( (retCode[0] <> 0) cor (retCode[1] = 1) ) ^0; endif;
  showWaitCurs();
  /* set startFrame position in trace */
  retCode := prim_trcReadFrameSet(trace, startFrame) ;
  if (retCode <> 0)
  then 
   showOldCurs();
   ^retCode
  endif ;
  /* modified by cjchen 1996/12/23 */
  if not(startFrame=firstFrame(theTraceBrowser))
    if( numFrames < 20 )
      numFrames := 20;    /* force min. amount requested to 30 frames */
    endif;
  endif;
  /* eof cjchen 1996/12/23 */
  /* do the frame search */
  realStartRef  := new( Struct, 4 ) ;
  realEndRef    := new( Struct, 4 ) ;
  textAddrRef   := new( Struct, 4 ) ;
  textLenRef    := new( Struct, 2 ) ;
    if (nextOrPrevious = #Next)
    then
    retCode := forwardRead( trace, numFrames, realStartRef, realEndRef, 
                            textAddrRef, textLenRef ) ;
    else 
    retCode := backwardRead( trace, numFrames, realStartRef, realEndRef,
                             textAddrRef, textLenRef ) ;
    endif ;
  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) ) 
                             ) ;

  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) }
!!

Def remove(self)
{ 
 /* nothing to do for bus/clock cycles */;
}!!

/* 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 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 viewLineAddr(self, lineNum)
{ /* should never get here - but just incase linked cursor checks fail */
    ^nil
}!!

/* 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 }
!!

