/* 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 */
eventDescSet /* registered events */
readAhead /* true if read ahead activated */
reRead /* true if re-read on write */
windowIndex /* multiple window index */
addrUse /* auto, 16, or 32 */
/* the following contain default cmd settings */
defaultValues_checksum
defaultValues_compare
defaultValues_fill
defaultValues_move
defaultValues_search
defaultValues_test
workAddr1 workAddr2 /* address descriptors */
spaceSMM /* true if SMM, false if user */
pMode /* current pmode */
), 2, nil)!!

setClassVars(MPresenter, #())!!

now(class(MPresenter))!!

/* Perform the test.  If true, write the true value to the profile;
   otherwise, write the false value. */
Def saveIniTrueFalseValue(self, memPres, index, testValue,
   trueValue, falseValue, label | value)
{
  if (testValue)
    value := trueValue;
  else
    value := falseValue;
  endif;
  saveMemProfileEntry(self, memPres, index, label, value);
}!!

/* 9/12/1994 14:36 */
Def memIniLabel(self, index)
{
  ^("Memory" + asString(index));
}
!!

/* Save a profile entry. */
Def saveMemProfileEntry(self, memPres, index, key, value)
{
  if not(memPres) cor not(value)
    value := "";
  endif;
  saveProfileEntry(TheProfileInfoObj, memIniLabel(self, index),
     key, asString(value));
}!!

/* Save/clear all window parameters.  If memPres is nil, clear; otherwise,
   that's the handle of the window object to save for. */
Def saveWindowInfo(self, index, memPres |
   value offset status top dasm mem)
{
  if memPres
    top := topBrowser(memPres);
    dasm := dasmBrowse(memPres);
    mem := memBrowse(memPres);
  else
    /* when clearing, exit if the info doesn't exist for this window */
    if not(value := getIniValueStr(TheProfileInfoObj, memIniLabel(self, index),
      "DasmView"))
        ^nil;
    endif;
  endif;  /* otherwise, top/dasm/mem remain nil */
  
  /* dasm/memory */
  saveIniTrueFalseValue(self, memPres, index, (top=dasm), 1, 0, "DasmView");
  
  /* offset */
  if not(memPres)
    value := "";
  else
    /* copy address information from one browser to the other. */
    status :=copyAddress(AddressLibClass$Inst,
      baseAddressDescriptor(top),
      workAddressDescriptor(top));
    if status
      offset := getOffset(top);
    endif;
    if status cand offset
      status := addToAddress(AddressLibClass$Inst,
        workAddressDescriptor(top), offset);
    endif;
    if status cand offset
      value := getAddressText(AddressLibClass$Inst,
        workAddressDescriptor(top));
    else
      value := getAddressText(AddressLibClass$Inst,
        baseAddressDescriptor(top));
    endif;
    if not(value)
      value := 0;
    endif;
  endif;
  saveMemProfileEntry(self, memPres, index, "Offset", value);
   
  /* gather all of the memPres info in one spot to decrease code length */
  value := new(Array, 6);
  if memPres
    value[0] := memRadix(mem);
    value[1] := memByteGrouping(mem);
    value[2] := addrUse(memPres);
    value[3] := spaceSMM(memPres);
    value[4] := readAhead(memPres);
    value[5] := reRead(memPres);
  endif;
  
  /* memory radix */
  saveIniTrueFalseValue(self, memPres, index, (top=mem),
    value[0], 0, "MemRadix");
  
  /* byte grouping */
  saveIniTrueFalseValue(self, memPres, index, (top=mem),
    value[1], 0, "MemByteGrouping");
    
  /* address (16, 32, or auto) */
  saveMemProfileEntry(self, memPres, index, "AddrUse", value[2]);
  
  /* memory space */
  saveIniTrueFalseValue(self, memPres, index, value[3], 1, 0, "SpaceSMM");
    
  /* read-ahead */
  saveIniTrueFalseValue(self, memPres, index, value[4], 1, 0, "ReadAhead");
  
  /* re-read on write */
  saveIniTrueFalseValue(self, memPres, index, value[5], 1, 0, "RereadOnWrite");
}!!

/* clear out information for this window */
Def clearLayoutEntry(self, index)
{
  /* blank out all the fields. */
  saveWindowInfo(self, index, nil);
  /* note: label rather than index for ancestor call. */
  clearLayoutEntry(self:ancestor, memoryWindowLabel(MultMem, index));
}
!!

/* 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, index | tempServer tempPresenter)
{
  /* start presenter */
  tempPresenter := newStyle(MPresenter, nil, nil, "Memory",
                   sizeRect, nil, WS_OVERLAPPEDWINDOW);
  initializeShow(tempPresenter, showVal, index);
  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)!!

/* 3/23/1995 14:39 */
Def menuEditCompare(self | status)
{
  menuSelection(topBrowser);

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

/* 3/7/1995 14:43 */
/* handle edit checksum command */
Def menuEditChecksum(self | dlg fromaddr toaddr pattern tmpDesc)
{
  menuSelection(topBrowser);

  dlg := open(MemTestDialog);
  setValues(dlg, defaultValues_search);
  setHelpEntry(dlg, 6031);
  
  if (runModal(dlg, 402, ThePort) <> IDOK) /* DLG_MEM_CHECKSUM == 402 */
    ^self;
  endif;
  
  /* get value strings */
  defaultValues_fill := getValues(dlg);
  fromaddr := defaultValues_fill[0];
  toaddr := defaultValues_fill[1];

  /* make call, check status */
  showWaitCurs();

  /* set up from descriptor in workAddr1 */
  if not(processAddressString(self, fromaddr, workAddr1))
    showOldCurs();
    ^nil;
  endif;
  
  /* set up to descriptor in workAddr2 */
  if not(processAddressString(self, toaddr, workAddr2))
    showOldCurs();
    ^nil;
  endif;
 
  memChecksum(memServerInstance, workAddr1, workAddr2);

  showOldCurs();
  ^0
}!!

/* 3/13/1995 17:12 */
Def checkSegment(self, addrString)
{
  do(over(0,size(addrString)),
  {using(idx)
    if (addrString[idx] = 'p' cor addrString[idx] = ':')
      ^idx;
    endif;
  });
  ^nil;
}
!!

/* 3/7/1995 14:43 */
/* handle edit test command */
Def menuEditTest(self | dlg fromaddr toaddr pattern tmpDesc)
{
  menuSelection(topBrowser);

  dlg := open(MemTestDialog);
  setValues(dlg, defaultValues_search);
  setHelpEntry(dlg, 6030);
  
  if (runModal(dlg, 407, ThePort) <> IDOK) /* DLG_MEM_TEST == 407 */
    ^self;
  endif;
  
  /* get value strings */
  defaultValues_fill := getValues(dlg);
  fromaddr := defaultValues_fill[0];
  toaddr := defaultValues_fill[1];

  /* make call, check status */
  showWaitCurs();

  /* set up from descriptor in workAddr1 */
  if not(processAddressString(self, fromaddr, workAddr1))
    showOldCurs();
    ^nil;
  endif;
  
  /* set up to descriptor in workAddr2 */
  if not(processAddressString(self, toaddr, workAddr2))
    showOldCurs();
    ^nil;
  endif;
 
  memTest(memServerInstance, workAddr1, workAddr2);

  showOldCurs();
  ^0
}!!

/* check dword access */
Def markAccessDWord(self)
{
  uncheckAccessMenuItems(self);
  checkMenuItem(self, "&DWord Access");
}!!

/* check word access */
Def markAccessWord(self)
{
  uncheckAccessMenuItems(self);
  checkMenuItem(self, "&Word Access");
}!!

/* check byte access */
Def markAccessByte(self)
{
  uncheckAccessMenuItems(self);
  checkMenuItem(self, "&Byte Access");
}!!

/* check writeVerify */
Def markWVerifyOn(self)
{
  checkMenuItem(self, "Write &Verify");
}!!

/* uncheck writeVerify */
Def markWVerifyOff(self)
{
  unCheckMenuItem(self, "Write &Verify");
}!!

/* get the current pMode. */
Def getPmode(self | temp)
{  
  if not(temp := getPmode(AddressLibClass$Inst))
    ^nil;
  endif;
  ^temp[0];
}!!

/* Update memory display due to memory change */
Def checkAddrModeChange(self | temp)
{
  if not(temp := getPmode(self))
    ^nil;
  endif;
  
  if (temp <> pMode)
    updateAddrMode(memBrowse);
    updateAddrMode(dasmBrowse);
    doRefresh(dasmBrowse);
  endif;
  
  /* update pmode with new value */
  pMode := temp;
  
  ^0;
}
!!

/* get the current pMode. */
Def getPMode(self | temp)
{  
  if not(temp := getPmode(AddressLibClass$Inst))
    ^nil;
  endif;
  ^temp[0];
}!!

/* Given a memory attribute, return the default value if
   profile empty or missing, otherwise return value. */
Def getIniString(self, label, defaultValue | value)
{
  value := getIniValueStr(TheProfileInfoObj,
    memIniLabel(MPresenter, windowIndex), label);
  if not(value)
    ^defaultValue;
  endif;
  ^value;
}!!

/* Given a memory attribute, return the default value if
   profile empty or missing, otherwise return value. */
Def getIniNum(self, label, defaultValue | value)
{
  value := getIniValueNum(TheProfileInfoObj,
    memIniLabel(MPresenter, windowIndex), label);
  if not(value)
    ^defaultValue;
  endif;
  ^value;
}!!

/* Restore all previously-saved window parameters. */
Def restoreWindowInfo(self | value radix bytes offset status dasm addr)
{
  /* dasm/memory */
  if (dasm := getIniTrueFalseValue(self, "DasmView", nil, 0, nil))
    topBrowser := dasmBrowse;
  else
    topBrowser := memBrowse;
  endif;

  /* offset: convert text to addr desc, stuff into base, recalc addr parms. */  
  if (value := getIniString(self, "Offset", nil))
    if (addr := convertTextToAddress(AddressLibClass$Inst, value))
      /* insert address information. */
      if (copyAddress(AddressLibClass$Inst, addr,
        baseAddressDescriptor(topBrowser)))
          getSegmentInfo(topBrowser, baseAddressDescriptor(topBrowser), 0);
          gotoOffset(topBrowser, getOffset(AddressLibClass$Inst, addr));
      endif;
    endif;
  endif;
   
  /* memory radix and byte grouping */
  if dasm
    menuViewDisassembly(self);
  else
    if (TheProcFamily = PROC_FAMILY_X86)
      viewSizeMenuItemDisable(self);  /* initially disabled */
    endif;
    radix := getIniNum(self, "MemRadix", 16);
    bytes := getIniNum(self, "MemByteGrouping", 2);
    select
      case (bytes = 1) cand (radix = 16) is menuViewHexBytes(self);  endCase;
      case (bytes = 2) cand (radix = 16) is menuViewHexWords(self);  endCase;
      case (bytes = 4) cand (radix = 16) is menuViewHexDWords(self); endCase;
      case (bytes = 1) cand (radix = 10) is menuViewDecBytes(self);  endCase;
      case (bytes = 2) cand (radix = 10) is menuViewDecWords(self);  endCase;
      case (bytes = 4) cand (radix = 10) is menuViewDecDWords(self); endCase;
      default                               menuViewHexWords(self);
    endSelect;
  endif;    
    
  /* address (16, 32, or auto) */
  value := getIniNum(self, "AddrUse", ADDR_USE_AUTO);
  addrUse := nil;  /* force setting below */
  select
    case value = ADDR_USE_AUTO is menuViewAuto(self);    endCase;
    case value = ADDR_USE_16   is menuViewUse16(self);   endCase;
    case value = ADDR_USE_32   is menuViewUse32(self);   endCase;
    default                       menuViewAuto(self);
  endSelect;
  
  /* memory space */
  value := getIniTrueFalseValue(self, "spaceSMM", nil, 0, nil);
  if (value)
    spaceSMM := nil;  /* force change to SMM setting */
    menuViewSMM(self);
  else
    spaceSMM := 0;
    menuViewUser(self);  /* force change to SMM setting */
  endif;
  
  /* read-ahead */
  value := getIniTrueFalseValue(self, "readAhead", nil, 0, nil);
  readAhead := not(value);  /* force toggle */
  menuOptionsReadAhead(self);
  
  /* re-read on write */
  value := getIniTrueFalseValue(self, "RereadOnWrite", nil, 0, nil);
  reRead := not(value);  /* force toggle */
  menuOptionsReread(self);  

  show(topBrowser, 1);
  setFocus(topBrowser);
}!!

/* Given a memory attribute, return the default value if
   profile empty or missing, otherwise return value. */
Def getIniValue(self, label, defaultValue | value)
{
  value :=
    getIniValueNum(self, memIniLabel(MPresenter, windowIndex), label);
  if not(value)
    ^defaultValue;
  endif;
  ^value;
}!!

/* Perform the test.  If true, write the true value to the profile;
   otherwise, write the false value. */
Def saveIniTrueFalseValue(self, testValue, trueValue, falseValue, label |
   value)
{
  if (testValue)
    value := trueValue;
  else
    value := falseValue;
  endif;
  saveMemProfileEntry(self, label, value);
}!!

/* Given a memory attribute, return the default value if
   profile empty or missing, true value if 1, and false value
   if 0. */
Def getIniTrueFalseValue(self, label, defaultValue, trueValue, falseValue |
  value)
{
  value := getIniNum(self, label, defaultValue);
  select
    case not(value)  is ^defaultValue;    endCase;
    case (value = 1) is ^trueValue;       endCase;
    case (value = 0) is ^falseValue;      endCase;
    default             ^defaultValue;
  endSelect;
}!!

Def spaceSMM(self)
{
  ^spaceSMM;
}!!

Def addrUse(self)
{
  ^addrUse;
}!!

Def memBrowse(self)
{
  ^memBrowse;
}!!

Def dasmBrowse(self)
{
  ^dasmBrowse;
}!!

/* Save a profile entry. */
Def saveMemProfileEntry(self, key, value)
{
  saveProfileEntry(TheProfileInfoObj, "Memory" + asString(windowIndex),
     key, asString(value));
}!!

/* Save all window parameters.  Ignore label (no useful information).
   Use class method so that it can both save and clear with one method. */
Def saveWindowPos(self, label | value value2 offset status)
{
  saveWindowInfo(MPresenter, windowIndex, self);
  ^saveWindowPos(self:ancestor, label);
}!!

/* 8/24/1994 16:14 */
Def updateSpaceMenu(self, space)
{
  if (space = ADDR_SPACE_SMM)
    checkViewSMM(self);
  else
    checkViewUser(self);
  endif;
}
!!

/* uncheck SMM, check User */
Def checkViewUser(self)
{
  unCheckMenuItem(self, "S&MM");
  checkMenuItem(self, "&User");
}!!

/* uncheck User, check SMM */
Def checkViewSMM(self)
{
  unCheckMenuItem(self, "&User");
  checkMenuItem(self, "S&MM");
}!!

Def menuViewSMM(self)
{
  menuSelection(topBrowser);  
  
  if not(spaceSMM)
    checkViewSMM(self);
    spaceSMM := 0;
    updateAddressSpace(self);
  endif;
}!!

Def menuViewUser(self)
{
  menuSelection(topBrowser);  
  
  if spaceSMM
    checkViewUser(self);
    spaceSMM := nil;
    updateAddressSpace(self);
  endif;
}!!

Def updateAddressSpace(self | addrSpace offset)
{
  /* set up address descriptor */
  if not(copyAddress(AddressLibClass$Inst,
    baseAddressDescriptor(topBrowser),
    workAddressDescriptor(topBrowser)))
      ^nil;
  endif;
  
  /* get current offset */
  if not(offset := getOffset(topBrowser))
    ^nil;
  endif;
  
  /* set the address space */
  if spaceSMM
    addrSpace := ADDR_SPACE_SMM;
  else
    addrSpace := ADDR_SPACE_USER;
  endif;
  if not(setAddrSpace(AddressLibClass$Inst,
    workAddressDescriptor(topBrowser), addrSpace))
      ^nil;
  endif;
  
  /* stuff new info into top browser */
  if not(getSegmentInfo(topBrowser,
    workAddressDescriptor(topBrowser), nil))
      ^nil;
  endif;

  ^gotoOffset(topBrowser, offset);
}!!

/* 7/5/1994 17:34 */
Def topBrowser(self)
{
  ^topBrowser;
}
!!

Def debugDasmView(self)
{
  menuViewDisassembly(self);
}!!

Def debugHexView(self)
{
  menuViewHexBytes(self);
}!!

/* exchange address information; everything except offset. */
Def exchangeAddressInformation(self, fromBrowser, toBrowser)
{
  /* copy address information from one browser to the other. */
  if not(copyAddress(AddressLibClass$Inst,
    baseAddressDescriptor(fromBrowser),
    baseAddressDescriptor(toBrowser)))
      ^nil;
  endif;

  /* update address variables from new address information. */
  if not(getSegmentInfo(toBrowser,
    baseAddressDescriptor(toBrowser), 0))
      ^nil;
  endif;
}!!

Def updateDasmAddressSize(self)
{
  if not(setDasmAddressSize(DisAsmLibClass$Inst,
    dasmServerInstance, addrUse))
      ^nil;
  endif;
  /* use dasm server to update asm, too */
  if not(setDasmAddressSize(DisAsmLibClass$Inst,
    asmServerInstance, addrUse))
      ^nil;
  endif;
  doRefresh(dasmBrowse);
}!!

/* Perform common processing on an address string:
   - create address descriptor from string
   - copy base address into work address
   - copy offset into work address
   - reject address if segment not equal to base address
   > return nil if error, or side-effect work address if successful  */
Def processAddressString(self addressString workDescriptor | offset tmpDesc temp)
{
  if (firstAddr = 0)
    firstAddr := 1;
  else
    firstAddr := 0;
  endif;
  /* prepare first descriptor */
  if not(tmpDesc := convertTextToAddress(AddressLibClass$Inst, addressString))
    ^nil;
  endif;
   
  if (checkSegment(self, addressString))
    if not(copyAddress(AddressLibClass$Inst, tmpDesc, workDescriptor))
      destroyAddress(AddressLibClass$Inst, tmpDesc);
      ^nil;
    endif;
  else
    if (firstAddr <> 0)
      if not(copyAddress(AddressLibClass$Inst, baseAddressDescriptor(topBrowser),
        workDescriptor))
        destroyAddress(AddressLibClass$Inst, tmpDesc);
        ^nil;
      endif;
    else
      if not(copyAddress(AddressLibClass$Inst, firstAddrDesc, workDescriptor))
        destroyAddress(AddressLibClass$Inst, tmpDesc);
        ^nil;
      endif;
    endif;
  endif;
  
  /* get offset from addressString, set in work address descriptor */
  if not(offset := getOffset(AddressLibClass$Inst, tmpDesc))
    destroyAddress(AddressLibClass$Inst, tmpDesc);
    ^nil;
  endif;
  if not(setOffset(AddressLibClass$Inst, workDescriptor, offset))
    destroyAddress(AddressLibClass$Inst, tmpDesc);
    ^nil;
  endif;
  if (firstAddr <> 0)
    firstAddrDesc := workDescriptor;
  endif;
  
  ^0;
}
!!

Def viewSize(self)
{
  ^addrUse;
}!!

Def viewSizeMenuItemEnable(self)
{
  enableMenuItem(self, "Au&to");
  enableMenuItem(self, "Use&16");
  enableMenuItem(self, "Use&32");
}!!

Def viewSizeMenuItemDisable(self)
{
  grayMenuItem(self, "Au&to");
  grayMenuItem(self, "Use&16");
  grayMenuItem(self, "Use&32");
}!!

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

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

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

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

/* 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)
{
  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;
  
  /* get index */
  if windowIndex
     indexText := asString(windowIndex)
  else
     indexText := "";
  endif;
  
  /* return the ID string. */
  ^( "(" + indexText + "): " + typeText + sizeText + " 0x" + 
     asUnsignedStringRadix(asLong(getOffset(topBrowser)), 16));
}!!

/* 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 | status)
{
  menuSelection(topBrowser);

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


/* return value of reRead 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)
{
  markAccessByte(self);
  setAccessSize(self, 1);
  ^0;
}!!

/* set to dword access */
Def accessDWord(self)
{
  markAccessDWord(self);
  setAccessSize(self, 4);
  ^0;
}!!

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

/* set to word access */
Def accessWord(self)
{
  markAccessWord(self);
  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. */
  memServerInstance cand closeSession(memServerInstance);
  memServerInstance := nil;
  dasmServerInstance cand closeDasm(DisAsmLibClass$Inst, dasmServerInstance);
  dasmServerInstance := nil;
  asmServerInstance cand closeAsm(AsmLibClass$Inst, asmServerInstance);
  asmServerInstance := nil;
  
  /* close children */
  memBrowse cand close(memBrowse);
  dasmBrowse cand 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)
{
  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 */
  
  if not(dasmBrowse := newStyle(DasmBrowser, self, nil, "child", nil, 0,
    WS_CHILD bitOr WS_VSCROLL bitOr WS_HSCROLL))
      ^nil;
  endif;
  if not(initialize(dasmBrowse))
    ^nil;
  endif;

  /* memory browser is initially visible */
  if not(memBrowse := newStyle(MBrowser, self, nil, "child", nil, 0,
     WS_CHILD bitOr WS_VSCROLL bitOr WS_HSCROLL))
       ^nil;
  endif;
  if not(initialize(memBrowse))
    ^nil;
  endif;
  
  /* defer showing window until defaults restored */
  
  sizeKid(self);
}!!

/* initialize defaults for interactive commands */
Def initDefaults(self)
{
  /* nil start address, nil length, byte size / byte sum / carry ignore */
  defaultValues_checksum := #("", "", 0x49);
  /* nil values */
  defaultValues_compare := #("", "", "");
  defaultValues_test    := #("", "");
  defaultValues_fill    := #("", "", "");
  defaultValues_move    := #("", "", "");
  defaultValues_search  := #("", "", "");
}!!

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

  eventDescSet := new(Set, 1);

  /* dynamic to pick up current values */
  if (TheProcFamily = PROC_FAMILY_X86)
    events := tuple(EVENT_DASM_HALTED, EVENT_MEM_EDIT, EVENT_DASM_SYM_CHANGED,
      EVENT_CPU_EDIT, EVENT_BKPT_HALTED, EVENT_HL_BKPTEXEC_EMUL_STARTED,
      EVENT_HL_BKPTEXEC_EMUL_STEPPING);
  else
    events := tuple(EVENT_DASM_HALTED, EVENT_MEM_EDIT, EVENT_DASM_SYM_CHANGED);
  endif;
  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, index | temp)
{
  windowIndex := index;  /* window index needed for restore parms */
  show(self, showVal);  /* get up on screen fast */
    
  /* 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;
  
  /* create descriptor for work addresses */
  if not(workAddr1 := createAddress(AddressLibClass$Inst))
    ^nil;
  endif;
  if not(workAddr2 := createAddress(AddressLibClass$Inst))
    ^nil;
  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 */
  if not(initChildWind(self))
    ^nil;
  endif;
  
  okToReadMemory := 0;  /* all server init has been done */

  /* set initial values */
  restoreWindowInfo(self);
  setViewStatus(self);  /* update title bar */
  initDefaults(self);
  reflectWriteVerify(self);
  reflectAccessSize(self);
  
  /* save pMode */
  if (TheProcFamily = PROC_FAMILY_X86)
    if not(pMode := getPmode(self))
      ^nil;
    endif;
  endif;

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

/* Initialize the menus. */
Def initMenus(self | aMenu vCol procType)
{
  firstAddr := 0;
  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("&Test Memory...", #menuEditTest),
    tuple("C&hecksum Memory...", #menuEditChecksum),
    tuple("C&ompare Memory...", #menuEditCompare),
    tuple("&Copy Memory...", #menuEditCopy))));
  
  vCol := new(OrderedCollection, 4);
  add(vCol, tuple("Dis&assembly", #menuViewDisassembly));
  add(vCol, tuple(nil, nil));
  add(vCol, tuple("Hex &Bytes", #menuViewHexBytes));
  add(vCol, tuple("Hex &Words", #menuViewHexWords));
  add(vCol, tuple("Hex &DWords", #menuViewHexDWords));
  add(vCol, tuple("Decimal B&ytes", #menuViewDecBytes));
  add(vCol, tuple("Decimal W&ords", #menuViewDecWords));
  add(vCol, tuple("Decimal DWord&s", #menuViewDecDWords));

  /* Add operand/address size for Intel processors */
/**186**
  if (TheProcFamily = PROC_FAMILY_X86)
    add(vCol, tuple(nil, nil));
    add(vCol, tuple("Au&to", #menuViewAuto));
    add(vCol, tuple("Use&16", #menuViewUse16));
    add(vCol, tuple("Use&32", #menuViewUse32));
  endif;
**186**/

  /* Add space selection for Intel 386CX and 386EX processors */
  if not(procType := getSpecificProcessor(ProcLibClass$Inst))
    ^nil;
  endif;
  if procType = PROC_I80386CX_TB cor
     procType = PROC_I80386CX_SH cor
     procType = PROC_I80386EX_TB cor
     procType = PROC_I80386EX_SH
       add(vCol, tuple(nil, nil));
       add(vCol, tuple("&User", #menuViewUser));
       add(vCol, tuple("S&MM", #menuViewSMM));
  endif;

  add(vCol, tuple(nil, nil));
  add(vCol, tuple("Re&fresh Display", #menuViewRefresh));

  add(aMenu, tuple("&View", asArray(vCol)));


  add(aMenu, tuple("&Options", tuple(
    tuple("&Byte Access", #menuOptionsAccessByte),
    tuple("&Word Access", #menuOptionsAccessWord),
/**186**    tuple("&DWord Access", #menuOptionsAccessDWord),  **186**/
    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 tmpDesc)
{
  menuSelection(topBrowser);

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

  /* make call, check status */
  showWaitCurs();

  /* set up from descriptor in workAddr1 */
  if not(processAddressString(self, fromaddr, workAddr1))
    showOldCurs();
    ^nil;
  endif;
  
  /* set up to descriptor in workAddr2 */
  if not(processAddressString(self, toaddr, workAddr2))
    showOldCurs();
    ^nil;
  endif;
 
  memFill(memServerInstance, workAddr1, workAddr2, pattern);

  showOldCurs();
  ^0
}!!

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

/* 3/24/1992 11:10 */
Def menuEditSearch(self | dlg startaddr endaddr pattern found)
{
  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)
    showOldCurs();
    ^self;
  endif;
  
  defaultValues_search := getValues(dlg);
  startaddr := defaultValues_search[0];
  endaddr := defaultValues_search[1];
  pattern := defaultValues_search[2];

  /* set up start descriptor in workAddr1 */
  if not(processAddressString(self, startaddr, workAddr1))
    showOldCurs();
    ^nil;
  endif;
  
  /* set up end descriptor in workAddr2 */
  if not(processAddressString(self, endaddr, workAddr2))
    showOldCurs();
    ^nil;
  endif;
    
  /* call memSearch */
  showWaitCurs();
  found := memSearch(memServerInstance, workAddr1, workAddr2, 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;
      if (getAddressType(AddressLibClass$Inst, workAddr1) = 2)
        doGotoPhysical(topBrowser, found/16);
      endif;
      /*Fixed bug ID#234 by Eric 2/16/98*/
      if (getAddressType(AddressLibClass$Inst, workAddr1) = 0)
        doGotoVirtual(topBrowser, found/16, workAddr1);
      endif;
      /*eof Eric 2/16/98*/
      setOffset(topBrowser, found);
    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");
  doViewDecBytes(memBrowse);
  switchToMemory(self);
  setViewStatus(self);
}!!

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

Def menuViewDecWords(self)
{
  menuSelection(topBrowser);
  
  uncheckViewMenuItems(self);
  checkMenuItem(self, "Decimal W&ords");
  doViewDecWords(memBrowse);
  switchToMemory(self);
  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");
  doViewHexBytes(memBrowse);
  switchToMemory(self);
  setViewStatus(self);
}!!

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

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

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

/* reflect write verify setting */
Def reflectAccessSize(self | newAccessSize)
{
  if not(okToReadMemory)
    ^0;
  endif;
  
  newAccessSize := memGetAccessSize(memServerInstance);
  if newAccessSize
    select
      case newAccessSize = 1 is markAccessByte(self);  endCase
      case newAccessSize = 2 is markAccessWord(self);  endCase
      case newAccessSize = 4 is markAccessDWord(self); endCase
      default ^0;  /* avoid setting access size to strange value */
    endSelect;
    accessSize := newAccessSize;
  endif;
}!!

/* reflect write verify setting */
Def reflectWriteVerify(self | newWriteVerify)
{
  if not(okToReadMemory)
    ^0;
  endif;
  
  newWriteVerify := memGetVerifyWrites(memServerInstance);
  select
    case newWriteVerify = 0 is
      markWVerifyOff(self);
      setWriteVerify(self, nil);
    endCase
    case newWriteVerify = 1 is
      markWVerifyOn(self);
      setWriteVerify(self, 0);
    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)
{
  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;
  
  /* get index */
  if windowIndex
     indexText := asString(windowIndex)
  else
     indexText := "";
  endif;
  
  /* spit it all out */
  setText(self, "Memory (" + indexText + "): " + typeText +
     sizeText + " View");
  ^0;
}!!

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

/* set the writeVerify flag off */
Def setWVerifyOff(self)
{
  setWriteVerify(self, nil);
  markWVerifyOff(self);
  memSetVerifyWrites(memServerInstance, nil);
}!!

/* set the writeVerify flag on */
Def setWVerifyOn(self)
{
  setWriteVerify(self, 0);
  markWVerifyOn(self);
  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);
  
  if topBrowser
    setFocus(topBrowser);
  endif;
}!!

/* switch to showing dasm browser */
Def switchToDasm(self)
{
  if displayingMemory(self)
    deactivateWindow(memBrowse);
    show(memBrowse, 0);
    setFocus(dasmBrowse);
    
    topBrowser := dasmBrowse;

    /* the following code is commented out; memory and dasm displays
       will operate independently
       COMMENTED OUT...
    // move display of dasm browser to where mem browser was
    if not(exchangeAddressInformation(self, memBrowse, dasmBrowse))
      ^nil;
    endif;

    invalidateCache(dasmBrowse);  // force realignment of dasm display
    gotoOffset(dasmBrowse, getOffset(memBrowse));
       ...END OF COMMENTED OUT
    */
    
    show(dasmBrowse, 1);
    viewSizeMenuItemEnable(self);
  endif;
}!!

/* switch to showing memory browser */
Def switchToMemory(self)
{
  if displayingDasm(self)
    deactivateWindow(dasmBrowse);
    show(dasmBrowse, 0);
    setFocus(memBrowse);
    
    topBrowser := memBrowse;
    
    /* the following code is commented out; memory and dasm displays
       will operate independently
       COMMENTED OUT...
    // move display of mem browser to where dasm browser was
    if not(exchangeAddressInformation(self, dasmBrowse, memBrowse))
      ^nil;
    endif;
    
    gotoOffset(memBrowse, getOffset(dasmBrowse));
       ...END OF COMMENTED OUT
    */
    
    show(memBrowse, 1);
    viewSizeMenuItemDisable(self);
  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 cor
         event = EVENT_CPU_EDIT is
      memCacheInvalidate(MemServLibClass$Inst);
      doRefresh(self);
    endCase
    case event = EVENT_BKPT_HALTED cor
         event = EVENT_HL_BKPTEXEC_EMUL_STARTED cor
         event = EVENT_HL_BKPTEXEC_EMUL_STEPPING
      checkAddrModeChange(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 */
