// *********************************************************************
//    Copyright (c) 1989-2002  Warren Furlow
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
// *********************************************************************

// *********************************************************************
// MainWindow.cpp : implementation file
// *********************************************************************

// 23 03 05 Martin Lafferty
// Updated to support HP41-shaped window and dragging without title bar.
//
// in order to ensure that 'GetClientRect' and 'ClientToScreen' functions return
// the correct values during the call to 'SetKeyboard' it is necessary to call
// UpdateMenus before SetKeyboard, rather than afterwards. This means that the
// value of pHP41->GetKeyboard() may not return the correct value during  a
// call to SetMenuChecks. Hence I have added an (optional) parameter to UpdateMenus
// to allow the new Keyboard style to be passed in. The default value is eKeyboardNone
// in which case pHP41->GetKeyboard will be called by SetMenuChecks.

#include"StdAfx.h"
#include"V41.h"

/**************************************/
BEGIN_MESSAGE_MAP( CMainWindow, CFrameWnd )
  //{{AFX_MSG_MAP( CMainWindow )
  ON_COMMAND(ID_FILE_NEW, OnFileNew)
  ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
  ON_COMMAND(ID_FILE_EDIT, OnFileEdit)
  ON_COMMAND(ID_FILE_EXIT, OnFileExit)
  ON_COMMAND(ID_FILE_SAVE, OnFileSave)
  ON_COMMAND(ID_FILE_SAVEAS, OnFileSaveas)
  ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
  ON_WM_CREATE()
  ON_WM_DESTROY()
  ON_WM_SYSCOMMAND()
  ON_WM_ENDSESSION()
  ON_WM_PAINT()
  ON_WM_COPYDATA()
  ON_WM_KEYDOWN()
  ON_WM_KEYUP()
  ON_WM_LBUTTONDOWN()
  ON_WM_LBUTTONUP()
  ON_WM_CONTEXTMENU()
  ON_WM_MOUSEMOVE()
  ON_WM_NCMOUSEMOVE()
  ON_WM_NCHITTEST()
  ON_COMMAND(ID_OPTIONS_TINY, OnOptionsTiny)
  ON_COMMAND(ID_OPTIONS_SMALL, OnOptionsSmall)
  ON_COMMAND(ID_OPTIONS_MEDIUM, OnOptionsMedium)
  ON_COMMAND(ID_OPTIONS_LARGE, OnOptionsLarge)
  ON_COMMAND(ID_OPTIONS_XLARGE, OnOptionsXLarge)
  ON_COMMAND(ID_BACK, OnBack)
  ON_COMMAND(ID_OPTIONS_SETTINGS, OnOptionsSettings)
  ON_COMMAND(ID_HELP_USAGE, OnHelpUsage)
  ON_COMMAND(ID_HELP_SOLINDEX, OnHelpIndex)
  ON_COMMAND(ID_FILE_PUT, OnFilePut)
  ON_COMMAND(ID_FILE_GET, OnFileGet)
  ON_COMMAND(ID_FILE_COPY, OnFileCopy)
  ON_WM_QUERYNEWPALETTE()
  ON_WM_PALETTECHANGED()
  ON_COMMAND(ID_OPTIONS_JUMPTOFOREGROUND, OnOptionsJumpToForeground)
  ON_COMMAND(ID_OPTIONS_ALWAYSONTOP, OnOptionsAlwaysontop)
  ON_COMMAND(ID_OPTIONS_SHOWTITLE, OnOptionsShowTitle)
  ON_COMMAND(ID_OPTIONS_SHOWMENU, OnOptionsShowMenu)
  ON_COMMAND(ID_OPTIONS_RESET, OnOptionsReset)
  ON_COMMAND(ID_OPTIONS_TRACE, OnMcodeTrace)
  ON_COMMAND(ID_OPTIONS_CONSOLE, OnMcodeConsole)
  ON_COMMAND(ID_OPTIONS_RAMVIEW, OnOptionsRamView)
  ON_COMMAND(ID_OPTIONS_BREAKPOINTS, OnOptionsBreakpoints)
  ON_COMMAND(ID_OPTIONS_TRACE_SETTINGS, OnOptionsTraceSettings)
  ON_COMMAND(ID_FILE_PAGEVIEW, OnFilePageview)
  //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/**************************************/
CMainWindow::CMainWindow()
  : strLastFolderLod("")
  , strLastFolderRaw("")
  , bSessionNameValid(true)
  {
  LoadFrame(IDR_MAINFRAME,WS_CLIPCHILDREN);

  #if _MSC_VER >= 1900 // VS2015 and later
    m_bIsWindows8orLater=IsWindows8OrGreater();
  #else
    OSVERSIONINFO osvi;
    osvi.dwOSVersionInfoSize=sizeof(osvi);
    GetVersionEx(&osvi);
    m_bIsWindows8orLater =
      ((osvi.dwMajorVersion > 6) ||
      ((osvi.dwMajorVersion == 6) && (osvi.dwMinorVersion >= 2)));
  #endif
  }

/**************************************/
void CMainWindow::OnFileNew()
  {
  if (IDCANCEL!=FileSave(false))
    {
    pHP41->nBreakPts=0;             // cleanup breakpoint list
    pHP41->m_fUdpCfgLoaded=FALSE;   // $UDP configuration data not loaded
    dlgMcode->Invalidate();         // update Mcode Console
    dlgBreakPoints->LoadListBox();  // update breakpoint list

    pHP41->Halt();
    pHP41->StopHpil();
    WaveSound.Close();

    // question to remove the plug-in modules
    if (AfxMessageBox("Remove all plug-in modules?",MB_YESNO|MB_DEFBUTTON2|MB_ICONQUESTION)==IDYES)
      {
      // unload all modules except OS
      POSITION pos=pHP41->ModuleList.GetHeadPosition();
      while (pos!=NULL)
        {
        ModuleHeader *pModule=(ModuleHeader *)pHP41->ModuleList.GetAt(pos);
        pHP41->ModuleList.GetNext(pos);
        if (pModule->Category != CATEGORY_OS)
          {
          // unload the module
          pHP41->UnloadMOD(pModule);
          }
        }
      }

    pHP41->HardwareReset();
    pHP41->StartHpil();
    pHP41->Run();
    pHP41->SetPC(0x0232);           // cold start initialization
    pHP41->Wakeup();
    bSessionNameValid = false;
    lstrcpy(theApp.szSessionName,theApp.szUntitledName);
    SetTitle();
    InvalidateRect(pHP41->pRectLCD,FALSE);
    InvalidateRect(pHP41->pRectAnnun,FALSE);
    }
  }

/**************************************/
void CMainWindow::OnFileEdit()
  {
  CEditConfig EditConfigDlg;
  EditConfigDlg.pHP41=pHP41;
  ModuleHeader *pModule;     // pointer to system module list
  ModuleHeader *pMod;        // pointer to dialog module list

  // load up the dialog mod list with current config
  POSITION pos=pHP41->ModuleList.GetHeadPosition();
  while (pos!=NULL)
    {
    pModule=(ModuleHeader*)pHP41->ModuleList.GetAt(pos);
    pMod=new ModuleHeader;
    lstrcpy(pMod->szFullFileName,pModule->szFullFileName);
    lstrcpy(pMod->szTitle,pModule->szTitle);
    lstrcpy(pMod->szVersion,pModule->szVersion);
    lstrcpy(pMod->szPartNumber,pModule->szPartNumber);
    lstrcpy(pMod->szAuthor,pModule->szAuthor);
    pMod->Category=pModule->Category;
    EditConfigDlg.ModList.AddTail(pMod);
    pHP41->ModuleList.GetNext(pos);
    }
  if (IDOK==EditConfigDlg.DoModal())
    {
    pHP41->Halt();
    pHP41->StopHpil();
    // free all modules and rom pages
    while (!pHP41->ModuleList.IsEmpty())
      {
      pModule=(ModuleHeader *)pHP41->ModuleList.GetHead();
      if (pModule->AppAutoUpdate && !pModule->Original)
        pHP41->SaveMOD(pModule,pModule->szFullFileName);      // save it
      pHP41->UnloadMOD(pModule);
      }
    // reload modules
    pos=EditConfigDlg.ModList.GetHeadPosition();
    while (pos!=NULL)
      {
      pMod=(ModuleHeader*)EditConfigDlg.ModList.GetAt(pos);
      int nRes=pHP41->LoadMOD(pModule,pMod->szFullFileName);
      if (nRes>=1 && nRes<=4)
        {
        LPCTSTR lpszMsg[] =
          {
          "File not found: %s",
          "Error reading file: %s",
          "Invalid file format: %s",
          "Load conflict or no space: %s"
          };

        CString sMsg;
        sMsg.Format(lpszMsg[nRes-1],pMod->szFullFileName);
        AfxMessageBox(sMsg);
        }
      EditConfigDlg.ModList.GetNext(pos);
      }
    dlgRamView->UpdateRamView(); // update RAM view
    pHP41->ReconfigHepax();      // reconfigure HEPAX ROM to free module page
    pHP41->ReconfigRamboxBS();   // reconfigure W&W RAMBOX II bank switcher mapping
    pHP41->SetPC(pHP41->PC_REG);
    pHP41->StartHpil();
    pHP41->Run();
    }
  // clear dialog info list
  while (!EditConfigDlg.ModList.IsEmpty())
    {
    pMod=(ModuleHeader*)EditConfigDlg.ModList.RemoveTail();
    delete pMod;
    }
  }

/**************************************/
void CMainWindow::OnFilePageview()
  {
  CPageView PageViewDlg;
  PageViewDlg.pHP41=pHP41;
  PageViewDlg.DoModal();
  }

/**************************************/
void CMainWindow::OnFileOpen()
  {
  if (IDCANCEL!=FileSave(false))
    {
    CFileDialog dlgOpen(TRUE,"*.lod",NULL,OFN_HIDEREADONLY,"Configuration Load Files (*.lod)|*.lod||");
    dlgOpen.m_ofn.lpstrInitialDir=strLastFolderLod;
    if (dlgOpen.DoModal()!=IDOK)
      return;

    strLastFolderLod=getPath(dlgOpen.m_ofn.lpstrFile);
    FileOpen(dlgOpen.m_ofn.lpstrFile);
    }
  }

/**************************************/
bool CMainWindow::FileOpen(LPCTSTR lpszFileName)
  {
  pHP41->Halt();
  pHP41->StopHpil();
  WaveSound.Close();
  int nErrors=pHP41->LoadConfig(lpszFileName);
  if (nErrors > 1)                  // multiple errors
    {
    CString sMsg;
    sMsg.Format("%d error(s) loading configuration: %s",nErrors,lpszFileName);
    AfxMessageBox(sMsg);
    }
  if (nErrors >= 0)                 // no critical errors
    {
    lstrcpy(theApp.szSessionName,lpszFileName);
    AfxGetApp()->AddToRecentFileList(theApp.szSessionName);
    dlgMcode->Invalidate();         // update Mcode Console
    dlgRamView->Clear();            // delete content
    dlgRamView->UpdateRamView();    // update RAM view
    dlgBreakPoints->LoadListBox();  // update breakpoint list
    }
  pHP41->StartHpil();
  pHP41->Run();
  SetTitle();
  return nErrors == 0;
  }

/**************************************/
void CMainWindow::OnFileExit()
  {
  if (0==strcmpi(theApp.szSessionName,theApp.szUntitledName))  // if session is untitled
    OnFileSaveas();

  DestroyWindow();
  }

/**************************************/
void CMainWindow::OnFileSave()
  {
  FileSave(true);
  }

/**************************************/
void CMainWindow::OnFileSaveas()
  {
  CFileDialog dlgSaveAs(FALSE,"*.lod",NULL,OFN_CREATEPROMPT|OFN_OVERWRITEPROMPT,"Configuration Load Files (*.lod)|*.lod||");
  dlgSaveAs.m_ofn.lpstrInitialDir=strLastFolderLod;
  if (dlgSaveAs.DoModal()==IDOK)
    {
    bSessionNameValid = true;
    strLastFolderLod=getPath(dlgSaveAs.m_ofn.lpstrFile);
    lstrcpy(theApp.szSessionName,dlgSaveAs.m_ofn.lpstrFile);

    pHP41->Halt();
    pHP41->SaveConfig(theApp.szSessionName);
    pHP41->Run();
    SetTitle();
    }
  }

/**************************************/
// writes out current .LOD file
// Return code :
// IDYES    File successfuly saved
// IDNO     File not saved
// IDCANCEL Cancel command
/**************************************/
UINT CMainWindow::FileSave(
  bool bAutoSave)
  {
  int nErr;
  UINT uReply;

  if (bAutoSave)
    uReply = IDYES;
  else
    uReply = AfxMessageBox(_T("Do you want to save changes?"),MB_YESNOCANCEL|MB_ICONEXCLAMATION|MB_SETFOREGROUND);

  if (uReply != IDYES) return (uReply);

  if (0==strcmpi(theApp.szSessionName,theApp.szUntitledName))  // if session is untitled
    {
    OnFileSaveas();
    nErr = bSessionNameValid ? 0 : 1;
    }
  else
    {
    pHP41->Halt();
    nErr = pHP41->SaveConfig(theApp.szSessionName);
    pHP41->Run();
    }
  return (nErr == 0 ? IDYES : IDNO);
  }

/**************************************/
void CMainWindow::OnFileGet()
  {
  CFileDialog dlgOpen(TRUE,"*.raw",NULL,OFN_HIDEREADONLY,"User Code Files (*.raw)|*.raw||");
  dlgOpen.m_ofn.lpstrInitialDir=strLastFolderRaw;

  if (dlgOpen.DoModal()!=IDOK)
    return;

  pHP41->Halt();
  char szError[64]="";
  strLastFolderRaw=getPath(dlgOpen.m_ofn.lpstrFile);
  if (!pHP41->GetUserCode(dlgOpen.m_ofn.lpstrFile,szError))
    {
    CString sMsg;
    sMsg.Format("Error: %s\nFile: %s",szError,dlgOpen.m_ofn.lpstrFile);
    AfxMessageBox(sMsg);
    }
  pHP41->fRamWritten=true;
  pHP41->Run();
  }

/**************************************/
void CMainWindow::OnFilePut()
  {
  flag fFirst=TRUE;
  CPtrArray CatArray;       // a list of Cat1Label structs
  Cat1Label *pLbl;          // catalog info

  pHP41->Halt();            // Catalog1() alreay reading calculator RAM

  pLbl=new Cat1Label;
  while (pHP41->Catalog1(fFirst,pLbl))
    {
    CatArray.Add(pLbl);
    pLbl=new Cat1Label;
    }
  delete pLbl;              // deleting last unused label

  CSelectDlg SelectDlg;
  SelectDlg.pCatArray=&CatArray;
  if (SelectDlg.DoModal()==IDOK)
    {
    CFileDialog dlgSaveAs(FALSE,"*.raw",NULL,OFN_CREATEPROMPT|OFN_OVERWRITEPROMPT,"User Code Files (*.raw)|*.raw||");
    dlgSaveAs.m_ofn.lpstrInitialDir=strLastFolderRaw;
    if (dlgSaveAs.DoModal()==IDOK)
      {
      char szError[50]="";

      std::vector<Cat1Label *> vpLbl;
      for (unsigned i=0;i<SelectDlg.vnProgramSel.size();++i)
        {
        vpLbl.push_back((Cat1Label*)CatArray[CatArray.GetSize()-1-SelectDlg.vnProgramSel[i]]);
        }

      strLastFolderRaw=getPath(dlgSaveAs.m_ofn.lpstrFile);
      if (!pHP41->PutUserCode(dlgSaveAs.m_ofn.lpstrFile,szError,vpLbl))
        {
        CString sMsg;
        sMsg.Format("Error: %s\nFile: %s",szError,dlgSaveAs.m_ofn.lpstrFile);
        AfxMessageBox(sMsg);
        }
      }
    }

  pHP41->Run();

  // clean up catalog
  for (int i=0;i<CatArray.GetSize();i++)
    delete CatArray[i];
  }

/**************************************/
void CMainWindow::OnBack()
  {
  dlgBack->ShowWindow(SW_SHOW);
  }

/**************************************/
void CMainWindow::OnAppAbout()
  {
  CAboutDlg AboutDlg;
  AboutDlg.DoModal();
  }

/**************************************/
void CMainWindow::OnHelpUsage()
  {
  ShellExecute(NULL,NULL,"notepad.exe","Help.txt",getPath(theApp.szAppFullPath),SW_SHOWNORMAL);
  }

/**************************************/
void CMainWindow::OnHelpIndex()
  {
  ShellExecute(NULL,NULL,"notepad.exe","Index.txt",getPath(theApp.szAppFullPath),SW_SHOWNORMAL);
}

/**************************************/
BOOL CMainWindow::PreCreateWindow(CREATESTRUCT& cs)
  {
  if (!CFrameWnd::PreCreateWindow(cs))
    return FALSE;
  cs.lpszClass=_T(MAKEINTRESOURCE(IDR_MAINFRAME));
  return TRUE;
  }

/**************************************/
int CMainWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
  {
  HKEY hKey;

  if (CFrameWnd::OnCreate(lpCreateStruct)==-1)
    return(-1);
  theApp.m_pMainWnd=this;

  MainMenu.LoadMenu(IDR_MAINFRAME);
  PopupMenu.LoadMenu(IDR_POPUPMENU);

  int eKeyboard=HP41::eKeyboardNone;
  fEndSession=FALSE;
  fAutoSave=TRUE;
  fAlwaysOnTop=FALSE;
  fJumpToForeground=TRUE;
  fTrueType=TRUE;
  fShowTitle=TRUE;
  fShowMenu=TRUE;
  fClassicCursor=FALSE;
  fShowConsole=FALSE;
  fShowRamView=FALSE;
  fRamViewLockWinUpdate=TRUE;               // use LockWindowsUpdate for Win8 or greater
  fShowBreakpoints=FALSE;
  WinKeyDown=0;
  WinMouseKeyDown=0;
  ProcInterval=DEFAULT_PROC_INTERVAL;
  ProcCycles=DEFAULT_PROC_CYCLES;
  TurboFactor=10;

  CWnd *pWndParent=GetDesktopWindow();
  pHP41=new HP41();

  dlgMcode=new CMcodeDlg();
  dlgMcode->pHP41=pHP41;
  dlgMcode->Create(IDD_MCODE,pWndParent);

  dlgRamView=new CRamViewDlg();
  dlgRamView->pHP41=pHP41;
  dlgRamView->Create(IDD_RAMVIEW,pWndParent);

  dlgBreakPoints=new CBreakPointsDlg();
  dlgBreakPoints->pHP41=pHP41;
  dlgBreakPoints->Create(IDD_BREAKPOINTS,pWndParent);

  dlgBack=new CBackDlg();
  dlgBack->Create(IDD_BACK,pWndParent);

  // get user preferences from registery - for some reason could not get RegQueryValueEx to work on Win98
  if (ERROR_SUCCESS==RegOpenKeyEx(HKEY_CURRENT_USER,APP_KEY,0,KEY_QUERY_VALUE,&hKey))
    {
    DWORD dwDirSize=_MAX_DIR;
    LPSTR szLastFolderLod =  strLastFolderLod.GetBuffer(_MAX_DIR);
    RegQueryValueEx(hKey,APP_LASTFOLDER_LOD,NULL,NULL,(LPBYTE)szLastFolderLod,&dwDirSize);
    strLastFolderLod.ReleaseBuffer();
    dwDirSize=_MAX_DIR;
    LPSTR szLastFolderRaw =  strLastFolderRaw.GetBuffer(_MAX_DIR);
    RegQueryValueEx(hKey,APP_LASTFOLDER_RAW,NULL,NULL,(LPBYTE)szLastFolderRaw,&dwDirSize);
    strLastFolderRaw.ReleaseBuffer();

    DWORD dwValue,dwValue2,dwValue3,dwValue4;
    DWORD dwSize=sizeof(DWORD);
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_LEFT,NULL,NULL,(LPBYTE)&dwValue,&dwSize) &&
      ERROR_SUCCESS==RegQueryValueEx(hKey,APP_TOP,NULL,NULL,(LPBYTE)&dwValue2,&dwSize))
      SetWindowLocation(this,dwValue,dwValue2);
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_MCODE_LEFT,NULL,NULL,(LPBYTE)&dwValue,&dwSize) &&
      ERROR_SUCCESS==RegQueryValueEx(hKey,APP_MCODE_TOP,NULL,NULL,(LPBYTE)&dwValue2,&dwSize))
      {
      SetWindowLocation(dlgMcode,dwValue,dwValue2);
      }
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_RAMVIEW_LEFT,NULL,NULL,(LPBYTE)&dwValue,&dwSize) &&
      ERROR_SUCCESS==RegQueryValueEx(hKey,APP_RAMVIEW_TOP,NULL,NULL,(LPBYTE)&dwValue2,&dwSize) &&
      ERROR_SUCCESS==RegQueryValueEx(hKey,APP_RAMVIEW_RIGHT,NULL,NULL,(LPBYTE)&dwValue3,&dwSize) &&
      ERROR_SUCCESS==RegQueryValueEx(hKey,APP_RAMVIEW_BOTTOM,NULL,NULL,(LPBYTE)&dwValue4,&dwSize))
      {
      SetWindowLocation(dlgRamView,dwValue,dwValue2,dwValue3-dwValue,dwValue4-dwValue2);
      }
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_RAMVIEW_LOCKWINPDATE,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      fRamViewLockWinUpdate=(flag)dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_RAMVIEW_SHOWEMPTYREG,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      dlgRamView->fRamShowEmptyReg=(flag)dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_RAMVIEW_SHOWFLAGS,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      dlgRamView->fRamShowFlags=(flag)dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_RAMVIEW_BUFFERNAME,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      dlgRamView->fRamBufferName=(flag)dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_BREAKPTS_LEFT,NULL,NULL,(LPBYTE)&dwValue,&dwSize) &&
      ERROR_SUCCESS==RegQueryValueEx(hKey,APP_BREAKPTS_TOP,NULL,NULL,(LPBYTE)&dwValue2,&dwSize))
      {
      SetWindowLocation(dlgBreakPoints,dwValue,dwValue2);
      }
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_CONTRAST,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      pHP41->SetContrast(dwValue);
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_FONTCOLOR,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      pHP41->SetFontColor(dwValue);
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_TRUETYPE,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      fTrueType=(flag)dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_KEYBOARD,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      eKeyboard=dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_PROC_INTERVAL,NULL,NULL,(LPBYTE)&dwValue,&dwSize) &&
      ERROR_SUCCESS==RegQueryValueEx(hKey,APP_PROC_CYCLES,NULL,NULL,(LPBYTE)&dwValue2,&dwSize))
      {
      ProcInterval=dwValue;
      ProcCycles=dwValue2;
      }
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_TURBO_FACTOR,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      TurboFactor=dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_WAVE_VOLUME,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      {
      if (dwValue > 127) dwValue >>= 9;
      WaveSound.SetVolume((BYTE)dwValue);
      }
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_AUTOSAVE,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      fAutoSave=(flag)dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_ALWAYSONTOP,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      fAlwaysOnTop=(flag)dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_JUMPTOFOREGROUND,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      fJumpToForeground=(flag)dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_SHOWTITLE,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      fShowTitle=(flag)dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_SHOWMENU,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      fShowMenu=(flag)dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_CLASSICCURSOR,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      fClassicCursor=(flag)dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_SOUNDMODE,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      pHP41->SetSoundMode(dwValue);
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_INST_SET,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      pHP41->ChangeInstSet(dwValue);
    DWORD dwTracepathSize=sizeof(pHP41->szTraceFilename)/sizeof(pHP41->szTraceFilename[0]);
    RegQueryValueEx(hKey,APP_TRACE_FILENAME,NULL,NULL,(LPBYTE)pHP41->szTraceFilename,&dwTracepathSize);
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_TRACE_FILEMODE,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      pHP41->eTraceMode=(HP41::TRACE_MODE)dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_SHOWREG_IN_TRACE,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      pHP41->fTraceRegister = (flag)dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_SHOWOPC_IN_TRACE,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      pHP41->fTraceOpcode = (flag)dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_SHOWOCTALDISASM,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      pHP41->fOctal = (flag)dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_SHOWHPIL_IN_TRACE,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      pHP41->fTraceHpil = (flag)dwValue;
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_INDICATOR,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      pHP41->SetIndicator((word)dwValue);

    // HPIL settings
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_CONNECTTIMEOUT,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      {
      pHP41->dwConnectTimeout=dwValue;
      }
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_ENABLEAUTOIDY,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      {
      pHP41->fEnableAutoIDY=(flag)dwValue;
      pHP41->m_pHpil->EnableAutoIDY(pHP41->fEnableAutoIDY);
      }
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_ENABLERFC,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      {
      pHP41->fEnableRFC=(flag)dwValue;
      pHP41->m_pHpil->EnableRFC(pHP41->fEnableRFC);
      }
    RegCloseKey(hKey);
    }
  else               // bring up help for first time install
    OnHelpUsage();

  // initialize cursors
  hCursorArrow = ::LoadCursor(NULL,IDC_ARROW);
  hCursorHand  = ::LoadCursor(NULL,IDC_HAND);
  if (fClassicCursor || hCursorHand == NULL)
    {
    hCursorHand = hCursorArrow;
    }

  // always on top for non modal dialogs
  NonModalAlwaysOnTop(fAlwaysOnTop);

  // initialize main loop
  pHP41->SetProcParams(ProcInterval,ProcCycles);

  // if keyboard size not specified in registery, select keyboard based on screen size
  if ((eKeyboard!=HP41::eKeyboardTiny)&&(eKeyboard!=HP41::eKeyboardSmall)&&(eKeyboard!=HP41::eKeyboardMedium)&&(eKeyboard!=HP41::eKeyboardLarge)&&(eKeyboard!=HP41::eKeyboardXLarge))
    {
    CDC *pDC=GetDC();
    int BitsPerPixel=GetDeviceCaps(pDC->m_hAttribDC,BITSPIXEL);
    ReleaseDC(pDC);
    if (BitsPerPixel<8)
      AfxMessageBox("Your system does not support more than 16 colors");
    if (GetSystemMetrics(SM_CXSCREEN)<800)
      eKeyboard=HP41::eKeyboardSmall;
    else if (GetSystemMetrics(SM_CXSCREEN)<1024)
      eKeyboard=HP41::eKeyboardMedium;
    else
      eKeyboard=HP41::eKeyboardLarge;
    }

  // init background window
  UpdateMenus(eKeyboard);
  pHP41->SetKeyboard(eKeyboard,fTrueType,fShowTitle,fShowMenu);

  // load the ROM images and other config
  if (theApp.szSessionName[0]==0)   // no parameter given on command line
    {
    char drive[_MAX_DRIVE],dir[_MAX_DIR];
    _splitpath(theApp.szAppFullPath,drive,dir,NULL,NULL);
    _makepath(theApp.szSessionName,drive,dir,"HP-41CX","lod");
    }
  int nErrors=pHP41->LoadConfig(theApp.szSessionName);
  if (nErrors > 1)                  // multiple errors
    {
    CString sMsg;
    sMsg.Format("%d error(s) loading configuration: %s",nErrors,theApp.szSessionName);
    AfxMessageBox(sMsg);
    }
  if (nErrors >= 0)                 // no critical errors
    {
    AfxGetApp()->AddToRecentFileList(theApp.szSessionName);
    }

  if (theApp.fConsole)
    {
    pHP41->fTimerEnable=FALSE;                          // disable timer increment
    pHP41->TimerInstrCnt=pHP41->GetInstrTimerUpdate();  // set instruction counter for timer increment
    fShowConsole=TRUE;
    dlgMcode->ShowWindow(SW_SHOW);
    }
  else
    {
    pHP41->EnableRun();
    pHP41->Run();
    }
  SetTitle();

  return(0);
  }

/**************************************/
void CMainWindow::OnDestroy()
  {
  pHP41->Halt();
  pHP41->StopHpil();

  // not child windows, so detroy them manually
  dlgMcode->DestroyWindow();
  dlgRamView->DestroyWindow();
  dlgBreakPoints->DestroyWindow();
  dlgBack->DestroyWindow();

  // save window position and other info to registry
  HKEY hKey;
  if (ERROR_SUCCESS!=RegCreateKeyEx(HKEY_CURRENT_USER,APP_KEY,0,"",0,KEY_WRITE,NULL,&hKey,NULL))
    return;

  // save last session name
  if (bSessionNameValid)
    {
    RegSetValueEx(hKey,APP_LASTSESSION,0,REG_SZ,(LPBYTE)theApp.szSessionName,(lstrlen(theApp.szSessionName)+1) * sizeof(*theApp.szSessionName));
    }

  RegSetValueEx(hKey,APP_LASTFOLDER_LOD,0,REG_SZ,(LPBYTE)(LPCTSTR)strLastFolderLod,(lstrlen(strLastFolderLod)+1) * sizeof(TCHAR));
  RegSetValueEx(hKey,APP_LASTFOLDER_RAW,0,REG_SZ,(LPBYTE)(LPCTSTR)strLastFolderRaw,(lstrlen(strLastFolderRaw)+1) * sizeof(TCHAR));

  DWORD dwValue;
  WINDOWPLACEMENT wp;
  wp.length = sizeof(wp);
  if (GetWindowPlacement(&wp))
    {
    dwValue=wp.rcNormalPosition.left;
    RegSetValueEx(hKey,APP_LEFT,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
    dwValue=wp.rcNormalPosition.top;
    RegSetValueEx(hKey,APP_TOP,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
    }
  dwValue=dlgMcode->Left;
  RegSetValueEx(hKey,APP_MCODE_LEFT,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=dlgMcode->Top;
  RegSetValueEx(hKey,APP_MCODE_TOP,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=dlgRamView->Left;
  RegSetValueEx(hKey,APP_RAMVIEW_LEFT,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=dlgRamView->Top;
  RegSetValueEx(hKey,APP_RAMVIEW_TOP,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=dlgRamView->Right;
  RegSetValueEx(hKey,APP_RAMVIEW_RIGHT,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=dlgRamView->Bottom;
  RegSetValueEx(hKey,APP_RAMVIEW_BOTTOM,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=fRamViewLockWinUpdate;
  RegSetValueEx(hKey,APP_RAMVIEW_LOCKWINPDATE,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=dlgRamView->fRamShowEmptyReg;
  RegSetValueEx(hKey,APP_RAMVIEW_SHOWEMPTYREG,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=dlgRamView->fRamShowFlags;
  RegSetValueEx(hKey,APP_RAMVIEW_SHOWFLAGS,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=dlgRamView->fRamBufferName;
  RegSetValueEx(hKey,APP_RAMVIEW_BUFFERNAME,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=dlgBreakPoints->Left;
  RegSetValueEx(hKey,APP_BREAKPTS_LEFT,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=dlgBreakPoints->Top;
  RegSetValueEx(hKey,APP_BREAKPTS_TOP,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=pHP41->GetContrast();
  RegSetValueEx(hKey,APP_CONTRAST,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=pHP41->GetFontColor();
  RegSetValueEx(hKey,APP_FONTCOLOR,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=pHP41->GetKeyboard();
  RegSetValueEx(hKey,APP_KEYBOARD,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=ProcInterval;
  RegSetValueEx(hKey,APP_PROC_INTERVAL,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=ProcCycles;
  RegSetValueEx(hKey,APP_PROC_CYCLES,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=TurboFactor;
  RegSetValueEx(hKey,APP_TURBO_FACTOR,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=WaveSound.GetVolume();
  RegSetValueEx(hKey,APP_WAVE_VOLUME,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=fAutoSave;
  RegSetValueEx(hKey,APP_AUTOSAVE,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=fAlwaysOnTop;
  RegSetValueEx(hKey,APP_ALWAYSONTOP,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=fJumpToForeground;
  RegSetValueEx(hKey,APP_JUMPTOFOREGROUND,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=fShowTitle;
  RegSetValueEx(hKey,APP_SHOWTITLE,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=fShowMenu;
  RegSetValueEx(hKey,APP_SHOWMENU,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=fClassicCursor;
  RegSetValueEx(hKey,APP_CLASSICCURSOR,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=pHP41->GetSoundMode();
  RegSetValueEx(hKey,APP_SOUNDMODE,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=fTrueType;
  RegSetValueEx(hKey,APP_TRUETYPE,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=pHP41->GetInstSet();
  RegSetValueEx(hKey,APP_INST_SET,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  RegSetValueEx(hKey,APP_TRACE_FILENAME,0,REG_SZ,(LPBYTE)pHP41->szTraceFilename,(lstrlen(pHP41->szTraceFilename)+1) * sizeof(pHP41->szTraceFilename[0]));
  dwValue=pHP41->eTraceMode;
  RegSetValueEx(hKey,APP_TRACE_FILEMODE,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=pHP41->fTraceRegister;
  RegSetValueEx(hKey,APP_SHOWREG_IN_TRACE,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=pHP41->fTraceOpcode;
  RegSetValueEx(hKey,APP_SHOWOPC_IN_TRACE,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=pHP41->fOctal;
  RegSetValueEx(hKey,APP_SHOWOCTALDISASM,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=pHP41->fTraceHpil;
  RegSetValueEx(hKey,APP_SHOWHPIL_IN_TRACE,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=pHP41->GetIndicator();
  RegSetValueEx(hKey,APP_INDICATOR,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=theApp.fSingle;
  RegSetValueEx(hKey,APP_SINGLE,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=theApp.nFileCount;
  RegSetValueEx(hKey,APP_MRU_FILECOUNT,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));

  // HPIL settings
  dwValue=pHP41->dwConnectTimeout;
  RegSetValueEx(hKey,APP_CONNECTTIMEOUT,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=pHP41->fEnableAutoIDY;
  RegSetValueEx(hKey,APP_ENABLEAUTOIDY,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));
  dwValue=pHP41->fEnableRFC;
  RegSetValueEx(hKey,APP_ENABLERFC,0,REG_DWORD,(LPBYTE)&dwValue,sizeof(DWORD));

  RegCloseKey(hKey);

  if (bSessionNameValid && fAutoSave)
    pHP41->SaveConfig(theApp.szSessionName,fEndSession);

  CFrameWnd::OnDestroy();

  delete dlgMcode;
  delete dlgRamView;
  delete dlgBreakPoints;
  delete dlgBack;
  delete pHP41;
  }

/**************************************/
void CMainWindow::OnSysCommand(UINT nID, LPARAM lParam)
{
  switch (nID & 0xFFF0)
  {
  case SC_CLOSE:
    OnFileExit();
    return;
  }
  CFrameWnd::OnSysCommand(nID, lParam);
}

/**************************************/
void CMainWindow::OnEndSession(BOOL bEnding)
{
  CFrameWnd::OnEndSession(bEnding);
  if (bEnding)
    {
    fEndSession=TRUE;
    DestroyWindow();
    }
}

/**************************************/
void CMainWindow::OnPaint()
  {
  PAINTSTRUCT ps;
  CDC *pCDC=BeginPaint(&ps);
  if (!IsIconic())
    pHP41->Draw(pCDC);
  EndPaint(&ps);
  }

/**************************************/
void CMainWindow::OnLButtonDown(UINT nFlags, CPoint point)
  {
  WinMouseKeyDown=pHP41->MapPointToKey(point);
  if (WinMouseKeyDown)                    // valid mouse key down
    {
    if (WinMouseKeyDown==1)               // LCD
      OnFileCopy();
    else if (WinMouseKeyDown==2)          // slide
      ;
    else if (WinMouseKeyDown==3)          // close
      ;
    else
      pHP41->SetKeyDown(WinMouseKeyDown);
    pHP41->MoveKey(WinMouseKeyDown,MOVE);
    SetCapture();
    if (dlgMcode->IsWindowVisible())
      dlgMcode->Invalidate();             // update Mcode Console
    sndPlaySound("KeyDown.wav",SND_ASYNC|SND_NODEFAULT);
    }
  CFrameWnd::OnLButtonDown(nFlags,point);
  }

/**************************************/
void CMainWindow::OnLButtonUp(UINT nFlags,CPoint point)
  {
  if (WinMouseKeyDown)
    {
    ReleaseCapture();
    pHP41->MoveKey(WinMouseKeyDown,NORMAL);
    if (WinMouseKeyDown==1)       // LCD
      ;
    else if (WinMouseKeyDown==2)  // slide
      ;
    else if (WinMouseKeyDown==3)  // close
      PostMessage(WM_COMMAND, ID_FILE_EXIT, 0);
    else
      pHP41->SetKeyUp(WinMouseKeyDown);
    WinMouseKeyDown=0;
    }
  CFrameWnd::OnLButtonUp(nFlags,point);
  }

/**************************************/
void CMainWindow::OnContextMenu(CWnd* pWnd, CPoint point)
  {
  if (WinMouseKeyDown == 0)             // no mouse key pressed
    {
    if (point.x == -1 && point.y == -1) // VK_APPS
      {
      RECT rc;

      GetCursorPos(&point);             // get active mouse position
      pWnd->GetWindowRect(&rc);         // get position of active window
      if (PtInRect(&rc,point)==FALSE)   // mouse position outside active window
        {
        point.x = 15;                   // default position inside client area
        point.y = 15;
        ClientToScreen(&point);
        }
      }

    PopupMenu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON,point.x,point.y,this);
    }
  }

/**************************************/
BOOL CMainWindow::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
  {
  if (   pCopyDataStruct->dwData == CDID_FILENAME
      && (pCopyDataStruct->cbData > 0 && pCopyDataStruct->lpData != NULL))
    {
    char szBufferFilename[MAX_PATH];
    char szActFilename[MAX_PATH];
    LPTSTR lpFilePart;  // address of file name in path
    GetFullPathName((LPCSTR) pCopyDataStruct->lpData,sizeof(szBufferFilename),szBufferFilename,&lpFilePart);
    GetFullPathName(theApp.szSessionName,sizeof(szActFilename),szActFilename,&lpFilePart);
    if (lstrcmpi(szBufferFilename,szActFilename) != 0)
      {
      pHP41->Halt();
      pHP41->StopHpil();
      if (fAutoSave && 0 != strcmpi(theApp.szSessionName,theApp.szUntitledName))
        {
        FileSave(false);
        }
      FileOpen(szBufferFilename);
      }
  }
  return CFrameWnd::OnCopyData(pWnd, pCopyDataStruct);
  }

/**************************************/
void CMainWindow::OnKeyDown(
  UINT nChar,     // VK
  UINT nRepCnt,
  UINT nFlags)    // bit 8 is set for extended keys, bit 13 for alt, bit 14 for prev key.
  {
  if (nFlags&KF_REPEAT)  // prev key state - set to 1 when key is already pressed
    return;

  WinKeyDown=pHP41->MapKeyToKey((nFlags&KF_ALTDOWN)>>13,(nFlags&KF_EXTENDED)>>8,nChar); // alt,extended,VK
  if (WinKeyDown)                         // valid PC key down
    {
    if (WinKeyDown==1)                    // Control key copies LCD
      OnFileCopy();
    else if (WinKeyDown==3)               // TAB key causes turbo execution mode
      {
      if (!pHP41->m_pHpil->IsFrameInTransfer(0)) // no IL frame in transfer
        pHP41->SetProcParams(10,DEFAULT_PROC_CYCLES*TurboFactor); // set maximum speed values
      }
    else
      pHP41->SetKeyDown(WinKeyDown);
    pHP41->MoveKey(WinKeyDown,MOVE);
    if (dlgMcode->IsWindowVisible())
      dlgMcode->Invalidate();             // update Mcode Console
    sndPlaySound("KeyDown.wav",SND_ASYNC|SND_NODEFAULT);
    }
  else if (nChar==VK_F1)
    OnHelpUsage();
  CFrameWnd::OnKeyDown(nChar,nRepCnt,nFlags);
  }

/**************************************/
void CMainWindow::OnKeyUp(UINT nChar,UINT nRepCnt,UINT nFlags)
  {
  WinKeyDown=pHP41->MapKeyToKey((nFlags&0x2000)?1:0,(nFlags&0x0100)?1:0,nChar); // alt,extended,VK
  if (WinKeyDown)
    {
    pHP41->MoveKey(WinKeyDown,NORMAL);
    if (WinKeyDown==1)                                    // CONTROL
      ;
    else if (WinKeyDown==3)                               // TAB release stops turbo mode
      pHP41->SetProcParams(ProcInterval,ProcCycles);      // set run speed values
    else
      pHP41->SetKeyUp(WinKeyDown);
    WinKeyDown=0;
    }
  CFrameWnd::OnKeyUp(nChar,nRepCnt,nFlags);
  }


/**************************************/
// Microsoft changed the UI specification to prevent windows from jumping to foreground.
// this code forces it anyway.  Thanks to Alexander Shargin for article documenting the three methods
/**************************************/
void CMainWindow::ForceToForeground(CWnd *pWnd)
  {
  // this method works on Win98/ME/2000
  DWORD dwThreadID=::GetCurrentThreadId();
  DWORD dwCurThreadID=::GetWindowThreadProcessId(::GetForegroundWindow(), NULL);
  AttachThreadInput(dwThreadID,dwCurThreadID,TRUE);
  pWnd->SetForegroundWindow();
  AttachThreadInput(dwThreadID,dwCurThreadID,FALSE);
  }

/**************************************/
void CMainWindow::OnMouseMove(UINT nFlags, CPoint point)
  {
  // set cursor
  _ASSERT(hCursorArrow != NULL && hCursorHand != NULL);
  // make sure that class cursor is NULL
  _ASSERT(GetClassLongPtr(GetSafeHwnd(),GCLP_HCURSOR) == 0);

  // cursor over button -> hand cursor else normal arrow cursor
  SetCursor((pHP41->MapPointToKey(point) != 0) ? hCursorHand : hCursorArrow);

  CFrameWnd ::OnMouseMove(nFlags, point);

  if (fJumpToForeground && GetActiveWindow()!=this)
    ForceToForeground(this);
  }

/**************************************/
void CMainWindow::OnNcMouseMove(UINT nFlags, CPoint point)
  {
  CFrameWnd ::OnNcMouseMove(nFlags, point);

  if (fJumpToForeground && GetActiveWindow()!=this)
    ForceToForeground(this);
  }

/**************************************/
LRESULT CMainWindow::OnNcHitTest(CPoint point)
  {
  if (fShowTitle)
    {
    return CFrameWnd::OnNcHitTest(point);
    }
  else
    {
    POINT ClientPoint = point;
    ScreenToClient(&ClientPoint);
    //if y < 0 then point is in the menu
    if (   (ClientPoint.y < 0) || PtInRect(&(pHP41->ActiveRect), ClientPoint)
        || (pHP41->pRectCloseButton != NULL && PtInRect(pHP41->pRectCloseButton, ClientPoint))
       )
      return(CFrameWnd::OnNcHitTest(point));
    else
      return(HTCAPTION);
    }
  }

/**************************************/
void CMainWindow::NonModalAlwaysOnTop(flag fEnable)
  {
  UINT nFlags;
  const CWnd* pWndPos;
  if (fEnable)                                  // Always On Top enabled
    {
    // redraw window
    nFlags=SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE;
    pWndPos=&wndTopMost;
    }
  else
    {
    // no redraw window
    nFlags=SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOREDRAW;
    pWndPos=&wndNoTopMost;
    }

  dlgMcode->SetWindowPos(pWndPos,0,0,0,0,nFlags);
  dlgRamView->SetWindowPos(pWndPos,0,0,0,0,nFlags);
  dlgBreakPoints->SetWindowPos(pWndPos,0,0,0,0,nFlags);
  }

/**************************************/
const CString CMainWindow::getPath(LPCTSTR szFullFilename)
  {
  char szPath[_MAX_PATH];
  lstrcpy(szPath,szFullFilename);
  // cut last at last '\' of directory path
  if (lstrlen(szPath)>=3)
    {
    char *szPtr=strrchr(&szPath[3],'\\');
    if (szPtr != NULL) *szPtr=0;
    }
  return szPath;
  }

/**************************************/
void CMainWindow::SetWindowLocation(CWnd *pWnd,INT nPosX,INT nPosY,INT nWidth,INT nHeight)
  {
  WINDOWPLACEMENT wndpl;
  RECT *pRc = &wndpl.rcNormalPosition;

  wndpl.length = sizeof(wndpl);
  pWnd->GetWindowPlacement(&wndpl);
  if (nWidth == 0 || nHeight == 0)
    {
    pRc->right -= pRc->left;
    pRc->bottom -= pRc->top;
    }
  else  // given width and height
    {
    pRc->right = nWidth;
    pRc->bottom = nHeight;
    }
  pRc->right += nPosX;
  pRc->bottom += nPosY;
  pRc->left = nPosX;
  pRc->top = nPosY;
  wndpl.showCmd = SW_HIDE;
  pWnd->SetWindowPlacement(&wndpl);
  }

/**************************************/
void CMainWindow::SetTitle()
  {
  CString strSession;
  int index;
  const char *psz;
  psz=strrchr(theApp.szSessionName,'\\');   // copy everything after last slash
  if (psz)
    strSession = psz+1;
  else
    strSession = theApp.szSessionName;
  index = strSession.ReverseFind('.');
  if (index != -1)                          // truncate off file extension
    strSession = strSession.Left(index);
  SetWindowText(strSession);
  }

/**************************************/
void CMainWindow::OnOptionsTiny()
  {
  UpdateMenus(HP41::eKeyboardTiny);
  pHP41->SetKeyboard(HP41::eKeyboardTiny,fTrueType,fShowTitle,fShowMenu);
  }

/**************************************/
void CMainWindow::OnOptionsSmall()
  {
  UpdateMenus(HP41::eKeyboardSmall);
  pHP41->SetKeyboard(HP41::eKeyboardSmall,fTrueType,fShowTitle,fShowMenu);
  }

/**************************************/
void CMainWindow::OnOptionsMedium()
  {
  UpdateMenus(HP41::eKeyboardMedium);
  pHP41->SetKeyboard(HP41::eKeyboardMedium,fTrueType,fShowTitle,fShowMenu);
  }

/**************************************/
void CMainWindow::OnOptionsLarge()
  {
  UpdateMenus(HP41::eKeyboardLarge);
  pHP41->SetKeyboard(HP41::eKeyboardLarge,fTrueType,fShowTitle,fShowMenu);
  }

/**************************************/
void CMainWindow::OnOptionsXLarge()
  {
  UpdateMenus(HP41::eKeyboardXLarge);
  pHP41->SetKeyboard(HP41::eKeyboardXLarge,fTrueType,fShowTitle,fShowMenu);
  }

/**************************************/
void CMainWindow::OnOptionsJumpToForeground()
  {
  fJumpToForeground=!fJumpToForeground;
  SetMenuChecks(&MainMenu);
  SetMenuChecks(&PopupMenu);
  }

/**************************************/
void CMainWindow::OnOptionsAlwaysontop()
  {
  fAlwaysOnTop=!fAlwaysOnTop;
  SetMenuChecks(&MainMenu);
  SetMenuChecks(&PopupMenu);
  UpdateMenus(pHP41->GetKeyboard());
  NonModalAlwaysOnTop(fAlwaysOnTop);
  }

/**************************************/
void CMainWindow::OnOptionsShowTitle()
  {
  fShowTitle=!fShowTitle;
  UpdateMenus(pHP41->GetKeyboard());
  pHP41->SetKeyboard(pHP41->GetKeyboard(),fTrueType,fShowTitle,fShowMenu);   // just to resize window
  }

/**************************************/
void CMainWindow::OnOptionsShowMenu()
  {
  fShowMenu=!fShowMenu;
  UpdateMenus(pHP41->GetKeyboard());
  pHP41->SetKeyboard(pHP41->GetKeyboard(),fTrueType,fShowTitle,fShowMenu);   // just to resize window
  }

/**************************************/
void CMainWindow::OnOptionsSettings()
  {
  CSettingsDlg SettingsDlg;

  pHP41->Halt();
  SettingsDlg.pHP41=pHP41;
  SettingsDlg.Contrast=pHP41->GetContrast();
  SettingsDlg.FontColor=pHP41->GetFontColor();
  SettingsDlg.Interval=ProcInterval;
  SettingsDlg.Turbo=TurboFactor;
  SettingsDlg.fSpeakerSoundAvail=pHP41->SpeakerSoundAvail;
  SettingsDlg.fWaveSoundAvail=WaveSound.IsAvailable();
  SettingsDlg.SoundMode=pHP41->GetSoundMode();
  SettingsDlg.WaveVolume=WaveSound.GetVolume();
  SettingsDlg.fAutoSave=fAutoSave;
  SettingsDlg.fTrueType=fTrueType;
  SettingsDlg.fSingle=theApp.fSingle;
  SettingsDlg.fAutoIdy=pHP41->fEnableAutoIDY;
  SettingsDlg.strOutAddr=pHP41->strAddrOut;
  SettingsDlg.wOutPort=pHP41->wPortOut;
  SettingsDlg.wInPort=pHP41->wPortIn;
  if (IDOK==SettingsDlg.DoModal())
    {
    pHP41->StopHpil();  // stop TCP/IP server to free port
    pHP41->SetContrast(SettingsDlg.Contrast);
    pHP41->SetFontColor(SettingsDlg.FontColor);
    ProcInterval=SettingsDlg.Interval;
    pHP41->SetProcParams(ProcInterval,ProcCycles);
    TurboFactor=SettingsDlg.Turbo;
    fAutoSave=SettingsDlg.fAutoSave;
    if (SettingsDlg.fWaveSoundAvail && SettingsDlg.SoundMode==eSoundWave)
      WaveSound.SetVolume(SettingsDlg.WaveVolume);
    pHP41->SetSoundMode(SettingsDlg.SoundMode);
    fTrueType=SettingsDlg.fTrueType;
    pHP41->SetKeyboard(pHP41->GetKeyboard(),fTrueType,fShowTitle,fShowMenu);
    theApp.fSingle=SettingsDlg.fSingle;
    pHP41->fEnableAutoIDY=SettingsDlg.fAutoIdy;
    pHP41->m_pHpil->EnableAutoIDY(pHP41->fEnableAutoIDY);
    pHP41->strAddrOut=SettingsDlg.strOutAddr;
    pHP41->wPortOut=SettingsDlg.wOutPort;
    pHP41->wPortIn=SettingsDlg.wInPort;
    pHP41->StartHpil(); // start with new TCP/IP settings
    }
  pHP41->Run();         // restarts with new params
  }

/**************************************/
// save the lcd display to the clipboard
/**************************************/
void CMainWindow::OnFileCopy()
  {
  CString DisStr;

  pHP41->GetDisplay(DisStr.GetBuffer(30));
  DisStr.ReleaseBuffer();
  DisStr.TrimLeft();
  DisStr.TrimRight();

  if (OpenClipboard())
    {
    if (EmptyClipboard())
      {
      MSG msg;

      HANDLE hData=GlobalAlloc(GMEM_MOVEABLE,DisStr.GetLength()+1);
      if (hData!=NULL)
        {
        LPSTR lpData=(LPSTR)GlobalLock(hData);
        if (lpData!=NULL)
          {
          lstrcpy(lpData, (LPCTSTR)DisStr);
          GlobalUnlock(hData);
          ::SetClipboardData(CF_TEXT, hData);
          }
        }

      // DIB bitmap
      #define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)

      // pump WM_PAINT message for closing menu before getting image
      while (PeekMessage(&msg,GetSafeHwnd(),WM_PAINT,WM_PAINT,PM_REMOVE))
        DispatchMessage(&msg);

      CRect rectDisp;                       // display rect over LCD and annunciator area
      rectDisp.UnionRect(pHP41->pRectLCD,pHP41->pRectAnnun);
      rectDisp.InflateRect(2,2);            // add 2 pixel border

      CDC *pMainDC = GetDC();
      HDC hBmpDC = CreateCompatibleDC(pMainDC->m_hDC);
      HBITMAP hBmp = CreateCompatibleBitmap(pMainDC->m_hDC,rectDisp.Width(),rectDisp.Height());

      hBmp = (HBITMAP) SelectObject(hBmpDC,hBmp);
      // get display area from main window
      BitBlt(hBmpDC,0,0,rectDisp.Width(),rectDisp.Height(),pMainDC->m_hDC,rectDisp.left,rectDisp.top,SRCCOPY);
      hBmp = (HBITMAP) SelectObject(hBmpDC,hBmp);

      // fill BITMAP structure for size information
      BITMAP bm;
      GetObject(hBmp,sizeof(bm),&bm);

      WORD wBits = bm.bmPlanes * bm.bmBitsPixel;
      // make sure bits per pixel is valid
      if (wBits <= 1)
        wBits = 1;
      else if (wBits <= 4)
        wBits = 4;
      else if (wBits <= 8)
        wBits = 8;
      else // if greater than 8-bit, force to 24-bit
        wBits = 24;

      DWORD dwSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * wBits) * bm.bmHeight;

      // calculate memory size to store CF_DIB data
      DWORD dwLen = sizeof(BITMAPINFOHEADER) + dwSizeImage;
      if (wBits != 24)                      // a 24 bitcount DIB has no color table
        {
        // add size for color table
         dwLen += (DWORD) (1 << wBits) * sizeof(RGBQUAD);
        }

      // memory allocation for clipboard data
      HANDLE hClipObj;
      if ((hClipObj = GlobalAlloc(GMEM_MOVEABLE, dwLen)) != NULL)
        {
        LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER) GlobalLock(hClipObj);
        if (lpbi != NULL)
          {
          // initialize BITMAPINFOHEADER
          lpbi->biSize = sizeof(BITMAPINFOHEADER);
          lpbi->biWidth = bm.bmWidth;
          lpbi->biHeight = bm.bmHeight;
          lpbi->biPlanes = 1;
          lpbi->biBitCount = wBits;
          lpbi->biCompression = BI_RGB;
          lpbi->biSizeImage = dwSizeImage;
          lpbi->biXPelsPerMeter = 0;
          lpbi->biYPelsPerMeter = 0;
          lpbi->biClrUsed = 0;
          lpbi->biClrImportant = 0;
          // get bitmap color table and bitmap data
          GetDIBits(hBmpDC, hBmp, 0, lpbi->biHeight, (LPBYTE)lpbi + dwLen - dwSizeImage,
            (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
          GlobalUnlock(hClipObj);
          ::SetClipboardData(CF_DIB, hClipObj);
          ::SetClipboardData(CF_PALETTE, CreatePalette(theApp.pPalForeground));
          }
        }

      VERIFY(DeleteObject(hBmp));
      VERIFY(DeleteDC(hBmpDC));
      VERIFY(ReleaseDC(pMainDC));
      #undef WIDTHBYTES
      }
    CloseClipboard();
    }
  }

/**************************************/
void CMainWindow::OnPaletteChanged(CWnd* pFocusWnd)
  {
  CFrameWnd ::OnPaletteChanged(pFocusWnd);
  if (pFocusWnd==theApp.m_pMainWnd)      // responding to own message - nothing to do
    return;
  OnQueryNewPalette();
  }

/**************************************/
BOOL CMainWindow::OnQueryNewPalette()
  {
  CPalette *pCPalOld,*pCPal;
  CDC *pDC=theApp.m_pMainWnd->GetDC();
  pCPal=new CPalette;
  pCPal->CreatePalette(theApp.pPalForeground);
  pCPalOld=pDC->SelectPalette(pCPal,FALSE);
  int nEntries=pDC->RealizePalette();
  if (nEntries)
    theApp.m_pMainWnd->InvalidateRect(NULL,FALSE);
  pDC->SelectPalette(pCPalOld,TRUE);
  pDC->RealizePalette();
  theApp.m_pMainWnd->ReleaseDC(pDC);
  delete pCPal;
  return(nEntries!=0);
  }

/**************************************/
void CMainWindow::OnOptionsReset()
  {
  if ((AfxMessageBox("Are you sure you want to execute a CPU Reset?",MB_YESNO|MB_ICONEXCLAMATION))==IDYES)
    {
    pHP41->Halt();
    pHP41->SetPC(0);
    pHP41->CARRY = pHP41->DisplayOn ? 0 : 1;
    pHP41->Run();
    }
  }

/**************************************/
void CMainWindow::OnMcodeTrace()
  {
  pHP41->SwitchTrace();
  SetMenuChecks(&MainMenu);
  SetMenuChecks(&PopupMenu);
  }

/**************************************/
//if keyboard == HP41::eKeyboardNone then read current setting from pHP41. Otherwise use value specified. MGL
void CMainWindow::UpdateMenus(int eKeyboard)
  {
  // show or hide title bar
  DWORD styleTitle=WS_OVERLAPPED|WS_SYSMENU|WS_CAPTION|WS_MINIMIZEBOX;
  DWORD styleNoTitle=WS_POPUP|WS_DLGFRAME;
  DWORD style=GetStyle();
  if (fShowTitle && ((GetStyle()&styleTitle)!=styleTitle))      // show title if not already showing it
    {
    ModifyStyle(styleNoTitle,styleTitle);
    CMenu *pMenu=GetSystemMenu(FALSE);      // remove size and maximize menu items from system menu
    pMenu->RemoveMenu(SC_MAXIMIZE,MF_BYCOMMAND);
    pMenu->RemoveMenu(SC_SIZE,MF_BYCOMMAND);
    }
  if (!fShowTitle && ((GetStyle()&styleNoTitle)!=styleNoTitle))  // hide title
    ModifyStyle(styleTitle,styleNoTitle);

  // show or hide main menu
  if (fShowMenu)
    SetMenu(&MainMenu);
  else
    SetMenu(0);        // remove main menu

  // always on top
  SetWindowPos(fAlwaysOnTop?&wndTopMost:&wndNoTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOREDRAW);

  // set checks
  SetMenuChecks(&MainMenu,eKeyboard);
  SetMenuChecks(&PopupMenu,eKeyboard);
  }

/**************************************/
void CMainWindow::SetMenuChecks(
  CMenu *pMenu, int eKeyboard)
  {
  if (eKeyboard==HP41::eKeyboardNone)
    eKeyboard=pHP41->GetKeyboard();
  pMenu->CheckMenuItem(ID_OPTIONS_TINY,MF_BYCOMMAND|((eKeyboard==HP41::eKeyboardTiny)?MF_CHECKED:MF_UNCHECKED));
  pMenu->CheckMenuItem(ID_OPTIONS_SMALL,MF_BYCOMMAND|((eKeyboard==HP41::eKeyboardSmall)?MF_CHECKED:MF_UNCHECKED));
  pMenu->CheckMenuItem(ID_OPTIONS_MEDIUM,MF_BYCOMMAND|((eKeyboard==HP41::eKeyboardMedium)?MF_CHECKED:MF_UNCHECKED));
  pMenu->CheckMenuItem(ID_OPTIONS_LARGE,MF_BYCOMMAND|((eKeyboard==HP41::eKeyboardLarge)?MF_CHECKED:MF_UNCHECKED));
  pMenu->CheckMenuItem(ID_OPTIONS_XLARGE,MF_BYCOMMAND|((eKeyboard==HP41::eKeyboardXLarge)?MF_CHECKED:MF_UNCHECKED));
  pMenu->CheckMenuItem(ID_OPTIONS_JUMPTOFOREGROUND,MF_BYCOMMAND|(fJumpToForeground?MF_CHECKED:MF_UNCHECKED));
  pMenu->CheckMenuItem(ID_OPTIONS_ALWAYSONTOP,MF_BYCOMMAND|(fAlwaysOnTop?MF_CHECKED:MF_UNCHECKED));
  pMenu->CheckMenuItem(ID_OPTIONS_SHOWTITLE,MF_BYCOMMAND|(fShowTitle?MF_CHECKED:MF_UNCHECKED));
  pMenu->CheckMenuItem(ID_OPTIONS_SHOWMENU,MF_BYCOMMAND|(fShowMenu?MF_CHECKED:MF_UNCHECKED));
  pMenu->CheckMenuItem(ID_OPTIONS_CONSOLE,MF_BYCOMMAND|(fShowConsole?MF_CHECKED:MF_UNCHECKED));
  pMenu->CheckMenuItem(ID_OPTIONS_RAMVIEW,MF_BYCOMMAND|(fShowRamView?MF_CHECKED:MF_UNCHECKED));
  pMenu->CheckMenuItem(ID_OPTIONS_BREAKPOINTS,MF_BYCOMMAND|(fShowBreakpoints?MF_CHECKED:MF_UNCHECKED));
  pMenu->CheckMenuItem(ID_OPTIONS_TRACE,MF_BYCOMMAND|(pHP41->GetTrace()?MF_CHECKED:MF_UNCHECKED));
  }

/**************************************/
void CMainWindow::CloseConsole()
  {
  fShowConsole=FALSE;
  SetMenuChecks(&MainMenu);
  SetMenuChecks(&PopupMenu);
  dlgMcode->ShowWindow(SW_HIDE);
  pHP41->EnableRun();
  pHP41->Run();
  }

/**************************************/
void CMainWindow::OpenConsole()
  {
  pHP41->fTimerEnable=FALSE;                          // disable timer increment
  pHP41->TimerInstrCnt=pHP41->GetInstrTimerUpdate();  // set instruction counter for timer increment
  pHP41->DisableRun();
  pHP41->Halt();
  fShowConsole=TRUE;
  SetMenuChecks(&MainMenu);
  SetMenuChecks(&PopupMenu);
  dlgMcode->ShowWindow(SW_SHOW);
  }

/**************************************/
void CMainWindow::OnMcodeConsole()
  {
  fShowConsole=!fShowConsole;
  SetMenuChecks(&MainMenu);
  SetMenuChecks(&PopupMenu);
  if (dlgMcode->ShowWindow(SW_SHOWNA))
    {
    dlgMcode->ShowWindow(SW_HIDE);
    pHP41->EnableRun();
    pHP41->Run();
    }
  else
    {
    pHP41->fTimerEnable=FALSE;                          // disable timer increment
    pHP41->TimerInstrCnt=pHP41->GetInstrTimerUpdate();  // set instruction counter for timer increment
    pHP41->DisableRun();
    pHP41->Halt();
    dlgMcode->ShowWindow(SW_SHOW);
    dlgMcode->SetFocus();
    }
  }

/**************************************/
void CMainWindow::CloseRamView()
  {
  fShowRamView=FALSE;
  SetMenuChecks(&MainMenu);
  SetMenuChecks(&PopupMenu);
  dlgRamView->ShowWindow(SW_HIDE);
  }

/**************************************/
void CMainWindow::OnOptionsRamView()
  {
  fShowRamView=!fShowRamView;
  SetMenuChecks(&MainMenu);
  SetMenuChecks(&PopupMenu);
  dlgRamView->m_bWin8=fRamViewLockWinUpdate && m_bIsWindows8orLater;
  if (dlgRamView->ShowWindow(SW_SHOWNA))
    {
    dlgRamView->ShowWindow(SW_HIDE);
    }
  else
    {
    dlgRamView->ShowWindow(SW_SHOW);
    dlgRamView->SetFocus();
    }
  }

/**************************************/
void CMainWindow::UpdateRamView()
  {
  dlgRamView->UpdateRamView();                        // update RAM view window
  }

/**************************************/
void CMainWindow::OpenBreakpoints()
  {
  fShowBreakpoints=TRUE;
  pHP41->fBreakPtsEnable=TRUE;
  SetMenuChecks(&MainMenu);
  SetMenuChecks(&PopupMenu);
  dlgBreakPoints->ShowWindow(SW_SHOW);
  }

/**************************************/
void CMainWindow::CloseBreakpoints()
  {
  fShowBreakpoints=FALSE;
  pHP41->fBreakPtsEnable=FALSE;
  SetMenuChecks(&MainMenu);
  SetMenuChecks(&PopupMenu);
  dlgBreakPoints->ShowWindow(SW_HIDE);
  }

/**************************************/
void CMainWindow::OnOptionsBreakpoints()
  {
  fShowBreakpoints=!fShowBreakpoints;
  pHP41->fBreakPtsEnable=fShowBreakpoints;
  SetMenuChecks(&MainMenu);
  SetMenuChecks(&PopupMenu);
  if (dlgBreakPoints->ShowWindow(SW_SHOWNA))
    dlgBreakPoints->ShowWindow(SW_HIDE);
  else
    {
    dlgBreakPoints->ShowWindow(SW_SHOW);
    dlgBreakPoints->SetFocus();
    }
  }

/**************************************/
void CMainWindow::OnOptionsTraceSettings()
  {
  CTraceSettings TraceDlg;
  lstrcpy(TraceDlg.szTraceFilename,pHP41->szTraceFilename);
  TraceDlg.eTraceMode=pHP41->eTraceMode;
  TraceDlg.fTraceRegister=pHP41->fTraceRegister;
  TraceDlg.fTraceOpcode=pHP41->fTraceOpcode;
  TraceDlg.fOctal=pHP41->fOctal;
  TraceDlg.fTraceHpil=pHP41->fTraceHpil;

  if (IDOK==TraceDlg.DoModal())
    {
    lstrcpy(pHP41->szTraceFilename,TraceDlg.szTraceFilename);
    pHP41->eTraceMode=TraceDlg.eTraceMode;
    pHP41->fTraceRegister=TraceDlg.fTraceRegister;
    pHP41->fTraceOpcode=TraceDlg.fTraceOpcode;
    pHP41->fOctal=TraceDlg.fOctal;
    pHP41->fTraceHpil=TraceDlg.fTraceHpil;
    }
  }
