// *********************************************************************
//    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.
// *********************************************************************

// *********************************************************************
//  V41.cpp
// *********************************************************************

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

#ifdef _MCODE
#define new MCODE_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CApp theApp;     // the one and only CApp object

const char CApp::szUntitledName[] = "Untitled";

/**************************************/
BEGIN_MESSAGE_MAP(CApp,CWinApp)
  //{{AFX_MSG_MAP(CApp)
  //}}AFX_MSG
END_MESSAGE_MAP()

/**************************************/
CApp::CApp()
  {
  }

/**************************************/
class MyCmdLine : public CCommandLineInfo
  {
  public:
  virtual void ParseParam(const char* pszParam,BOOL bFlag,BOOL bLast)
    {
    if (bFlag)
      MyParseParamFlag(pszParam);
  else
      CCommandLineInfo::ParseParamNotFlag(pszParam);
    ParseLast(bLast);
    }
  protected:
  void MyParseParamFlag(const char* pszParam)
    {
    if (lstrcmpA(pszParam,"console") == 0)
      theApp.fConsole=TRUE;
    else
    CCommandLineInfo::ParseParamFlag(pszParam);
    }
  };

/**************************************/
void CApp::AddToRecentFileList(LPCTSTR lpszPathName)
  {
  // lpszPathName will be added to the top of the MRU list.
  // If lpszPathName already exists in the MRU list, it will be moved to the top
  if (m_pRecentFileList != NULL)
    {
    m_pRecentFileList->Add(lpszPathName);
    }
  }

/**************************************/
BOOL CApp::InitInstance()
  {
  char szModulePath[_MAX_PATH];             // full path of application
  char szLastSession[_MAX_PATH] = { 0, };   // last session name

  fConsole=FALSE;
  fSingle=TRUE;
  nFileCount=4;                             // no. of MRU entries

  ::GetModuleFileName(NULL,szModulePath,_MAX_PATH);
  GetFullPathName(szModulePath,sizeof(szAppFullPath),szAppFullPath,NULL);

  HKEY hKey;
  if (ERROR_SUCCESS==RegOpenKeyEx(HKEY_CURRENT_USER,APP_KEY,0,KEY_QUERY_VALUE,&hKey))
    {
    // get single instance option
    DWORD dwValue;
    DWORD dwSize=sizeof(dwValue);
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_SINGLE,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      fSingle=(flag)dwValue;

    // get last session name
    dwSize=sizeof(szLastSession);
    if (ERROR_SUCCESS!=RegQueryValueEx(hKey,APP_LASTSESSION,NULL,NULL,(LPBYTE)szLastSession,&dwSize))
      szLastSession[0]=0;

    // get maximum of Recent File List entries
    dwSize=sizeof(dwValue);
    if (ERROR_SUCCESS==RegQueryValueEx(hKey,APP_MRU_FILECOUNT,NULL,NULL,(LPBYTE)&dwValue,&dwSize))
      nFileCount=dwValue;

    RegCloseKey(hKey);
    }

  MyCmdLine cmdInfo;
  ParseCommandLine(cmdInfo);
  if (cmdInfo.m_nShellCommand==CCommandLineInfo::FileOpen)
    {
    CString strFileName;
    char drive[_MAX_DRIVE],dir[_MAX_DIR],fname[_MAX_FNAME],ext[_MAX_EXT];
    _splitpath(cmdInfo.m_strFileName,drive,dir,fname,ext);
    strFileName = fname;            // filename without extention
    if (_stricmp(ext,".lod") != 0)  // not the .lod extention
      {
      strFileName += ext;           // the extention is part of the filename
      }
    if (*drive == 0 && *dir == 0)   // no path name
      _splitpath(szAppFullPath,drive,dir,fname,ext);
    _makepath(szSessionName,drive,dir,strFileName,"lod");
    }
  else
    szSessionName[0]=0;

  // get single instance option
  // Q141752, Q238100:
  CWnd *pWndPrev;
  if (fSingle && (pWndPrev=CWnd::FindWindow(_T(MAKEINTRESOURCE(IDR_MAINFRAME)),NULL)))  // activate previous windows and terminate
    {
    if (pWndPrev->IsIconic())
      pWndPrev->ShowWindow(SW_RESTORE);
    pWndPrev->GetLastActivePopup()->SetForegroundWindow();

    if (*szSessionName != 0)  // have a filename to send?
      {
      COPYDATASTRUCT sCDS;

      // size of file name incl. EOS
      sCDS.cbData = (lstrlen(szSessionName) + 1) * sizeof(szSessionName[0]);
      sCDS.lpData = szSessionName;

      // fill the COPYDATA structure and send file name to the other instance
      sCDS.dwData = CDID_FILENAME;  // function identifier
      pWndPrev->SendMessage(WM_COPYDATA,(WPARAM) NULL,(LPARAM) &sCDS);
      }

    return FALSE;
    }

  // disable TIMER_RESOLUTION throttling for Windows 11 and later
  {
  typedef const BOOL(WINAPI* LPFN_SPI)(HANDLE hProcess,INT ProcessInformationClass,LPVOID ProcessInformation,DWORD ProcessInformationSize);

  // SetProcessInformation() is available since Windows 8, PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION since Windows 11
  LPFN_SPI fnSetProcessInformation = (LPFN_SPI) GetProcAddress(GetModuleHandle(_T("kernel32")), "SetProcessInformation");

  if (fnSetProcessInformation != NULL)			// running on Windows 8 or later
    {
    PROCESS_POWER_THROTTLING_STATE Ppts;

    ZeroMemory(&Ppts,sizeof(Ppts));
    Ppts.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION;
    Ppts.ControlMask = PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION;

    // don't check for success, success only on Windoes 11 and later
    fnSetProcessInformation(GetCurrentProcess(),ProcessPowerThrottling,&Ppts,sizeof(Ppts));
    }
  }

  // create file MRU
  SetRegistryKey(_T(""));
  m_pRecentFileList = new CRecentFileList(0,"Recent File List","File%d",nFileCount);
  m_pRecentFileList->ReadList();

  if (*szSessionName==0)                    // session name empty
    lstrcpy(szSessionName,szLastSession);   // use last session

  // register window class manually
  WNDCLASS wndcls;
  memset(&wndcls,0,sizeof(WNDCLASS));
  wndcls.style=CS_HREDRAW|CS_VREDRAW;
  wndcls.lpfnWndProc=::DefWindowProc;
  wndcls.hInstance=AfxGetInstanceHandle();
  wndcls.hIcon=LoadIcon(IDR_MAINFRAME);
  wndcls.hCursor=NULL;
  wndcls.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
  wndcls.lpszMenuName=NULL;
  wndcls.lpszClassName=_T(MAKEINTRESOURCE(IDR_MAINFRAME));
  if(!AfxRegisterClass(&wndcls))
    return FALSE;

  theApp.pPalForeground=NULL;

#if _MSC_VER <= 1200 // MSVC6 and earlier
  Enable3dControls();
#endif
  pMainWnd=new CMainWindow();
  m_pMainWnd=pMainWnd;
  m_pMainWnd->ShowWindow(m_nCmdShow);
  m_pMainWnd->UpdateWindow();

  // start HPIL after main window showed
  pMainWnd->GetHP41()->StartHpil();
  return TRUE;
  }

/**************************************/
int CApp::ExitInstance()
  {
  ::UnregisterClass(_T(MAKEINTRESOURCE(IDR_MAINFRAME)),AfxGetInstanceHandle());
  return CWinApp::ExitInstance();
  }

/**************************************/
CDocument* CApp::OpenDocumentFile(LPCTSTR lpszFileName)
  {
  bool bSucc=true;
  if (IDCANCEL!=pMainWnd->FileSave(false))
    bSucc = pMainWnd->FileOpen(lpszFileName);
  return(bSucc ? (CDocument*) 1 : NULL); // CWinApp::OpenDocumentFile(lpszFileName);
  }
