/* 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
addrUse /* auto, 16, or 32 */), 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 )
{
  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)!!

/* 10/22/1996 13:33 */

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

/* 10/8/1996 16:07 */

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

/* 10/8/1996 16:10 */

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,"&Address");
  else 
     checkMenuItem(self,"&Address");
  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;
}!!

/* 10/8/1996 16:07 */

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

/* 10/8/1996 16:07 */

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

/* 10/8/1996 16:07 */

Def setTPFg(self | flag)
{
  flag:=getOptionFlag(theTrace, 5);
   if flag == 0 then
     checkMenuItem(self,"T&P(Trace Port)");
  else 
     unCheckMenuItem(self,"T&P(Trace Port)");
  endif;   
  setOptionFlag(theTrace, 5); 
}  !!

/* 10/8/1996 16:06 */

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

/* 10/8/1996 16:06 */

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

/* 10/8/1996 16:06 */

Def setDataFg(self | flag)
{
  flag:=getOptionFlag(theTrace, 2);
   if flag == 0 then
     checkMenuItem(self,"&Data");
  else 
     unCheckMenuItem(self,"&Data");
  endif;   
  setOptionFlag(theTrace, 2); 
}!!

/* 10/8/1996 16:05 */

Def setAddressFg(self | flag)
{
  flag:=getOptionFlag(theTrace, 1);
   if flag == 0 then
     checkMenuItem(self,"&Address");
  else 
     unCheckMenuItem(self,"&Address");
  endif;   
  setOptionFlag(theTrace, 1); 
}  
!!

/* 10/8/1996 16:05 */

Def setTimestampFg(self | flag)
{
  flag:=getOptionFlag(theTrace, 0);
   if flag == 0 then
     checkMenuItem(self,"&Timestamp");
  else 
     unCheckMenuItem(self,"&Timestamp");
  endif;   
  setOptionFlag(theTrace, 0); 
}  !!

/* PRIVATE
   View trace data as bus cycles.
 */
Def trcBtm(self | curVal text aStr)
{
  curVal := trcBtmGet(theTrace);
  if( curVal[1] = 0 ) 
    trcBtmSet(theTrace,1);
    checkMenuItem(self,"BT&M Cycles");
    text := "enabled";
  else
    unCheckMenuItem(self,"BT&M Cycles");
    trcBtmSet(theTrace,0);
    text := "disabled";
  endif;
  saveProfileEntry(TheProfileInfoObj,"TraceInfo","btmCycles",text);  
}
!!

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){
  if (flagBufclr = 1) 
    new(ErrorBox, ThePort, "The trace buffer is empty !", "Message", 0);
  else  
    flagBufclr := 1;
    invalidateCache(browser(self), nil);
    invalidate(self);
  endif;  
/*  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);
  trcTraceClose(theTrace);
/**186**  close(trcbrowser);  **186**/
  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;
}
!!

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

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

/* 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 ) 
    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)
{ 
  invalidateCache(browser(self), traceBufferStart(theTrace));
}
!!

/* PRIVATE
   Goto to trigger frame
 */
Def gotoTriggerFrame(self)
{ 
  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 err) {
  frameAlign := TRIGGER_ALIGN;  /* @@ only support TRIGGER alignment */
  cycleMode := getSaveFormat(saveAsDlg);
  trace := traceOpen(requireWithPath(TraceLib, "trace.dll"),
    "hwtrc", cycleMode, frameAlign);
  if (cycleMode = INST_CYCLE)
    dq := dqOpen(requireWithPath(DqLib, getDasmDLLName(PreLauncher)),
      descriptor(trace));
    dadSetDqSymbol(dq,1);
  else
    dq := nil;
  endif; 
  frameAlign := traceBufferInfo(trace);  /* reuse frameAlign variable */
  
  loop
  while numBufs <> 0
  begin 
    if( trcReadBufferSet(trace, curBuffer) = 0 )
      if( doEntireBuf? = #true )
        endFrame := frameAlign[2];
        startFrame := frameAlign[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(startFrame) cor (frameAlign[0] > startFrame) )
          startFrame := frameAlign[0];
        endif;
        if( not(endFrame) cor (frameAlign[2] < endFrame) )
          endFrame := frameAlign[2];
        endif;
      endif;
      if( cycleMode = INST_CYCLE )    
        err := printInstBuffer(self,trace,curBuffer,tuple(startFrame,
             endFrame),saveFile,dq);
      else
        err := printTraceBuffer(self,trace,curBuffer,tuple(startFrame,
             endFrame),saveFile);
      endif;
      if( err = 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(requireWithPath(EventLib, "event.dll"), "default");
  endif;

  theTrace := traceOpen(requireWithPath(TraceLib, "trace.dll"),
    "hwtrc",CLOCK_CYCLE,TRIGGER_ALIGN);
  if not(theTrace) then
    ^nil;
  endif;
  theDq := dqOpen(requireWithPath(DqLib, getDasmDLLName(PreLauncher)),
    descriptor(theTrace));
  if not(theDq) then
    trcTraceClose(theTrace); /* added by Eric 2/3/98 */
    ^nil;
  endif;
  theTrigger :=
    triggerOpen(requireWithPath(TriggerLib, "trig.dll"), "", "default");
  /* added by cjchen 1996/12/23 */  
  theTraceBrowser:=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));
              });
  setBrowser(self,theTraceBrowser);
  /* eof by cjchen 1996/12/23 */
  /* removed by cjchen 1996/12/23     
  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));
  def(UserType, #AddrDescArray, #(
      long descs 150));
  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_DASM_SYM_CHANGED,
                   EVENT_TRIG_TRC_BUF_NUM) ;
  eventDescSet := registerEvents(EvNoteLibClass$Inst, hWnd(self), events);
}
!!

/* PRIVATE
   Initialize the menus.
 */
Def initMenus(self | aMenu)
{ 
/*  flagBufclr := 0;  */
  aMenu := new(OrderedCollection, 8);
  initMenu(self);
  
  /* menu item 0 */
  add(aMenu, tuple("&File",tuple(
                      tuple("&Save As...", #traceSave),
                      tuple("E&xit", #trcExit))));
                      
/*  add(aMenu, tuple("&Search",#trcSearch));                     */
  /* menu item 1 */
  add(aMenu, tuple("&Edit",tuple(
                      tuple("E&vents...",#trcEvent),
                      tuple("S&earch...", #trcSearch),
                      tuple(nil,    nil),
                      tuple("&Clear Trace", #clearTrace) 
                      ))); 
                      
                                                                                                                                   
  /* menu item 2 */
  initViewMenu(self, aMenu);
  
  /* menu item 3 */
/*186*  add(aMenu, tuple("&Trace",tuple(
     tuple(
              "&Start" + asString(Tab) + "F3", #trcTraceStart),
                      tuple("Sto&p" + asString(Tab) + "F4", #trcTraceStop),
                      tuple(nil,nil), 

     tuple("&Trace Control...",    #trcTraceConfig))));
*186*/
/* 186-MTAT2 */
     add(aMenu, tuple("&Display",tuple(
                      tuple("&Timestamp", #setTimestampFg),  
/*                    tuple("&Address",#setAddressFg),
                      tuple("&Data",#setDataFg), */
                      tuple("&Status",#setStatusFg),
                      tuple("&External Trace Bit",#setETBFg),
                      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)
/*186* grayMenuItem(self, "&Clock"); *186*/
/*186* grayMenuItemByPosition(self, 4); *186*/ /* match menu item for T&imestamp */
  endif;
  
  if (TheProcFamily = PROC_FAMILY_X86)
    menuViewAuto(self);
  endif;

  drawMenu(self);
}!!

/* PRIVATE
   Initialize the scrollbar range and position.
 */
Def initScroll(self)
{ setRange(horzbar, 0, 100);  /* default is 0, 100 */
  hbpos := 0;
  setPos(horzbar, hbpos);    /* default is 0 */
}!!

Def initTextMetrics(self | hdc, tm,  oldFont)
{
  hFont := Call GetStockObject(SYSTEM_FIXED_FONT) ;
  tm := new(Struct, 32);
  hdc := getContext(self);
  oldFont := Call SelectObject(hdc,hFont);
  Call GetTextMetrics(hdc, tm);
  tmWidth := asInt(wordAt(tm, 10));
  tmHeight := asInt(wordAt(tm, 8)) + asInt(wordAt(tm, 0));
  if oldFont
    Call SelectObject(hdc,oldFont);
  endif;
  releaseContext(self, hdc);
}
!!

/* PRIVATE
   Initialize the menus.
 */
Def initViewMenu(self, aMenu | cpuType)
{ 
  /* menu item 2 */
   cpuType := getCpuType(ProcLibClass$Inst);
   if (cpuType = PROC_CPU_80386) then
      add(aMenu, tuple("&View",tuple(
                      tuple("&Clock", #viewClockCycles),
                      tuple("&Bus", #viewBusCycles),
                      tuple("&Instruction",#toggleSymbolEnable),
                      tuple(nil,    nil),
                      tuple("&Linked Cursor", #trcLinked),
                      tuple(nil,    nil),
                      tuple("BT&M Cycles", #trcBtm),                      
                      tuple(nil,    nil),
                      tuple("&Timestamp", #timestamp),
                      tuple(nil, nil),
                      tuple("&Auto", #menuViewAuto),
                      tuple("Use&16", #menuViewUse16),
                      tuple("Use&32", #menuViewUse32))));
   else   
     add(aMenu, tuple("&View",tuple(
               /*186* tuple("&Clock", #viewClockCycles), *186*/
                      tuple("&Bus", #viewBusCycles),
                      tuple("&Instruction",#toggleSymbolEnable),
                      tuple(nil,    nil),
                      tuple("&Linked Cursor", #trcLinked)))); 
   endif;                                             
}!!

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

Def menuViewUse32(self)
{
  if (addrUse <> ADDR_USE_32)
    uncheckViewSizeMenuItems(self);
    checkMenuItem(self, "Use&32");
    addrUse := ADDR_USE_32;
    updateDasmAddressSize(self);
  endif;
}!!

Def menuViewUse16(self)
{
  if (addrUse <> ADDR_USE_16)
    uncheckViewSizeMenuItems(self);
    checkMenuItem(self, "Use&16");
    addrUse := ADDR_USE_16;
    updateDasmAddressSize(self);
  endif;
}!!

Def menuViewAuto(self)
{
  if (addrUse <> ADDR_USE_AUTO)
    uncheckViewSizeMenuItems(self);
    checkMenuItem(self, "&Auto");
    addrUse := ADDR_USE_AUTO;
    updateDasmAddressSize(self);
  endif;
}!!

/* title window wasn't being painted after trace presenter minimumized
   then brought it up again.
 */
Def paint(self, hdc){
  paint(titleWindow,hdc);
  ^paint(self:ancestor,hdc);
}   
!!

/*  @@ After trace forwardRead() interface update.
       Before corresponding DQ dadForwardDqInst() update.
  Notes: 
    [1] There appears to be no CheckAbort here.
    [2] as 15 locals are allocated, 2 variables are aliased
    in the non-dq case: handle=textLenRef and retHandleRef=textAddrRef.
*/
Def printTraceBuffer(self,trace,buffer,frames,file
               | textLenRef retHandleRef curFrame title startRef endRef
                 retCode numFrames)
{ 
  if( (retCode:=prim_trcReadFrameSet(trace, frames[0])) <> 0 )
    ^retCode;
  endif;
  write(file,"Trace Buffer:  "+asString(buffer)+CR_LF);
  write(file,"Frames: "+asString(frames[0])+" to "+asString(frames[1])+CR_LF);
  write(file,CR_LF);
  add(title := new(TextCollection, 3), "");
  insertText(title,removeNulls(physicalString(trcGetHeader(trace))),0,0);
  do(size(title),
  {using(line) 
    write(file, fill(new(String, hscrollIndex),' '));
    write(file, copyFrom( title[line], 0, size(title[line])));
    write(file,CR_LF); 
  });
  
  curFrame := frames[0];
  startRef  := new( Struct, 4 ) ;
  endRef    := new( Struct, 4 ) ;
  retHandleRef := new( Struct, 4 ) ; /* alias for textAddrRef */
  textLenRef := new( Struct, 2 ) ; 
  loop
  while curFrame < frames[1]
  begin 
    numFrames := frames[1] - curFrame;
    if( numFrames > 100 ) numFrames := 100; endif;
    retCode := forwardRead(trace,numFrames,startRef,endRef,retHandleRef,
                           textLenRef);
    if( (retCode <> 0) cor 
         (TaskLibClass$Inst cand queryAbort(TaskLibClass$Inst)) 
         cor (wordAt(textLenRef,0) == 0) ) 
      curFrame := frames[1];   /* just leave with what we have */
      if(TaskLibClass$Inst cand queryAbort(TaskLibClass$Inst))
        retCode := 1; /* want calling routine to abort too */
      endif;
    else
      curFrame := longAt(endRef,0);
    endif;
    write(file, 
          physicalString(
                 copyFromLong( new(Struct, wordAt(textLenRef,0)), /* textLen */
                               longAt(retHandleRef, 0) ) )    /* textAddr */
         ) ;
    write(file,physicalString("**************************************"+CR_LF));
    cFree( MallocLibClass$Inst, longAt(retHandleRef, 0) ) ;
  endLoop;
  ^retCode;
}
!!

Def printInstBuffer(self,trace,buffer,frames,file,dq
               | textLenRef textAddrRef curFrame startRef endRef
                 retCode numFrames addrDescRef descArray)
{ 
  if( (retCode:=prim_trcReadFrameSet(trace, frames[0])) <> 0 )
    ^retCode;
  endif;
  write(file,"Trace Buffer:  "+asString(buffer)+CR_LF);
  write(file,"Frames: "+asString(frames[0])+" to "+asString(frames[1])+CR_LF);
  write(file,CR_LF);
  curFrame := frames[0];
  startRef  := new( Struct, 4 ) ;
  endRef  := new( Struct, 4 ) ;
  addrDescRef  := new( Struct, 4 ) ;
  textAddrRef := new( Struct, 4);
  textLenRef := new( Struct, 2 ) ; 
  loop
  while curFrame < frames[1]
  begin 
    numFrames := frames[1] - curFrame;
    if( numFrames > 40 ) numFrames := 40; endif;
    retCode := dadForwardDqInst(dq,numFrames,startRef,endRef,textAddrRef,
                                textLenRef,addrDescRef);
    if( retCode = 0)
      prim_trcReadFrameSet(trace, (longAt(endRef,0) + 1L));
    endif;
    if( (retCode <> 0) cor 
         (TaskLibClass$Inst cand queryAbort(TaskLibClass$Inst)) 
         cor (wordAt(textLenRef,0) == 0) ) 
      curFrame := frames[1];   /* just leave with what we have */
      if(TaskLibClass$Inst cand queryAbort(TaskLibClass$Inst))
        retCode := 1; /* want calling routine to abort too */
      endif;
    else
      curFrame := longAt(endRef,0);
    endif;
    write(file, 
          physicalString(
                 copyFromLong( new(Struct, wordAt(textLenRef,0)),
                               longAt(textAddrRef, 0) ) )        
         ) ;
    cFree( MallocLibClass$Inst, longAt(textAddrRef, 0) ) ;
    descArray := cStructFromStruct(TbirdStruct,#AddrDescArray,
                   copyFromLong(new(Struct,600),longAt(addrDescRef,0)));

    numFrames := 0;  /* alias numFrames since too many locals */
    loop
    while (numFrames < 150)
    begin
      if (descArray[#descs][numFrames] <> 0) then
        destroyAddress(AddressLibClass$Inst,descArray[#descs][numFrames]);
      endif;
      numFrames := numFrames + 1;
    endLoop;
    cFree( MallocLibClass$Inst, longAt(addrDescRef, 0) ) ;

  endLoop;
  ^retCode;
}
!!

Def profileSetup(self | aStr val timestampStr)  {
/* This order is CRITICAL! Relative vs delta timestamp force the 
   timestamp value to be TRUE.  Setting the bus/clock mode causes the
   trace data to be read - thus timestamp needs to be set up correctly
   prior.
 */
  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","systemFrequency"," ");
  /* if system frequency never defined */
  if( not(aStr[0]) cor (size(aStr[0]) = 0) )
    /* and if there is trace data we need to dislay then we need to
       prompt user for system frequency */
    if( trcNumFramesGet(theTrace) <> 0 )
      timestampSetup(self);
    endif;
  else
     trcSystemCrystalSet(TraceLibClass$Inst, aStr[0]);
  endif;
/*  saveProfileEntry(TheProfileInfoObj,"TraceInfo","timestamp",timestampStr[0]); 
  if( timestampStr[0] = "on" )
    val := 1;
    checkMenuItem(self,"&Timestamp");
  else
    val := 0;
    clearTimestampModeSelection(self);
    unCheckMenuItem(self,"&Timestamp");
  endif;
  trcTimestampSet(theTrace,val);
*/  
  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;
  val := trcBtmGet(theTrace);
  if( val[1] = 0 ) 
    unCheckMenuItem(self,"BT&M Cycles");
  else
    checkMenuItem(self,"BT&M Cycles");
  endif;
  initOptionFlag(self);
}!!

/* PUBLIC
   Respond to a windows message to resize the window.
   wp and lp are standard windows arguments.
 */
Def reSize(self, wp, lp) {
  if not(bufferDlg)
  then ^0;
  endif;
  sizeKids(self);
}!!

/* set browser variable */
Def setBrowser(self, value)
{ trcbrowser := value;
}
!!

/* 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");
  grayMenuItem(self,"&Auto");
  grayMenuItem(self,"Use&16");
  grayMenuItem(self,"Use&32");
  /* 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;
}
!!

/* PRIVATE
   Set scroll bar position, avoiding divide by 0.
 */
Def setHScrollPos(self, pos)
{ 
  if xMax(browser(self))
  then setPos(horzbar, pos);
       hbpos := pos;
  endif;
}!!

/* PRIVATE
   View trace data as bus cycles. Use incoming frame to position trace
   data.
 */
Def setBusCycles(self,frame)
{ 
  showWaitCurs();
  clearCycleViewSelection(self);
  checkMenuItem(self,"&Bus");
  TheCursorIsLinked? := nil;
  propagatePC(TheCursorLinkServer, self, nil);          
  grayMenuItem(self,"&Linked Cursor");
  grayMenuItem(self,"&Auto");
  grayMenuItem(self,"Use&16");
  grayMenuItem(self,"Use&32");
  setBrowserInfo(browser(self),TRviewInfo);
  trcTraceCycleSet(theTrace,BUS_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","bus");  
}
!!

/* PUBLIC
   Show self and all of the child windows.
 */
Def show(self, arg){ 
  show(self:WindowsObject, arg);
  if (arg = SW_NORMAL)
    show(horzbar, arg);
    show(titleWindow, arg);
    show(trcbrowser, arg);
  endif;
}!!

/* PRIVATE
   Make the trace browser window start after title area and end leaving
   enough room for the horitizal scroll bar at the bottom.
 */
Def sizeKids(self | width height titleHeight)
{ /* calculate the portions of the window */
  width := width(clientRect(self));
  height := height(clientRect(self));
  titleHeight := titleHeight(titleWindow)*tmHeight + 2;
  /* set the locations of the child windows */
  setCRect(titleWindow, rect(0, 0, width, titleHeight));
  setCRect(browser(self), rect(0, titleHeight, width, height-tmHeight-1));
  setCRect(horzbar, rect(hscrollIndex*tmWidth+2, height-tmHeight, width, height));

  /* move them */
  moveWindow(horzbar);
  moveWindow(titleWindow);
  moveWindow(browser(self));
  invalidate(self);
}!!

/* PRIVATE
   View trace data as bus cycles.
 */
Def timestampSetup(self | text rc)
{
  /* return immediately if micepack */
  if micepack?(ProcLibClass$Inst)
    ^nil;
  endif;
  showWaitCurs();
  if (runModal(systemCrystalDlg, DLG_TRACESYS, ThePort) = IDOK)
    text := getFrequency(systemCrystalDlg);
    if (text)
      if ((rc:=trcSystemCrystalSet(TraceLibClass$Inst, text)) = 0)
        text := trcSystemCrystalGet(TraceLibClass$Inst);
        setFrequency(systemCrystalDlg, text);
        saveProfileEntry(TheProfileInfoObj, "TraceInfo", "systemFrequency",
          text);  
      else 
        timestampSetup(self);               
      endif;
    endif;                      
  endif;
  showOldCurs();
}
!!

/* PRIVATE
   View trace data as bus cycles.
 */
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();
}
!!

/* PRIVATE
   View trace data as bus cycles.
 */
Def timestamp(self | curVal text aStr)
{
  /* return immediately if micepack 
  if micepack?(ProcLibClass$Inst)
    ^nil;
  endif;*/
  showWaitCurs();
  curVal := trcTimestampGet(theTrace);
  if( curVal = 0 ) 
    aStr := getProfileEntry(TheProfileInfoObj,"TraceInfo","tsmode"," ");
    if( aStr[0] = "delta" )
      timestampDelta(self);
    else 
      if ( aStr[0]="absoluate")
         timestampAbsoluate(self);
      else
         timestampRelative(self);
      endif;   
    endif;
    text := "on";
  else
    unCheckMenuItem(self,"&Timestamp");
    clearTimestampModeSelection(self);
    trcTimestampSet(theTrace,0);
    text := "off";
  endif;
  showOldCurs();
  saveProfileEntry(TheProfileInfoObj,"TraceInfo","timestamp",text);  
}
!!

/* PRIVATE
   View trace data as bus cycles.
 */
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");  
}
!!

/* PRIVATE
   View trace data as bus cycles.
 */
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/4/1992 9:38 */
Def tmHeight(self)
{ ^tmHeight}
!!

/* 2/4/1992 9:38 */
Def tmWidth(self)
{ ^tmWidth}
!!

/* PRIVATE
   Enable/disable symbol in disassembly.
 */
Def toggleSymbolEnable(self | aStr) {
  newViewMode := INST_CYCLE;
  setBrowserInfo(browser(self),DQviewInfo);
  setTitle(titleWindow,nil);
  clearCycleViewSelection(self);
  enableMenuItem(self,"&Linked Cursor");
  aStr := getProfileEntry(TheProfileInfoObj,"TraceInfo","linkedCursor"," ");
  if( aStr[0] = "on" )
    TheCursorIsLinked?:= #true;
  else
    TheCursorIsLinked?:= #false;
  endif;
  checkMenuItem(self,"&Instruction");
  enableMenuItem(self,"&Auto");
  enableMenuItem(self,"Use&16");
  enableMenuItem(self,"Use&32");
  dadSetDqSymbol(theDq,symbolOn); 
  invalidateCache(browser(self), nil);
  sizeKids(self);  /* want to get rid of title area if in dasm mode */
  invalidate(self);
  saveProfileEntry(TheProfileInfoObj,"TraceInfo","viewType","instruction");
}
!!

/* 2/5/1992 11:43 */
Def trace(self)
{ ^theTrace}
!!

/* PRIVATE
   Save trace data in ascii to a file. 
 */
Def traceSave(self | numBufs saveFile saveFileName 
  doEntireBuf? tmpNum  curBuffer startFrame endFrame bufInfo)
{ 
  /* use COMMDLG FileOpen dialog */ 
  if (saveFileName := getFileName(CLIULibraryClass$Inst, 
                             self,
                             HE_DLGF_SAVE_TRACE,
                             IDS_TRACE_FILTER, 
                             nil /* no initial path */, 
                             FILE_SAVE)) then
    setFileName(saveAsDlg, saveFileName);
    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
 */
Def trcEvent(self)
{ showWaitCurs();
  if (exists(EventWindow) cand TheEventPresenter)
  then 
    Call BringWindowToTop(getHWnd(TheEventPresenter)); 
    show( TheEventPresenter, SW_SHOWNORMAL ) ;
  else
    TheEventPresenter := open(EventWindow);
  endif;
  showOldCurs();
}
!!
/* PRIVATE
   Exit trace presenter
 */
Def trcExit(self)
{ 
  if shouldClose( self ) 
  then close( self ) ;
  endif ;
}
!!

/* PRIVATE
   Display status of linked cursor.  If selected then toggle
   value of linked cursor.
 */
Def trcLinked(self) { 
  /* @@@ how do I reflect current value of TheCursorIsLinked? -
     if one of the other presenters change value my check mark
     is still active!?
   */
  if( TheCursorIsLinked? = #true )
    TheCursorIsLinked? := nil;
    unCheckMenuItem(self,"&Linked Cursor");
    /* Nghia - Clear all client's LC */ 
    propagatePC(TheCursorLinkServer, self, nil);          
    saveProfileEntry(TheProfileInfoObj,"TraceInfo","linkedCursor","off");  
  else
    TheCursorIsLinked? := #true;
    checkMenuItem(self,"&Linked Cursor");
    saveProfileEntry(TheProfileInfoObj,"TraceInfo","linkedCursor","on");  
  endif;
  invalidate(self);   /* want to cause a repaint - non a cache flush */
}
!!

/* 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);
      ^self;
    endif;
    if( (status:=runModal(searchDlg, DLG_TRACESEA, ThePort)) = IDOK )
      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);
        ^self;
      endif;
      if( trcSearchEventSet(theTrace,getEvent(searchDlg)) <> 0)
       prim_trcReadBufferSet(theTrace,savBuf);
       ^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);
              ^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;
}
!!

/* 6/1/1992 15:02 */
Def trcTraceConfig(self | dlg){   
  dlg := new(TraceControlDialog);
  runModal(dlg, DLG_TRACECON, ThePort);
}!!

/* PRIVATE
 */
Def trcTraceStop(self){ 

  ^actionTraceStop(TheToolBarPresenter);

}!!

/* PRIVATE
 */
Def trcTraceStart(self){ 

  ^actionTraceStart(TheToolBarPresenter);

}!!

Def updateDasmAddressSize(self)
{
  if not(setDasmAddressSize(DisAsmLibClass$Inst, theDq, addrUse))
    ^nil;
  endif;
  flushCache(browser(self));
  setFrameLimitsFromTrace(browser(self));
  invalidateCache(browser(self), nil); 
  invalidate(self);
}!!

Def uncheckViewSizeMenuItems(self)
{
  unCheckMenuItem(self, "&Auto");
  unCheckMenuItem(self, "Use&16");
  unCheckMenuItem(self, "Use&32");
}!!

/* PRIVATE
   View trace data as bus cycles with no specific frame
 */
Def viewBusCycles(self)
{ newViewMode := BUS_CYCLE;
  setBusCycles(self,nil);  
}
!!

/* PRIVATE
   View trace data as clock cycles 
 */
Def viewClockCycles(self) {
  newViewMode := CLOCK_CYCLE;
  setClockCycles(self, nil); 
}
!!

/* WINDOWS -- sent by event manager (evNoteLib) */
Def WM_EVENT(self, wP, event | linesWanted aStr buffer popupHandle startFrame returnString numChars)
{ 
  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) )
    flagBufclr := 0;
    invalidateCache(browser(self), nil);
    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); 
  /* added by cjchen 1996/12/17 */
  numChars:=Call GetPrivateProfileString(asciiz("TrigInfo"),
     asciiz("traceAlignment"),asciiz(""),returnString:=new(String,256),256,
     asciiz(getFilename(ProfileControl)));
  returnString:=subString(returnString,0,numChars);
  if (returnString="center") cor (returnString="post")
     pageDown(browser(self));
     pageUp(browser(self)); 
  endif;
  if (returnString="pre")
     pageUp(browser(self));
     pageDown(browser(self));
  endif;   
  invalidate(self);
  
  ^0
}
!!

/* WINDOWS
   Handle horizontal scrolling differently because only the trace data
   section of the display scrolls.
 */
Def WM_HSCROLL(self, wP, lP | mChars mCadj xMax)
{
  /* reject thumb tracking */
  if wP = SB_THUMBTRACK cor wP = SB_ENDSCROLL
    ^0;
  endif;
  
  xMax := xMax(browser(self));
  mChars := max(getTitleLength(titleWindow),maxTextWidth(browser(self)));
  mCadj := mChars - (xMax-2);
  select
    case mChars <= xMax and leftChar == 0
    is ^0  
    endCase
    case wP == SB_LINEDOWN is
      if leftChar < mCadj
        leftChar := leftChar + 1;
      else
        ^0;  /* ignore useless scroll request */
      endif;
    endCase
    case wP == SB_PAGEDOWN
    is leftChar := min(leftChar + xMax-1, mCadj);
    endCase
    case wP == SB_LINEUP is
      if leftChar > 0
        leftChar := leftChar - 1;
      else
        ^0;  /* ignore useless scroll request */
      endif;
    endCase 
    case wP == SB_PAGEUP
    is leftChar := max(0, leftChar - xMax + 2);
    endCase
    case wP == SB_THUMBPOSITION
    is leftChar := asInt((mCadj*low(lP))/100);
    endCase
  endSelect;
  setHScrollPos(self,(100*leftChar)/max(1, mChars-(xMax-2)));
  invalidate(browser(self));
  invalidate(titleWindow);
} 
!!

/* Allow "arrow" keys and the tab key to work
 without using accelerators. */
Def WM_KEYDOWN(self, wp, lp)
{ if between(wp, 37, 40)
  then command(self, wp, 0x10000);
  else WM_KEYDOWN(self:ancestor, wp, lp);
  endif;
}!!

/* 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(self))
    paint(self, hdc);
    Call SelectObject(hdc, oldFont);
    Call EndPaint(getHWnd(self), paintStruct);
  endif;
  ^0;
}
!!
