/* class comment */!!

inherit(AutomaticMenu, #MPresenter, #(/* server instances */
memServerInstance
dasmServerInstance
asmServerInstance
okToReadMemory /* true if ... */
screenDirty /* true if screen dirty */
memBrowse /* memory browser handle */
dasmBrowse /* disassembly browser */
topBrowser /* browser that's visible */
writeVerify  /* true if write verify selected */
accessSize /* 1:byte, 2:word, 4:dword */
topOffset /* memory offset at top of screen */
eventDescSet /* registered events */
identityString /* identifies save/restore file */
readAhead /* true if read ahead activated */
reRead /* true if re-read on write */
windowIndex /* multiple window index */
/* the following contain default cmd settings */
defaultValues_checksum
defaultValues_compare
defaultValues_fill
defaultValues_move
defaultValues_search
defaultValues_test
), 2, nil)!!

setClassVars(MPresenter, #())!!

now(class(MPresenter))!!

/* start presenter with default position */
Def open(self)
{
  ^openWithPosition(self, rect(40, 10, 600, 170));
}
!!

/* start presenter with specific position */
Def openWithPosition(self, sizeRect | tempServer, tempPresenter)
{
  /* start presenter */
  tempPresenter := newStyle(MPresenter, nil, nil, "Memory",
                   sizeRect, nil, WS_OVERLAPPEDWINDOW);
  initialize(tempPresenter);
  invalidate(tempPresenter);  /* needs this to show scroll bar arrows */
  ^tempPresenter
}
!!

/* start presenter with specific position */
Def openWithPosAndState(self, sizeRect, showVal | tempServer tempPresenter)
{
  /* start presenter */
  tempPresenter := newStyle(MPresenter, nil, nil, "Memory",
                   sizeRect, nil, WS_OVERLAPPEDWINDOW);
  initializeShow(tempPresenter, showVal);
  invalidate(tempPresenter);  /* needs this to show scroll bar arrows */
  ^tempPresenter
}
!!


/* Define self class */
Def wndClass(self)
{
  ^"MPresenter";
}
!!

/* Return the name of self window icon */
Def wndIcon(self)
{
  ^"MEMORY";
}
!!

now(MPresenter)!!

/* 11/28/1995 9:34 */
Def menuEditComp(self | dlg toaddr status)
{
  menuSelection(topBrowser);

  /* call memCompDlg */
  status := memCompDlg(memServerInstance, handle(self) );
  if not(status)
    ^0;  /* error reporting done by library */
  endif;
}
!!

/* 11/22/1995 17:43 */
/* handle edit checksum command */
Def menuEditChecksum(self |
       dlg fromaddr toaddr fromOffset toOffset tmpDesc sum cap result)
{
  menuSelection(topBrowser);

  dlg := open(MemSearchOrFillDialog);
  setValues(dlg, defaultValues_checksum);
  setHelpEntry(dlg, HELP_ENTRY_MEMORY);
  
  if (runModal(dlg, DLG_MEM_SEARCH, ThePort) = IDOK)
    /* get value strings */
    defaultValues_checksum := getValues(dlg);
    fromaddr := defaultValues_checksum[0];
    toaddr := defaultValues_checksum[1];
    
    /* make call, check status */
    showWaitCurs();
    
    /* fromaddr, toaddr have already been validated by MemEditGeneralDlg */
    tmpDesc := convertTextToAddress(AddressLibClass$Inst,fromaddr);
    fromOffset := getOffset(AddressLibClass$Inst, tmpDesc);
    destroyAddress(AddressLibClass$Inst, tmpDesc);
    if not(fromOffset)
      fromOffset := getSymbolicOffset(AddressLibClass$Inst, fromaddr);
    endif;
    
    tmpDesc := convertTextToAddress(AddressLibClass$Inst,toaddr);
    toOffset := getOffset(AddressLibClass$Inst, tmpDesc);
    destroyAddress(AddressLibClass$Inst, tmpDesc);
    if not(toOffset)
      toOffset := getSymbolicOffset(AddressLibClass$Inst, toaddr);
    endif;
    
    sum := memChecksum(memServerInstance, fromOffset, toOffset);
    if sum then
      if (accessSize = 1) then
        sum := sum bitAnd 0x000000FF;
      else
        sum := sum bitAnd 0x0000FFFF;
      endif;  
      result := asStringRadix(sum,16)+asString(asChar(0));
      cap := "Checksum"+asString(asChar(0));
      Call MessageBox(hWnd,"Checksum Value is : 0x"+result,cap,MB_OK);  
    endif;  
  endif;
  showOldCurs();
  ^0
}
!!

/* 11/22/1995 17:43 */
/* handle edit test command */
Def menuEditTest(self |
       dlg fromaddr toaddr fromOffset toOffset tmpDesc status cap result retAddr)
{
  menuSelection(topBrowser);
  retAddr := new(Struct,4);
  
  dlg := open(MemSearchOrFillDialog);
  setValues(dlg, defaultValues_test);
  setHelpEntry(dlg, HELP_ENTRY_MEMORY);
  
  if (runModal(dlg, DLG_MEM_SEARCH, ThePort) = IDOK)
    /* get value strings */
    defaultValues_test := getValues(dlg);
    fromaddr := defaultValues_test[0];
    toaddr := defaultValues_test[1];
    
    /* make call, check status */
    showWaitCurs();
    
    /* fromaddr, toaddr have already been validated by MemEditGeneralDlg */
    tmpDesc := convertTextToAddress(AddressLibClass$Inst,fromaddr);
    fromOffset := getOffset(AddressLibClass$Inst, tmpDesc);
    destroyAddress(AddressLibClass$Inst, tmpDesc);
    if not(fromOffset)
      fromOffset := getSymbolicOffset(AddressLibClass$Inst, fromaddr);
    endif;
    
    tmpDesc := convertTextToAddress(AddressLibClass$Inst,toaddr);
    toOffset := getOffset(AddressLibClass$Inst, tmpDesc);
    destroyAddress(AddressLibClass$Inst, tmpDesc);
    if not(toOffset)
      toOffset := getSymbolicOffset(AddressLibClass$Inst, toaddr);
    endif;
    
    status := memTest(memServerInstance, fromOffset, toOffset, retAddr);
    if status then
      if status = 0 then
        result := "RAM Test OK."+asString(asChar(0));
      else
        fromOffset := longAt(retAddr,0);
        result := "RAM Test fail at : 0x"+asStringRadix(fromOffset,16);
        result := result + asString(asChar(0));
      endif;  
      cap := "Memory Test"+asString(asChar(0));    
      Call MessageBox(hWnd,result,cap,MB_OK);  
    endif;
  endif;
  showOldCurs();
  ^0
}
!!

/* 11/8/1995 13:16 */
Def setViewSpace(self, space)
{ 
  setDadAddrSpace(DisAsmLibClass$Inst, dasmServerInstance, space);
  setDadAddrSpace(DisAsmLibClass$Inst, asmServerInstance, space); 
  memSetAddrSpace(memServerInstance, space);
  doRefresh(self);
}
!!

/* 11/8/1995 17:36 */
Def uncheckViewSpaceMenuItems(self)
{ 
  unCheckMenuItem(self, "S&P Space");
  unCheckMenuItem(self, "SD Sp&ace");
  unCheckMenuItem(self, "UP Spa&ce");
  unCheckMenuItem(self, "UD Spac&e");
  ^0; 
}
!!

/* 10/3/1995 15:48 */
Def menuViewUD(self)
{
  menuSelection(topBrowser);
  
  uncheckViewSpaceMenuItems(self);
  checkMenuItem(self, "UD Spac&e");
  setViewSpace(self, 1);
  setViewStatus(self);
}!!

/* 10/3/1995 15:41 */
Def menuViewUP(self)
{
  menuSelection(topBrowser);
  
  uncheckViewSpaceMenuItems(self);
  checkMenuItem(self, "UP Spa&ce");
  setViewSpace(self, 2);
  setViewStatus(self);
}!!

/* 10/3/1995 15:47 */
Def menuViewSD(self)
{
  menuSelection(topBrowser);
  
  uncheckViewSpaceMenuItems(self);
  checkMenuItem(self, "SD Sp&ace");
  setViewSpace(self, 5);
  setViewStatus(self);
}!!

/* 10/3/1995 15:41 */
Def menuViewSP(self)
{
  menuSelection(topBrowser);
  
  uncheckViewSpaceMenuItems(self);
  checkMenuItem(self, "S&P Space");
  setViewSpace(self, 6);
  setViewStatus(self);
}!!

/* 4/13/1994 17:56 - PRIVATE 
  Return #true if memServer is opened, else nil
*/
Def memServerValid?(self)
{ 
  ^memServerInstance; 
}
!!

/* Return ID string including window index, display type & size, offset. */
Def memoryWindowID(self | radix grouping typeText sizeText indexText spaceText spaceID)
{
  if displayingDasm(self)
    typeText := "Disassembly";
    sizeText := " ";
  else
    radix := memRadix(memBrowse);
    if radix = 16
      typeText := "Hex";
    else
      typeText := "Decimal";
    endif;
    
    grouping := memByteGrouping(memBrowse);
    select
      case grouping = 1 is sizeText := " Bytes";  endCase
      case grouping = 2 is sizeText := " Words";  endCase
      case grouping = 4 is sizeText := " DWords"; endCase
      default              sizeText := "";
    endSelect;
  endif;
  
  spaceID := memGetAddrSpace(memServerInstance);
  select
    case spaceID = 1 is spaceText := " (UD)";  endCase
    case spaceID = 2 is spaceText := " (UP)";  endCase
    case spaceID = 5 is spaceText := " (SD)";  endCase
    case spaceID = 6 is spaceText := " (SP)";  endCase
    default             spaceText := "";
  endSelect;  

  /* get index */
  if windowIndex
     indexText := asString(windowIndex)
  else
     indexText := "";
  endif;
  
  /* return the ID string. */
  ^( "(" + indexText + "): " + typeText + sizeText + spaceText + " 0x" + 
     asUnsignedStringRadix(asLong(getOffset(topBrowser)), 16));
}!!

/* Receive the identifying index of this memory window. */
Def receiveIndex(self, index)
{
  windowIndex := index;
  setViewStatus(self);
}
!!

/* 11/19/1993 12:12 */
Def WM_SIZE(self, wP, lP)
{
  WM_SIZE(self:ancestor, wP, lP);
  if (topBrowser)    
    if (wP = SIZEICONIC)
      deactivateWindow(topBrowser);
    else
      activateWindow(topBrowser);
    endif;
  endif;
}
!!

/* 5/23/1993 15:35 */
Def menuEditCopy(self | dlg toaddr status)
{
  menuSelection(topBrowser);

  /* do MemDialog call */

    /* call memCopyDlg */
    status := memCopyDlg(memServerInstance, handle(self) );
    if not(status)
      ^0;  /* error reporting done by library */
    endif;
}
!!


/* return value of readAhead flag */
Def reRead(self)
{
  ^reRead;
}
!!

Def menuOptionsReread(self)
{
  menuSelection(topBrowser);
  
  if reRead(self)
    reRead := nil;
    unCheckMenuItem(self, "R&eread On Write");
  else
    reRead := 0;
    checkMenuItem(self, "R&eread On Write");
  endif;
  ^0;
}!!

/* return value of readAhead flag */
Def readAhead(self)
{
  ^readAhead;
}
!!

Def menuOptionsReadAhead(self)
{
  menuSelection(topBrowser);
  
  if readAhead(self)
    readAhead := nil;
    unCheckMenuItem(self, "&Read Ahead");
  else
    readAhead := 0;
    checkMenuItem(self, "&Read Ahead");
  endif;
  ^0;
}!!

/* set to byte access */
Def accessByte(self)
{
  uncheckAccessMenuItems(self);
  checkMenuItem(self, "&Byte Access");
  setAccessSize(self, 1);
  ^0;
}!!

/* set to dword access */
Def accessDWord(self)
{
  uncheckAccessMenuItems(self);
  checkMenuItem(self, "&DWord Access");
  setAccessSize(self, 4);
  ^0;
}!!

/* get access size; 1:byte, 2:word, 4:dword */
Def accessSize(self)
{
  ^accessSize;
}
!!

/* set to word access */
Def accessWord(self)
{
  uncheckAccessMenuItems(self);
  checkMenuItem(self, "&Word Access");
  setAccessSize(self, 2);
  ^0;
}!!

/* return asm server instance */
Def asmServer(self)
{
  if not(asmServerInstance)
    displayFormattedError(ErrorTextLibClass$Inst, 
       ER_INTERNAL, FORCE_POPUP, "Initialization not correct",
       "MPresenter:asmServer", nil);
  endif;
  ^asmServerInstance;
}!!

Def close(self)
{
  closeEvents(self);

  /* close servers; don't check for errors because we want to close as
     much as possible. */
  closeSession(memServerInstance);
  memServerInstance := nil;
  closeDasm(DisAsmLibClass$Inst, dasmServerInstance);
  dasmServerInstance := nil;
  closeAsm(AsmLibClass$Inst, asmServerInstance);
  asmServerInstance := nil;
  
  /* close children */
  close(memBrowse);
  close(dasmBrowse);

  /* free entry in memory presenter */
  freeMemoryIndex(MultMem, windowIndex);

  /* close */
  close(self:ancestor);
}
!!

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

/* Dispatch menu choices, accelerators. */
Def command(self, wP, lP | msg)
{ select
    case wP == EDIT_PRIOR is
      ^WM_VSCROLL(topBrowser, SB_PAGEUP, 0);
    endCase
    case wP == EDIT_NEXT is
      ^WM_VSCROLL(topBrowser, SB_PAGEDOWN, 0);
    endCase
    case wP == 38 cor wP == 40
      ^arrows(topBrowser, wP);
    endCase
  endSelect;
  
  /* if menuId is defined */
  if msg := action(menu(self), wP)   
    /* Clear ESC key */
    if (TaskLibClass$Inst)
      checkAbort(TaskLibClass$Inst);
    endif;
    /* do the corresponding action */
    perform(self, msg);                  
  else   /* dynamic window menu dropdown. */
    if not(doAction(PreLauncher, wP))
      command(self:ancestor, wP, lP);
    endif ;
  endif;
}!!

/* return dasm server instance */
Def dasmServer(self)
{
  if not(dasmServerInstance)
    displayFormattedError(ErrorTextLibClass$Inst, 
       ER_INTERNAL, FORCE_POPUP, "Initialization not correct",
       "MPresenter:dasmServer", nil);
  endif;
  ^dasmServerInstance;
}!!

/* true if displaying dasm */
Def displayingDasm(self)
{
  if topBrowser = dasmBrowse
    ^0
  endif;
  ^nil
}!!

/* true if displaying memory */
Def displayingMemory(self)
{
  if topBrowser = memBrowse
    ^0
  endif;
  ^nil
}!!

Def doRefresh(self)
{
  doRefresh(memBrowse);
  doRefresh(dasmBrowse);
}
!!

/* return location rectangle. */
Def getMemoryRect(self)
{
  ^locRect
}
!!

/* pass along to display window. */
Def gotFocus(self, hWndPrev | newWriteVerify newAccessSize)
{
  /* 04/19/94 - Nghia
  ** GPF - exit mem window
  */
  if not(memServerInstance)
    ^nil;
  endif; 
  /* focus top presenter */
  if topBrowser
    setFocus(topBrowser);
  endif;
  
  /* get values from server */
  reflectAccessSize(self);
  reflectWriteVerify(self);
  
  ^gotFocus(self:ancestor, hWndPrev);
}!!

/* initialize child */
Def initChildWind(self)
{
  /* dasm browser is initially hidden */
  dasmBrowse := newStyle(DasmBrowser, self, nil, "child", nil, 0,
     WS_CHILD bitOr WS_VSCROLL bitOr WS_HSCROLL);
  initialize(dasmBrowse);
  show(dasmBrowse, 1);  /* show normal size */
  show(dasmBrowse, 0);  /* then hide it */

  /* memory browser is initially visible */
  memBrowse := newStyle(MBrowser, self, nil, "child", nil, 0,
     WS_CHILD bitOr WS_VSCROLL bitOr WS_HSCROLL);
  initialize(memBrowse);
  topBrowser := memBrowse;
  show(topBrowser, 1);
  
  sizeKid(self);
}!!

/* initialize defaults for interactive commands */
Def initDefaults(self)
{
  /* nil start address, nil length, byte size / byte sum / carry ignore */
  defaultValues_checksum := #("", "", 0x49,"Checksum",1);
  /* nil values */
  defaultValues_compare := #("", "", "","Compare Memory",2);
  defaultValues_test    := #("", "", "","Memory Test",3);
  defaultValues_fill    := #("", "", "","Fill Memory",4);
  defaultValues_move    := #("", "", "","Move Memory",5);
  defaultValues_search  := #("", "", "","Search Memory",6);
}!!

/* PRIVATE */
Def initEvents(self | eventDesc, events)
{
  /* REGISTER with Event Notification for Whatever... */

  eventDescSet := new(Set, 1);

  /* dynamic to pick up current values */
  events := tuple(EVENT_DASM_HALTED, EVENT_MEM_EDIT, EVENT_DASM_SYM_CHANGED);
  do(events,
   { using(event)
    eventDesc := register(EvNoteLibClass$Inst, event, hWnd(self));
      if (eventDesc <> 0)
      then
        add(eventDescSet, eventDesc);
      endif;
  });

}
!!

/* initialize display */
Def initialize(self)
{
  /* always display */
  initializeShow(self, 1);
}!!

/* initialize display */
Def initializeShow(self, showVal)
{
  /* get up on screen fast */
  show(self, showVal);
    
  /* initialize the minimum in order to get on screen fast */
  initMenus(self);
  
  /* load dll's */
  requireWithPath(MemServLib, "mem.dll");
  requireWithPath(DisAsmLib, getDasmDLLName(PreLauncher));
  requireWithPath(AsmLib, getDasmDLLName(PreLauncher));
  requireWithPath(AddressLib, "addr.dll");
  if not(memServerInstance := openSession(MemServLibClass$Inst))
    ^0;  /* error reporting done by library */
  endif;

  if not(dasmServerInstance := simpleOpenDasm(DisAsmLibClass$Inst))
    ^0;  /* error reporting done by library */
  endif;

  if not(asmServerInstance := simpleOpenAsm(AsmLibClass$Inst))
    ^0;  /* error reporting done by library */
  endif;

  /* load up the memory and dasm browsers */
  initChildWind(self);
  
  okToReadMemory := 0;  /* all server init has been done */

  /* set initial values */
  reflectWriteVerify(self);  /* show server setting */
  reflectAccessSize(self);   /* show server setting */
  menuViewSD(self);  
  menuViewHexWords(self);    /* hex word display */
  initDefaults(self);

  /* identityString := "Memory Presenter Configuration File"; */

  /* init events after everything else done */
  initEvents(self);
}!!

/* Initialize the menus. */
Def initMenus(self | aMenu)
{
  aMenu := new(OrderedCollection, 4);
  initMenu(self);
  add(aMenu, tuple("&File", tuple(
                 tuple("E&xit", #menuFileExit))));
  add(aMenu, tuple("&Edit", tuple(
                 tuple("Go To &Address...", #menuEditGoto),
                 tuple("S&earch Memory...", #menuEditSearch),
                 tuple("&Fill Memory...", #menuEditFill),  
                 tuple("&Copy Memory...", #menuEditCopy),
                 tuple("C&hecksum...", #menuEditChecksum),
                 tuple("C&ompare Memory...", #menuEditComp),
                 tuple("&Test Memory...", #menuEditTest))));
  add(aMenu, tuple("&View", tuple(
                 tuple("Dis&assembly", #menuViewDisassembly),
                 tuple(nil, nil),
                 tuple("Hex &Bytes", #menuViewHexBytes),
                 tuple("Hex &Words", #menuViewHexWords),
                 tuple("Hex &DWords", #menuViewHexDWords),
                 tuple("Decimal B&ytes", #menuViewDecBytes),
                 tuple("Decimal W&ords", #menuViewDecWords),
                 tuple("Decimal DWord&s", #menuViewDecDWords),
                 tuple(nil, nil),
                 tuple("S&P Space", #menuViewSP),
                 tuple("SD Sp&ace", #menuViewSD),
                 tuple("UP Spa&ce", #menuViewUP),
                 tuple("UD Spac&e", #menuViewUD),
                 tuple(nil, nil),
                 tuple("Re&fresh Display", #menuViewRefresh))));
  add(aMenu, tuple("&Options", tuple(
                 tuple("&Byte Access", #menuOptionsAccessByte),
                 tuple("&Word Access", #menuOptionsAccessWord),
                 /* tuple("&DWord Access", #menuOptionsAccessDWord),  01-15-98 removed by Winky */
                 tuple(nil, nil),
                 tuple("Write &Verify", #menuOptionsWVerify),
                 tuple(nil, nil),
                 tuple("&Read Ahead", #menuOptionsReadAhead),
                 tuple(nil, nil),
                 tuple("R&eread On Write", #menuOptionsReread))));

  attachMenuChoices(self,aMenu);
  
  addWindowAndHelp(self, "&Memory", HELP_ENTRY_MEMORY);
  registerF1Help(CLIULibraryClass$Inst, HI_ENTRY_MEMORY,
     getHWnd(self), HELP_ENTRY_MEMORY);
    /* add "Windows" and "Help" */

  /* initialize for interactive use */
  drawMenu(self);
}!!

/* pass along to display window. */
Def losingFocus(self, hWndNew)
{
  losingFocus(topBrowser, hWndNew);
  /*
  deactivateWindow(topBrowser);
  */
  ^losingFocus(self:ancestor, hWndNew);
}!!

/* child informs us screen is clean */
Def markScreenClean(self)
{
  screenDirty := nil;
  ^0;
}!!

/* child informs us screen is dirty */
Def markScreenDirty(self)
{
  screenDirty := 0;
  ^0;
}!!

/* return memory server instance */
Def memServer(self)
{
  if not(memServerInstance)
    displayFormattedError(ErrorTextLibClass$Inst, 
       ER_INTERNAL, FORCE_POPUP, "Initialization not correct",
       "MPresenter:memServer", nil);
  endif;
  ^memServerInstance;
}!!

/* handle edit fill command */
Def menuEditFill(self |
       dlg fromaddr toaddr pattern status fromOffset toOffset tmpDesc )
{
  menuSelection(topBrowser);

  dlg := open(MemSearchOrFillDialog);
  setValues(dlg, defaultValues_fill);
  setHelpEntry(dlg, HE_DLGR_MEM_FILL);
  
  if (runModal(dlg, DLG_MEM_FILL, ThePort) = IDOK)
    /* get value strings */
    defaultValues_fill := getValues(dlg);
    fromaddr := defaultValues_fill[0];
    toaddr := defaultValues_fill[1];
    pattern := defaultValues_fill[2];

    /* make call, check status */
    showWaitCurs();
    
    /* fromaddr, toaddr have already been validated by MemEditGeneralDlg */
    tmpDesc := convertTextToAddress(AddressLibClass$Inst,fromaddr);
    fromOffset := getOffset(AddressLibClass$Inst, tmpDesc);
    destroyAddress(AddressLibClass$Inst, tmpDesc);
    if not(fromOffset)
      fromOffset := getSymbolicOffset(AddressLibClass$Inst, fromaddr);
    endif;
    
    tmpDesc := convertTextToAddress(AddressLibClass$Inst,toaddr);
    toOffset := getOffset(AddressLibClass$Inst, tmpDesc);
    destroyAddress(AddressLibClass$Inst, tmpDesc);
    if not(toOffset)
      toOffset := getSymbolicOffset(AddressLibClass$Inst, toaddr);
    endif;
    
    status := memFill(memServerInstance, fromOffset, toOffset, pattern);
      
  endif;
  showOldCurs();
  ^0
}!!

Def menuEditGoto(self)
{
  menuSelection(topBrowser);
  
  doGoto(topBrowser, nil);
}
!!

/* 3/24/1992 11:10 */
Def menuEditSearch(self | dlg startaddr, endaddr, pattern,
                           addr1 addr2 found tmpDesc)
{
  menuSelection(topBrowser);
  
  dlg := open(MemSearchOrFillDialog);
  setValues(dlg, defaultValues_search);
  setHelpEntry(dlg, HE_DLGR_MEM_SEARCH);

  /* get selections, save as defaults */
  if (runModal(dlg, DLG_MEM_SEARCH, ThePort) = IDOK)
    defaultValues_search := getValues(dlg);
    startaddr := defaultValues_search[0];
    endaddr := defaultValues_search[1];
    pattern := defaultValues_search[2];

    tmpDesc := convertTextToAddress(AddressLibClass$Inst, startaddr);
    addr1 := getOffset(AddressLibClass$Inst, tmpDesc);
    destroyAddress(AddressLibClass$Inst, tmpDesc);
    if not(addr1)
      addr1 := getSymbolicOffset(AddressLibClass$Inst, startaddr);
    endif;

    tmpDesc := convertTextToAddress(AddressLibClass$Inst, endaddr);
    addr2 := getOffset(AddressLibClass$Inst, tmpDesc);
    destroyAddress(AddressLibClass$Inst, tmpDesc);
    if not(addr2)
      addr2 := getSymbolicOffset(AddressLibClass$Inst, endaddr);
    endif;
    
    /* call memSearch */
    showWaitCurs();
    found := memSearch(memServerInstance, addr1, addr2, 0, pattern);
    if found
      if found = -1
        displayFormattedError(ErrorTextLibClass$Inst, 
           ER_SEARCH_NOT_FOUND, FORCE_POPUP, nil, nil, nil);
      else
        /* if dasm browser, display found addr in popup; the mem browser
           sets the cursor to the proper location. */
        if topBrowser = dasmBrowse then
          displayFormattedError(ErrorTextLibClass$Inst, 
             ER_SEARCH_FOUND, FORCE_POPUP, 
             asUnsignedStringRadix(asLong(found), 16), nil, nil);
        endif;
        setOffset(topBrowser, found);
      endif;
    endif;
  endif;
  showOldCurs();
}
!!

Def menuFileExit(self)
{
  menuSelection(topBrowser);
  
  close(self);
}
!!

/* set to byte access */
Def menuOptionsAccessByte(self)
{
  menuSelection(topBrowser);
  accessByte(self);
  ^0;
}!!

/* set to dword access */
Def menuOptionsAccessDWord(self)
{
  menuSelection(topBrowser);
  accessDWord(self);
  ^0;
}!!

/* set to word access */
Def menuOptionsAccessWord(self)
{
  menuSelection(topBrowser);
  accessWord(self);
  0;
}!!

/* set the writeVerify flag appropriately */
Def menuOptionsWVerify(self)
{
  menuSelection(topBrowser);
  wVerify(self);
  ^0;
}!!

Def menuViewDecBytes(self)
{
  menuSelection(topBrowser);
  
  uncheckViewMenuItems(self);
  checkMenuItem(self, "Decimal B&ytes");
  switchToMemory(self);
  doViewDecBytes(topBrowser);
  setViewStatus(self);
}!!

Def menuViewDecDWords(self)
{
  menuSelection(topBrowser);
  
  uncheckViewMenuItems(self);
  checkMenuItem(self, "Decimal DWord&s");
  switchToMemory(self);
  doViewDecDWords(topBrowser);
  setViewStatus(self);
}!!

Def menuViewDecWords(self)
{
  menuSelection(topBrowser);
  
  uncheckViewMenuItems(self);
  checkMenuItem(self, "Decimal W&ords");
  switchToMemory(self);
  doViewDecWords(topBrowser);
  setViewStatus(self);
}!!

Def menuViewDisassembly(self)
{
  menuSelection(topBrowser);

  uncheckViewMenuItems(self);
  checkMenuItem(self, "Dis&assembly");
  switchToDasm(self);
  setViewStatus(self);
}
!!

Def menuViewHexBytes(self)
{
  menuSelection(topBrowser);
  
  uncheckViewMenuItems(self);
  checkMenuItem(self, "Hex &Bytes");
  switchToMemory(self);
  doViewHexBytes(topBrowser);
  setViewStatus(self);
}!!

Def menuViewHexDWords(self)
{
  menuSelection(topBrowser);
  
  uncheckViewMenuItems(self);
  checkMenuItem(self, "Hex &DWords");
  switchToMemory(self);
  doViewHexDWords(topBrowser);
  setViewStatus(self);
}!!

Def menuViewHexWords(self)
{
  menuSelection(topBrowser);
  
  uncheckViewMenuItems(self);
  checkMenuItem(self, "Hex &Words");
  switchToMemory(self);
  doViewHexWords(topBrowser);
  setViewStatus(self);
}!!

Def menuViewRefresh(self)
{
  menuSelection(topBrowser);
  memCacheInvalidate(MemServLibClass$Inst);
  doRefresh(self);
  setViewStatus(self);
}
!!

/* reflect write verify setting */
Def reflectAccessSize(self | newAccessSize)
{
  if not(okToReadMemory)
    ^0;
  endif;
  
  newAccessSize := memGetAccessSize(memServerInstance);
  if newAccessSize
    select
      case newAccessSize = 1 is accessByte(self);  endCase
      case newAccessSize = 2 is accessWord(self);  endCase
      case newAccessSize = 4 is accessDWord(self); endCase
    endSelect;
  endif;
}!!

/* reflect write verify setting */
Def reflectWriteVerify(self | newWriteVerify)
{
  if not(okToReadMemory)
    ^0;
  endif;
  
  newWriteVerify := memGetVerifyWrites(memServerInstance);
  select
    case newWriteVerify = 0 is setWVerifyOff(self); endCase
    case newWriteVerify = 1 is setWVerifyOn(self); endCase
  endSelect;
}!!

/* reSize just resizes the kids! */
Def reSize(self, lP, wP)
{
  sizeKid(self);
}!!

/* set access size; 1:byte, 2:word, 4:dword */
Def setAccessSize(self, value)
{
  if value <> 1 cand value <> 2 cand value <> 4
    displayFormattedError(ErrorTextLibClass$Inst, 
       ER_INTERNAL, FORCE_POPUP, "Illegal access size value",
       "MPresenter:setAccessSize", nil);
  endif;
  accessSize := value;
  memSetAccessSize(memServerInstance, value);
  ^0;
}
!!

/* display viewing status in title bar
   dasmFlag: true if dasm display
   hexFlag:  true if hex display
   byteCount:  1 -> byte, 2 -> word, 4 -> dword */
Def setViewStatus(self | radix grouping typeText sizeText indexText spaceText spaceID)
{
  if displayingDasm(self)
    typeText := "Disassembly";
    sizeText := "";
  else
    radix := memRadix(memBrowse);
    if radix = 16
      typeText := "Hex";
    else
      typeText := "Decimal";
    endif;
    
    grouping := memByteGrouping(memBrowse);
    select
      case grouping = 1 is sizeText := " Bytes";  endCase
      case grouping = 2 is sizeText := " Words";  endCase
      case grouping = 4 is sizeText := " DWords"; endCase
      default              sizeText := "";
    endSelect;
  endif;
  
  spaceID := memGetAddrSpace(memServerInstance);
  select
    case spaceID = 1 is spaceText := " (UD)";  endCase
    case spaceID = 2 is spaceText := " (UP)";  endCase
    case spaceID = 5 is spaceText := " (SD)";  endCase
    case spaceID = 6 is spaceText := " (SP)";  endCase
    default             spaceText := "";
  endSelect;

  /* get index */
  if windowIndex
     indexText := asString(windowIndex)
  else
     indexText := "";
  endif;
  
  /* spit it all out */
  setText(self, "Memory (" + indexText + "): " + typeText +
     sizeText + " View" + spaceText);
  ^0;
}!!

/* set value of writeVerify flag */
Def setWriteVerify(self, value)
{
  writeVerify := value;
  ^0;
}
!!

/* set the writeVerify flag off */
Def setWVerifyOff(self)
{
  setWriteVerify(self, nil);
  unCheckMenuItem(self, "Write &Verify");
  memSetVerifyWrites(memServerInstance, nil);
}!!

/* set the writeVerify flag on */
Def setWVerifyOn(self)
{
  setWriteVerify(self, 0);
  checkMenuItem(self, "Write &Verify");
  memSetVerifyWrites(memServerInstance, 0);
}!!

/* Return true if ok for window to close. */
Def shouldClose(self)
{
  /* check for updates; abort command if abort selected by user */
  /*
  ^confirmExit(memBrowse);*/
}
!!

/* resize both child windows, the visible and the invisible */
Def sizeKid(self | pRect)
{
  /* return if we're not ready yet */
  if not(memBrowse) cor not(dasmBrowse)
    ^0;
  endif;
  
  pRect := clientRect(self);  /* get parent's rect */
  
  /* size memory browser */
  setCRect(memBrowse, pRect);
  moveWindow(memBrowse);
  
  /* size dasm browser */
  setCRect(dasmBrowse, pRect);
  moveWindow(dasmBrowse);
  
  setFocus(topBrowser);
}!!

/* switch to showing dasm browser */
Def switchToDasm(self)
{
  if displayingMemory(self)
    show(memBrowse, 0);
    deactivateWindow(memBrowse);
    setFocus(dasmBrowse);
    
    topBrowser := dasmBrowse;
    invalidateCache(dasmBrowse);  /* force realignment of dasm display */
    setOffset(dasmBrowse, getOffset(memBrowse));
    
    show(dasmBrowse, 1);
  endif;
}!!

/* switch to showing memory browser */
Def switchToMemory(self)
{
  if displayingDasm(self)
    show(dasmBrowse, 0);
    deactivateWindow(dasmBrowse);
    setFocus(memBrowse);
    
    topBrowser := memBrowse;
    setOffset(memBrowse, getOffset(dasmBrowse));
    
    show(memBrowse, 1);
  endif;
}!!

Def uncheckAccessMenuItems(self)
{
  unCheckMenuItem(self, "&Byte Access");
  unCheckMenuItem(self, "&Word Access");
  unCheckMenuItem(self, "&DWord Access");
}!!

Def uncheckViewMenuItems(self)
{
  unCheckMenuItem(self, "Dis&assembly");
  unCheckMenuItem(self, "Hex &Bytes");
  unCheckMenuItem(self, "Hex &Words");
  unCheckMenuItem(self, "Hex &DWords");
  unCheckMenuItem(self, "Decimal B&ytes");
  unCheckMenuItem(self, "Decimal W&ords");
  unCheckMenuItem(self, "Decimal DWord&s");
}!!

/* Update memory display due to memory change */
Def WM_EVENT(self, target, event)
{
  select
    case ((event = EVENT_MEM_EDIT) cor (event = EVENT_DASM_HALTED)
    cor (event = EVENT_DASM_SYM_CHANGED)) is
      doRefresh(self);
    endCase
  endSelect;
  ^0;
}
!!

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

/* return value of writeVerify flag */
Def writeVerify(self)
{
  ^writeVerify;
}
!!

/* set the writeVerify flag appropriately */
Def wVerify(self)
{
  if writeVerify(self)
    setWVerifyOff(self);
  else
    setWVerifyOn(self);
  endif;
  ^0;
}!!

/* MPresenter Class Initialization Code */
