/* CLASS:  Button or ToolBar style window:

   REQUIRE: PRJINFO.CLS, EVENTS.H
   This window consists of a menu, labels, and BitMapButtons.
 */!!

inherit(Window, #ButtonWindow, #(buttonActionDict  /* id->invocation-action */
buttonPressDict  /* id->bitmap-button */
tmWidth
tmHeight
groupWidthDict
inClose? /* closing app semaphore */
eventDescSet /* events descriptor set */
eventRespSet /* events Response set */
timerCallBackFun
afterFIrstCallback /* nil the 1st time */
TimerEventID
saveLayoutOnExit
initComplete  /* true when init complete */
closeWithoutConfirm
  /* true if closing immediately */
), 2, nil)!!

now(class(ButtonWindow))!!

/* Return the default window style. */
Def style(self)
{ ^(WS_SYSMENU bitOr WS_MINIMIZEBOX bitOr WS_OVERLAPPED);
}!!

/* PUBLIC - Define class */
Def wndClass(self)
{
  ^"ButtonBarPresenter";
}!!

/* Return the name of this class's Windows window icon
  either for registration or new window creation. */
Def wndIcon(self)
{ ^"ButtonB";
}!!

now(ButtonWindow)!!

/* 7/20/1992 14:29 - PRIVATE
  Save the StartPC and set the current PC position for the system.
*/
Def eventLoadStartPC(self | addrDesc, cloneDesc)
{
  /* Save the startup PC and set the current PC to it */
  if (addrDesc := getStartPCAddr(LoaderLibClass$Inst)) then
    setLoadStartPC(currentLoadFile(TheProjectInfoObj), addrDesc);
    /* Make a clone descriptor of the PC address descriptor */
    if (cloneDesc := duplicateAddress(AddressLibClass$Inst, addrDesc)) then
      /* Set the startup PC for current loadfile */
      setProgramCounter(CpuLibClass$Inst, cloneDesc);
    endif;
  endif;
  /* Event CPU_CHANGES notification will update the data display */
  ^GOOD;
}

!!

/* 10/7/1994 9:39 */
Def noPeri(self)
{
}
!!

/* 7/20/1994 9:16
   Indicate that PowerViews should close without the confirmation dialog. */
Def closeWithoutConfirm(self)
{
  closeWithoutConfirm := 0;
}
!!

/* menu action */
Def menuConfSym(self)
{
  if not(updateSymbolBases(SymbolLibClass$Inst))
    ^nil;
  endif;
}
!!

/* 7/20/1992 14:29 - PRIVATE
  Save the StartPC and set the current PC position for the system.
*/
Def getStartPC(self | addrDesc, cloneDesc)
{
  /* Save the startup PC and set the current PC to it */
  if (addrDesc := getStartPCAddr(LoaderLibClass$Inst)) then
    setLoadStartPC(currentLoadFile(TheProjectInfoObj), addrDesc);
    /* Make a clone descriptor of the PC address descriptor */
    if (cloneDesc := duplicateAddress(AddressLibClass$Inst, addrDesc)) then
      /* Set the startup PC for current loadfile */
      setProgramCounter(CpuLibClass$Inst, cloneDesc);
    endif;
  endif;
  /* Let Event Notification update the data display */
  ^GOOD;
}

!!

/* 12/3/1992 15:48 - PRIVATE
  Set stepMask mode on/off.
*/
Def menuStepMask(self)
{
  /* Set stepMask if stepMask is not ON, else clear it */
  if (getStepMask(HLBreakLibClass$Inst) <> BOOL_TRUE) then
      setStepMask(HLBreakLibClass$Inst, BOOL_TRUE);
      checkMenuItem(self, 513);
  else
    setStepMask(HLBreakLibClass$Inst, BOOL_FALSE);
    unCheckMenuItem(self, 513);
  endif;
}
!!

/* Got this from window.cls; modified to add shortcuts on Exit, About. */
Def addAbout(self | hMenu, appName)
{ hMenu := Call GetSystemMenu(hWnd, 0);
  appName := loadString(IDSNAME);
  Call ModifyMenu(hMenu, SC_CLOSE, MF_BYCOMMAND,
    SC_CLOSE, asciiz("E&xit MP/SLD..."));
}!!

/* menu action */
Def menuRestCS(self | inputstr)
{
   /* use COMMDLG FileOpen dialog */ 
   if (inputstr := getFileName(CLIULibraryClass$Inst, 
                               self,
                               HE_DLGF_RESTORECS,
                               IDS_CS_FILTER, 
                               nil /* no initial path */, 
                               FILE_OPEN)) then
      restoreCS(MapLibClass$Inst, inputstr);
   endif;
}
!!

/* menu action */
Def menuSaveCS(self | inputstr)
{
  /* use COMMDLG FileSave dialog */ 
  if (inputstr := getFileName(CLIULibraryClass$Inst, 
                              self,
                              HE_DLGF_SAVECS,
                              IDS_CS_FILTER, 
                              nil /* no initial path */, 
                              FILE_SAVE)) then
    saveCS(MapLibClass$Inst, inputstr);   
  endif;
}!!

/* menu action */
Def menuConfCS(self)
{
  configCS(MapLibClass$Inst);
}
!!

/* menu entry: reset the CPU. */
Def menuReset(self)
{
  /* 04/25/94 - Nghia
  ** Move Warning message to CpuLib 
  */
  if (CpuLibClass$Inst) then
    reset(CpuLibClass$Inst);
  endif;
}
!!

/* menu entry: reset the CPU only. */
Def menuResetOnly(self)
{
  /* 04/25/94 - Nghia
  ** Move Warning message to CpuLib 
  */
  if (CpuLibClass$Inst) then
    resetCpuOnly(CpuLibClass$Inst);
  endif;  
}
!!

/* menu entry: relink EP. <Judy> */
Def menuRelink(self)
{
  /* 04/25/94 - Nghia
  ** Move Warning message to MemServLib
  */
  if (MapLibClass$Inst) then
    RelinkEP(MapLibClass$Inst);
  endif;  
}
!!

/* menu selection Save Layout on Exit. */
Def menuLayoutExit(self)
{

/* returns 1 if TRUE, 0 if false */
  saveLayoutOnExit := getIniSaveLayoutOnExit(PreLauncher);

  if saveLayoutOnExit=1
    unCheckMenuItem(self, 520);
    putIniSaveLayoutOnExit(PreLauncher, 0);
  else
    checkMenuItem(self, 520);
    putIniSaveLayoutOnExit(PreLauncher, 1);
  endif;
}
!!

/* Save Layout Now. */
Def menuLayoutNow(self)
{
   saveAllPresenterPos(PreLauncher);
}
!!

/* process menu selection */
Def menuSymDasm(self | dasmSymbols)
{
  dasmSymbols := getDasmSymbol(DisAsmLibClass$Inst);
  if dasmSymbols = 0  /* off */
    setDasmSymbol(DisAsmLibClass$Inst,1);
    checkMenuItem(self, 507);
  else
    setDasmSymbol(DisAsmLibClass$Inst,0);
    unCheckMenuItem(self, 507);
  endif;
}
!!

/* process menu selection */
Def menuShowCycles(self | cycles lastError)
{
  /* invert show cycles (1 = on, 0 = off, nil = error) */
  cycles := showCycles?(memoryServer(MemServLibClass$Inst));

  if ((lastError := getLastSdError(SharedDataLibClass$Inst)) 
                                                    <> ER_SIM_UNREADABLE)
    displayError(ErrorTextLibClass$Inst, lastError, CHECK_MODE);
  endif;

  select
    case cycles = 1
    is
      showCyclesOff(memoryServer(MemServLibClass$Inst));
      unCheckMenuItem(self, 506);    
    endCase
    case cycles = 0
    is
      showCyclesOn(memoryServer(MemServLibClass$Inst));
      checkMenuItem(self, 506);
    endCase
    case not(cycles)
    is
      unCheckMenuItem(self, 506);
      grayMenuItem(self, 506);
    endCase
  endSelect;
  
}
!!

/* toolbar got focus */
Def gotFocus(self, hWndPrev)
{
  checkMenuItems(self);
  ^gotFocus(self:ancestor, hWndPrev);
}
!!

/* toolbar got focus */
Def checkMenuItems(self | cycles lastError)
{
  /* don't do it until initialization complete, DLLs hooked up */
  if not(initComplete)
    ^nil;
  endif;

  /* make sure run access properly checked */
  if (getRunAccess(HLBrkRootLibClass$Inst) = BOOL_TRUE)
    checkMenuItem(self, 505);
  else
    unCheckMenuItem(self, 505);
  endif;
  
  /* make sure stepMask properly checked */
  if (getStepMask(HLBreakLibClass$Inst) = BOOL_TRUE)
    checkMenuItem(self, 513);
  else
    unCheckMenuItem(self, 513);
  endif;

  /* make sure show cycles properly checked (1 = on, 0 = off, nil = error) */
  cycles := showCycles?(memoryServer(MemServLibClass$Inst));

  if (((lastError := getLastSdError(SharedDataLibClass$Inst)) <> GOOD) cand
    (lastError <> ER_SIM_UNREADABLE)) 
    if (lastError)
      displayError(ErrorTextLibClass$Inst, lastError, CHECK_MODE);
    endif;
  endif;

  select
    case cycles = 0 is 
      enableMenuItem(self, 506);
      unCheckMenuItem(self, 506);
    endCase
    case cycles = 1 is 
      enableMenuItem(self, 506);
      checkMenuItem(self, 506);
    endCase
    case not(cycles) is
      unCheckMenuItem(self, 506);
      grayMenuItem(self, 506);
    endCase
  endSelect;


  /* make sure dasm symbols properly checked (0 = off, 1 = on) */
  if getDasmSymbol(DisAsmLibClass$Inst) = 0
    unCheckMenuItem(self, 507);
  else
    checkMenuItem(self, 507);
  endif;

  /* make sure save layout now properly checked (0 = off, 1 = on) */
  saveLayoutOnExit := getIniSaveLayoutOnExit(PreLauncher);
  if saveLayoutOnExit=1
    checkMenuItem(self, 520);
  else
    unCheckMenuItem(self, 520);
  endif;
}
!!


/* 12/3/1992 15:46 - PRIVATE
  Init layout menu
*/
Def initMenuLayout(self | aMenu)
{
 /* layout menu */
 aMenu := newPopup(MenuItem, "&Layout");
 addItem(aMenu, new(MenuItem, "Save Layout On E&xit", 520, #menuLayoutExit));
 addItem(aMenu, new(MenuItem, "Save Layout &Now",     521, #menuLayoutNow));
 ^aMenu;

}
!!

/* 12/3/1992 15:46 - PRIVATE
  Init configure menu
*/
Def initMenuConfigure(self | aMenu procType procGroup menuCol i)
{
 /* get processor type */
 procType := getSpecificProcessor(ProcLibClass$Inst);
 
 /* set procGroup (1: moto/other, 2: 386dx/sx/cx, 4: 386ex) */
 select
   case procType = PROC_I80386CX_TB cor
        procType = PROC_I80386SX_TB cor
        procType = PROC_I80386DX_TB cor
        procType = PROC_I80386CX_SH cor
        procType = PROC_I80386SX_SH cor
        procType = PROC_I80386DX_SH is
           procGroup := 2;
   endCase
   case procType = PROC_I80386EX_TB cor
        procType = PROC_I80386EX_SH is
           procGroup := 4;
   endCase;
   default
      procGroup := 1;
  endSelect;
 
 /* prepare menu entries */
 menuCol := new(OrderedCollection, 3);
 /* first element of tuple is the OR of the procGroup bits representing the
    processors the menu entries should appear for, e.g. 7 is 1 | 2 | 4),
    1 is just moto. */
 add(menuCol, tuple(7, new(MenuItem, "&Map...",            504, #actionOverlay)));
 add(menuCol, tuple(7, new(MenuItem, "Run &Access",        505, #menuRunAccess)));
 add(menuCol, tuple(1, new(MenuItem, "&Show Cycles",       506, #menuShowCycles)));
 add(menuCol, tuple(7, new(MenuItem, "S&ymbolic Disassembly", 507, #menuSymDasm)));
/* add(menuCol,
   tuple(1, new(MenuItem, "Mas&k Interrupts For Step", 513, #menuStepMask))); */
 add(menuCol, tuple(7, nil));
/**186**
 add(menuCol, tuple(5, new(MenuItem, "Sa&ve Chip Selects...", 508, #menuSaveCS)));
 add(menuCol,
   tuple(5, new(MenuItem, "&Restore Chip Selects...", 509, #menuRestCS)));
 add(menuCol,
   tuple(1, new(MenuItem, "&Configure Chip Selects", 510, #menuConfCS)));
 add(menuCol, tuple(5, nil));
**186**/
 add(menuCol,
   tuple(6, new(MenuItem, "Confi&gure Symbols", 510, #menuConfSym)));
 add(menuCol, tuple(6, nil));
 add(menuCol, tuple(7, new(MenuItem, "R&eset",             511, #menuReset)));
 add(menuCol, tuple(7, new(MenuItem, "Reset CPU &Only",    512, #menuResetOnly)));
 add(menuCol, tuple(7, new(MenuItem, "ReLink",             514, #menuRelink)));
 
 /* place menu entries if they match the processor. */
 aMenu := newPopup(MenuItem, "&Configure");
 i := 0;
 loop
 while i < size(menuCol)
    if ((menuCol[i][0] bitAnd procGroup) > 0)
      addItem(aMenu, menuCol[i][1]);
    endif;
    i := i + 1;
 endLoop;
 ^aMenu;
}
!!

/* Redefine minimize and restore so they affect all windows in product.
   Model to follow is that of Visual Basic.
   All others messages are passed through to the default window proc. */
Def WM_SYSCOMMAND(self, wP, lP | wParam )
{
/* Four low-order bits of WM_SYSCOMMAND(wP) are used internally by Windows.
 * They need to be set to 0 before comparison.
 * see WM_SYSCOMMAND entry in SDK manual */
 wParam := wP bitAnd 0xFFF0;

 if (wParam = 0xF020)   /* SC_MINIMIZE: 0xF020 */
 then
    hideAllPresenters(PreLauncher);
 endif;

 if (wParam = 0xF120)   /* SC_RESTORE: 0xF120 */
 then
     showAllPresenters(PreLauncher);
 endif;

  ^asInt(execWindowProc(self, #WM_SYSCOMMAND, wP, lP));
}!!

/* 12/9/1992 11:17 - PRIVATE
  When user change RunAccess status from the CLI, event will generate to notify
  the presenter. Change the menu status accordingly.
*/
Def eventRunAccessOff(self)
{
  unCheckMenuItem(self, 504); /* 504 - menu command ID */
}
!!

/* 12/9/1992 11:17 - PRIVATE
  When user change RunAccess status from the CLI, event will generate to notify
  the presenter. Change the menu status accordingly.
*/
Def eventRunAccessOn(self)
{
  checkMenuItem(self, 504); /* 504 - menu command ID */
}
!!

/* 12/3/1992 15:48 - PRIVATE
  Set runAccess mode on/off.
*/
Def menuRunAccess(self)
{
  /* Set runAccess if RunAccess is not ON, else clear it */
  if (getRunAccess(HLBrkRootLibClass$Inst) <> BOOL_TRUE) then
      setRunAccess(HLBrkRootLibClass$Inst);
      checkMenuItem(self, 505);
  else
    clearRunAccess(HLBrkRootLibClass$Inst);
    unCheckMenuItem(self, 505);
  endif;
}
!!

/* BUTTON */
Def actionCliPresenter(self)
{
  launchCLIPresenter( PreLauncher, nil, SW_NORMAL ) ;
}
!!

/* BUTTON */
Def actionCPU(self)
{
  launchCPUPresenter( PreLauncher, nil, SW_NORMAL  ) ;
}
!!

/* BUTTON */
Def actionEmuGo(self)
{
  HLBreakLibClass$Inst cor requireWithPath( HLBreakLib, "bkptexec.dll" ) ;

  if HLBreakLibClass$Inst
  then
    showWaitCurs();
    go( HLBreakLibClass$Inst ) ;
    showOldCurs();
  else
    displayFormattedError(ErrorTextLibClass$Inst,
       ER_CANT_DO_COMMAND, FORCE_POPUP, asciiz("Go"), nil, nil);
  endif ;
}
!!

/* BUTTON */
Def actionEmuHalt(self)
{
  HLBreakLibClass$Inst cor requireWithPath( HLBreakLib, "bkptexec.dll" ) ;

  if HLBreakLibClass$Inst
  then
    showWaitCurs();
    if TheSourcePresenter then
      stopAnimating(TheSourcePresenter);
    endif;
    halt( HLBreakLibClass$Inst ) ;
    showOldCurs();
  else
    displayFormattedError(ErrorTextLibClass$Inst,
       ER_CANT_DO_COMMAND, FORCE_POPUP, asciiz("Halt"), nil, nil);
  endif ;
}
!!

/* BUTTON */
Def actionLoadCode(self)
{
  requireWithPath(ProcLib,     "proc.dll"      );
  requireWithPath(SymbolLib,   "symbl.dll"     );
  requireWithPath(AddressLib,  "addr.dll"      );
  requireWithPath(MemServLib,  "mem.dll"       );
  requireWithPath(CpuLib,      "cpu.dll"       );
  requireWithPath(LoaderLib,   "loader.dll"    );
  ^invokeLoader(LoaderLibClass$Inst, self);
}
!!

/* BUTTON */
Def actionMemory(self)
{
  launchMemoryPresenter( PreLauncher, nil, SW_NORMAL  ) ;
}
!!

/* BUTTON */
Def actionOverlay(self)
{
  if (getSystemType(ProcLibClass$Inst) = PROC_POWERSCOPE) then
    displayFormattedError(ErrorTextLibClass$Inst,
       ER_NOT_IN_POWERSCOPE, FORCE_POPUP, asciiz("Overlay memory"), nil, nil);
    ^nil;
  endif;
  launchOverlayPresenter( PreLauncher, self ) ;
}!!

/* BUTTON */
Def actionSourceCode(self)
{
  launchSourcePresenter( PreLauncher, nil, SW_NORMAL  ) ;
}
!!

/* BUTTON */
Def actionStack(self)
{
  launchStackPresenter( PreLauncher, nil, SW_NORMAL  ) ;
}
!!

/* BUTTON */
Def actionPeripheral(self)
{
  launchPeripheralPresenter(PreLauncher, nil, SW_NORMAL );
}
!!

/* BUTTON */
Def actionTracePresenter(self)
{
  if (getSystemType(ProcLibClass$Inst) = PROC_POWERSCOPE) then
    displayFormattedError(ErrorTextLibClass$Inst,
       ER_NOT_IN_POWERSCOPE, FORCE_POPUP, asciiz("Trace display"), nil, nil);
    ^nil;
  endif;
  launchTracePresenter( PreLauncher, nil, SW_NORMAL  ) ;
}
!!

/* BUTTON */
Def actionTraceStart(self)
{
  if (getSystemType(ProcLibClass$Inst) = PROC_POWERSCOPE) then
    displayFormattedError(ErrorTextLibClass$Inst,
       ER_NOT_IN_POWERSCOPE, FORCE_POPUP, asciiz("Trace"), nil, nil);
    ^nil;
  endif;
/*
  if (getSystemType(ProcLibClass$Inst) = PROC_MICEPACK) then
    ^nil;
  endif;
*/
  select
    case TraceLibClass$Inst
    is trcTracingSet(TraceLibClass$Inst,1);
    endCase

    default
      showWaitCurs();
      requireWithPath( EvttmpltLib, "evttmplt.dll"  );
      requireWithPath( EventLib,    "event.dll"     );
      requireWithPath( TriggerLib,  "trig.dll"      );
      requireWithPath( TraceLib,    "trace.dll"     );
      requireWithPath( DisAsmLib,   getDasmDLLName(PreLauncher));
      showOldCurs();
      if not(TraceLibClass$Inst)
      then ^nil ;
      else ^actionTraceStart( self ) ;
      endif ;
  endSelect;
}
!!

/* BUTTON */
Def actionTraceStop(self)
{
  if (getSystemType(ProcLibClass$Inst) = PROC_POWERSCOPE) then
    displayFormattedError(ErrorTextLibClass$Inst,
       ER_NOT_IN_POWERSCOPE, FORCE_POPUP, asciiz("Trace"), nil, nil);
    ^nil;
  endif;
/*
  if (getSystemType(ProcLibClass$Inst) = PROC_MICEPACK) then
    ^nil;
  endif;
*/
  select
    case TraceLibClass$Inst
    is trcTracingSet(TraceLibClass$Inst,0);
    endCase

    default
      showWaitCurs();
      requireWithPath( EvttmpltLib, "evttmplt.dll"  );
      requireWithPath( EventLib,    "event.dll"     );
      requireWithPath( TriggerLib,  "trig.dll"      );
      requireWithPath( TraceLib,    "trace.dll"     );
      requireWithPath( DisAsmLib,   getDasmDLLName(PreLauncher));
      showOldCurs();
      if not(TraceLibClass$Inst)
      then ^nil ;
      else ^actionTraceStart( self ) ;
      endif ;
  endSelect;
}
!!

/* BUTTON */
Def actionTriggerPresenter(self)
{
  if (getSystemType(ProcLibClass$Inst) = PROC_POWERSCOPE) then
    displayFormattedError(ErrorTextLibClass$Inst,
       ER_NOT_IN_POWERSCOPE, FORCE_POPUP, asciiz("Trigger definition"), nil, nil);
    ^nil;
  endif;
  launchTriggerPresenter( PreLauncher, nil, SW_NORMAL  ) ;
}
!!

/* PRIVATE -- as a button to dictionaries as specified.
 Nota Bene: selected bitmap is shared between buttons.
*/
Def addButton(self, buttonName, buttonID, selectedButtonID,
              actionSymbol, positionRect | aButton)
{
  aButton := new(BitMapButton, buttonID, self,
        buttonName, asString(buttonID), asString(selectedButtonID));
  add(buttonPressDict, buttonID, aButton);

  add(buttonActionDict, buttonID, actionSymbol);
  setCRect(aButton, positionRect);
  moveWindow(aButton);

  ^aButton
}
!!

/* termination processing */
Def close(self | temp)
{
  if inClose? then ^nil; endif ;

  inClose? := #true ;
  /* Destroy TheProjectInfoObj which contains address desc */
  if TheProjectInfoObj cand isDirty(TheProjectInfoObj) then
    saveProjectProfile(TheProjectInfoObj);
    if isLoaded(currentLoadFile(TheProjectInfoObj)) then
      /* Remove the old loadfile Info */
      deleteLoadFile(currentLoadFile(TheProjectInfoObj));
      deleteLoadFileAddr(currentLoadFile(TheProjectInfoObj));
    endif;
    TheProjectInfoObj := nil;
  endif;
  /* Close and destroy the CL server */
  if TheCursorLinkServer then
    close(TheCursorLinkServer);
    TheCursorLinkServer := nil;
  endif;

  if TimerEventID
  then
    Call KillTimer( hWnd(self), TimerEventID ) ;
    timerCallBackFun cand free( timerCallBackFun ) ;
  endif ;
  closeEvents(EvNoteLibClass$Inst, eventDescSet);
  eventRespSet := nil;
  if TheToolBarPresenter then
    saveWindowPos(TheToolBarPresenter, "TheToolBarPresenter");
    TheToolBarPresenter := nil
  else
    clearLayoutEntry(Window, "TheToolBarPresenter");
  endif;

  /*  removeWindowMenu( self ) -- really do need to delete this here */
  close(TheHelpObject, hWnd(self)); /* Close PwrViews WindowHelp */
  closeAllPresenters(PreLauncher);
  /* Force the Stack server to terminate itself */
  terminateServer(StackLibClass$Inst);
  /* Force the Loader Server to terminate itself */
  terminateServer(LoaderLibClass$Inst);
  /* All libraries are gone - do not access library */
  removeAllLibs(ProvidedLibs);

  close(self:ancestor);
}!!

/* WINDOWS */
Def command(self, wP, lP | msg)
{
  if (msg := at(buttonActionDict, wP))
  then
    perform( self, msg ) ;
    if ((wP = TB_TRACE_START_ID) cor (wP = TB_TRACE_STOP_ID) cor
        (wP = TB_EMU_GO_ID) cor (wP = TB_EMU_HALT_ID)) then
      Call SetFocus(getHWnd(self));
    endif;
  else if (msg := action(menu, wP))
    then
      perform( self, msg ) ;
    else
      if not( doAction(PreLauncher, wP) )
      then
        command( self:ancestor, wP, lP ) ;
      endif ;
    endif ;
  endif ;
}
!!

/* WINDOWS */
Def destroy(self)
{
  if not(inClose?)
  then
    inClose? := #true ;
    closeEvents(EvNoteLibClass$Inst, eventDescSet);
    eventRespSet := nil;
    if TheToolBarPresenter then TheToolBarPresenter := nil endif ;
    closeAllPresenters( PreLauncher ) ;
    removeAllLibs( ProvidedLibs ) ;
    nilifyPowerViews( PreLauncher ) ;  /* needed in development only */
  endif ;

  do(buttonPressDict,
    {using(aButton) destroy(aButton);}
  );

  destroy( self:ancestor ) ;
}
!!

/* PRIVATE -- use buttonActionDict to draw labels */
Def drawLabels(self, hDC | hPen, hPenOld)
{
  hPen := Call CreatePen( 0 /* SP_SOLID */,
                          2, /* width */
                          Call GetSysColor(COLOR_WINDOWTEXT) );
  hPenOld := Call SelectObject( hDC, hPen ) ;

  assocsDo(groupWidthDict, /* symbol->rect */
  {using(a | k v mid textStart)
    mid := ( width(v := value(a)) / 2 ) ;
    textStart := mid + left(v) - (((size(k := key(a)) +1) * tmWidth) / 2);
    Call TextOut( hDC, textStart,                             /* X */
                      (top(v) - (2*TB_TO_BORDER + tmHeight)), /* Y */
                      asciiz(asString(k)), size(k) ) ;
    Call Rectangle( hDC, left(v), top(v)-(TB_TO_BORDER+2),
                         right(v), top(v)-TB_TO_BORDER ) ;
  });

  Call SelectObject( hDC, hPenOld ) ;
  Call DeleteObject( hPen ) ;
}!!

/* PUBLIC EVENT */
Def eventCloseApplication(self)
{
  close( self ) ;
}!!

/* 7/20/1992 14:12 - PRIVATE
  OPERATION NOTES:
    The Event_Symbol_Deleted will destroy the old loadfile info, if any.
    This method respond to both Window or CLI loading event to retrieve the information.
*/
Def eventLoadingCompleted(self | loadInfo, newLoadFile, symInfo, string, i)
{
  /* NOTES: loadInfo = #(fileName, loadSpace, loadFlags) */
  if not(loadInfo := getLoadOptions(LoaderLibClass$Inst))
    ^nil;
  endif;
  /* Save loadfile info to the current loadfile */
  if isLoaded(currentLoadFile(TheProjectInfoObj)) then
    setLoadFileName(currentLoadFile(TheProjectInfoObj), loadInfo[0]);
    setLoadStatus(currentLoadFile(TheProjectInfoObj), #true);
  else
    setCurrentLoadFile(TheProjectInfoObj, 
      init(currentLoadFile(TheProjectInfoObj), loadInfo[0], #true));
  endif;
  /* Add the new last loadfile to the collections  - only update the Source
  ** Window if there is changes 
  */
  if setLastLoadFile(TheProjectInfoObj, loadInfo) cand TheSourcePresenter then
     /* Rebuild the last loadfiles list in File Menu */
     rebuildSourceLastLoadFileList(TheSourcePresenter, lastLoadFiles(TheProjectInfoObj));
  endif;
  /* Store project info */
  setLoadFlags(TheProjectInfoObj, loadInfo[2]); /* load flags encoded */

  /*find path and add to .INI Hera 12/18/96*/
  string := loadInfo[0];
  i := size(string)-1;
  loop
  while i > 0
    if (string[i] = '\')
    then
        string := subString(string,0,i+1);
        i := 0;
    else
        i := i - 1;
    endif;
  endLoop;
  addAliasPath(TheProjectInfoObj,string);

  /* Symbol loading */
  if (((loadInfo[2] bitAnd LOAD_SYMBOL) <> 0) cand
     ((symInfo := getSymbolsInfo(SymbolLibClass$Inst)) cand
     (symInfo[0] > 0) cand (symInfo[1] > 0))) then 
    /* NOTES: symInfo = #(numSymbols, numModules, numTypes) */ 
    setNumberOfModules(currentLoadFile(TheProjectInfoObj), symInfo[1]);  
    /* Source Window opened, update it current view and menu */
    if TheSourcePresenter then
      eventDasmSymChanged(TheSourcePresenter);
      validateSourceCommands(TheSourcePresenter);
    endif;  
  endif;
  setPrjDirty(TheProjectInfoObj, #true);
  beep();
  ^GOOD;
}

!!

/* 7/20/1992 14:33 - PRIVATE
  When symbol_deleted event occurred, remove all symbolic information of the
  Project Info's CurrentLoadFile.
*/
Def eventSymbolDeleted(self)
{
  if isLoaded(currentLoadFile(TheProjectInfoObj)) then
    /* Remove the old loadfile Info */
    deleteLoadFile(currentLoadFile(TheProjectInfoObj));
    /* Update the Source Presenter and its commands */
    if TheSourcePresenter then
      /* Reset the Source Presenter display */
      removeSourceSymbols(TheSourcePresenter);
    endif;
    ^GOOD;
  endif;
  ^nil;
}

!!

/* 7/20/1992 14:33 - PRIVATE
  When symbol_initLoad event occurred, remove all symbolic information of the
  Project Info's CurrentLoadFile.
*/
Def eventSymbolInitLoad(self)
{
  if isLoaded(currentLoadFile(TheProjectInfoObj)) then
    /* Remove the old loadfile Info */
    deleteLoadFile(currentLoadFile(TheProjectInfoObj));
    /* Update the Source Presenter and its commands */
    if TheSourcePresenter then
      removeSourceSymbols(TheSourcePresenter);
    endif;
    ^GOOD;
  endif;
  ^nil;
}

!!

/* PRIVATE -- N.B. initButtons() must be called before drawLabels() */
Def init(self)
{
  init(self:ancestor);
  initTextMetrics(self);
  initButtons(self,
     (2 * TB_TO_BORDER) + tmHeight
  );
  initMenuBar(self);
  addAbout(self);              /* About box & Exit app */
  TheProjectInfoObj := init(new(PrjInfo));
  TheCursorLinkServer := new(CLServer, 1);
  initComplete := 0;
  checkMenuItems(self);
}
!!

/* PRIVATE
   Set up BitMapButtons
*/
Def initButtons(self, topPos | leftPos tmpPos, mt2Flag)
{
  /* Create child controls for execution buttons */
  buttonPressDict  := new(Dictionary, 15) ;
  buttonActionDict := new(Dictionary, 15) ;
  groupWidthDict   := new(Dictionary, 5) ;
  leftPos := tmpPos := ( 0 + TB_TO_BORDER ) ;

  if (getTraceModule(ProcLibClass$Inst) <> nil) then
     mt2Flag:=1;
  else
     mt2Flag:=0;
  endif;
  if (mt2Flag=1) then
     tmpPos  := initSetupButtons( self, topPos, leftPos ) ;
  else
     tmpPos  := initSetupMButtons( self, topPos, leftPos ) ;
  endif;
  add( groupWidthDict, #Setup,
       rect(leftPos, topPos, tmpPos, topPos+TB_BUTTON_WIDTH) ) ;

  leftPos := tmpPos + TB_BETWEEN_GROUPS ;
  tmpPos  := initTargetButtons( self, topPos, leftPos ) ;
  add( groupWidthDict, #Target,
       rect(leftPos, topPos, tmpPos, topPos+TB_BUTTON_WIDTH) ) ;

  leftPos := tmpPos + TB_BETWEEN_GROUPS ;
  tmpPos  := initEmulationButtons( self, topPos, leftPos ) ;
  add( groupWidthDict, #Emulation,
       rect(leftPos, topPos, tmpPos, topPos+TB_BUTTON_WIDTH) ) ;

  if (mt2Flag=1) then
     leftPos := tmpPos + TB_BETWEEN_GROUPS ;
     tmpPos  := initTraceButtons( self, topPos, leftPos ) ;
     add( groupWidthDict, #Trace,
          rect(leftPos, topPos, tmpPos, topPos+TB_BUTTON_WIDTH) ) ;
  else
  endif;

  leftPos := tmpPos + TB_BETWEEN_GROUPS + TB_BETWEEN_GROUPS ;
  tmpPos  := initUtilityButtons( self, topPos, leftPos ) ;
  add( groupWidthDict, #Misc,
       rect(leftPos, topPos, tmpPos, topPos+TB_BUTTON_WIDTH) ) ;

  /* Fuzz is required because Windows does not give the number of
     pixels asked for.  Ask uSoft why...  8^( */
  leftPos := ( tmpPos + TB_TO_BORDER + TB_MS_FUZZ ) ;

  /* set up client rect for window (left, top, right, bottom) */
  /* put at 10@10, upper left corner */
  setCRect( self, rect(0, 0, leftPos, 
           (4*tmHeight) + (tmHeight/3) + TB_BUTTON_WIDTH + TB_TO_BORDER) ) ;
  moveWindow( self ) ;
}!!

Def initEmulationButtons(self, topPos, leftPos)
{
  addButton(self, "Go!",
                  TB_EMU_GO_ID, TB_EMU_GO_SELECTED_ID,
                  #actionEmuGo,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */

  leftPos := ( leftPos + TB_BUTTON_WIDTH + TB_BETWEEN_BUTTONS ) ;

  addButton(self, "Halt!",
                  TB_EMU_HALT_ID, TB_EMU_HALT_SELECTED_ID,
                  #actionEmuHalt,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */

  leftPos := ( leftPos + TB_BUTTON_WIDTH ) ;

  ^leftPos
}!!

/* 7/20/1992 14:06 - PRIVATE */
Def initEvents(self | events)
{
  /* REGISTER with Event Notification for
   *       Loading LoadFiles events,
   *       Whatever...
   */

  eventRespSet := new(Dictionary, 8);

  /* dynamic to pick up current values */
  events := tuple(
                  EVENT_BKROOT_RUNACCESS_ON,
                  EVENT_BKROOT_RUNACCESS_OFF,
                  EVENT_SYMBOL_INIT_LOAD,
                  EVENT_SYMBOL_DELETED,
                  EVENT_LDR_START_PC,
                  EVENT_LDR_LOAD_COMPLETE,
                  EVENT_CLOSE_APPLICATION
                 ) ;
  /* Setup events respond messages */
  add(eventRespSet, EVENT_BKROOT_RUNACCESS_ON   , #eventRunAccessOn);
  add(eventRespSet, EVENT_BKROOT_RUNACCESS_OFF  , #eventRunAccessOff);
  add(eventRespSet, EVENT_SYMBOL_INIT_LOAD      , #eventSymbolInitLoad);
  add(eventRespSet, EVENT_SYMBOL_DELETED        , #eventSymbolDeleted);
  add(eventRespSet, EVENT_LDR_START_PC          , #eventLoadStartPC);
  add(eventRespSet, EVENT_LDR_LOAD_COMPLETE     , #eventLoadingCompleted);
  add(eventRespSet, EVENT_CLOSE_APPLICATION     , #eventCloseApplication);

  /* register with Event Notification library */
  requireWithPath( EvNoteLib, "enlib.dll");
  ^(eventDescSet := registerEvents( EvNoteLibClass$Inst, hWnd(self), events));
}


!!

/* PRIVATE */
Def initMenuBar(self)
{
 menu := create(new(Menu), self);
 hMenu := handle(menu);

 addItem(menu, initMenuFile(self));
 addItem(menu, initMenuConfigure(self));
 addItem(menu, initMenuLayout(self));

 if (getSystemType(ProcLibClass$Inst) = PROC_POWERSCOPE)
   grayMenuItem(menu, 504);  /* map */
 endif;

 Call AppendMenu(hMenu,
                 MF_POPUP,
                 windowsMenu(PreLauncher),
                 asciiz("&Windows"));

 addItem(menu, initMenuHelp(self));
 /* Check for Options Menu */
 if (getRunAccess(HLBrkRootLibClass$Inst) = BOOL_TRUE) then
   checkMenuItem(self, 504);
 endif;

/* returns 1 if TRUE, 0 if false */
  saveLayoutOnExit := getIniSaveLayoutOnExit(PreLauncher);
  if saveLayoutOnExit=1
    unCheckMenuItem(self, 520);
  else
    putIniSaveLayoutOnExit(PreLauncher, 0);  /* create it */
    checkMenuItem(self, 520);
  endif;

 drawMenu(self);
}
!!

/* PRIVATE */
Def initMenuFile(self | aMenu)
{
 /* FILE menu */
 aMenu := newPopup(MenuItem, "&File");
 addItem(aMenu, new(MenuItem,
                    "E&xit MP/SLD...",
                     503,
                     #menuExitApplication));
 ^aMenu;
}
!!

/* BUTTON */
Def initMenuHelp(self | aMenu)
{
 /* HELP menu */
 aMenu := newPopup(MenuItem, "&Help");
 addItem(aMenu, new(MenuItem,
                    "Help &Index",
                     INDEX_HELP,
                     #menuHelpContents));
 addItem(aMenu, new(MenuItem,
                    "&Help With Help",
                     USING_HELP,
                     #menuHelpHelp));
 addItem(aMenu, nil);
 addItem(aMenu, new(MenuItem,
                    "About &MP/SLD...",
                     IDSABOUT,
                     #menuAbout));
 ^aMenu;

 ^aMenu
}
!!

Def initSetupButtons(self, topPos, leftPos)
{
  if (getSystemType(ProcLibClass$Inst) <> PROC_POWERSCOPE) then
    addButton(self, "Overlay",
                  TB_OVERLAY_ID, TB_OVERLAY_SELECTED_ID,
                  #actionOverlay,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */
  else
    addButton(self, "Overlay",
                  TB_NO_OVERLAY_ID, TB_NO_OVERLAY_ID,
                  #actionOverlay,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */
  endif;

  leftPos := ( leftPos + TB_BUTTON_WIDTH + TB_BETWEEN_BUTTONS ) ;

  addButton(self, "Load Code",
                  TB_LOAD_ID, TB_LOAD_SELECTED_ID,
                  #actionLoadCode,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */

  leftPos := ( leftPos + TB_BUTTON_WIDTH + TB_BETWEEN_BUTTONS ) ;

  addButton(self, "Setup Trigger",
                  TB_TRACE_SETUP_ID, TB_TRACE_SETUP_SELECTED_ID,
                  #actionTriggerPresenter,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */
  leftPos := ( leftPos + TB_BUTTON_WIDTH ) ;

  ^leftPos
}!!

Def initSetupMButtons(self, topPos, leftPos)
{
  if (getSystemType(ProcLibClass$Inst) <> PROC_POWERSCOPE) then
    addButton(self, "Overlay",
                  TB_OVERLAY_ID, TB_OVERLAY_SELECTED_ID,
                  #actionOverlay,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */
  else
    addButton(self, "Overlay",
                  TB_NO_OVERLAY_ID, TB_NO_OVERLAY_ID,
                  #actionOverlay,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */
  endif;

  leftPos := ( leftPos + TB_BUTTON_WIDTH + TB_BETWEEN_BUTTONS ) ;

  addButton(self, "Load Code",
                  TB_LOAD_ID, TB_LOAD_SELECTED_ID,
                  #actionLoadCode,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */

  leftPos := ( leftPos + TB_BUTTON_WIDTH ) ;

  ^leftPos
}!!

Def initTargetButtons(self, topPos, leftPos | procType)
{
  addButton(self, "Code", /* source code */
                  TB_SOURCE_ID, TB_SOURCE_SELECTED_ID,
                  #actionSourceCode,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */

  leftPos := ( leftPos + TB_BUTTON_WIDTH + TB_BETWEEN_BUTTONS ) ;

  addButton(self, "Stack",
                  TB_STACK_ID, TB_STACK_SELECTED_ID,
                  #actionStack,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */

  leftPos := ( leftPos + TB_BUTTON_WIDTH + TB_BETWEEN_BUTTONS ) ;

  addButton(self, "CPU",
                  TB_CPU_ID, TB_CPU_SELECTED_ID,
                  #actionCPU,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */

  leftPos := ( leftPos + TB_BUTTON_WIDTH + TB_BETWEEN_BUTTONS ) ;

  addButton(self, "Mem",
                  TB_MEMORY_ID, TB_MEMORY_SELECTED_ID,
                  #actionMemory,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */


  leftPos := ( leftPos + TB_BUTTON_WIDTH + TB_BETWEEN_BUTTONS ) ;
  
  /* get processor type */
  procType := getSpecificProcessor(ProcLibClass$Inst);
  
  select
    case procType = PROC_I80386CX_TB cor
         procType = PROC_I80386SX_TB cor
         procType = PROC_I80386CX_SH cor
         procType = PROC_I80386SX_SH is
           /* gray button out */
           addButton(self, "Periph",
                  TB_NO_PERIPHERAL_ID, TB_NO_PERIPHERAL_ID,
                  #noPeri,
                  rect( leftPos,
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) );
    endCase;
    default
      addButton(self, "Periph",
                  TB_PERIPHERAL_ID, TB_PERIPHERAL_SELECTED_ID,
                  #actionPeripheral,
                  rect( leftPos,
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) );
  endSelect;

  leftPos := ( leftPos + TB_BUTTON_WIDTH ) ;

  ^leftPos
}!!

/* PRIVATE
  Initialize text metrics data for this window.  Load the font data
  into textMetrics, set the text width and height instance variables.
*/
Def initTextMetrics(self | hdc, tm)
{ tm := new(Struct, 32);
  Call GetTextMetrics(hdc := getContext(self), tm);
  Call SelectObject(hdc, Call GetStockObject(SYSTEM_FIXED_FONT));
  tmWidth  := asInt(wordAt(tm, 10));
  tmHeight := asInt(wordAt(tm, 8)) + asInt(wordAt(tm, 0));
  Call SelectObject(hdc, Call GetStockObject(SYSTEM_FONT));
  releaseContext(self, hdc);
}!!

/* PRIVATE to PreLauncher
 -- initialize a timer and provide a callback function
*/
Def initTimer(self)
{
  if TimerEventID then ^TimerEventID; endif ; /* already called */

  /* create a window callback function to service timer ticks */
/*@@{
  timerCallBackFun :=
    create( Callback,
            tuple(0,0,0,1),
            {using(hWnd,winMsg,IDEvent,sysTime)
              if afterFIrstCallback
              then
                getBkptCause(HLBreakLibClass$Inst); /* force a comm read *@
                printNewLine("Timer Tick: " + asHex(sysTime)) ;
              else
                afterFIrstCallback := #true ;
                /*@@ startupScript( PreLauncher ) ; @@*@
                printNewLine("first timer tick " +asHex(sysTime));
              endif ;
              1;  /* return value -- of interest?? *@
            }
          ) ;
                     /* 1/2 second = 500 milliSeconds *@
   TimerEventID := Call SetTimer(0,0,1000,lock(timerCallBackFun)) ;
}@@*/

   TimerEventID := 0 ;

   if ((Call SetTimer(hWnd(self),TimerEventID,1000,0)) = 0)  /* error! */
   then TimerEventID := nil ;
   endif ;

   ^TimerEventID  /* N.B. Caller must check! */
}
!!

Def initTraceButtons(self, topPos, leftPos)
{
  if (getSystemType(ProcLibClass$Inst) = PROC_POWERPACK) then
    addButton(self, "Start!",
                  TB_TRACE_START_ID, TB_TRACE_START_SELECTED_ID,
                  #actionTraceStart,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */

    leftPos := ( leftPos + TB_BUTTON_WIDTH + TB_BETWEEN_BUTTONS ) ;

    addButton(self, "Stop!",
                  TB_TRACE_STOP_ID, TB_TRACE_STOP_SELECTED_ID,
                  #actionTraceStop,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */

    leftPos := ( leftPos + TB_BUTTON_WIDTH + TB_BETWEEN_BUTTONS ) ;

    addButton(self, "Show",
                  TB_TRACE_SHOW_ID, TB_TRACE_SHOW_SELECTED_ID,
                  #actionTracePresenter,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */

    leftPos := ( leftPos + TB_BUTTON_WIDTH ) ;
  else
    if (getSystemType(ProcLibClass$Inst) = PROC_POWERSCOPE) then
      addButton(self, "Show",
                  TB_NO_TRACE_SHOW_ID, TB_NO_TRACE_SHOW_ID,
                  #actionTracePresenter,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */
    else
      addButton(self, "Start!",
                  TB_TRACE_START_ID, TB_TRACE_START_SELECTED_ID,
                  #actionTraceStart,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */

      leftPos := ( leftPos + TB_BUTTON_WIDTH + TB_BETWEEN_BUTTONS ) ;

      addButton(self, "Stop!",
                  TB_TRACE_STOP_ID, TB_TRACE_STOP_SELECTED_ID,
                  #actionTraceStop,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */

      leftPos := ( leftPos + TB_BUTTON_WIDTH + TB_BETWEEN_BUTTONS ) ;

      addButton(self, "Show",
                  TB_TRACE_SHOW_ID, TB_TRACE_SHOW_SELECTED_ID,
                  #actionTracePresenter,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */
    endif;

    leftPos := ( leftPos + TB_BUTTON_WIDTH ) ;
  endif;

  ^leftPos
}!!

Def initUtilityButtons(self, topPos, leftPos)
{
  addButton(self, "Shell",
                  TB_SHELL_ID, TB_SHELL_SELECTED_ID,
                  #actionCliPresenter,
                  rect( leftPos, /* (left, top, right, bottom) */
                        topPos,
                        leftPos+TB_BUTTON_WIDTH,
                        topPos+TB_BUTTON_WIDTH) ); /* width=height */

  leftPos := ( leftPos + TB_BUTTON_WIDTH ) ;

  ^leftPos
}
!!

/* BUTTON */
Def menuAbout(self)
{
  if not(CLIULibraryClass$Inst) then
     ^nil;
  else
     showAboutBox(CLIULibraryClass$Inst);
  endif;
}
!!

/* BUTTON */
Def menuExitApplication(self)
{
  if shouldClose( self )
  then
    close( self ) ;
  endif ;
}
!!

/* BUTTON */
Def menuHelpContents(self)
{
  contents( TheHelpObject, hWnd(self) ) ;
}
!!

/* BUTTON */
Def menuHelpHelp(self)
{
  help( TheHelpObject, hWnd(self) ) ;
}
!!

/* BUTTON */
Def menuRestoreAll(self)
{
}
!!

/* BUTTON */
Def menuSaveAll(self)
{
}
!!

/* WINDOWS (PUBLIC) */
Def paint(self, hDC)
{
  initTextColors( self, hDC ) ;
  drawLabels( self, hDC ) ;
}!!

Def shouldClose(self | setClose?)
{
  if inClose?
  then
    ^#true
  else
    /* check windows 1st */
    do(presenterNames(PreLauncher),
    {using(key | win)
      if (win := at(Actor, key))
        if (win <> self) cand not(shouldClose(win))
          ^nil;
        endif;
      endif;
    });
    if closeWithoutConfirm
      setClose? := 0;
    else
      setClose? :=
        (errMessageBox(ErrorTextLibClass$Inst, "MP/SLD",
              "Exit MP/SLD?",
              MB_YESNO bitOr MB_ICONQUESTION bitOr 0x2000,
              HE_DLGM_BUTTONWI_1) = IDYES);
     endif;

     if setClose?
       setOkToClose(TheApp:late);
     endif;


     ^setClose?
  endif;
}!!

/* WINDOWS */
Def WM_CLOSE(self, wP, lP)
{
  if shouldClose( self )
  then close( self ) ;
  endif ;
}!!

/* WINDOWS -- propagate to ownerdraw buttons */
Def WM_DRAWITEM(self, wP, lP)
{
  WM_DRAWITEM(at(buttonPressDict,wP), wP, lP)
}
!!

/* 7/20/1992 14:50 - WINDOWS (Tbird's message)
  Sent by event manager (evNoteLib)
*/
Def WM_EVENT(self, ignored, event)
{
  if event cand at(eventRespSet, event) then
    perform(self, at(eventRespSet, event));
  else
    /* Impossible case, unless Windows failed to delivery private messages */
    displayFormattedError(ErrorTextLibClass$Inst,
       ER_UNKNOWN_EVENT, FORCE_POPUP, asciiz(asHex(event)), nil, nil);
  endif;
  ^0
}
!!

/* WINDOWS */
Def WM_INITMENU(self, wp, lp)
{
  ^WM_INITMENU( PreLauncher, wp, lp ) ;
}
!!

/* WINDOWS -- keep constant size -- see also WM_SIZE */
Def WM_MOVE(self, wP, lP | oldRect fixup)
{ setLocRect( self ) ;

  if  (Call IsIconic(hWnd(self)) <> 0) /* iconized? */
  then ^self
  endif ;

  oldRect := cRect( self ) ;
  cRect := windowRect( self ) ;

  if not( cRect and oldRect )
  then ^self
  endif ;

  if (width(oldRect) <> width(cRect))
  then
    fixup := #true ;
    setRight( cRect, left(cRect) + width(oldRect) ) ;
  endif ;
  if (height(oldRect) <> height(cRect))
  then
    fixup := #true ;
    setBottom( cRect, top(cRect) + height(oldRect) ) ;
  endif ;

  if fixup
  then moveWindow( self ) ;
  endif ;

}
!!

/* WINDOWS
  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)
{ hdc := Call BeginPaint(getHWnd(self), paintStruct);
  Call SelectObject(hdc, Call GetStockObject(SYSTEM_FIXED_FONT));
  paint(self, hdc);
  Call SelectObject(hdc, Call GetStockObject(SYSTEM_FONT));
  Call EndPaint(getHWnd(self), paintStruct);
  ^0;
}!!

/* End MS-Windows message.  If self is the main
  window, then go through Actor shutdown so that users
  can save their work.  They can cancel ending the
  session, according to the return value of the
  shouldClose method.  Returning a 0 cancels.  Every
  non-main window returns 1. */
Def WM_QUERYENDSESSION(self, wP, lP)
{ if shouldClose(self)
  then
    setOkToClose( TheApp:late ) ;
    ^1 /* OK */
  else
    ^0 /* not OK */
  endif ;
}!!

/* WINDOWS -- keep constant size based on cRect -- see also WM_MOVE */
Def WM_SIZE(self, wP, lP)
{
  if cRect cand (Call IsIconic(hWnd(self)) = 0)
  then
    moveWindow(self);
    invalidate(self);
  endif ;
}!!

/* WINDOWS
  timer event
*/
Def WM_TIMER(self, wP, lP)
{
   if afterFIrstCallback
     hitSharedDataServer(SharedDataLibClass$Inst); /* force a comm read */
   else
     afterFIrstCallback := #true;
     startupScript(PreLauncher);
     openAllSavedWindows( PreLauncher );
  endif;

  ^0
}
!!
