/* Trace presenter */!!

inherit(AutomaticMenu, #TracePresenter, #(trcbrowser /* a trace browser window */
horzbar /* horizontal scroll bar */
hbpos /* horizontal scroll bar position */
symbolOn /*TRUE if symbols enabled */
theTrace /*  interface to trace server */
theDq /* interface to the dq server */
hscrollIndex /* size of unscrollable region in trace browser */
leftChar /* used to handle hscrolling */
searchDlg  /* trace search dialog */
numFrames /* use as an indicator that trace has changed */
titleWindow
tmHeight
tmWidth
hFont
theTrigger
eventDescSet
saveAsDlg
bufferDlg
frameDlg
zeroTSDlg
systemCrystalDlg
newViewMode
prevViewMode), 2, nil)!!

now(class(TracePresenter))!!

/* PUBLIC */
Def open(self | newInstance)
{
  newInstance := new( TracePresenter, nil, nil, "Trace", nil ) ;
  if newInstance then show(newInstance, SW_SHOW) endif ; 
  ^newInstance ;
}
!!

/* PUBLIC */
Def openWithPosAndState(self, sizeRect showVal | newInstance )
{
  if sizeRect = nil then
    sizeRect := &(100,85,630,350);
  endif;

  newInstance := newStyle(TracePresenter, nil, nil, "Execution Trace",
                   sizeRect, nil, WS_OVERLAPPEDWINDOW);
  if newInstance then show(newInstance, showVal) endif ;
  ^newInstance ;
}!!



/* PUBLIC
   Return the default window style. 
 */
Def style(self)
{ 
  ^WS_OVERLAPPEDWINDOW;
}!!

Def wndClass(self)
{ ^"TracePresenter"
}!!

/* return name of trace icon */
Def wndIcon(self)
{ ^"trace" }!!

now(TracePresenter)!!

/* PRIVATE
 */
Def trcEvent(self)
{ showWaitCurs();
  if (exists(EventWindow) cand TheEventPresenter)
  then 
    Call BringWindowToTop(getHWnd(TheEventPresenter)); 
    show( TheEventPresenter, SW_SHOWNORMAL ) ;
  else
    TheEventPresenter := open(EventWindow);
  endif;
  showOldCurs();
}!!

/* 3/5/1997 16:00 */
 
Def setTPFg(self | flag)
{
  flag:=getOptionFlag(theTrace, 1);
   if flag == 0 then
     checkMenuItem(self,"Trace &Port");
  else 
     unCheckMenuItem(self,"Trace &Port");
  endif;   
  setOptionFlag(theTrace, 1); 
} !!

/* 2/26/1997 16:32 */
 
Def initOptionFlag(self | fval)
{
  fval := getOptionFlag(theTrace, 0);
  if( fval = 0 ) 
     unCheckMenuItem(self,"&Timestamp");
  else 
     checkMenuItem(self,"&Timestamp");
  endif;
  fval := getOptionFlag(theTrace, 1);
  if( fval = 0 ) 
     unCheckMenuItem(self,"Trace &Port");
  else 
     checkMenuItem(self,"Trace &Port");
  endif;
  fval := getOptionFlag(theTrace, 2);
  if( fval = 0 ) 
     unCheckMenuItem(self,"&Data");
  else 
     checkMenuItem(self,"&Data");
  endif;
  fval := getOptionFlag(theTrace, 3);
  if( fval = 0 ) 
     unCheckMenuItem(self,"&Status");
  else 
     checkMenuItem(self,"&Status");
  endif;
  fval := getOptionFlag(theTrace, 4);
  if( fval = 0 ) 
     unCheckMenuItem(self,"&External Trace Bit");
  else 
     checkMenuItem(self,"&External Trace Bit");
  endif;
  fval := getOptionFlag(theTrace, 5);
  if( fval = 0 ) 
     unCheckMenuItem(self,"A&ction");
  else 
     checkMenuItem(self,"A&ction");
  endif;
  fval := getOptionFlag(theTrace, 6);
  if( fval = 0 ) 
     unCheckMenuItem(self,"S&L(Sequence Level)");
  else 
     checkMenuItem(self,"S&L(Sequence Level)");
  endif;
  fval := getOptionFlag(theTrace, 7);
  if( fval = 0 ) 
     unCheckMenuItem(self,"&Bus-Event-Matched Bits");
  else 
     checkMenuItem(self,"&Bus-Event-Matched Bits");
  endif;
}!!

/* 2/26/1997 16:32 */
 
Def setBEMFg(self | flag)
{
  flag:=getOptionFlag(theTrace, 7);
   if flag == 0 then
     checkMenuItem(self,"&Bus-Event-Matched Bits");
  else 
     unCheckMenuItem(self,"&Bus-Event-Matched Bits");
  endif;   
  setOptionFlag(theTrace, 7); 
}  !!

/* 2/26/1997 16:31 */
 
Def setSLFg(self | flag)
{
  flag:=getOptionFlag(theTrace, 6);
   if flag == 0 then
     checkMenuItem(self,"S&L(Sequence Level)");
  else 
     unCheckMenuItem(self,"S&L(Sequence Level)");
  endif;   
  setOptionFlag(theTrace, 6); 
}  !!

/* 2/26/1997 16:31 */
 
Def setActionFg(self | flag)
{
  flag:=getOptionFlag(theTrace, 5);
   if flag == 0 then
     checkMenuItem(self,"A&ction");
  else 
     unCheckMenuItem(self,"A&ction");
  endif;   
  setOptionFlag(theTrace, 5); 
}  !!

/* 2/26/1997 16:31 */
 
Def setETBFg(self | flag)
{
  flag:=getOptionFlag(theTrace, 4);
   if flag == 0 then
     checkMenuItem(self,"&External Trace Bit");
  else 
     unCheckMenuItem(self,"&External Trace Bit");
  endif;   
  setOptionFlag(theTrace, 4); 
} !!

/* 2/26/1997 16:31 */
 
Def setStatusFg(self | flag)
{
  flag:=getOptionFlag(theTrace, 3);
   if flag == 0 then
     checkMenuItem(self,"&Status");
  else 
     unCheckMenuItem(self,"&Status");
  endif;   
  setOptionFlag(theTrace, 3); 
} !!

/* 2/26/1997 16:30 */
 
Def setTimestampFg(self | flag)
{
  flag:=getOptionFlag(theTrace, 0);
   if flag == 0 then
     checkMenuItem(self,"&Timestamp");
  else 
     unCheckMenuItem(self,"&Timestamp");
  endif;   
  setOptionFlag(theTrace, 0); 
} !!

/* 2/26/1997 16:26 */
 
Def profileSetup(self | aStr val timestampStr) {
  aStr := getProfileEntry(TheProfileInfoObj,"TraceInfo","linkedCursor"," ");
  if( aStr[0] = "on" )
    TheCursorIsLinked?:= #true;
    checkMenuItem(self,"&Linked Cursor");
  else
    TheCursorIsLinked?:= #false;
    unCheckMenuItem(self,"&Linked Cursor");
  endif;
  timestampStr := getProfileEntry(TheProfileInfoObj,"TraceInfo","timestamp"," ");
  aStr := getProfileEntry(TheProfileInfoObj,"TraceInfo","tsmode"," ");
  if( aStr[0] = "delta" )
    timestampDelta(self);
  else 
    if ( aStr[0] = "absoluate" ) 
       timestampAbsoluate(self);
    else
       timestampRelative(self);
    endif;   
  endif;
  aStr := getProfileEntry(TheProfileInfoObj,"TraceInfo","viewType"," ");
  if( aStr[0] = "clock" )
    newViewMode := CLOCK_CYCLE;
    prevViewMode := BUS_CYCLE;
    viewClockCycles(self);
  else 
    if( aStr[0] = "bus" )
      newViewMode := BUS_CYCLE;
      prevViewMode:= CLOCK_CYCLE;
      viewBusCycles(self);
    else
      newViewMode := INST_CYCLE;
      prevViewMode := BUS_CYCLE;
      toggleSymbolEnable(self);
    endif;
  endif;  
  initOptionFlag(self);
}!!

/* 2/26/1997 16:25 */
 
Def timestampFrame(self | frame)
{
  /* return immediately if micepack
  if micepack?(ProcLibClass$Inst)
    ^nil;
  endif; */
  showWaitCurs();
  if( runModal(zeroTSDlg, 435, ThePort) = IDOK )
    frame := asInt(getZeroFrame(zeroTSDlg),10);
    if( not(frame) )
      frame := 0;
    endif;
    trcTimestampZeroFrameSet(theTrace, frame);
    /* Nghia - 08/13/93 - Fixed PPR8829 */
    checkMenuItem(self,"&Timestamp");
  endif;
  showOldCurs();
}!!

/* 2/26/1997 16:25 */
 
Def timestampRelative(self)
{
  /* return immediately if micepack 
  if micepack?(ProcLibClass$Inst)
    ^nil;
  endif;*/
  showWaitCurs();
  clearTimestampModeSelection(self);
  checkMenuItem(self,"&Relative To Frame");
  enableMenuItem(self, "&Zero At Frame...");
  trcTimestampModeSet(theTrace,0);
  showOldCurs();
  saveProfileEntry(TheProfileInfoObj,"TraceInfo","tsmode","relative");  
  saveProfileEntry(TheProfileInfoObj,"TraceInfo","timestamp","on");  
}!!

/* 2/26/1997 16:24 */
 
Def timestampDelta(self)
{
  /* return immediately if micepack 
  if micepack?(ProcLibClass$Inst)
    ^nil;
  endif;*/
  showWaitCurs();
  clearTimestampModeSelection(self);
  checkMenuItem(self,"&Delta");
  grayMenuItem(self, "&Zero At Frame...");
  trcTimestampModeSet(theTrace,1);
  showOldCurs();
  saveProfileEntry(TheProfileInfoObj,"TraceInfo","tsmode","delta");  
  saveProfileEntry(TheProfileInfoObj,"TraceInfo","timestamp","on");  
}!!

/* 2/26/1997 16:24 */
 
Def timestampAbsoluate(self)
{
  /* return immediately if micepack 
  if micepack?(ProcLibClass$Inst)
    ^nil;
  endif;*/
  showWaitCurs();
  clearTimestampModeSelection(self);
  checkMenuItem(self,"&Absoluate");
  grayMenuItem(self, "&Zero At Frame...");
  trcTimestampModeSet(theTrace,2);
  showOldCurs();
  saveProfileEntry(TheProfileInfoObj,"TraceInfo","tsmode","absoluate");  
  saveProfileEntry(TheProfileInfoObj,"TraceInfo","timestamp","on");  
}!!

/* WINDOWS -- sent by event manager (evNoteLib) */
Def WM_EVENT(self, wP, event | linesWanted aStr buffer popupHandle startFrame)
{ 
  if (trcGetQTraceActive(theTrace) = 1)
    saveProfileEntry(TheProfileInfoObj,"TraceInfo","viewType","bus");
    clearCycleViewSelection(self);
    checkMenuItem(self, "&bus");
    grayMenuItem(self, "&Instruction");
  else
    enableMenuItem(self, "&Instruction");
  endif;
  startFrame := nil; 
  if( asLong(event) = EVENT_TRIG_TRC_BUF_NUM )
    if( trigTraceConfigureGet(theTrigger) <> 1 )
      enableMenuItem(self,"&Next Buffer");
      enableMenuItem(self,"&Previous Buffer");
      enableMenuItem(self,"&Buffer...");
    else
      grayMenuItem(self,"&Next Buffer");
      grayMenuItem(self,"&Previous Buffer");
      grayMenuItem(self,"&Buffer..."); 
    endif;
    ^self;
  endif;
  if( asLong(event) = EVENT_TRACE_CLEAR_TRACE )
    if( trcReadBufferSet(theTrace,0) = 0 )
      aStr := "Trace - Buffer: 0";
      setText(self,aStr);
    endif;
  endif;
  if( asLong(event) = EVENT_TRACE_HEADER_CHANGED )
    startFrame := getTopLineFrameNumber(browser(self));
    aStr := getProfileEntry(TheProfileInfoObj,"TraceInfo","viewType"," ");
    if( (aStr[0] = "clock") cor  (aStr[0] = "bus") )
      setTitle(titleWindow,trcGetHeader(theTrace));
    endif;
  endif; 
  if( asLong(event) = EVENT_TRACE_TRACING_OFF )      
    showWaitCurs();
    trcUpdateTrace(theTrace);
    buffer := trcReadBufferGet(theTrace);
    aStr := "Trace - Buffer: "+asString(buffer);
    setText(self,aStr);
    if( (aStr[0] = "clock") cor  (aStr[0] = "bus") )
      /* need to check address space field */
      setTitle(titleWindow,trcGetHeader(theTrace));
    endif;
  endif;
  if( (asLong(event) = EVENT_TRACE_TRACING_ON))
/*    invalidateCache(browser(self),nil); */
    flushCache(browser(self));
    invalidate(self);
    ^0;
  endif;  
  if( (asLong(event) = EVENT_DASM_SYM_CHANGED) )
    invalidateCache(browser(self), nil);
    invalidate(self);
    ^0;
  endif;
  
  flushCache(browser(self));
  setFrameLimitsFromTrace(browser(self));
  invalidateCache(browser(self), startFrame); 
  invalidate(self);
  
  ^0
} !!

/* 1/17/1996 9:46 */
Def trcDlgQualTrace(self|rc) {  
   rc := trcDlgQTrace(theTrace, handle(self));
/***
   if (rc = 1) 
      checkMenuItem(self, "Trace &Qualify...");
   else
      unCheckMenuItem(self, "Trace &Qualify...");
   endif;
***/
}
!!

/* PRIVATE
 */
Def trcSearch(self | frame buf status numBuf savBuf beginFrame endFrame){ 
  buf := trcReadBufferGet(theTrace);
  savBuf := buf;   /* if search fails want to stay in starting buffer */
  status := IDYES;
  loop
  while ( status = IDYES )
  begin 
    if( prim_trcSearchBufferSet(theTrace,buf) <> 0)
      displayFormattedError(ErrorTextLibClass$Inst, 
         ER_TRACE_DATA, FORCE_POPUP, nil, nil, nil);
      showOldCurs();
      ^self;
    endif;
    if( (status:=runModal(searchDlg, DLG_TRACESEA, ThePort)) = IDOK )
      showWaitCurs();
      beginFrame := traceBufferStart(theTrace);
      endFrame := traceBufferEnd(theTrace);
      frame := asInt(getStartFrame(searchDlg),10);
      if( not(frame) )
        frame := beginFrame;
      endif;
      if (frame < beginFrame)
        /* tried to search from before the trace buffer begins */
        frame := beginFrame;
      endif;
      if (frame > endFrame) frame := endFrame-1; endif;
      if( trcSearchFrameSet(theTrace, frame) <> 0 ) 
        prim_trcReadBufferSet(theTrace,savBuf);
        showOldCurs();
        ^self;
      endif;
      if( trcSearchEventSet(theTrace,getEvent(searchDlg)) <> 0)
       prim_trcReadBufferSet(theTrace,savBuf);
       showOldCurs();
       ^self;
      endif;
      if( trcTraceSearch(theTrace) = 1 )
        frame := trcSearchFrameGet(theTrace);
        setStartFrame(searchDlg,asString(frame+1));
        savBuf := buf;   /* go back to buffer where last match occurred */
        invalidateCache(browser(self), frame);
        status := IDNO;
      else
        if( (numBuf:=trcEndTraceBuffer(theTrace)) > 1 )
          status := errMessageBox(ErrorTextLibClass$Inst, "Frame Not Found", 
              "Do you want to search next buffer?", 
              MB_YESNO bitOr MB_ICONQUESTION, HE_DLGM_TRACEPRE_1);
          if( status = IDYES )
            if( buf < numBuf )
              buf := buf + 1;
            else   /* wrap around to buffer 0 */
              buf := 0;
            endif;
            if( prim_trcReadBufferSet(theTrace,buf) <> 0)
              prim_trcReadBufferSet(theTrace,savBuf);
              showOldCurs();
              ^self;
            endif;
            frame := traceBufferStart(theTrace);
            setStartFrame(searchDlg,asString(frame));
          endif;
        else
          status := displayFormattedError(ErrorTextLibClass$Inst, 
                       ER_NO_TRACE_FRAME, FORCE_POPUP, nil, nil, nil);
        endif;
      endif;
    else
      /* if user cancels want to restore buffer to starting or last found
         buffer.  I.e.: match buffer number currently displayed */
      prim_trcReadBufferSet(theTrace,savBuf);
    endif;
  endLoop;
  showOldCurs();
}
!!

/* PRIVATE
   Save trace data in ascii to a file. 
 */
Def traceSave(self | fileDlg numBufs saveFile doEntireBuf? tmpNum
                  curBuffer startFrame endFrame bufInfo)
{ 
  saveFile := "*.trc";
  fileDlg := new(SaveFileDialog, saveFile);
  setHelpEntry(fileDlg, HE_DLGF_SAVE_TRACE);
  if (runModal(fileDlg, FILE_BOX, self) = IDOK) 
    setFileName(saveAsDlg,loadFile(fileDlg));
    if( runModal(saveAsDlg, DLG_TRACESAV, ThePort) = IDOK ) 
      showWaitCurs();
      saveFile := new(TextFile);
      setName(saveFile, getFileName(saveAsDlg));
      create(saveFile);
      if( not(checkError(saveFile)) )
        ^self;
      endif;
      if( size(leftJustify(getStartBuffer(saveAsDlg))) = 0 )
        numBufs := trigTraceConfigureGet(theTrigger);
        curBuffer := 0;
        doEntireBuf? := #true;
      else
        curBuffer := asInt(getStartBuffer(saveAsDlg),10);
        if( not(curBuffer) )  /* if asInt errors out need default */
          curBuffer := 0;
        endif;
        numBufs := 1;
        doEntireBuf? := #false;
        if( size(leftJustify(getEndBuffer(saveAsDlg))) <> 0 )
          tmpNum := asInt(getEndBuffer(saveAsDlg),10);
          if( not(tmpNum) cor
              (tmpNum > trigTraceConfigureGet(theTrigger)) )
            numBufs := trigTraceConfigureGet(theTrigger);
          else
            numBufs := tmpNum;
          endif;
          numBufs := numBufs - curBuffer + 1;
          if( numBufs > 1 )
            doEntireBuf? := #true;
          endif;
        endif;
        if( size(leftJustify(getStartFrame(saveAsDlg))) <> 0 )
          tmpNum := asInt(getStartFrame(saveAsDlg),10);
          /* if a bad start frame is entered - default to doing entire
             buffer - @@@ this could be painful.
           */
          if( not(tmpNum) )
             doEntireBuf? := #true;  
          else
             if( size(leftJustify(getEndFrame(saveAsDlg))) = 0 )
               setEndFrame(saveAsDlg, asString(tmpNum+10));
             endif;
          endif;
        else
          doEntireBuf? := #true;
        endif;
      endif;
      handleSavingIt(self,doEntireBuf?,numBufs,curBuffer,saveAsDlg,saveFile);
      close(saveFile);
    endif;
    showOldCurs();
  endif;
}
!!

/* PRIVATE
   View trace data as clock cycles 
 */
Def setClockCycles(self, frame) {
  /* if micepack, map to bus */
  if micepack?(ProcLibClass$Inst)
    ^viewBusCycles(self);
  endif;
  showWaitCurs();
  clearCycleViewSelection(self);
  checkMenuItem(self,"&Clock");
  /* Nghia 08/13/93 - CLOCK mode does not support LinkedCursor - disable */
  grayMenuItem(self,"&Linked Cursor");
  /* Nghia - Clear all client's LC */ 
  propagatePC(TheCursorLinkServer, self, nil);          
  setBrowserInfo(browser(self),TRviewInfo);
  trcTraceCycleSet(theTrace,CLOCK_CYCLE);
  setTitle(titleWindow,trcGetHeader(theTrace));
  invalidateCache(browser(self), frame);
  sizeKids(self);  /* want to have title area if in bus mode */
  invalidate(self);
  showOldCurs();
  saveProfileEntry(TheProfileInfoObj,"TraceInfo","viewType","clock");  
}
!!

/* PUBLIC */
Def setPrevViewMode(self mode) {
  prevViewMode := mode;
}
!!

/* PUBLIC */
Def setNewViewMode(self mode) {
  newViewMode := mode;
}
!!

/* PUBLIC */
Def getNewViewMode(self) {
  ^newViewMode;
}
!!

/* PUBLIC */
Def getPrevViewMode(self) {
  ^prevViewMode;
}
!!

/* PRIVATE
 */
Def trcTraceStop(self){ 

  ^actionTraceStop(TheToolBarPresenter);

}!!

/* PRIVATE
 */
Def trcTraceStart(self){ 

  ^actionTraceStart(TheToolBarPresenter);

}!!

Def browser(self)
{ ^trcbrowser;
}
!!

/* Used only by event definition window */
Def childIsClosing(self, handle)
{
}
!!

/* PRIVATE
   Turn off all checks for view - cycle selection options 
 */
Def clearTimestampModeSelection(self) {  
  unCheckMenuItem(self,"&Absoluate");            
  unCheckMenuItem(self,"&Relative To Frame");
  unCheckMenuItem(self,"&Delta");
  /* Nghia - 08/13/93 - Only enable if "Relative to frame" enabled */
  grayMenuItem(self, "&Zero At Frame...");
}
!!

/* PRIVATE
   Turn off all checks for view - cycle selection options 
 */
Def clearCycleViewSelection(self) {            
  unCheckMenuItem(self,"&Clock");
  unCheckMenuItem(self,"&Bus");
  unCheckMenuItem(self,"&Instruction");
}
!!

/* PRIAVTE
   Clear all trace buffers.  This operation can only be done on the
   trace hardware.
 */
Def clearTrace(self){ 
  trcTraceBufferClear(theTrace);
}
!!

/* termination processing */
Def close(self | temp)
{ 
  /* Notify parent of close -- pdr2 */
  if parent then
    childIsClosing( parent, self ) ;
  endif;

  /* Nghia - Clear all client's LC */ 
  /* 10/04/93 - For some reasons, TheCursorLinkServer is nil sometimes */
  if TheCursorLinkServer then
    propagatePC(TheCursorLinkServer, self, nil);         
  endif; 
  if TheTracePresenter then TheTracePresenter := nil endif ;
  closeEvents(self);
  if (theTrace)
     trcTraceClose(theTrace);
  endif;
  close(trcbrowser);
  close(self:ancestor);
}!!

/* PRIVATE 
   UNREGISTER with Event Notification for opened events
*/
Def closeEvents(self) {
  if eventDescSet
    do(eventDescSet,
    {using(eventDescriptor)
      unRegister( EvNoteLibClass$Inst, eventDescriptor ) ;
    });
    eventDescSet := nil;
  endif ;
}
!!

/* PUBLIC
   Routine that responds to the menu events. The wp argument gives the 
   selected menu id. Given the menu id we get the action routine from the
   menu object. 
   NOTES: Nghia - 12/10/93
   Clear ESC key before processing command. 
 */
Def command(self, wP, lp | actionmsg) {
  
  if actionmsg := action(menu, wP) then    
    /* Clear ESC key */
    if (TaskLibClass$Inst)
      checkAbort(TaskLibClass$Inst);
    endif;
    ^perform(self, actionmsg);
  else
    select
      case wP == EDIT_PRIOR
      is ^WM_VSCROLL(browser(self), SB_PAGEUP, 0);
      endCase
      case wP == EDIT_NEXT
      is ^WM_VSCROLL(browser(self), SB_PAGEDOWN, 0);
      endCase;
      case wP == 40   /* down arrow */
      is ^WM_VSCROLL(browser(self), SB_LINEDOWN, 0);
      endCase;
      case wP == 38   /* up arrow */
      is ^WM_VSCROLL(browser(self), SB_LINEUP, 0);
      endCase;
      case wP == 39   /* right arrow */
      is ^WM_HSCROLL(self, SB_LINEDOWN, 0);
      endCase;
      case wP == 37   /* left arrow */
      is ^WM_HSCROLL(self, SB_LINEUP, 0);
      endCase;
      default  
        ^command(self:ancestor, wP, lp);
    endSelect;
  endif;
}
!!

/* 2/11/1992 9:24 */
Def getFont(self)
{ ^hFont;
}
!!

/* PRIVATE
   Goto to end frame
 */
Def gotoBuffer(self | buf aStr) {
  if( trigTraceConfigureGet(theTrigger) <> 1 )
    if( runModal(bufferDlg, DLG_TRACENUM, ThePort) = IDOK ) 
      buf := asInt((aStr:=getSelected(bufferDlg)),10);
      if( not(buf) )
        buf:=0;
      endif;
      if( trcReadBufferSet(theTrace,buf) = 0 )
        aStr := "Trace - Buffer: " + asString(buf);
        setText(self,aStr);
        flushCache(browser(self));
        setFrameLimitsFromTrace(browser(self));
        invalidateCache(browser(self), nil);
      endif;
    endif;
  else
    displayFormattedError(ErrorTextLibClass$Inst, 
       ER_SINGLE_TRACE_BUFFER, FORCE_POPUP, nil, nil, nil);
  endif;
}
!!

/* PRIVATE
   Goto to end frame
 */
Def gotoEndFrame(self){ 
  thumbScroll(browser(self), 100);
}
!!

/* PRIVATE
   Goto to a user given frame number
 */
Def gotoFrame(self | frame)
{ 
  if( runModal(frameDlg, DLG_TRACENUM, ThePort) = IDOK ) 
    setPreFrameTS(theTrace);
    frame := asInt(getSelected(frameDlg),10);
    invalidateCache(browser(self), frame);
  endif;
}
!!

/* PRIVATE
   Goto to end frame
 */
Def gotoNextBuffer(self | buf numBuf aStr)
{ 
  if( (numBuf := trcEndTraceBuffer(theTrace)) <> 0 )
    buf := trcReadBufferGet(theTrace);
    if( buf+1 <= numBuf )
      buf := buf + 1;
      if( trcReadBufferSet(theTrace,buf) = 0 )
        aStr := "Trace - Buffer: " + asString(buf);
        setText(self,aStr);
        flushCache(browser(self));
        setFrameLimitsFromTrace(browser(self));
        invalidateCache(browser(self), nil);
      endif;
    endif;
  endif;
}
!!

/* PRIVATE
   Goto to end frame
 */
Def gotoPrevBuffer(self | buf numBuf aStr)
{ 
  if( (numBuf := trcEndTraceBuffer(theTrace)) <> 0 )
    buf := trcReadBufferGet(theTrace);
    if( buf <> 0 )
      buf := buf - 1;
      if( trcReadBufferSet(theTrace,buf) = 0 )
        aStr := "Trace - Buffer: " + asString(buf);
        setText(self,aStr);
        flushCache(browser(self));
        setFrameLimitsFromTrace(browser(self));
        invalidateCache(browser(self), nil);
      endif;
    endif;
  endif;
}
!!

/* PRIVATE
   Goto to start frame.
 */
Def gotoStartFrame(self | frame)
{  
  setPreFrameTS(theTrace);
  invalidateCache(browser(self), traceBufferStart(theTrace));
}
!!

/* PRIVATE
   Goto to trigger frame
 */
Def gotoTriggerFrame(self)
{  
  setPreFrameTS(theTrace);
  flushCache(browser(self));
  invalidateCache(browser(self), nil);
}
!!

/* private - broke trace save up since it was getting too long */
Def handleSavingIt(self,doEntireBuf?,numBufs,curBuffer,saveAsDlg,saveFile |
                  startFrame endFrame frameAlign cycleMode trace dq ) {
  frameAlign := TRIGGER_ALIGN;  /* @@ only support TRIGGER alignment */
  cycleMode := getSaveFormat(saveAsDlg);
  trace:=traceOpen(require(TraceLib),"hwtrc",cycleMode,frameAlign);
  if( cycleMode = INST_CYCLE )
    dq := dqOpen( require( DqLib ), descriptor(trace));
    dadSetDqSymbol(dq,1);
  else
    dq := nil;
  endif;
  loop
  while numBufs <> 0
  begin 
    if( trcReadBufferSet(trace, curBuffer) = 0 )
      if( doEntireBuf? = #true )
        startFrame := traceBufferInfo(trace);
        endFrame := startFrame[2];
        startFrame := startFrame[0];
      else
        /* at this point I know startFrame is valid numeric
           but I still need to test end Frame asInt conversion.
         */
        startFrame := asInt(getStartFrame(saveAsDlg),10);
        endFrame := asInt(getEndFrame(saveAsDlg),10);
        if( not(endFrame) )
          endFrame := traceBufferInfo(trace);
          endFrame := endFrame[2];
        endif;
      endif;
      if( printTraceBuffer(self,trace,curBuffer,startFrame,
             endFrame,saveFile,dq) = 0 )
        curBuffer := curBuffer + 1;
        numBufs := numBufs - 1;        
      else /* want to get out of loop if any error from printTraceBuffer */
        numBufs := 0;
      endif;
    else
      numBufs := 0; /* get out if invalid buffer */
    endif;
  endLoop;
  if( trace )
    trcTraceClose(trace);
  endif;
}

/* PUBLIC */
Def hscrollIndex(self)
{ ^hscrollIndex;
}
!!

/* PUBLIC
   Initialize a new TracePresenter by initializing the menus and the 
   child windows.  The constants used as child window IDs are defined 
   in TRCPRSNT.H.
 */
Def init(self | aStr buffer) { 
  showWaitCurs();
  initTextMetrics(self);
  if not($commonEventLib)
    $commonEventLib := eventOpen(require(EventLib),"default" ) ; 
  endif;

  theTrace := traceOpen(require(TraceLib),"hwtrc",CLOCK_CYCLE,TRIGGER_ALIGN);
  if not(theTrace) then
    ^nil;
  endif;
  theDq := dqOpen( require( DqLib ), descriptor(theTrace)) ; 
  if not(theDq) then
    trcTraceClose(theTrace); /* added by Eric 2/3/98 */
    ^nil;
  endif;
  theTrigger := triggerOpen(require(TriggerLib),"", "default" ) ; 
  
  setBrowser(self,open(TraceBrowser,self,nil,0,theTrace,theDq,TRviewInfo,
              {using(textStr, lineNum, hDC | txt index)
                txt := copyFrom(textStr, 0, hscrollIndex);
                index := size(txt);
                Call TextOut( hDC, 0, (lineNum * tmHeight), txt, index ) ;
                txt := copyFrom(textStr, leftChar+hscrollIndex,size(textStr));
                index := index * tmWidth;
                Call TextOut(hDC, index, (lineNum * tmHeight), txt, size(txt));
              }));

  horzbar := newHorz(ScrollBar, HSCROLL, self);
  hscrollIndex := trcFrameNumberAreaSizeGet(theTrace); 
  leftChar := 0; 

  titleWindow    := new(TraceTitleWindow, self, nil, 0);

  searchDlg := new(TraceSearchDlg);
  saveAsDlg := new(TraceSaveDialog);
  bufferDlg := new(TraceNumberDialog, "Buffer", "&Trace Buffer",
    #trcStartTraceBuffer, #trcEndTraceBuffer);
  setHelpEntry(bufferDlg, HE_DLGD_TRACENUM_BUFFER);
  frameDlg := new(TraceNumberDialog, "Frame", "&Frame Number",
    #traceBufferStart, #traceBufferEnd);
  zeroTSDlg := new(TimestampZeroDlg);
  systemCrystalDlg := new(SystemCrystalDlg);
                   
  setHelpEntry(frameDlg, HE_DLGD_TRACENUM_FRAME);
  initMenus(self);
  initScroll(self);
  sizeKids(self);
  symbolOn := 1;
  profileSetup(self);
  initEventNotifier(self);
  /* generate an initial false event to setup menu selection - do it
     this way rather than duplicate the code. */
  notify(EvNoteLibClass$Inst,EVENT_TRIG_TRC_BUF_NUM);

  buffer := trcReadBufferGet(theTrace);
  aStr := "Trace - Buffer: "+asString(buffer);
  setText(self,aStr);
  setFrameLimitsFromTrace(browser(self));
  showOldCurs();
}!!

/* PRIVATE -- register for event notification */
Def initEventNotifier(self | eventDesc, events){
  eventDescSet := new( Set, 1 ) ;
  /* dynamic to pick up current values */
  events := tuple( EVENT_TRACE_CLEAR_TRACE,
                   EVENT_TRACE_HEADER_CHANGED,
                   EVENT_TRACE_TRACING_OFF,
                   EVENT_TRACE_TRACING_ON,
                   EVENT_MEM_EDIT,
                   EVENT_DASM_SYM_CHANGED,
                   EVENT_TRIG_TRC_BUF_NUM) ;
  eventDescSet := registerEvents(EvNoteLibClass$Inst, hWnd(self), events);
}
!!

/* PRIVATE Initialize the menus. */
Def initMenus(self | aMenu proc)
{
  aMenu := new(OrderedCollection, 8);
  proc  := getSpecificProcessor(ProcLibClass$Inst);
  initMenu(self);
  
  /* menu item 0 */
  add(aMenu, tuple("&File",
      tuple(tuple("&Save As...", #traceSave),
      tuple("E&xit", #trcExit))));
                      
  /* menu item 1 */
      add(aMenu, tuple("&Edit",
          tuple(tuple("E&vents...",#trcEvent),
          tuple("S&earch...", #trcSearch))));
                                                                                                                                   
  /* menu item 2 */
      add(aMenu, tuple("&View",tuple(
          /*306* tuple("&Clock", #viewClockCycles), *306*/
          tuple("&Bus", #viewBusCycles),
          tuple("&Instruction",#toggleSymbolEnable),
          tuple(nil, nil),
          tuple("&Linked Cursor", #trcLinked))));

  /* menu item 3 */
     add(aMenu, tuple("&Display",tuple(
                      tuple("&Timestamp", #setTimestampFg),  
                      tuple("&Status",#setStatusFg),
                      tuple("&External Trace Bit",#setETBFg),
                      tuple("Trace &Port",#setTPFg),
                      tuple("A&ction",#setActionFg),
                      tuple("S&L(Sequence Level)",#setSLFg),
                      tuple("&Bus-Event-Matched Bits",#setBEMFg))));
   

  /* menu item 4: change grayMenuItemByPosition call if order changes */
  add(aMenu, tuple("T&imestamp",tuple(
      tuple("&Absoluate", #timestampAbsoluate),
      tuple("&Relative To Frame", #timestampRelative),
      tuple("&Delta",#timestampDelta),
      tuple(nil,    nil),
      tuple("&Zero At Frame...", #timestampFrame))));
/*      tuple(nil,    nil),
      tuple("&Setup...",    #timestampSetup)))); */

  /* menu item 5 */
  add(aMenu, tuple("&Goto",tuple(
      tuple("&Start Frame", #gotoStartFrame),
      tuple("&Trigger Frame", #gotoTriggerFrame),
      tuple("&End Frame", #gotoEndFrame),
      tuple("&Frame...", #gotoFrame))));
/*      tuple("&Next Buffer", #gotoNextBuffer),
      tuple("&Previous Buffer", #gotoPrevBuffer),
      tuple("&Buffer...", #gotoBuffer)))); */
  attachMenuChoices(self,aMenu);
  addWindowAndHelp(self, "Tr&ace", HELP_ENTRY_TRACE);
  registerF1Help(CLIULibraryClass$Inst, HI_ENTRY_TRACE,
     getHWnd(self), HELP_ENTRY_TRACE);
  /* disable Clock & Timestamp menu if micepack */
  if micepack?(ProcLibClass$Inst)
 /*    grayMenuItem(self, "&Clock");   */
 /*    grayMenuItemByPosition(self, 4);*/ /* match menu item for T&imestamp */
  endif;
  
  drawMenu(self);
}!!!!
