home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / APPCORE.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-03  |  21.7 KB  |  892 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1997 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12. #include <malloc.h>
  13. #ifdef _MAC
  14. #include <macname1.h>
  15. #include <Types.h>
  16. #include <GestaltEqu.h>
  17. #include <AERegistry.h>
  18. #include <Errors.h>
  19. #include <macname2.h>
  20. #endif
  21.  
  22. #ifdef AFX_CORE1_SEG
  23. #pragma code_seg(AFX_CORE1_SEG)
  24. #endif
  25.  
  26. #ifdef _DEBUG
  27. #undef THIS_FILE
  28. static char THIS_FILE[] = __FILE__;
  29. #endif
  30.  
  31. static const TCHAR szFileSection[] = _T("Recent File List");
  32. static const TCHAR szFileEntry[] = _T("File%d");
  33. static const TCHAR szPreviewSection[] = _T("Settings");
  34. static const TCHAR szPreviewEntry[] = _T("PreviewPages");
  35.  
  36. /////////////////////////////////////////////////////////////////////////////
  37. // globals (internal library use)
  38.  
  39. // CDocManager statics are in this file for granularity reasons
  40. BOOL CDocManager::bStaticInit = TRUE;
  41. CDocManager* CDocManager::pStaticDocManager = NULL;
  42. CPtrList* CDocManager::pStaticList = NULL;
  43.  
  44. BEGIN_MESSAGE_MAP(CWinApp, CCmdTarget)
  45.     //{{AFX_MSG_MAP(CWinApp)
  46.     // Global File commands
  47.     ON_COMMAND(ID_APP_EXIT, OnAppExit)
  48.     // MRU - most recently used file menu
  49.     ON_UPDATE_COMMAND_UI(ID_FILE_MRU_FILE1, OnUpdateRecentFileMenu)
  50.     ON_COMMAND_EX_RANGE(ID_FILE_MRU_FILE1, ID_FILE_MRU_FILE16, OnOpenRecentFile)
  51.     //}}AFX_MSG_MAP
  52. END_MESSAGE_MAP()
  53.  
  54. /////////////////////////////////////////////////////////////////////////////
  55. // _AFX_WIN_STATE implementation
  56.  
  57. #ifdef AFX_INIT_SEG
  58. #pragma code_seg(AFX_INIT_SEG)
  59. #endif
  60.  
  61. _AFX_WIN_STATE::_AFX_WIN_STATE()
  62. {
  63.     // Note: it is only necessary to intialize non-zero data.
  64.  
  65. #ifdef _MAC
  66.     // by default, don't override DefWindowProc's coloring
  67.     m_crDlgTextClr = (COLORREF)-1;
  68. #endif
  69. }
  70.  
  71. #ifdef AFX_TERM_SEG
  72. #pragma code_seg(AFX_TERM_SEG)
  73. #endif
  74.  
  75. _AFX_WIN_STATE::~_AFX_WIN_STATE()
  76. {
  77.     AfxDeleteObject((HGDIOBJ*)&m_hDlgBkBrush);
  78. }
  79.  
  80. #ifdef AFX_INIT_SEG
  81. #pragma code_seg(AFX_INIT_SEG)
  82. #endif
  83.  
  84. CWinApp::CWinApp(LPCTSTR lpszAppName)
  85. {
  86.     if (lpszAppName != NULL)
  87.         m_pszAppName = _tcsdup(lpszAppName);
  88.     else
  89.         m_pszAppName = NULL;
  90.  
  91.     // initialize CWinThread state
  92.     AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
  93.     AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;
  94.     ASSERT(AfxGetThread() == NULL);
  95.     pThreadState->m_pCurrentWinThread = this;
  96.     ASSERT(AfxGetThread() == this);
  97.     m_hThread = ::GetCurrentThread();
  98.     m_nThreadID = ::GetCurrentThreadId();
  99.  
  100.     // initialize CWinApp state
  101.     ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please
  102.     pModuleState->m_pCurrentWinApp = this;
  103.     ASSERT(AfxGetApp() == this);
  104.  
  105.     // in non-running state until WinMain
  106.     m_hInstance = NULL;
  107.     m_pszHelpFilePath = NULL;
  108.     m_pszProfileName = NULL;
  109.     m_pszRegistryKey = NULL;
  110.     m_pszExeName = NULL;
  111.     m_pRecentFileList = NULL;
  112.     m_pDocManager = NULL;
  113.     m_atomApp = m_atomSystemTopic = NULL;
  114.     m_lpCmdLine = NULL;
  115.     m_pCmdInfo = NULL;
  116.  
  117.     // initialize wait cursor state
  118.     m_nWaitCursorCount = 0;
  119.     m_hcurWaitCursorRestore = NULL;
  120.  
  121.     // initialize current printer state
  122.     m_hDevMode = NULL;
  123.     m_hDevNames = NULL;
  124.     m_nNumPreviewPages = 0;     // not specified (defaults to 1)
  125.  
  126.     // initialize DAO state
  127.     m_lpfnDaoTerm = NULL;   // will be set if AfxDaoInit called
  128.  
  129.     // other initialization
  130.     m_bHelpMode = FALSE;
  131.     m_nSafetyPoolSize = 512;        // default size
  132.  
  133. #ifdef _MAC
  134.     m_nSaveOption = saveAsk;
  135. #endif
  136. }
  137.  
  138. BOOL CWinApp::InitApplication()
  139. {
  140.     if (CDocManager::pStaticDocManager != NULL)
  141.     {
  142.         if (m_pDocManager == NULL)
  143.             m_pDocManager = CDocManager::pStaticDocManager;
  144.         CDocManager::pStaticDocManager = NULL;
  145.     }
  146.  
  147.     if (m_pDocManager != NULL)
  148.         m_pDocManager->AddDocTemplate(NULL);
  149.     else
  150.         CDocManager::bStaticInit = FALSE;
  151.  
  152.     return TRUE;
  153. }
  154.  
  155. BOOL CWinApp::InitInstance()
  156. {
  157.     return TRUE;
  158. }
  159.  
  160. void CWinApp::LoadStdProfileSettings(UINT nMaxMRU)
  161. {
  162.     ASSERT_VALID(this);
  163.     ASSERT(m_pRecentFileList == NULL);
  164.  
  165.     if (nMaxMRU != 0)
  166.     {
  167.         // create file MRU since nMaxMRU not zero
  168.         m_pRecentFileList = new CRecentFileList(0, szFileSection, szFileEntry,
  169.             nMaxMRU);
  170.         m_pRecentFileList->ReadList();
  171.     }
  172.     // 0 by default means not set
  173.     m_nNumPreviewPages = GetProfileInt(szPreviewSection, szPreviewEntry, 0);
  174. }
  175.  
  176. void CWinApp::ParseCommandLine(CCommandLineInfo& rCmdInfo)
  177. {
  178. #ifndef _MAC
  179.     for (int i = 1; i < __argc; i++)
  180.     {
  181.         LPCTSTR pszParam = __targv[i];
  182.         BOOL bFlag = FALSE;
  183.         BOOL bLast = ((i + 1) == __argc);
  184.         if (pszParam[0] == '-' || pszParam[0] == '/')
  185.         {
  186.             // remove flag specifier
  187.             bFlag = TRUE;
  188.             ++pszParam;
  189.         }
  190.         rCmdInfo.ParseParam(pszParam, bFlag, bLast);
  191.     }
  192. #else
  193.     // WLM command line can contain only one parameter,
  194.     // /Embedding
  195.  
  196.     if (m_lpCmdLine[0] == '-' || m_lpCmdLine[0] == '/')
  197.     {
  198.         rCmdInfo.ParseParam(m_lpCmdLine+1, TRUE, TRUE);
  199.     }
  200.  
  201. #endif // _MAC
  202. }
  203.  
  204. /////////////////////////////////////////////////////////////////////////////
  205. // CCommandLineInfo implementation
  206.  
  207. CCommandLineInfo::CCommandLineInfo()
  208. {
  209.     m_bShowSplash = TRUE;
  210.     m_bRunEmbedded = FALSE;
  211.     m_bRunAutomated = FALSE;
  212.     m_nShellCommand = FileNew;
  213. }
  214.  
  215. CCommandLineInfo::~CCommandLineInfo()
  216. {
  217. }
  218.  
  219. void CCommandLineInfo::ParseParam(const TCHAR* pszParam,BOOL bFlag,BOOL bLast)
  220. {
  221.     if (bFlag)
  222.     {
  223.         USES_CONVERSION;
  224.         ParseParamFlag(T2CA(pszParam));
  225.     }
  226.     else
  227.         ParseParamNotFlag(pszParam);
  228.  
  229.     ParseLast(bLast);
  230. }
  231.  
  232. #ifdef UNICODE
  233. void CCommandLineInfo::ParseParam(const char* pszParam, BOOL bFlag, BOOL bLast)
  234. {
  235.     if (bFlag)
  236.         ParseParamFlag(pszParam);
  237.     else
  238.         ParseParamNotFlag(pszParam);
  239.  
  240.     ParseLast(bLast);
  241. }
  242. #endif // UNICODE
  243.  
  244. void CCommandLineInfo::ParseParamFlag(const char* pszParam)
  245. {
  246.     // OLE command switches are case insensitive, while
  247.     // shell command switches are case sensitive
  248.  
  249.     if (lstrcmpA(pszParam, "pt") == 0)
  250.         m_nShellCommand = FilePrintTo;
  251.     else if (lstrcmpA(pszParam, "p") == 0)
  252.         m_nShellCommand = FilePrint;
  253.     else if (lstrcmpiA(pszParam, "Unregister") == 0 ||
  254.              lstrcmpiA(pszParam, "Unregserver") == 0)
  255.         m_nShellCommand = AppUnregister;
  256.     else if (lstrcmpA(pszParam, "dde") == 0)
  257.     {
  258.         AfxOleSetUserCtrl(FALSE);
  259.         m_nShellCommand = FileDDE;
  260.     }
  261.     else if (lstrcmpiA(pszParam, "Embedding") == 0)
  262.     {
  263.         AfxOleSetUserCtrl(FALSE);
  264.         m_bRunEmbedded = TRUE;
  265.         m_bShowSplash = FALSE;
  266.     }
  267.     else if (lstrcmpiA(pszParam, "Automation") == 0)
  268.     {
  269.         AfxOleSetUserCtrl(FALSE);
  270.         m_bRunAutomated = TRUE;
  271.         m_bShowSplash = FALSE;
  272.     }
  273. }
  274.  
  275. void CCommandLineInfo::ParseParamNotFlag(const TCHAR* pszParam)
  276. {
  277.     if (m_strFileName.IsEmpty())
  278.         m_strFileName = pszParam;
  279.     else if (m_nShellCommand == FilePrintTo && m_strPrinterName.IsEmpty())
  280.         m_strPrinterName = pszParam;
  281.     else if (m_nShellCommand == FilePrintTo && m_strDriverName.IsEmpty())
  282.         m_strDriverName = pszParam;
  283.     else if (m_nShellCommand == FilePrintTo && m_strPortName.IsEmpty())
  284.         m_strPortName = pszParam;
  285. }
  286.  
  287. #ifdef UNICODE
  288. void CCommandLineInfo::ParseParamNotFlag(const char* pszParam)
  289. {
  290.     if (m_strFileName.IsEmpty())
  291.         m_strFileName = pszParam;
  292.     else if (m_nShellCommand == FilePrintTo && m_strPrinterName.IsEmpty())
  293.         m_strPrinterName = pszParam;
  294.     else if (m_nShellCommand == FilePrintTo && m_strDriverName.IsEmpty())
  295.         m_strDriverName = pszParam;
  296.     else if (m_nShellCommand == FilePrintTo && m_strPortName.IsEmpty())
  297.         m_strPortName = pszParam;
  298. }
  299. #endif
  300.  
  301. void CCommandLineInfo::ParseLast(BOOL bLast)
  302. {
  303.     if (bLast)
  304.     {
  305.         if (m_nShellCommand == FileNew && !m_strFileName.IsEmpty())
  306.             m_nShellCommand = FileOpen;
  307.         m_bShowSplash = !m_bRunEmbedded && !m_bRunAutomated;
  308.     }
  309. }
  310.  
  311. /////////////////////////////////////////////////////////////////////////////
  312. // CWinApp MAC implementation
  313.  
  314. #ifdef _MAC
  315. BOOL CWinApp::CreateInitialDocument()
  316. {
  317.     if (m_pMainWnd != NULL)
  318.         m_pMainWnd->SendMessage(WM_COMMAND, ID_FILE_NEW);
  319.     else if (m_pDocManager != NULL)
  320.     {
  321.         POSITION pos = m_pDocManager->GetFirstDocTemplatePosition();
  322.         if (pos != NULL)
  323.         {
  324.             CDocTemplate* pTemplate = m_pDocManager->GetNextDocTemplate(pos);
  325.  
  326.             // if MDI, or SDI but we haven't opened any documents yet, open a new one
  327.             if (pTemplate != NULL &&
  328.                 (pTemplate->IsKindOf(RUNTIME_CLASS(CMultiDocTemplate)) ||
  329.                 m_pDocManager->GetOpenDocumentCount() == 0))
  330.             {
  331.                 OnFileNew();
  332.             }
  333.         }
  334.     }
  335.  
  336.     return TRUE;
  337. }
  338.  
  339. /////////////////////////////////////////////////////////////////////////////
  340. // required AppleEvent handlers
  341.  
  342. static OSErr MissingParams(AppleEvent* pae)
  343. {
  344.     OSErr       err;
  345.     DescType    dtT;
  346.     Size        lT;
  347.  
  348.     err = AEGetAttributePtr(pae, keyMissedKeywordAttr, typeWildCard,
  349.             &dtT, NULL, 0, &lT);
  350.  
  351.     if (err == errAEDescNotFound)
  352.         return noErr;
  353.     else if (err == noErr)
  354.         return errAEEventNotHandled;
  355.     else
  356.         return err;
  357. }
  358.  
  359. static OSErr HandlerCommon(AppleEvent* pae, long lRefcon, CWinApp*& rpApp)
  360. {
  361.     OSErr err = MissingParams(pae);
  362.     if (err != noErr)
  363.         return err;
  364.  
  365.     rpApp = (CWinApp*) lRefcon;
  366.     ASSERT_VALID(rpApp);
  367.     ASSERT_KINDOF(CWinApp, rpApp);
  368.  
  369.     return noErr;
  370. }
  371.  
  372. OSErr PASCAL _AfxOpenAppHandler(AppleEvent* pae, AppleEvent*, long lRefcon)
  373. {
  374.     CWinApp* pApp;
  375.     OSErr err = HandlerCommon(pae, lRefcon, pApp);
  376.     if (err == noErr)
  377.     {
  378.         if (pApp->CreateInitialDocument())
  379.             err = noErr;
  380.         else
  381.             err = errAEEventNotHandled;
  382.     }
  383.     AfxOleSetUserCtrl(TRUE);
  384.     return err;
  385. }
  386.  
  387. OSErr PASCAL _AfxOpenDocHandler(AppleEvent* pae, AppleEvent*, long lRefcon)
  388. {
  389.     AEDescList docList;
  390.     OSErr err = AEGetParamDesc(pae, keyDirectObject, typeAEList, &docList);
  391.     if (err == noErr)
  392.     {
  393.         CWinApp* pApp;
  394.         err = HandlerCommon(pae, lRefcon, pApp);
  395.         if (err == noErr)
  396.         {
  397.             long cDoc;
  398.             VERIFY(AECountItems(&docList, &cDoc) == noErr);
  399.  
  400.             for (int iDoc = 1; iDoc <= cDoc; iDoc++)
  401.             {
  402.                 AEKeyword key;
  403.                 DescType dt;
  404.                 long lcb;
  405.                 FSSpec fss;
  406.  
  407.                 if (AEGetNthPtr(&docList, iDoc, typeFSS, &key, &dt, (Ptr) &fss,
  408.                         sizeof(FSSpec), &lcb) == noErr)
  409.                 {
  410.                     ASSERT(dt == typeFSS);
  411.                     ASSERT(lcb == sizeof(FSSpec));
  412.  
  413.                     char sz[256];
  414.                     if (WrapFile(&fss, sz, sizeof(sz)))
  415.                         pApp->OpenDocumentFile(sz);
  416.                 }
  417.             }
  418.         }
  419.         VERIFY(AEDisposeDesc(&docList) == noErr);
  420.     }
  421.  
  422.     AfxOleSetUserCtrl(TRUE);
  423.     return err;
  424. }
  425.  
  426. OSErr PASCAL _AfxPrintDocHandler(AppleEvent* pae, AppleEvent*, long lRefcon)
  427. {
  428.     AEDescList docList;
  429.  
  430.     SetCursor(afxData.hcurArrow);
  431.     OSErr err = AEGetParamDesc(pae, keyDirectObject, typeAEList, &docList);
  432.     if (err == noErr)
  433.     {
  434.         CWinApp* pApp;
  435.         err = HandlerCommon(pae, lRefcon, pApp);
  436.         if (err == noErr)
  437.         {
  438.             long cDoc;
  439.             AEInteractAllowed level;
  440.             BOOL bLevelChanged = TRUE;
  441.  
  442.             VERIFY(AECountItems(&docList, &cDoc) == noErr);
  443.             if (AEGetInteractionAllowed(&level) != noErr)
  444.             {
  445.                 bLevelChanged = FALSE;
  446.             }
  447.  
  448.             for (int iDoc = 1; iDoc <= cDoc; iDoc++)
  449.             {
  450.                 AEKeyword key;
  451.                 DescType dt;
  452.                 long lcb;
  453.                 FSSpec fss;
  454.  
  455.                 if ((iDoc == 2) && (bLevelChanged) &&
  456.                     (AESetInteractionAllowed(kAEInteractWithSelf) != noErr))
  457.                 {
  458.                     bLevelChanged = FALSE;
  459.                 }
  460.  
  461.                 if (AEGetNthPtr(&docList, iDoc, typeFSS, &key, &dt, (Ptr) &fss,
  462.                         sizeof(FSSpec), &lcb) == noErr)
  463.                 {
  464.                     CDocument* pDoc = NULL;
  465.  
  466.                     ASSERT(dt == typeFSS);
  467.                     ASSERT(lcb == sizeof(FSSpec));
  468.  
  469.                     char sz[256];
  470.                     if (WrapFile(&fss, sz, sizeof(sz)))
  471.                         pDoc = pApp->OpenDocumentFile(sz);
  472.  
  473.                     if(pDoc != NULL)
  474.                     {
  475.                         POSITION pos = pDoc->GetFirstViewPosition();
  476.                         CView* pView = pDoc->GetNextView(pos);
  477.  
  478.                         if(pView != NULL)
  479.                         {
  480.                             pView->SendMessage(WM_COMMAND, ID_FILE_PRINT);
  481.                         }
  482.                         pDoc->OnCloseDocument();
  483.                     }
  484.                 }
  485.             }
  486.             if (bLevelChanged)
  487.             {
  488.                 AESetInteractionAllowed(level);
  489.             }
  490.         }
  491.         VERIFY(AEDisposeDesc(&docList) == noErr);
  492.     }
  493.  
  494.     AfxOleSetUserCtrl(TRUE);
  495.     return err;
  496. }
  497.  
  498. OSErr PASCAL _AfxQuitHandler(AppleEvent* pae, AppleEvent*, long lRefcon)
  499. {
  500.     long newSave;
  501.     DescType dt;
  502.     long lcb;
  503.  
  504.     if (AEGetParamPtr(pae, keyAESaveOptions, typeEnumeration, &dt,
  505.             (Ptr) &newSave, sizeof(newSave), &lcb) != noErr)
  506.         newSave = kAEAsk;
  507. #ifdef _DEBUG
  508.     else
  509.     {
  510.         ASSERT(dt == typeEnumeration);
  511.         ASSERT(lcb == sizeof(newSave));
  512.     }
  513. #endif
  514.  
  515.     CWinApp* pApp;
  516.     OSErr err = HandlerCommon(pae, lRefcon, pApp);
  517.     if (err != noErr)
  518.         return err;
  519.  
  520.     CWinApp::SaveOption oldSave = pApp->m_nSaveOption;
  521.  
  522.     switch (newSave)
  523.     {
  524.         case kAEYes:
  525.             pApp->m_nSaveOption = CWinApp::saveYes;
  526.             break;
  527.  
  528.         case kAENo:
  529.             pApp->m_nSaveOption = CWinApp::saveNo;
  530.             break;
  531.  
  532.         case kAEAsk:
  533.             pApp->m_nSaveOption = CWinApp::saveAsk;
  534.             break;
  535.  
  536.         default:
  537.             break;
  538.     }
  539.  
  540.     ASSERT(err == noErr);   // initial state assumed by the following code
  541.  
  542.     if (pApp->m_pMainWnd != NULL)
  543.     {
  544.         pApp->m_pMainWnd->SendMessage(WM_COMMAND, ID_APP_EXIT);
  545.         if (pApp->m_pMainWnd != NULL)
  546.             err = userCanceledErr;
  547.     }
  548.     else
  549.     {
  550.         // Perhaps the app is using a dialog as its UI. Just tell it
  551.         // to quit directly.
  552.  
  553.         AfxPostQuitMessage(0);
  554.     }
  555.     pApp->m_nSaveOption = oldSave;
  556.  
  557.     return err;
  558. }
  559.  
  560. #endif //_MAC
  561.  
  562. /////////////////////////////////////////////////////////////////////////////
  563. // App termination
  564.  
  565. CWinApp::~CWinApp()
  566. {
  567.     // free doc manager
  568.     if (m_pDocManager != NULL)
  569.         delete m_pDocManager;
  570.  
  571.     // free recent file list
  572.     if (m_pRecentFileList != NULL)
  573.         delete m_pRecentFileList;
  574.  
  575.     // free static list of document templates
  576.     if (!afxContextIsDLL)
  577.     {
  578.         if (CDocManager::pStaticList != NULL)
  579.         {
  580.             delete CDocManager::pStaticList;
  581.             CDocManager::pStaticList = NULL;
  582.         }
  583.         if (CDocManager::pStaticDocManager != NULL)
  584.         {
  585.             delete CDocManager::pStaticDocManager;
  586.             CDocManager::pStaticDocManager = NULL;
  587.         }
  588.     }
  589.  
  590.     // free printer info
  591.     if (m_hDevMode != NULL)
  592.         AfxGlobalFree(m_hDevMode);
  593.     if (m_hDevNames != NULL)
  594.         AfxGlobalFree(m_hDevNames);
  595.  
  596.     // free atoms if used
  597.     if (m_atomApp != NULL)
  598.         ::GlobalDeleteAtom(m_atomApp);
  599.     if (m_atomSystemTopic != NULL)
  600.         ::GlobalDeleteAtom(m_atomSystemTopic);
  601.  
  602.     // free cached commandline
  603.     if (m_pCmdInfo != NULL)
  604.         delete m_pCmdInfo;
  605.  
  606.     // cleanup module state
  607.     AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
  608.     if (pModuleState->m_lpszCurrentAppName == m_pszAppName)
  609.         pModuleState->m_lpszCurrentAppName = NULL;
  610.     if (pModuleState->m_pCurrentWinApp == this)
  611.         pModuleState->m_pCurrentWinApp = NULL;
  612.  
  613.     // free various strings allocated with _tcsdup
  614.     free((void*)m_pszAppName);
  615.     free((void*)m_pszRegistryKey);
  616.     free((void*)m_pszExeName);
  617.     free((void*)m_pszHelpFilePath);
  618.     free((void*)m_pszProfileName);
  619. }
  620.  
  621. void CWinApp::SaveStdProfileSettings()
  622. {
  623.     ASSERT_VALID(this);
  624.  
  625.     if (m_pRecentFileList != NULL)
  626.         m_pRecentFileList->WriteList();
  627.  
  628.     if (m_nNumPreviewPages != 0)
  629.         WriteProfileInt(szPreviewSection, szPreviewEntry, AfxGetApp()->m_nNumPreviewPages);
  630. }
  631.  
  632. int CWinApp::ExitInstance()
  633. {
  634.     // if we remember that we're unregistering,
  635.     // don't save our profile settings
  636.  
  637.     if (m_pCmdInfo == NULL ||
  638.         m_pCmdInfo->m_nShellCommand != CCommandLineInfo::AppUnregister)
  639.     {
  640.         if (!afxContextIsDLL)
  641.             SaveStdProfileSettings();
  642.     }
  643.  
  644.     // Cleanup DAO if necessary
  645.     if (m_lpfnDaoTerm != NULL)
  646.     {
  647.         // If a DLL, YOU must call AfxDaoTerm prior to ExitInstance
  648.         ASSERT(!afxContextIsDLL);
  649.         (*m_lpfnDaoTerm)();
  650.     }
  651.  
  652.     return m_msgCur.wParam; // returns the value from PostQuitMessage
  653. }
  654.  
  655. /////////////////////////////////////////////////////////////////////////////
  656.  
  657. #ifdef AFX_CORE1_SEG
  658. #pragma code_seg(AFX_CORE1_SEG)
  659. #endif
  660.  
  661. // Main running routine until application exits
  662. int CWinApp::Run()
  663. {
  664.     if (m_pMainWnd == NULL && AfxOleGetUserCtrl())
  665.     {
  666.         // Not launched /Embedding or /Automation, but has no main window!
  667.         TRACE0("Warning: m_pMainWnd is NULL in CWinApp::Run - quitting application.\n");
  668.         AfxPostQuitMessage(0);
  669.     }
  670.     return CWinThread::Run();
  671. }
  672.  
  673. #ifdef AFX_TERM_SEG
  674. #pragma code_seg(AFX_TERM_SEG)
  675. #endif
  676.  
  677. void AFXAPI AfxPostQuitMessage(int nExitCode)
  678. {
  679.     // cleanup OLE libraries
  680.     CWinThread* pThread = AfxGetThread();
  681.     if (pThread != NULL && pThread->m_lpfnOleTermOrFreeLib != NULL)
  682.         (*pThread->m_lpfnOleTermOrFreeLib)(TRUE, TRUE);
  683.  
  684.     ::PostQuitMessage(nExitCode);
  685. }
  686.  
  687. /////////////////////////////////////////////////////////////////////////////
  688. // WinHelp Helper
  689.  
  690. #ifdef AFX_CORE1_SEG
  691. #pragma code_seg(AFX_CORE1_SEG)
  692. #endif
  693.  
  694. void CWinApp::WinHelp(DWORD dwData, UINT nCmd)
  695. {
  696.     CWnd* pMainWnd = AfxGetMainWnd();
  697.     ASSERT_VALID(pMainWnd);
  698.  
  699.     // return global app help mode state to FALSE (backward compatibility)
  700.     m_bHelpMode = FALSE;
  701.     pMainWnd->PostMessage(WM_KICKIDLE); // trigger idle update
  702.  
  703.     pMainWnd->WinHelp(dwData, nCmd);
  704. }
  705.  
  706. /////////////////////////////////////////////////////////////////////////////
  707. // Special exception handling
  708.  
  709. LRESULT CWinApp::ProcessWndProcException(CException* e, const MSG* pMsg)
  710. {
  711.     // handle certain messages in CWinThread
  712.     switch (pMsg->message)
  713.     {
  714.     case WM_CREATE:
  715.     case WM_PAINT:
  716.         return CWinThread::ProcessWndProcException(e, pMsg);
  717.     }
  718.  
  719.     // handle all the rest
  720.     UINT nIDP = AFX_IDP_INTERNAL_FAILURE;   // generic message string
  721.     LRESULT lResult = 0;        // sensible default
  722.     if (pMsg->message == WM_COMMAND)
  723.     {
  724.         if ((HWND)pMsg->lParam == NULL)
  725.             nIDP = AFX_IDP_COMMAND_FAILURE; // command (not from a control)
  726.         lResult = (LRESULT)TRUE;        // pretend the command was handled
  727.     }
  728.     if (e->IsKindOf(RUNTIME_CLASS(CMemoryException)))
  729.     {
  730.         e->ReportError(MB_ICONEXCLAMATION|MB_SYSTEMMODAL, nIDP);
  731.     }
  732.     else if (!e->IsKindOf(RUNTIME_CLASS(CUserException)))
  733.     {
  734.         // user has not been alerted yet of this catastrophic problem
  735.         e->ReportError(MB_ICONSTOP, nIDP);
  736.     }
  737.     return lResult; // sensible default return from most WndProc functions
  738. }
  739.  
  740. /////////////////////////////////////////////////////////////////////////////
  741. // CWinApp idle processing
  742.  
  743. BOOL CWinApp::OnIdle(LONG lCount)
  744. {
  745.     if (lCount <= 0)
  746.     {
  747.         CWinThread::OnIdle(lCount);
  748.  
  749.         // call doc-template idle hook
  750.         POSITION pos = NULL;
  751.         if (m_pDocManager != NULL)
  752.             pos = m_pDocManager->GetFirstDocTemplatePosition();
  753.  
  754.         while (pos != NULL)
  755.         {
  756.             CDocTemplate* pTemplate = m_pDocManager->GetNextDocTemplate(pos);
  757.             ASSERT_KINDOF(CDocTemplate, pTemplate);
  758.             pTemplate->OnIdle();
  759.         }
  760.     }
  761.     else if (lCount == 1)
  762.     {
  763.         VERIFY(!CWinThread::OnIdle(lCount));
  764.     }
  765.     return lCount < 1;  // more to do if lCount < 1
  766. }
  767.  
  768. /////////////////////////////////////////////////////////////////////////////
  769. // CWinApp idle processing
  770.  
  771. void CWinApp::DevModeChange(LPTSTR lpDeviceName)
  772. {
  773.     if (m_hDevNames == NULL)
  774.         return;
  775.  
  776. #ifndef _MAC
  777.     LPDEVNAMES lpDevNames = (LPDEVNAMES)::GlobalLock(m_hDevNames);
  778.     ASSERT(lpDevNames != NULL);
  779.     if (lstrcmp((LPCTSTR)lpDevNames + lpDevNames->wDeviceOffset,
  780.         lpDeviceName) == 0)
  781.     {
  782.         HANDLE hPrinter;
  783.         if (!OpenPrinter(lpDeviceName, &hPrinter, NULL))
  784.             return;
  785.  
  786.         // DEVMODE changed for the current printer
  787.         if (m_hDevMode != NULL)
  788.             AfxGlobalFree(m_hDevMode);
  789.  
  790.         // A zero for last param returns the size of buffer needed.
  791.         int nSize = DocumentProperties(NULL, hPrinter, lpDeviceName,
  792.             NULL, NULL, 0);
  793.         ASSERT(nSize >= 0);
  794.         m_hDevMode = GlobalAlloc(GHND, nSize);
  795.         LPDEVMODE lpDevMode = (LPDEVMODE)GlobalLock(m_hDevMode);
  796.  
  797.         // Fill in the rest of the structure.
  798.         if (DocumentProperties(NULL, hPrinter, lpDeviceName, lpDevMode,
  799.             NULL, DM_OUT_BUFFER) != IDOK)
  800.         {
  801.             AfxGlobalFree(m_hDevMode);
  802.             m_hDevMode = NULL;
  803.         }
  804.         ClosePrinter(hPrinter);
  805.     }
  806. #else
  807.     UNUSED_ALWAYS(lpDeviceName);
  808. #endif
  809. }
  810.  
  811. ///////////////////////////////////////////////////////////////////////////
  812. // CWinApp diagnostics
  813.  
  814. #ifdef _DEBUG
  815. void CWinApp::AssertValid() const
  816. {
  817.     CWinThread::AssertValid();
  818.  
  819.     ASSERT(afxCurrentWinApp == this);
  820.     ASSERT(afxCurrentInstanceHandle == m_hInstance);
  821.  
  822.     if (AfxGetThread() != (CWinThread*)this)
  823.         return;     // only do subset if called from different thread
  824.  
  825.     if (m_pDocManager != NULL)
  826.         ASSERT_VALID(m_pDocManager);
  827. }
  828.  
  829. void CWinApp::Dump(CDumpContext& dc) const
  830. {
  831.     CWinThread::Dump(dc);
  832.  
  833.     dc << "m_hInstance = " << (UINT)m_hInstance;
  834.     dc << "\nm_hPrevInstance = " << (UINT)m_hPrevInstance;
  835.     dc << "\nm_lpCmdLine = " << m_lpCmdLine;
  836.     dc << "\nm_nCmdShow = " << m_nCmdShow;
  837.     dc << "\nm_pszAppName = " << m_pszAppName;
  838.     dc << "\nm_bHelpMode = " << m_bHelpMode;
  839.     dc << "\nm_pszExeName = " << m_pszExeName;
  840.     dc << "\nm_pszHelpFilePath = " << m_pszHelpFilePath;
  841.     dc << "\nm_pszProfileName = " << m_pszProfileName;
  842.     dc << "\nm_hDevMode = " << (UINT)m_hDevMode;
  843.     dc << "\nm_hDevNames = " << (UINT)m_hDevNames;
  844.     dc << "\nm_dwPromptContext = " << m_dwPromptContext;
  845. #ifdef _MAC
  846.     dc << "\nm_nSaveOption = " << (UINT)m_nSaveOption;
  847. #endif
  848.  
  849.     if (m_pRecentFileList != NULL)
  850.     {
  851.         dc << "\nm_strRecentFiles[] = ";
  852.         int nSize = m_pRecentFileList->GetSize();
  853.         for (int i = 0; i < nSize; i++)
  854.         {
  855.             if ((*m_pRecentFileList)[i].GetLength() != 0)
  856.                 dc << "\n\tFile: " << (*m_pRecentFileList)[i];
  857.         }
  858.     }
  859.  
  860.     if (m_pDocManager != NULL)
  861.         m_pDocManager->Dump(dc);
  862.  
  863.     dc << "\nm_nWaitCursorCount = " << m_nWaitCursorCount;
  864.     dc << "\nm_hcurWaitCursorRestore = " << (UINT)m_hcurWaitCursorRestore;
  865.     dc << "\nm_nNumPreviewPages = " << m_nNumPreviewPages;
  866.  
  867.     dc << "\nm_msgCur = {";
  868.     dc << "\n\thwnd = " << (UINT)m_msgCur.hwnd;
  869.     dc << "\n\tmessage = " << (UINT)m_msgCur.message;
  870.     dc << "\n\twParam = " << (UINT)m_msgCur.wParam;
  871.     dc << "\n\tlParam = " << (void*)m_msgCur.lParam;
  872.     dc << "\n\ttime = " << m_msgCur.time;
  873.     dc << "\n\tpt = " << CPoint(m_msgCur.pt);
  874.     dc << "\n}";
  875.  
  876.     dc << "\n";
  877. }
  878. #endif
  879.  
  880. #ifdef AFX_INIT_SEG
  881. #pragma code_seg(AFX_INIT_SEG)
  882. #endif
  883.  
  884. IMPLEMENT_DYNAMIC(CWinApp, CWinThread)
  885.  
  886. #pragma warning(disable: 4074)
  887. #pragma init_seg(lib)
  888.  
  889. PROCESS_LOCAL(_AFX_WIN_STATE, _afxWinState)
  890.  
  891. /////////////////////////////////////////////////////////////////////////////
  892.