// WgsCnf.cpp : WgsCnf (GUI) main application class
//

#include "stdafx.h"
#include "WgsCnf.h"

#include "MainFrm.h"
#include "CnfDoc.h"
#include "OptTree.h"
#include "gcommlib.h"
#include "CnfAsrt.h"
#include "levels.h"
#include "StrEdit.h"
#include "edtoff.h"
#include "CantRun.h"
#include "wgsmsx.h"
#include "MsxDlg.h"
#include "anychg.h"
#include "Collect.h"

#define FILREV "$Revision: $"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

extern void init();
extern int lodnxt();

static void msxErrHandler( int ecode, char *estring );

/////////////////////////////////////////////////////////////////////////////
// CWgsCnfApp

BEGIN_MESSAGE_MAP(CWgsCnfApp, CWinApp)
     //{{AFX_MSG_MAP(CWgsCnfApp)
     ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
     ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
     ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)
     ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut)
     ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
     ON_COMMAND(ID_EDIT_CUT, OnEditCut)
     ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
     ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
     ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
     ON_UPDATE_COMMAND_UI(ID_FILE_PRINT_PREVIEW, OnUpdateFilePrintPreview)
     ON_UPDATE_COMMAND_UI(ID_FILE_PRINT, OnUpdateFilePrint)
     ON_UPDATE_COMMAND_UI(IDD_TEXTREPORT, OnUpdateTextreport)
     //}}AFX_MSG_MAP
     // Standard file based document commands
     ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
     ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
     // Standard print setup command
     ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CWgsCnfApp construction

CWgsCnfApp::CWgsCnfApp()
{
     m_runOk = FALSE;
     m_nCmdShow = SW_MINIMIZE;
     m_anyChanges = FALSE;
     m_dumpToFile = FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CWgsCnfApp object

CWgsCnfApp theApp;

/////////////////////////////////////////////////////////////////////////////
// CWgsCnfApp initialization

const char helpfn[] = "help\\wgscnf.hlp";

BOOL CWgsCnfApp::InitInstance()
{
     m_nCmdShow = SW_MINIMIZE;

#ifdef _AFXDLL
     Enable3dControls();           // Call this when using MFC in a shared DLL
#else
     Enable3dControlsStatic();     // Call this when linking to MFC statically
#endif

     SetRegistryKey( "Galacticomm" );

     LoadStdProfileSettings(0);

     // Register the application's document templates.  Document templates
     //  serve as the connection between documents, frame windows and views.

     CSingleDocTemplate* pDocTemplate;
     pDocTemplate = new CSingleDocTemplate(
          IDR_MAINFRAME,
          RUNTIME_CLASS(CnfDoc),
          RUNTIME_CLASS(CMainFrame),       // main SDI frame window
          RUNTIME_CLASS(OptionTree));
     AddDocTemplate(pDocTemplate);

     // Parse command line for standard shell commands, DDE, file open
     // (and ignore them - PR)
     WgsCnfCmdLineInfo cmdInfo;
     ParseCommandLine(cmdInfo);

     OnFileNew();
     if (m_pMainWnd == NULL)
     {
          return( FALSE );
     }

     m_pMainWnd->UpdateWindow();

     if (! canRunWGSCNF())
     {
          CantRun dlg;
          dlg.DoModal();
          CnfAssert( theMainFrame != NULL );
          theMainFrame->DontSaveSettings();
          return(FALSE);
     }

     if (anychg(TRUE))             // run WGSINT if we can and should
     {
          if (canRunWGSINT())
          {
               CWaitCursor cursor;
               allowWGSINT();
               BOOL      runRes = RunWgsInt();
          }
     }

     theMainFrame->RestorePosition();

     init();

     free( (void *)m_pszHelpFilePath );
     m_pszHelpFilePath = _tcsdup( helpfn );

     m_runOk = TRUE;

     return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
     CAboutDlg();

// Dialog Data
     //{{AFX_DATA(CAboutDlg)
     enum { IDD = IDD_ABOUTBOX };
     CString   m_regName;
     //}}AFX_DATA

     // ClassWizard generated virtual function overrides
     //{{AFX_VIRTUAL(CAboutDlg)
     protected:
     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
     //}}AFX_VIRTUAL

// Implementation
protected:
     //{{AFX_MSG(CAboutDlg)
          // No message handlers
     //}}AFX_MSG
     DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
     //{{AFX_DATA_INIT(CAboutDlg)
     m_regName = _T("");
     //}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
     CDialog::DoDataExchange(pDX);
     //{{AFX_DATA_MAP(CAboutDlg)
     DDX_Text(pDX, ID_REGNAME, m_regName);
     DDV_MaxChars(pDX, m_regName, 46);
     //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
     //{{AFX_MSG_MAP(CAboutDlg)
          // No message handlers
     //}}AFX_MSG_MAP
END_MESSAGE_MAP()

// App command to run the dialog
void CWgsCnfApp::OnAppAbout()
{
     CAboutDlg aboutDlg;
     aboutDlg.m_regName = m_regName;
     aboutDlg.DoModal();
}

/////////////////////////////////////////////////////////////////////////////
// CWgsCnfApp commands

BOOL                               //   TRUE if there's more to do
CWgsCnfApp::OnIdle(                // background option loading
LONG lCount)                       //   number of calls since last message
{
     static BOOL noMoreToDo = FALSE;
     
     if (CWinApp::OnIdle(lCount))
          return( TRUE );

     if ((lCount > 1) && ExternalEditorActive())
     {
          int  rc = -1;

          if (Finish( rc ))
          {
               CnfDoc *doc = GetDocument();

               doc->FinishExternal( rc );
          }
     }

     if (noMoreToDo)
          return( ExternalEditorActive() );

     if ( lCount > 2 )
     {
          CollectingDialog *cd = NULL;

          if (m_dumpToFile)
          {
               cd = new CollectingDialog();
               cd->Create( IDD_PREPARINGDUMP );
          }

          do
          {
               if (lodnxt() == 0)
               {
                    noMoreToDo = TRUE;
                    theMainFrame->m_sofar = theMainFrame->m_total;

                    CnfDoc *doc = GetDocument();

                    if (doc != NULL)
                    {
                         doc->SetFullyLoaded( TRUE );
                         theMainFrame->ForceStatusBarUpdate();
                    }

                    if (m_dumpToFile)
                    {
                         OptionTree *tree = doc->GetTreeView();

                         tree->TextReport( m_dumpFileName );
                         theMainFrame->SendMessage( WM_CLOSE );
                         delete cd;
                         return( FALSE );
                    }
               }
               else if (cd != NULL)
               {
                    theMainFrame->UpdateWindow();
                    cd->UpdateWindow();
               }
          } while ( m_dumpToFile );

          theMainFrame->UpdateStatusBar();
     }

     return( TRUE );
}


WgsCnfCmdLineInfo::WgsCnfCmdLineInfo() : CCommandLineInfo()
{
     m_nextIsOutputFile = FALSE;
}


void WgsCnfCmdLineInfo::ParseParam( LPCTSTR lpszParam, BOOL bFlag, BOOL bLast )
{
     if (bFlag && (tolower( lpszParam[ 0 ] ) == 'l'))
     {
          m_nextIsOutputFile = FALSE;

          level = atoi( lpszParam + 1 );

          if (level == 0)
          {
               level = -1;
               HideSecrets( FALSE );
          }
     }
     else if (bFlag && (tolower( lpszParam[ 0 ] ) == 'd'))
     {
          m_nextIsOutputFile = FALSE;

          if (strlen( lpszParam ) > 1)
          {
               theApp.SetDumpFile( lpszParam + 1 );
          }
          else
          {
               m_nextIsOutputFile = TRUE;
          }
     }
     else
     {
          if (m_nextIsOutputFile)
          {
               theApp.SetDumpFile( lpszParam );
               m_nextIsOutputFile = FALSE;
          }
     }
}


CnfDoc * CWgsCnfApp::GetDocument() const
{
     POSITION dpos = NULL;
     CDocTemplate *temp = NULL;
     CnfDoc *doc = NULL;

     dpos = GetFirstDocTemplatePosition();

     if (dpos != NULL)
     {
          temp = GetNextDocTemplate( dpos );
     }

     if (temp != NULL)
     {
          dpos = temp->GetFirstDocPosition();
     }
     else
     {
          dpos = NULL;
     }

     if (dpos != NULL)
     {
          doc = static_cast< CnfDoc * >( temp->GetNextDoc( dpos ) );
     }

     return( doc );
}


void CWgsCnfApp::SetRegName( const char *st )
{
     m_regName = st;
}

void CWgsCnfApp::OnEditPaste() 
{
     CnfAssert( theMainFrame != NULL );
     CWnd     *focus = theMainFrame->GetFocus();

     if ((focus != NULL) && focus->IsKindOf( RUNTIME_CLASS( CEdit ) ))
     {
          CEdit     *edit = static_cast< CEdit * >( focus );
          edit->Paste();
     }
}


void CWgsCnfApp::OnEditCut() 
{
     CnfAssert( theMainFrame != NULL );
     CWnd     *focus = theMainFrame->GetFocus();

     if ((focus != NULL) && focus->IsKindOf( RUNTIME_CLASS( CEdit ) ))
     {
          CEdit     *edit = static_cast< CEdit * >( focus );
          edit->Cut();
     }
}

void CWgsCnfApp::OnEditCopy() 
{
     CnfAssert( theMainFrame != NULL );
     CWnd     *focus = theMainFrame->GetFocus();

     if ((focus != NULL) && focus->IsKindOf( RUNTIME_CLASS( CEdit ) ))
     {
          CEdit     *edit = static_cast< CEdit * >( focus );
          edit->Copy();
     }
}

void CWgsCnfApp::OnEditUndo() 
{
     CnfAssert( theMainFrame != NULL );
     CWnd     *focus = theMainFrame->GetFocus();

     if (focus != NULL)
     {
          if (focus->IsKindOf( RUNTIME_CLASS( StringEdit ) ))
          {
               StringEdit     *edit = static_cast< StringEdit * >( focus );
               edit->Undo();
          }
          else if (focus->IsKindOf( RUNTIME_CLASS( CEdit ) ))
          {
               CEdit     *edit = static_cast< CEdit * >( focus );
               edit->Undo();
          }
     }
}

void CWgsCnfApp::ForceExit()
{
     CnfDoc *doc = GetDocument();
     CnfAssert( doc != NULL );

     doc->SetModifiedFlag( FALSE );

     theMainFrame->SendMessage( WM_CLOSE );
}

BOOL CWgsCnfApp::RunWgsInt()
{
     PROCESS_INFORMATION processInfo;
     STARTUPINFO startInfo;

     GetStartupInfo( &startInfo );

     BOOL      success = CreateProcess( "wgsint.exe", NULL,
                                        NULL, NULL,
                                        FALSE, NORMAL_PRIORITY_CLASS,
                                        NULL,
                                        NULL,
                                        &startInfo, &processInfo
                                      );

     if (success) 
     {
          HANDLE procHand = processInfo.hProcess;
          HANDLE threadHand = processInfo.hThread;

          ::WaitForSingleObject( procHand, INFINITE );

          DWORD     exCode = 0xFFFF;
          ::GetExitCodeProcess( procHand, &exCode );

          ::CloseHandle( procHand );
          ::CloseHandle( threadHand );

          success = (exCode == 0);
     }

     return( success );
}

int CWgsCnfApp::ExitInstance() 
{
     //   reindex MSG files if needed and possible
     //
     if (m_runOk && m_anyChanges && canRunUtil())
     {
          CHAR argc=0;
          CHAR *argv[]={""};

          MsxDialog dlg;

          dlg.Create( IDD_MSX );

          wgsmsx( argc, argv, &dlg, &dlg.m_source, &dlg.m_dest,
                  &dlg.m_singleProgress, &dlg.m_multiProgress,
                  msxErrHandler
                );

          dlg.DestroyWindow();
     }
     
     return CWinApp::ExitInstance();
}

static void msxErrHandler( int ecode, char *estring )
{
     CString   msxError;
     msxError.Format( "Message indexing error %i:\r\n"
                      "%s",
                      ecode, estring
                    );

     ::MessageBox( NULL, msxError, "Worlgroup Configuration Editor",
                   MB_OK | MB_ICONSTOP | MB_APPLMODAL
                 );
}

void
CWgsCnfApp::NoteChanges()          // remember that changes were made to .MSG's
{
     m_anyChanges = TRUE;
}

//   --   UI Update handlers   --
//

void CWgsCnfApp::OnUpdateEditPaste(CCmdUI* pCmdUI) 
{
     CnfAssert( theMainFrame != NULL );
     CWnd     *focus = theMainFrame->GetFocus();

     BOOL      enabled = (focus != NULL) && focus->IsKindOf( RUNTIME_CLASS( CEdit ) );

     if (enabled)
     {
          DWORD     style = ((CEdit *)focus)->GetStyle();

          enabled = ! (style & ES_READONLY);
     }

     pCmdUI->Enable( enabled );
}

void CWgsCnfApp::OnUpdateEditCut(CCmdUI* pCmdUI) 
{
     CnfAssert( theMainFrame != NULL );
     CWnd     *focus = theMainFrame->GetFocus();

     BOOL      enabled = (focus != NULL) && focus->IsKindOf( RUNTIME_CLASS( CEdit ) );

     if (enabled)
     {
          DWORD     style = ((CEdit *)focus)->GetStyle();

          enabled = ! (style & ES_READONLY);
     }

     if (enabled)
     {
          int       startSel;
          int       endSel;

          ((CEdit *)focus)->GetSel( startSel, endSel );

          enabled = (endSel > startSel);
     }

     pCmdUI->Enable( enabled );
}

void CWgsCnfApp::OnUpdateEditCopy(CCmdUI* pCmdUI) 
{
     CnfAssert( theMainFrame != NULL );
     CWnd     *focus = theMainFrame->GetFocus();

     BOOL      enabled = (focus != NULL) && focus->IsKindOf( RUNTIME_CLASS( CEdit ) );

     if (enabled)
     {
          int       startSel;
          int       endSel;

          ((CEdit *)focus)->GetSel( startSel, endSel );

          enabled = (endSel > startSel);
     }

     pCmdUI->Enable( enabled );
}

void CWgsCnfApp::OnUpdateEditUndo(CCmdUI* pCmdUI) 
{
     CnfAssert( theMainFrame != NULL );
     CWnd     *focus = theMainFrame->GetFocus();

     BOOL      enabled = (focus != NULL) && 
                         focus->IsKindOf( RUNTIME_CLASS( StringEdit ) ) &&
                         ((StringEdit *)focus)->CanUndo();

     pCmdUI->Enable( enabled );
}

void CWgsCnfApp::OnUpdateFilePrintPreview(CCmdUI* pCmdUI) 
{
     BOOL      enabled = FALSE;

     CnfDoc *doc = GetDocument();

     if (doc != NULL)
     {
          enabled = doc->FullyLoaded();
     }

     pCmdUI->Enable( enabled );
}


void CWgsCnfApp::OnUpdateFilePrint(CCmdUI* pCmdUI) 
{
     BOOL      enabled = FALSE;

     CnfDoc *doc = GetDocument();

     if (doc != NULL)
     {
          enabled = doc->FullyLoaded();
     }

     pCmdUI->Enable( enabled );
}



void CWgsCnfApp::OnUpdateTextreport(CCmdUI* pCmdUI) 
{
     BOOL      enabled = FALSE;

     CnfDoc *doc = GetDocument();

     if (doc != NULL)
     {
          enabled = doc->FullyLoaded();
     }

     pCmdUI->Enable( enabled );
}


void CWgsCnfApp::SetDumpFile( LPCTSTR dumpFileName )
{
     m_dumpFileName = dumpFileName;
     m_dumpToFile = TRUE;
}
