/* Trace browser.  */!!

inherit(Window, #TraceBrowser, #(title   /* header title for bus and clock cycles */
titleHeight  /* # of lines in title */
viewColl /* a TRviewCollection */
infoClass  /* which class to get information from (i.e.: trace or dq) */
drawRoutine /* a 2 argument block */
hiLited?  /* middle frame is hilited? */
firstFrame
lastFrame /* frame #s 1st..last are valid */
theTrace  /* trace instance for new text */
theDq  /* dq instance for new text */
xMax        /* Maximum number chars printable in line */
linkedRC  /* error trying to do linked cursor */
trcEvent /* tracing on event desc */
lastLCAddr /* save offset to compare */), 2, nil)!!

now(class(TraceBrowser))!!

/* 1/30/1992 13:26 */
Def open(self, parent, rect, style, aTrace, aDq, class, aDrawRoutine | newInstance)
{
  newInstance := new( self:Behavior ) ;
  setPaintStruct(newInstance, new(Struct, 32));
  create(newInstance, 
         parent, 
         "", 
         rect cor sizeRect(self),
         (style bitOr WS_VSCROLL bitOr WS_CHILD)
        ) ;
  setLocRect( newInstance ) ;

  if initialize( newInstance, aTrace, aDq, class, aDrawRoutine )
  then
    show( newInstance, SW_SHOW ) ; 
    ^newInstance
  else
    ^nil /* error */
  endif ;
}
!!

now(TraceBrowser)!!

/* PRIVATE 
  Add N (> 0) lines to the bottom of the display.  
  Returns the number of lines actually obtained.
*/ 
Def addNlinesToDisplayBottom(self, linesWanted 
   | startFrameNum newView viewStartLine)
{ 
  if not(firstFrame cand lastFrame) cor (flagBufclr = 1)
  then /* nothing to get views for */
    ^0 
  endif ;

  /* get some data -- use #frames to approx #lines */
  if (size(viewColl) = 0)
  then /* no views available */
    startFrameNum := firstFrame ;
  else /* get after last view */
    startFrameNum := ( lastFrameNum(last(viewColl)) + 1 ) ;
  endif ;
 
  if( startFrameNum > lastFrame ) ^0; endif;
  
  newView := newNextFrameGroup( infoClass, 
                                theTrace,
                                theDq,
                                startFrameNum,
                                linesWanted ) ;
                         
  /* error code returned? */
  if (class(newView) <> infoClass)
  then
    if( newView = ER_IPIPE_NOT_FUNC cor newView = ER_NO_BTM_CYCLES)
      setBusCycles(parent,startFrameNum);
      ^0;
    else
      ^0
    endif;
  endif ;

  if (size(viewColl) = 0)
  then
    viewStartLine := 0 ;
  else
    viewStartLine := ( viewEndLine(last(viewColl)) + 1 ) ;
  endif ;
  setViewStartLine( newView, viewStartLine ) ;
  add( viewColl, newView ) ;

  ^size( newView ) /* # lines actually obtained */
}!!

/* PRIVATE 
  Add N (> 0) lines to the top of the display.  
  Returns the number of lines actually obtained.
*/ 
Def addNlinesToDisplayTop(self, linesWanted | startFrameNum newView 
            viewStartLine firstView lines viewMode){
  if not(firstFrame cand lastFrame) cor (flagBufclr = 1)
  then /* nothing to get views for */
    ^0 
  endif ;

  /* get some data -- use #frames to approx #lines */
  if (size(viewColl) > 0)
  then  /* get before first view */
    firstView := first( viewColl ) ; 
    /* added by cjchen 1996/12/23 */
    viewMode:=getNewViewMode(parent);
    if (viewMode=0)
      if (linesWanted>20)
        startFrameNum:=(firstFrameNum(firstView)-linesWanted);
      else
        startFrameNum:=(firstFrameNum(firstView)-20);
      endif;  
      if (startFrameNum<firstFrame)
        startFrameNum:=firstFrame;
        linesWanted:=firstFrame-firstFrameNum(firstView);
      endif;
    else
      startFrameNum:=(firstFrameNum(firstView)-1);
    endif;
    /* eof cjchen 1996/12/23 */
    /* startFrameNum := ( firstFrameNum(firstView) - 1 ) ;  */
    newView := newPrevFrameGroup( infoClass, 
                                  theTrace,
                                  theDq,
                                  startFrameNum,
                                  linesWanted ) ;
    /* error code returned? */
    if (class(newView) <> infoClass) 
      if( newView = ER_IPIPE_NOT_FUNC cor newView = ER_NO_BTM_CYCLES)
        setBusCycles(parent,startFrameNum);
        ^0;
      else
        ^0;
      endif;
    endif ;
    viewStartLine := ( viewStartLine(firstView) - size(newView) ) ;
    setViewStartLine( newView, viewStartLine ) ;
    add( viewColl, newView ) ;
    ^size( newView ) /* # lines actually obtained */  
  endif;
}!!

/* PRIVATE -- show last page
*/
Def bottomPage(self | newView)
{
  if (flagBufclr = 1)
    ^0;
  endif;  

  flushCache( self ) ; /* redo from scratch */

  if infoClass = DQviewInfo
    newView := newNextFrameGroup( infoClass, 
                                  theTrace,
                                  theDq,
                                  lastFrame-35,
                                  visLines(self) ) ;
  else
    newView := newPrevFrameGroup( infoClass, 
                                  theTrace,
                                  theDq,
                                  lastFrame,
                                  visLines(self) ) ;
  endif;
  /* error code returned? */
  if (class(newView) <> infoClass)
  then
    if( newView = ER_IPIPE_NOT_FUNC cor newView = ER_NO_BTM_CYCLES)
      ^setBusCycles(parent,lastFrame);
    else
      /*@@ do error recovery here -- may be StartOfData @@*/
      displayFormattedError(ErrorTextLibClass$Inst, 
         ER_INTERNAL, FORCE_POPUP, asciiz(asStringRadix(newView,16)), 
         "tracebrowser", nil);
                        /* newView is error return code */
    endif;
  endif ;

  invalidate( self ) ; /* causes repaint, which does setVScrollPos */
}
!!

Def clearHiLite(self | hDC oldFont txt hiLiteLine hDC view) {
  if( hiLited? = #true )
    hiLiteLine := visLines(self)/2;
    view := viewFromLine(viewColl,hiLiteLine);
    loop
    while( not(view) cand (hiLiteLine <> 0) )
    begin
      hiLiteLine := hiLiteLine - 1;
      view := viewFromLine(viewColl,hiLiteLine);
    endLoop;      
    if( view )
      hDC := getContext( self ) ;
      initTextColors( self, hDC ) ;
      oldFont := Call SelectObject(hDC,getFont(parent));
      txt := fillWith(" ", hscrollIndex(parent));
      Call TextOut(hDC, 0, hiLiteLine*tmHeight(parent), txt, size(txt));
      txt := copyFrom(view[1],0,hscrollIndex(parent)); 
      Call TextOut(hDC, 0, hiLiteLine*tmHeight(parent), txt, size(txt));
      Call SelectObject(hDC, oldFont);
      releaseContext( self, hDC ) ;
    endif;
  endif;
  hiLited? := #false;
}
!!

Def close(self){ 
  if viewColl then freeDesc(viewColl); endif;
  unRegister( EvNoteLibClass$Inst, trcEvent ) ;
}
!!

Def doHiLite(self | txt view addrRef hiLiteLine instAddr? origBkColor
                    origBkMode hDC oldFont errMsg addrDesc) { 
  if( (TheCursorIsLinked? = #true) cand viewColl )
    errMsg := getProfileEntry(TheProfileInfoObj,"TraceInfo","viewType"," ");
    if( errMsg[0] = "clock" cor errMsg[0] = "bus" ) ^self; endif;
    if not(prim_processorHalted?(HLBrkRootLibClass$Inst)) 
      errMsg := getErrorText(ErrorTextLibClass$Inst, 
                  clearError(HLBrkRootLibClass$Inst));
      displayFormattedError(ErrorTextLibClass$Inst, 
         ER_TRACE_DISABLE_CURS, FORCE_POPUP, nil, nil, nil);
      trcLinked(parent);
      ^self;
    endif;
    hiLiteLine := visLines(self)/2;
    view := viewFromLine(viewColl,hiLiteLine);
    loop
    while( not(view) cand (hiLiteLine <> 0) )
    begin
      hiLiteLine := hiLiteLine - 1;
      view := viewFromLine(viewColl,hiLiteLine);
    endLoop;
    if( view )
      showWaitCurs();
      addrDesc := viewLineAddr(view[0], hiLiteLine);
      if( linkedRC = 0 ) 
        /*if (sendAddress?(self,getOffset(AddressLibClass$Inst, addrDesc)) )*/
          lastLCAddr := getOffset(AddressLibClass$Inst,addrDesc);
          /* hi lite center line */
          propagatePC(TheCursorLinkServer, self, 
                      duplicateAddress( AddressLibClass$Inst, addrDesc));
        /*endif;*/
      endif;
      hDC := getContext( self ) ;
      initTextColors( self, hDC ) ;
      oldFont := Call SelectObject(hDC,getFont(parent));
      origBkColor   := Call GetBkColor(   hDC ) ;
      origBkMode := Call SetBkMode( hDC, OPAQUE ) ;
      txt := fillWith(" ", hscrollIndex(parent));
      Call SetBkColor(hDC, $fieldColorDict(ATParser)[AT_PC_HERE_FIELD]);
      Call TextOut(hDC, 0, hiLiteLine*tmHeight(parent), txt, size(txt));
      Call SetBkMode( hDC, TRANSPARENT ) ;
      txt := copyFrom(view[1],0,hscrollIndex(parent)); 
      Call TextOut(hDC, 0, hiLiteLine*tmHeight(parent), txt, size(txt));
      Call SetBkColor(hDC, origBkColor) ;
      Call SetBkMode(hDC, origBkMode) ;
      hiLited? := #true;
      Call SelectObject(hDC, oldFont);
      releaseContext( self, hDC ) ;
      showOldCurs();
    endif;  
  endif;
}
!!

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

/* PRIVATE 
   Flush views; Do NOT redraw
*/
Def flushCache(self)
{
  /**186** if viewColl then freeDesc(viewColl); endif; **186**/
  viewColl := new( TRviewCollection ) ;
  dadDqFlush(theDq);
  hiLited? := #false;  
}

!!

/* PRIVATE */
Def frameRange(self)
{ ^(lastFrame - firstFrame + 1) }
!!

/* PUBLIC 
   Caller notifies us that we have to update snapshot & redraw...
*/
Def getTopLineFrameNumber(self | startFrameNum curView)
{
  if( viewColl )
    curView := focusView(viewColl); 
  endif;
  if( not(curView) )
    ^trcTimestampZeroFrameGet(trace(parent));
  else
    ^viewLineFrameNumber(curView,0);
  endif;
}

!!

/* PRIVATE */
Def initialize(self, aTrace, aDq, class, aDrawRoutine ){
  linkedRC := 0;
  hiLited? := #false; /* middle frame is hilited? */
  xMax := right( clientRect(self) ) / (tmWidth(parent) - 1) ; 
  setDrawRoutine( self, aDrawRoutine ) ;
  setTraceInstance(self, aTrace);
  setDqInstance(self, aDq);
  setBrowserInfo(self,class);
  trcEvent := register(EvNoteLibClass$Inst, EVENT_TRACE_TRACING_ON, 
                       hWnd(self));
}
!!

/* PUBLIC 
   Caller notifies us that we have to update snapshot & redraw...
*/
Def invalidateCache(self, startFrameNum | aStr buf newView trigger curView bufInfo mode numFrames temp)
{ numFrames := visLines(self);
  if( not(startFrameNum) )
    if( viewColl )
      curView := focusView(viewColl); 
    endif;
    if( not(curView) )
      bufInfo := traceBufferInfo(theTrace);
      trigger := bufInfo[1];
      mode := getProfileEntry(TheProfileInfoObj,"TraceInfo","viewType"," ");
      numFrames := visLines(self);
      if( mode[0] = "bus" ) 
        numFrames := 3 * visLines(self);   /* assume 3 clocks per bus */
      endif;
      if( mode[0] = "instruction" ) 
        numFrames := 50;            
      endif;
      startFrameNum := trigger-numFrames;
      if (trigger = 0) then
         startFrameNum := (trigger-numFrames)/2;  
      endif;       
      /* if there are no frames before the trigger then default to
         start showing frames from the trigger on - this is part
         of the trigger in the first 11 frames kludge @@@
       */
      if( startFrameNum < bufInfo[0] )
        startFrameNum := bufInfo[0];
      endif;
      if( ((trigger <> 0) cand (trigger < visLines(self)))
          cor ((trigger = 0) cand (bufInfo[0]=0)) )
        startFrameNum := 0;
      endif;
    else
      startFrameNum := viewLineFrameNumber(curView,0);
    endif;
  endif;
  
 /* flush views */
  flushCache( self ) ;

  /* Update Snapshot */
  newView := newNextFrameGroup( infoClass, 
                                theTrace, 
                                theDq,
                                startFrameNum,
                                numFrames ) ;

  /* error code returned? */
  if(newView = ER_DQ_NO_FRAMES_AVAILABLE) then ^nil endif;/*Eric 2/3/98*/
  if( (class(newView) <> infoClass) cor (size(newView)=0) )
  then
    if( newView <> ER_IPIPE_NOT_FUNC cand newView <> ER_NO_BTM_CYCLES)
      newView := newPrevFrameGroup( infoClass, 
                                    theTrace,
                                    theDq,
                                    startFrameNum,
                                    numFrames ) ;
    endif;
  endif;
  if( (class(newView) <> infoClass) cor (size(newView)=0) )
    if( newView = ER_IPIPE_NOT_FUNC cor newView = ER_NO_BTM_CYCLES)
      if (getNewViewMode(parent) = CLOCK_CYCLE)
        ^setClockCycles(parent,startFrameNum);
      endif;
      if (getNewViewMode(parent) = INST_CYCLE)
        if (getPrevViewMode(parent) = CLOCK_CYCLE)
          setNewViewMode(parent,CLOCK_CYCLE);
          ^setClockCycles(parent,startFrameNum);
        endif;
        if (getPrevViewMode(parent) = BUS_CYCLE)
          setNewViewMode(parent, BUS_CYCLE);
          ^setBusCycles(parent,startFrameNum);
        endif;
      endif;
      /* this is a safeguard, it should never run */
      ^setBusCycles(parent, startFrameNum);
    endif;
  else
    if (trigger)
      temp:=scanForTrigger(newView,trigger,visLines(self));
    else
      temp:= 0;
    endif;
    if (flagBufclr = 0)
      setViewStartLine( newView, temp ) ;
      add( viewColl, newView );
    endif;  
  endif;
  setPrevViewMode(parent, getNewViewMode(parent));
  /* Redraw */
  buf := trcReadBufferGet(theTrace);
  aStr := "Trace - Buffer: " + asString(buf);
  setText(parent,aStr);
  invalidate( self ) ;
}

!!

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

/* PRIVATE - scroll up 1 line (down arrow key) */
Def lineDown(self | fixRect)
{
  if (size(viewColl) > 0)
    if( (visLines(self) < (viewEndLine(last(viewColl))))
        cor (addNlinesToDisplayBottom(self, 1) > 0) )
    then /* added a line */
      clearHiLite(self);
      adjustViewCollOffset( viewColl, -1 ) ;
      trimDisplayViews( viewColl, visLines(self) ) ;
      fixRect := clientRect( self ) ;
      setTop( fixRect, (bottom(fixRect) - (tmHeight(parent) * 3)) ) ;
      Call ScrollWindow(hWnd, 0, negate(tmHeight(parent)), 0, 0) ;
      Call InvalidateRect( hWnd, fixRect, 1 ) ;
      setVScrollPos( self ) ;
    endif ;
  else
    invalidateCache(self,nil);
  endif;
}
!!

/* PRIVATE - scroll down 1 line (up arrow key)
 *
 * Notes (Ron, 6/8/93): Changed to use InputDlgWithHelp instead of
 *                      InputDialog as part of PowerViews Improvement
 *                      Project.
 */
!!
Def lineUp(self | hWind fixRect frameInfo frameBox frame)
{
  if (size(viewColl) > 0) 
    if( (viewStartLine(first(viewColl)) < 0)
         cor (addNlinesToDisplayTop(self,1)>0) )
    then /* added a line */
      clearHiLite(self);
      adjustViewCollOffset( viewColl, 1 ) ;
      trimDisplayViews( viewColl, visLines(self) ) ;
      /* do the Windows hacks */
      hWnd := hWnd( self ) ;
      fixRect := clientRect( self ) ;
      setBottom( fixRect, tmHeight(parent) + 6 ) ;
      Call ScrollWindow( hWnd, 0, tmHeight(parent), 0, 0 ) ;
      Call InvalidateRect( hWnd, fixRect, 1 ) ;
    endif ;
  else
    invalidateCache(self,nil);
  endif;
}
!!

/* PUBLIC
   Returns the length of the longest line found in the viewColl
 */
Def maxTextWidth(self | len)
{ len := 0;
  do(viewColl,
  {using(view | textColl, bufIndex, indexLimit, displayLineNumber)
    if view cand (textColl := bufText(view))
    then
      do(textColl,
      {using(line)
         len := max(len,size(line));
      });
    endif;
   });
  ^(len + hscrollIndex(parent));
}
!!

/* PRIVATE -- scroll up ~1 screen */
Def pageDown(self | displayLines linesToAdd linesLeft)
{
  if (size(viewColl) = 0) 
    invalidateCache(self,nil);
    ^self;
  endif;
  
  displayLines := visLines( self ) ;
  if((linesLeft:=viewEndLine(last(viewColl))-displayLines) < displayLines)
    linesToAdd := displayLines - linesLeft;
  else
    linesToAdd := 0;
  endif;
  if (linesToAdd > 0)
    if( (linesLeft:=addNlinesToDisplayBottom(self, linesToAdd)) <= 0 )
      linesLeft := 0;
    endif;
  endif;
  if( linesToAdd > linesLeft ) 
    /* if not able to add as many lines as needed adjust number of lines */
    displayLines := displayLines - (linesToAdd - linesLeft);
  endif;
  if( displayLines > 0 )
    adjustViewCollOffset( viewColl, negate(displayLines) ) ;
    trimDisplayViews( viewColl, displayLines ) ;
    invalidate( self ) ; /* causes repaint, which does setVScrollPos */
  endif;
}
!!

/*
 *
 * Notes (Ron, 6/8/93): Changed to use InputDlgWithHelp instead of
 *                      InputDialog as part of PowerViews Improvement
 *                      Project.
 */
!!
Def pageUp(self | displayLines linesAdded linesToAdd linesLeft
        frameBox frame frameInfo)
{
  displayLines := visLines( self ) ;
  if (size(viewColl) > 0) 
    if( negate(viewStartLine(first(viewColl))) < displayLines )
      linesToAdd := displayLines + viewStartLine(first(viewColl));
      linesLeft := displayLines - linesToAdd;
      linesAdded := addNlinesToDisplayTop(self, linesToAdd);
    else
      linesAdded := 0;
      linesLeft := displayLines;
    endif;
    if( displayLines < (linesAdded:=linesAdded + linesLeft) )
      linesAdded := displayLines;
    endif;
    adjustViewCollOffset( viewColl, linesAdded ) ;
    trimDisplayViews( viewColl, linesAdded ) ;
    invalidate( self ) ; /* causes repaint, which does setVScrollPos */
  else
    invalidateCache(self,nil);
  endif ;
}
!!

/* WINDOWS (PUBLIC) 
  Redraw the cacheText. Call the (client supplied) drawRoutine to do this. 
  Change local coordinates to virtual coordinates, as applicable. 
*/
Def paint(self, hDC | yPos, aStr txt) {
  if not( (size(viewColl) > 0) cand drawRoutine )
  then
    setVScrollPos( self ) ;
    ^nil;
  endif;
  initTextColors( self, hDC ) ;
  foreachVisibleLine( viewColl, 
                      visLines(self), 
                      {using(str,index)
                       eval(drawRoutine, str, index, hDC)}
                    ) ;
  setVScrollPos( self ) ;
  doHiLite(self);
}!!

Def reSize(self, wP, lP | numLinesVisible)
{ 
  if not(viewColl) /* init routine hit yet? */
  then ^0 ;
  endif ;
  xMax := right(clientRect(self)) / (tmWidth(parent)-1) ; 
  if( viewColl cand (size(viewColl) <> 0))
    numLinesVisible := (size(viewColl) + viewStartLine(first(viewColl))) ;
    if (visLines(self) > numLinesVisible)
      addNlinesToDisplayBottom( self, (visLines(self) - numLinesVisible) ) ;
    endif ;
    invalidate( self ) ;
  endif;
}!!

/* 8/22/1994 12:00 
   If incoming address is in the same instruction fetch return NIL
   so linked cursor doesn't update source presenter. */
Def sendAddress?(self, offset | bound){
  if not(lastLCAddr) ^#true; endif; /* if first time - send address */
  bound := getFetchBoundary(ProcLibClass$Inst);
  if (bound = PROC_BYTE) then
    if( offset = lastLCAddr )
      ^nil;
    endif;
  else 
    if( bound = PROC_WORD) then
      if( (offset bitAnd 0xfffffffe) = (lastLCAddr bitAnd 0xfffffffe) )
        ^nil;
      endif;
    else
      if( (offset bitAnd 0xfffffffc) = (lastLCAddr bitAnd 0xfffffffc) )
        ^nil;
      endif;
    endif;     
  endif;
  ^#true;
 }
!!

/* PUBLIC */
Def setBrowserInfo(self, aInfoClass)
{ infoClass := aInfoClass;
}
!!

/* Set the sizing rectangle to the specified Rect. */
Def setCRect(self, rect | result)
{
  result := setCRect( self:ancestor, rect ) ;
  xMax   := right(clientRect(self)) / (tmWidth(parent)-1) ;
  ^result
}!!

/* PRIVATE */
Def setDqInstance(self, aDq)
{ ^(theDq := aDq)
}
!!

/* PUBLIC 
   aBlock takes 2 args: [1] testString, [2] display line # [3] hdc
*/
Def setDrawRoutine(self, aBlock)
{ ^(drawRoutine := aBlock)
}
!!

/* PUBLIC */
Def setFirstFrame(self, frameNumber){
 ^(firstFrame := frameNumber)
}
!!

/* PRIVATE */
Def setFrameLimitsFromTrace(self | firstFrameNum lastFrameNum numFrames bInfo)
{
  /* get 1st and last frame #s */
  bInfo := traceBufferInfo(theTrace);
  firstFrameNum := bInfo[0];
  lastFrameNum  := bInfo[2];
  /*@@ error check correct? @@*/
  if not(firstFrameNum cand lastFrameNum)
  then ^nil
  endif ;

  /* aok if we get here */
  setFirstFrame( self, firstFrameNum ) ;
  setLastFrame(  self, lastFrameNum ) ;
}
!!

/* PUBLIC */
Def setLastFrame(self, frameNumber)
{ ^(lastFrame := frameNumber)
}
!!

/* PRIVATE */
Def setTraceInstance(self, aTrace)
{ ^(theTrace := aTrace)
}
!!

/* PRIVATE
   Set scroll bar position, avoiding divide by 0.
 */
Def setVScrollPos(self | pos line) {
  if (size(viewColl) = 0) cor not(firstFrame and lastFrame)
    pos := 0;
  else
    if( (line:=focusView(viewColl)) )
      pos := viewLineFrameNumber(line,0) - firstFrame;
    else
      ^self;
    endif;
    pos := (100 * pos ) / max( 1, frameRange(self) );
  endif; 
  Call SetScrollPos(hWnd,    /* our cachingBrowser window */    
                    SB_VERT, /* what bar to redraw (only 1) */
                    pos,     /* where to put it */
                    1) ;    /* do the redraw (why else would we call?) */
}!!

Def show(self, val)
{ show(self:ancestor, val);
  xMax := right(clientRect(self)) / (tmWidth(parent) - 1) ;
}!!

/* PRIVATE -- scroll to proximal var */
Def thumbScroll(self, percent | approxFrame newView offset)
{ 
  if (flagBufclr = 1)
    ^0;
  endif;  

  if( percent = 0 ) 
    approxFrame := firstFrame;
  else
    if( percent = 100 )
      approxFrame := lastFrame;
    else
      approxFrame := ( (frameRange(self) * percent) / 100 ) ;
      approxFrame := ( approxFrame + firstFrame) ; /* rebase */
    endif;
  endif;
  flushCache( self ) ;
  offset := 0;
  newView := newNextFrameGroup( infoClass, 
                                theTrace,
                                theDq,
                                approxFrame,
                                visLines(self) ) ;
  /* error code returned? */
  if(newView = ER_DQ_NO_FRAMES_AVAILABLE) then ^nil endif;/*Eric 2/3/98*/
  if( (class(newView) <> infoClass)
     cor (size(newView)=0) )
  then
    if( newView = ER_IPIPE_NOT_FUNC cor newView = ER_NO_BTM_CYCLES)
      ^setBusCycles(parent,approxFrame);
    else
      newView := newPrevFrameGroup( infoClass, 
                                    theTrace,
                                    theDq,
                                    approxFrame,
                                    visLines(self) ) ;
      if( size(newView) > visLines(self) )                       
        offset := visLines(self) - size(newView);
      endif;
      if( (class(newView) <> infoClass)
         cor (size(newView)=0) )
      then /* no data available */
        if( newView = ER_IPIPE_NOT_FUNC cor newView = ER_NO_BTM_CYCLES)
          ^setBusCycles(parent,approxFrame);
        else      
          invalidate( self ) ;
          ^0 ;
        endif;
      endif;
    endif ;
  endif ;
  setViewStartLine( newView, offset ) ;
  add( viewColl, newView ) ;
  invalidate( self ) ;
}
!!

/* PRIVATE -- show last page
*/
Def topPage(self)
{
  flushCache( self ) ; /* redo from scratch */

  addNlinesToDisplayBottom( self, visLines(self) ) ;

  invalidate( self ) ; /* causes repaint, which does setVScrollPos */
}

!!

/* Return the number of visible text lines in window. */
Def visLines(self)
{ ^((height(clientRect(self)) - tmHeight(parent)) / tmHeight(parent));
}!!

/* MS-Window's message to paint self -- sends a
  paint(self) message.  This overrides Window:WM_PAINT
  so that TextWindow and its descendants use the
  System Fixed Font instead of the System Font. */
Def WM_PAINT(self, wP, lP | hdc oldFont)
{ hdc := Call BeginPaint(getHWnd(self), paintStruct);
  if oldFont := Call SelectObject(hdc,getFont(parent))
    paint(self, hdc);
    Call SelectObject(hdc, oldFont);
    Call EndPaint(getHWnd(self), paintStruct);
  endif;
  ^0;
}
!!

/* WINDOWS
  Respond to MS-Window's vertical scrolling message. wP tells what kind of
  scrolling request has been made. This code is "inlined" because it should
  typically be fast.
  NOTES: Nghia - 10/12/93
  Clear ESC key before scrolling.
*/
Def WM_VSCROLL(self, wP, lP) {
  
  /* Clear ESC key */
  if (TaskLibClass$Inst)
    checkAbort(TaskLibClass$Inst);
  endif;
 
  if( prim_trcTracingGet(TraceLibClass$Inst)[1] == 1 )
    ^self;  /* if tracing don't do anything */
  endif;
  select
    case (wP == SB_LINEDOWN) 
    is 
      lineDown(self) ;
    endCase

    case wP == SB_PAGEDOWN
    is 
      pageDown(self) ;
    endCase

    case wP == SB_BOTTOM
    is 
      bottomPage(self) ;
    endCase

    case (wP == SB_LINEUP)
    is 
      lineUp(self) ;
    endCase

    case wP == SB_PAGEUP
    is
      pageUp(self) ;
    endCase

    case wP == SB_TOP
    is 
      topPage(self) ;
    endCase

    case  (wP == SB_THUMBPOSITION) /* cor (wP == SB_THUMBTRACK) */
    is 
      thumbScroll( self, low(lP) ) ;
    endCase
    /* "ignore" is the default */
  endSelect;
  /* Note:invalidate(self) causes a repaint; setVScrollPos done in paint() */
  ^0 
}!!

/* PRIVATE
   Return the xMax instance variable (denotes view width in characters). 
*/
Def xMax(self)
{ ^xMax;
}!!

Def WM_EVENT(self, wP, event){ 
  if( asLong(event) = EVENT_TRACE_TRACING_ON )
    linkedRC := 0;
  endif;
}
!!

