appstate.cpp

Go to the documentation of this file.
00001 // $Id: appstate.cpp 1282 2006-06-09 09:46:49Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 /*
00099 
00100 
00101     appstate.cpp
00102 
00103     This module saves the state of the application when it is closed, and restores it the next
00104     time it is run.
00105 */
00106 
00107 #include "camtypes.h"
00108 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 //#include "mario.h"
00110 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 #include "camelot.h"
00112 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00114 #include "camdoc.h"
00115 #include "ccmdikid.h"
00116 #include "scrcamvw.h"
00117 #include "vstate.h"
00118 #include "rulers.h"
00119 #include "filedlgs.h"
00120 #include "registry.h"
00121 #include "statline.h"
00122 //#include "justin.h"
00123 
00124 
00125 DECLARE_SOURCE("$Revision: 1282 $");
00126 
00127 
00128 // This preference controls whether we restore docs etc on startup.
00129 BOOL fRestoreWorkspaceOnStartup = FALSE;
00130 
00131 // This key holds the place in the registry to load and save the workspace.
00132 HKEY hWorkspaceRegKey = 0;
00133 
00134 // If TRUE then ScreenView::OnInitialUpdate *won't* automatically maximise new views.
00135 BOOL fDontMaximiseViews = FALSE;
00136 
00137 
00138 
00139 /********************************************************************************************
00140 >   static void MakeKeyFromViewState(HKEY hViewKey, ScreenCamView* pCamView)
00141 
00142     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00143     Created:    27/9/95
00144     Inputs:     hViewKey        the key to store the ViewState's data
00145                 pCamView        the view to store
00146     Purpose:    Saves the data of the given view under the given key.
00147     SeeAlso:    SaveAppWindowState; MakeViewStateFromKey
00148 ********************************************************************************************/
00149 
00150 static void MakeKeyFromView(HKEY hViewKey, ScreenCamView* pCamView)
00151 {
00152     // Get the ViewState & DocView associated with the given ScreenCamView.
00153     ERROR3IF(pCamView == NULL, "Null ScreenCamView* in MakeKeyFromView\n");
00154     ViewState* pvs = pCamView->GetViewState();
00155     ERROR3IF(pvs == NULL, "Null ViewState* in MakeKeyFromView\n");
00156     DocView* pdv = pCamView->GetDocViewPtr();
00157     ERROR3IF(pdv == NULL, "Null DocView* in MakeKeyFromView\n");
00158     
00159     // First, its frame window's position.
00160     SetRegValue(hViewKey, TEXT("FrameLoX"), REG_DWORD, &pvs->ViewRect.lo.x, sizeof(DWORD));
00161     SetRegValue(hViewKey, TEXT("FrameLoY"), REG_DWORD, &pvs->ViewRect.lo.y, sizeof(DWORD));
00162     SetRegValue(hViewKey, TEXT("FrameHiX"), REG_DWORD, &pvs->ViewRect.hi.x, sizeof(DWORD));
00163     SetRegValue(hViewKey, TEXT("FrameHiY"), REG_DWORD, &pvs->ViewRect.hi.y, sizeof(DWORD));
00164 
00165     // Next, its icon position.
00166     SetRegValue(hViewKey, TEXT("IconX"), REG_DWORD, &pvs->IconPoint.x, sizeof(DWORD));
00167     SetRegValue(hViewKey, TEXT("IconY"), REG_DWORD, &pvs->IconPoint.y, sizeof(DWORD));
00168 
00169     // Next, its scale factor.
00170     DWORD dwScale = (DWORD) pvs->ViewScale.GetRawLong();
00171     SetRegValue(hViewKey, TEXT("Scale"), REG_DWORD, &dwScale, sizeof(DWORD));
00172 
00173     // Next, its minimise/maximise state etc.
00174     DWORD dwFlags = (pdv->ViewFlags.GuidesShow      ? 0x2000 : 0) | // these in the DocView
00175                     (pdv->ViewFlags.GuidesSnap      ? 0x1000 : 0) |
00176                     (pdv->ViewFlags.LogicalView     ? 0x0800 : 0) |
00177                     (pdv->ViewFlags.PrintBorderShow ? 0x0400 : 0) |
00178                     (pdv->ViewFlags.MagObjectsSnap  ? 0x0200 : 0) |
00179                     (pdv->ViewFlags.ObjectsSnap     ? 0x0100 : 0) |
00180                     (pdv->ViewFlags.GridSnap        ? 0x0080 : 0) |
00181                     (pdv->ViewFlags.GridShow        ? 0x0040 : 0) |
00182 
00183                     (pvs->RulersVisible             ? 0x0020 : 0) | // these in the ViewState
00184                     (pvs->ScrollersVisible          ? 0x0010 : 0) |
00185                     (pvs->AlwaysOnTop               ? 0x0008 : 0) |
00186                     (pvs->IsMinimised               ? 0x0004 : 0) |
00187                     (pvs->IsMaximised               ? 0x0002 : 0) |
00188 
00189                     (pCamView->IsTopmost()          ? 0x0001 : 0);  // maintained by MFC
00190 
00191     SetRegValue(hViewKey, TEXT("Flags"), REG_DWORD, &dwFlags, sizeof(DWORD));
00192 
00193     // Next, the scroll position, which unfortunately is two 64-bit quantities.
00194     UINT32 nLow;
00195     INT32  nHigh;
00196     WorkCoord wcScroll = pvs->GetScrollPos(TRUE);
00197 
00198     // Save the x ordinate as a low-high pair of 32-bit numbers.
00199     wcScroll.x.GetHighLow(&nHigh, &nLow);
00200     SetRegValue(hViewKey, TEXT("ScrollLoX"), REG_DWORD, &nLow,  sizeof(DWORD));
00201     SetRegValue(hViewKey, TEXT("ScrollHiX"), REG_DWORD, &nHigh, sizeof(DWORD));
00202 
00203     // Save the y ordinate as a low-high pair of 32-bit numbers.
00204     wcScroll.y.GetHighLow(&nHigh, &nLow);
00205     SetRegValue(hViewKey, TEXT("ScrollLoY"), REG_DWORD, &nLow,  sizeof(DWORD));
00206     SetRegValue(hViewKey, TEXT("ScrollHiY"), REG_DWORD, &nHigh, sizeof(DWORD));
00207 
00208     // Save the z-ordering.
00209     SetRegValue(hViewKey, TEXT("zOrder"), REG_DWORD, &(pvs->zPos), sizeof(DWORD));
00210 }
00211 
00212 
00213 
00214 /********************************************************************************************
00215 >   static ViewState* MakeViewStateFromKey(HKEY hViewKey, BOOL* pfHadFocus)
00216 
00217     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00218     Created:    27/9/95
00219     Inputs:     hViewKey        the registry key containing view details
00220                 pfHadFocus      points to a flag that will be set to TRUE if the ViewState
00221                                 had the focus when it was saved out, FALSE otherwise
00222     Returns:    A pointer to a ViewState object representing the data in the key
00223     Purpose:    Makes a ViewState object from the view data in the given registry key.
00224     SeeAlso:    LoadAppWindowState; MakeKeyFromViewState
00225 ********************************************************************************************/
00226 
00227 static ViewState* MakeViewStateFromKey(HKEY hViewKey, BOOL* pfHadFocus)
00228 {
00229     // Get the position of the view etc and build a ViewState for it.
00230     ERROR3IF(!pfHadFocus, "No BOOL output parameter in MakeViewStateFromKey");
00231     ViewState* pvs = new ViewState;
00232     if (pvs == NULL)
00233     {
00234         TRACEUSER( "JustinF", _T("Couldn't allocate a ViewState in MakeViewStateFromKey\n"));
00235         return NULL;
00236     }
00237 
00238     // Read in the positional data.
00239     pvs->ViewRect.lo.x = (INT32) GetRegDword(hViewKey, TEXT("FrameLoX"));
00240     pvs->ViewRect.lo.y = (INT32) GetRegDword(hViewKey, TEXT("FrameLoY"));
00241     pvs->ViewRect.hi.x = (INT32) GetRegDword(hViewKey, TEXT("FrameHiX"));
00242     pvs->ViewRect.hi.y = (INT32) GetRegDword(hViewKey, TEXT("FrameHiY"));
00243     pvs->IconPoint.x   = (INT32) GetRegDword(hViewKey, TEXT("IconX"));
00244     pvs->IconPoint.y   = (INT32) GetRegDword(hViewKey, TEXT("IconY"));
00245 
00246     // Dirty trick to read in the fixed-point scale.
00247     INT32 nScale = (INT32) GetRegDword(hViewKey, TEXT("Scale"));
00248     pvs->ViewScale = FIXED16::FromRawLong(nScale);
00249 
00250     // Next, its flags etc.
00251     DWORD dwFlags = GetRegDword(hViewKey, TEXT("Flags"));
00252     pvs->RulersVisible    = (dwFlags & 0x0020) ? TRUE : FALSE;
00253     pvs->ScrollersVisible = (dwFlags & 0x0010) ? TRUE : FALSE;
00254     pvs->AlwaysOnTop      = (dwFlags & 0x0008) ? TRUE : FALSE;
00255     pvs->IsMinimised      = (dwFlags & 0x0004) ? TRUE : FALSE;
00256 
00257     // Don't restore any as maximised - it just doesn't work with the MDI client window.
00258     pvs->IsMaximised      = /* (dwFlags & 0x0002) ? TRUE : */ FALSE;
00259     
00260     // Did this view have the focus when it was saved out?
00261     *pfHadFocus           = (dwFlags & 0x0001) ? TRUE : FALSE;
00262 
00263     // That deals with the flags stored in the ViewState.  Set the remainder, which are stored
00264     // in the associated DocView, in a special place where ScreenCamView::OnInitialUpdate
00265     // will set them properly.
00266     pvs->_GridShow        = (dwFlags & 0x0040) ? TRUE : FALSE;
00267     pvs->_GridSnap        = (dwFlags & 0x0080) ? TRUE : FALSE;
00268     pvs->_ObjectsSnap     = (dwFlags & 0x0100) ? TRUE : FALSE;
00269     pvs->_MagObjectsSnap  = (dwFlags & 0x0200) ? TRUE : FALSE;
00270     pvs->_PrintBorderShow = (dwFlags & 0x0400) ? TRUE : FALSE;
00271     pvs->_LogicalView     = (dwFlags & 0x0800) ? TRUE : FALSE;
00272     pvs->_GuidesSnap      = (dwFlags & 0x1000) ? TRUE : FALSE;
00273     pvs->_GuidesShow      = (dwFlags & 0x2000) ? TRUE : FALSE;
00274 
00275     // Make sure this is marked as a "loaded" view, so that the view system won't override
00276     // the settings here with default values.
00277     pvs->IsNewView        = FALSE;
00278 
00279     // Next, the scroll position.
00280     UINT32 xlow  = GetRegDword(hViewKey, TEXT("ScrollLoX"));
00281     UINT32 ylow  = GetRegDword(hViewKey, TEXT("ScrollLoY"));
00282     INT32  xhigh    = (INT32) GetRegDword(hViewKey, TEXT("ScrollHiX"));
00283     INT32  yhigh    = (INT32) GetRegDword(hViewKey, TEXT("ScrollHiY"));
00284 
00285     // Build a WorkCoord.
00286     WorkCoord wc;
00287     wc.x.SetHighLow(xhigh, xlow);
00288     wc.y.SetHighLow(yhigh, ylow);
00289     pvs->SetScrollPos(wc, FALSE);
00290 
00291     // Finally, the z-order.
00292     pvs->zPos = GetRegDword(hViewKey, TEXT("zOrder"));
00293 
00294     // Return the ViewState.
00295     return pvs;
00296 }
00297 
00298 
00299 
00300 /********************************************************************************************
00301 >   BOOL SaveAppWindowState(BOOL fAutoRestart)
00302 
00303     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00304     Created:    18/9/95
00305     Inputss:    fAutoRestart        if TRUE then the registry is set to automatically
00306                                     restart Camelot the next time the user logs on
00307     Returns:    TRUE if successful.
00308     Purpose:    Saves the document/view window state into the registry/custom .INI file.
00309     SeeAlso:    LoadAppWindowState
00310 ********************************************************************************************/
00311 
00312 BOOL SaveAppWindowState(BOOL fAutoRestart)
00313 {
00314     // Don't do this under Win32s.
00315     if (IsWin32s() && !IsWin32c()) return FALSE;
00316 
00317     // Don't allow a call twice (now we have two document templates, each will try to call
00318     // this, so ignore second calls).
00319     static BOOL fHasBeenCalled = FALSE;
00320     if (fHasBeenCalled) return TRUE;
00321     fHasBeenCalled = TRUE;
00322 
00323     // If there's a status line then set it.
00324     CMainFrame* pMainWnd = GetMainFrame();
00325     if (pMainWnd != NULL)
00326     {
00327         pMainWnd->UpdateStatusBarText(&String_256(_R(IDS_SAVING_WORKSPACE_MSG)), FALSE);
00328     }
00329 
00330     // First open/create a new sub-key under the app-state key for holding window positions.
00331     HKEY hMDIKey = CreateRegKey(hAppStateRegKey, TEXT("Workspace\\MDI"));
00332     if (hMDIKey == NULL)
00333     {
00334         ERROR3("Can't get an MDI key in SaveAppWindowState");
00335         return FALSE;
00336     }
00337     
00338     // Get the 'selected' document, if any.
00339     Document* pKernelDoc = Document::GetSelected();
00340     if (pKernelDoc == NULL)
00341     {
00342         // There's no docs open to bother with.
00343         TRACEUSER( "JustinF", _T("No docs open so nothing to do in SaveAppWindowState\n"));
00344 
00345         // Write how many docs and views there are.
00346         DWORD n = 0;
00347         SetRegValue(hMDIKey, TEXT("OpenDocCount"), REG_DWORD, &n, sizeof(DWORD));
00348         SetRegValue(hMDIKey, TEXT("TotalViewCount"), REG_DWORD, &n, sizeof(DWORD));
00349         CloseRegKey(hMDIKey);
00350         return TRUE;
00351     }
00352     
00353     // This counts the total number of open docs & views.
00354     DWORD nDocs = 0;
00355     INT32 nTotalViewCount = 0;
00356 
00357     // Loop over each document template.
00358     POSITION posTmp = AfxGetApp()->GetFirstDocTemplatePosition();
00359     while (posTmp)
00360     {
00361         // Get the next doc template.
00362         CDocTemplate* pTemplate = AfxGetApp()->GetNextDocTemplate(posTmp);
00363 
00364         // Iterate through all the open documents, counting them.
00365         POSITION posDoc = pTemplate->GetFirstDocPosition();
00366         while (posDoc)
00367         {
00368             // Get this document, skipping any that aren't acting as a server (or hidden).
00369             CCamDoc* pDoc = (CCamDoc*) pTemplate->GetNextDoc(posDoc);
00370         #if (_OLE_VER >= 0x200)
00371             if (pDoc->IsEmbedded() || pDoc->GetKernelDoc()->IsAHiddenDoc()) continue;
00372         #endif
00373 
00374             // Create a new subkey for this doc.
00375             TCHAR szDocID[32];
00376             ::wsprintf(szDocID, TEXT("Doc %lu"), ++nDocs);
00377             HKEY hDocKey = CreateRegKey(hMDIKey, szDocID);
00378             if (hDocKey == NULL)
00379             {
00380                 ERROR3("Can't get a doc sub-key in SaveAppWindowState");
00381                 CloseRegKey(hMDIKey);
00382                 return FALSE;
00383             }
00384             
00385             // Iterate through each view on the doc, saving it's state, and counting them.
00386             DWORD nViews = 0;
00387             POSITION posView = pDoc->GetFirstViewPosition();
00388             while (posView)
00389             {
00390                 // Get this view.
00391                 ScreenCamView* pView = (ScreenCamView*) pDoc->GetNextView(posView);
00392 
00393                 // Create a new subkey for this view.
00394                 TCHAR szViewID[32];
00395                 ::wsprintf(szViewID, TEXT("View %lu"), ++nViews);
00396                 HKEY hViewKey = CreateRegKey(hDocKey, szViewID);
00397                 if (hViewKey == NULL)
00398                 {
00399                     ERROR3("Can't get a view sub-key in SaveAppWindowState");
00400                     CloseRegKey(hDocKey);
00401                     CloseRegKey(hMDIKey);
00402                     return FALSE;
00403                 }
00404 
00405                 // Write the view's state into the key.
00406                 MakeKeyFromView(hViewKey, pView);
00407                 CloseRegKey(hViewKey);
00408 
00409                 // COunt this view.
00410                 nTotalViewCount++;
00411             }
00412 
00413             // Save the state of the doc in the subkey.
00414             CString strDocPath = pDoc->GetPathName();
00415             if (strDocPath.IsEmpty())
00416             {
00417                 // Aha!  There is no path name, which means that either (i) the doc is untitled
00418                 // or (ii) the doc is based on a non-native import, eg. a JPEG, or (iii) the doc is
00419                 // as unsaved copy.  See if it has an 'original' path-name saved by the importer, if
00420                 // so then save that out.  Otherwise save out a null string, signifying an untitled doc.
00421                 strDocPath = pDoc->GetOriginalPath();
00422                 if (strDocPath.IsEmpty()) strDocPath = TEXT("");        // untitled
00423             }
00424             
00425         //      TRACEUSER( "JustinF", _T("SaveAppWindowState: path to doc is %s\n"), (LPCTSTR) strDocPath);
00426             SetRegValue(hDocKey, TEXT("FilePath"), REG_SZ,
00427                         (LPCTSTR) strDocPath, strDocPath.GetLength() + 1);
00428             SetRegValue(hDocKey, TEXT("AttachedViewCount"), REG_DWORD, &nViews, sizeof(DWORD));
00429             CloseRegKey(hDocKey);
00430         }
00431     }
00432 
00433     // Write how many docs and views there are.
00434     SetRegValue(hMDIKey, TEXT("OpenDocCount"), REG_DWORD, &nDocs, sizeof(DWORD));
00435     SetRegValue(hMDIKey, TEXT("TotalViewCount"), REG_DWORD, &nTotalViewCount, sizeof(DWORD));
00436     
00437     CloseRegKey(hMDIKey);
00438 
00439 
00440 /*************************************************** CCamApp::InitInstance does this for now!
00441     // Next, get and save the position of the main window.
00442     WINDOWPLACEMENT wp;
00443     wp.length = sizeof(wp);
00444     if (!GetMainFrame()->GetWindowPlacement(&wp))
00445     {
00446         ERROR3("Can't get main frame window placement info");
00447         return FALSE;
00448     }
00449 
00450     // Save the icon, normal, and maximised positions.
00451     SetRegValue(hDocKey, TEXT("FrameLoX"), REG_DWORD, &wp.rcNormalPosition.left,   sizeof(DWORD));
00452     SetRegValue(hDocKey, TEXT("FrameLoY"), REG_DWORD, &wp.rcNormalPosition.top,    sizeof(DWORD));
00453     SetRegValue(hDocKey, TEXT("FrameHiX"), REG_DWORD, &wp.rcNormalPosition.right,  sizeof(DWORD));
00454     SetRegValue(hDocKey, TEXT("FrameHiY"), REG_DWORD, &wp.rcNormalPosition.bottom, sizeof(DWORD));
00455     SetRegValue(hDocKey, TEXT("MaxiX"),    REG_DWORD, &wp.ptMaxPosition.x,         sizeof(DWORD));
00456     SetRegValue(hDocKey, TEXT("MaxiY"),    REG_DWORD, &wp.ptMaxPosition.y,         sizeof(DWORD));
00457     SetRegValue(hDocKey, TEXT("IconX"),    REG_DWORD, &wp.ptMinPosition.x,         sizeof(DWORD));
00458     SetRegValue(hDocKey, TEXT("IconY"),    REG_DWORD, &wp.ptMinPosition.y,         sizeof(DWORD));
00459 
00460     // Save the window's state.
00461     SetRegValue(hDocKey, TEXT(""), REG_DWORD, &wp.showCmd, sizeof(DWORD));
00462 */
00463 
00464     // Finally, if we are supposed to restart automatically . . .
00465     if (fAutoRestart)
00466     {
00467         // . . . we write a command-line to run under a special key.
00468         HKEY hRunOnceKey = CreateRegKey(HKEY_CURRENT_USER,
00469                                 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce"));
00470         if (hRunOnceKey == NULL)
00471         {
00472             ERROR3("Can't get a RunOnce key in SaveAppWindowState");
00473             return FALSE;
00474         }
00475 
00476         // Windows will run this command-line on startup.
00477         TCHAR szAutoCmd[_MAX_PATH * 2];
00478         ::wsprintf(szAutoCmd, TEXT("%s /Restore"), (LPCTSTR) szCamelotExePath);
00479         SetRegValue(hRunOnceKey, szCamelotAppRegistryID, REG_SZ,
00480                     szAutoCmd, ::camStrlen(szAutoCmd));
00481         CloseRegKey(hRunOnceKey);
00482 
00483         // If there's a status line then set it.
00484         TRACEUSER( "JustinF", _T("\nSee you later . . .\n\n"));
00485         StatusLine::SetPrefix(String_256(_R(IDS_SEE_YOU_LATER_MSG)));
00486     }
00487     
00488     // Success!
00489     return TRUE;
00490 }
00491 
00492 
00493 
00494 /********************************************************************************************
00495 >   BOOL LoadAppWindowState(CWnd* pSplashBox)
00496 
00497     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00498     Created:    18/9/95
00499     Inputs:     pSplashBox      pointer to the splash box window displayed on program
00500                                 startup.  This is repeatedly put to the front of the
00501                                 z-order whenever a view window is created.
00502     Returns:    TRUE if there were windows to restore, FALSE if there weren't or it all
00503                 went wrong.
00504     Purpose:    Loads the document/view window state from the registry/custom .INI file.
00505     SeeAlso:    SaveAppWindowState
00506 ********************************************************************************************/
00507 
00508 BOOL LoadAppWindowState(CWnd* pSplashBox)
00509 {
00510     // Check if we want to restore the workspace.
00511     if (!fRestoreWorkspaceOnStartup || (IsWin32s() && !IsWin32c())) return FALSE;
00512 
00513     // First open/create a new sub-key under the app-state key for holding window positions.
00514     HKEY hWorkspaceKey = CreateRegKey(hAppStateRegKey, TEXT("Workspace"));
00515     if (hWorkspaceKey == NULL)
00516     {
00517         ERROR3("Can't get a workspace key in LoadAppWindowState");
00518         return FALSE;
00519     }
00520 
00521     HKEY hMDIKey = CreateRegKey(hWorkspaceKey, TEXT("MDI"));
00522     if (hMDIKey == NULL)
00523     {
00524         ERROR3("Can't get an MDI key in LoadAppWindowState");
00525         CloseRegKey(hWorkspaceKey);
00526         return FALSE;
00527     }
00528 
00529     // If there's a status line then set it.
00530     StatusLine::SetPrefix(String_64(_R(IDS_LOADING_WORKSPACE_MSG)));
00531 
00532     // We really DON'T know anything about any filters to use . . .
00533     BaseFileDialog::SelectedFilter = 0;
00534 
00535     // Read in the number of documents & views.
00536     INT32 nTotalDocs = GetRegDword(hMDIKey, TEXT("OpenDocCount"));
00537     INT32 nTotalViews = GetRegDword(hMDIKey, TEXT("TotalViewCount"));
00538 //  TRACEUSER( "JustinF", _T("Restoring %d docs and %d views\n"), nTotalDocs, nTotalViews);
00539 
00540     // Maybe prevent maximising views.
00541     fDontMaximiseViews = (nTotalViews > 1);
00542 
00543     // Allocate an array to hold the address of each view frame, indexed by their z-order.
00544     CCamMDIChild** pzOrder = new CCamMDIChild*[nTotalViews];
00545     ERRORIF(pzOrder == NULL, FALSE, _R(IDE_NOMORE_MEMORY));
00546     memset(pzOrder, (INT32) NULL, nTotalViews * sizeof(CCamMDIChild*));
00547 
00548     // Find out how many open docs are stored away and loop over the required number of docs.  As
00549     // we load each view we will see if it had the focus, and remember which one had it.
00550     CCamMDIChild* pFocusFrame = NULL;
00551     BOOL fAtLeastOneLoaded = FALSE;
00552     for (DWORD nDoc = 1; nDoc <= (DWORD) nTotalDocs; nDoc++)
00553     {
00554 //      TRACEUSER( "JustinF", _T("restoring doc %ld\n"), (UINT32) nDoc);
00555 
00556         // Get the sub-key for the doc.
00557         TCHAR szDocID[32];
00558         ::wsprintf(szDocID, TEXT("Doc %ld"), nDoc);
00559         HKEY hDocKey = OpenRegKey(hMDIKey, szDocID);
00560         if (hDocKey == NULL)
00561         {
00562             TRACEUSER( "JustinF", _T("Can't find %s sub-key in LoadAppWindowState\n"), (LPCTSTR) szDocID);
00563             continue;
00564         }
00565 
00566         // Get the file-path, if any.
00567         String_256 strPath;
00568         if (!GetRegString(hDocKey, TEXT("FilePath"), &strPath))
00569         {
00570             TRACEUSER( "JustinF", _T("Can't get file-path in LoadAppWindowState\n"));
00571             continue;
00572         }
00573 
00574         // This code is taken from CWinApp::OnFileNew in MFC\SRC\APPDLG.CPP.
00575         // Get the app's document template.
00576 #if (_MFC_VER < 0x400)
00577         // MFC2/3 compatible code
00578         CPtrList& templateList = AfxGetApp()->m_templateList;
00579         ERROR3IF(templateList.GetCount() > 1, "Too many doc templates in LoadAppWindowState");
00580         CDocTemplate* pTemplate = (CDocTemplate*) templateList.GetHead();
00581 #else
00582         // MFC4 compatible code
00583         POSITION Pos = AfxGetApp()->GetFirstDocTemplatePosition();
00584         CDocTemplate* pTemplate = AfxGetApp()->GetNextDocTemplate(Pos);
00585 #endif
00586         ERROR3IF(pTemplate == NULL, "No doc template in LoadAppWindowState");
00587         ERROR3IF(!pTemplate->IsKindOf(RUNTIME_CLASS(CDocTemplate)),
00588                     "Not a doc template in LoadAppWindowsState");
00589 
00590         // Find out how many more views and create each view at the given position.
00591         CCamDoc* pDoc;
00592         CCamMDIChild* pFrame;
00593         DWORD nViewCount = GetRegDword(hDocKey, TEXT("AttachedViewCount"));
00594         for (DWORD nView = 1; nView <= nViewCount; nView++)
00595         {
00596 //          TRACEUSER( "JustinF", _T("\trestoring view %ld\n"), (UINT32) nView);
00597 
00598             // Get the sub-key for the view.
00599             TCHAR szViewID[32];
00600             ::wsprintf(szViewID, TEXT("View %lu"), nView);
00601             HKEY hViewKey = OpenRegKey(hDocKey, szViewID);
00602             if (hViewKey == NULL)
00603             {
00604                 TRACEUSER( "JustinF", _T("\tCan't find %s sub-key in LoadAppWindowState\n"),
00605                                      (LPCTSTR) szViewID);
00606                 continue;
00607             }
00608 
00609             // Make a ViewState if we can.
00610             BOOL fHadFocus;
00611             ViewState* pvs = MakeViewStateFromKey(hViewKey, &fHadFocus);
00612             if (pvs == NULL)
00613             {
00614                 delete[] pzOrder;
00615 
00616                 CloseRegKey(hViewKey);
00617                 CloseRegKey(hMDIKey);
00618                 CloseRegKey(hWorkspaceKey);
00619 
00620                 StatusLine::SetDefaultPrefix();
00621                 fDontMaximiseViews = FALSE;
00622                 ERROR(_R(IDE_NOMORE_MEMORY), FALSE);
00623             }
00624 
00625             // OK, now we've finished with the view delete it from the registry.
00626             DeleteRegKey(hDocKey, szViewID);
00627 
00628             // Save the z-order position in it, cos as soon as we create the view this will be trashed,
00629             // and whether it had the focus..
00630             INT32 zPos = pvs->zPos;
00631 
00632             // Set it to be the ViewState to use for subsequent creation.
00633             ScreenCamView::SetReadyMadeViewState(pvs);
00634 
00635             // Create the view.  If the view is the first onto a doc then create the doc
00636             // as well.
00637             if (nView == 1)
00638             {
00639                 // Prevent the normal doc importer from moving the view onto the doc etc.
00640                 Document::ShouldRestoreViewOnImport(FALSE);
00641 
00642                 // First view, so create/open the doc.
00643                 if (strPath.IsEmpty())
00644                 {
00645                     // If returns NULL, the user has already been alerted.  Note that this will create
00646                     // a single view window already attached to the doc.
00647                     pDoc = (CCamDoc*) pTemplate->OpenDocumentFile(NULL);
00648                 }
00649                 else
00650                 {
00651                     // We have a path to the doc, so open it.
00652                     pDoc = (CCamDoc*) AfxGetApp()->OpenDocumentFile(strPath);
00653                     ((CCamApp*) AfxGetApp())->MakeDocumentNative(pDoc, &PathName(strPath));
00654                 }
00655 
00656                 // Reset this to the default setting.
00657                 Document::ShouldRestoreViewOnImport(TRUE);
00658                 
00659                 // Succeeded in creating the doc?
00660                 if (pDoc != NULL)
00661                 {
00662                     // Yes, so get the address of the view's frame and make it active.
00663                     POSITION pos = pDoc->GetFirstViewPosition();
00664                     pFrame = (CCamMDIChild*) (pDoc->GetNextView(pos)->GetParentFrame());
00665                     pFrame->MDIActivate();
00666 
00667                     // Sort out the extension of the doc etc.
00668                     fAtLeastOneLoaded = TRUE;
00669                     pDoc->SetOriginalPath(strPath);
00670 
00671 //                  TRACEUSER( "JustinF", _T("\t\tdoc is %s\n"),
00672 //                                       (LPCTSTR) ((strPath.IsEmpty()) ? TEXT("new") : strPath));
00673                 }
00674                 else
00675                 {
00676                     // Failed to create initial doc, don't make any views.
00677                     TRACEUSER( "JustinF", _T("\t\tFailed to create doc %lu in LoadAppWindowState\n"),
00678                                             (UINT32) nDoc);
00679                     ScreenCamView::SetReadyMadeViewState(NULL);
00680                     delete pvs;
00681                     break;
00682                 }
00683             }
00684             else
00685             {
00686                 // Not the first view, so make a new view onto the doc.
00687                 pFrame = (CCamMDIChild*) pTemplate->CreateNewFrame(pDoc, pFrame);
00688                 if (pFrame == NULL)
00689                 {
00690                     TRACEUSER( "JustinF", _T("\t\tCouldn't create frame in LoadAppWindowState\n"));
00691                     continue;
00692                 }
00693 
00694                 // Draw and activate the view.
00695                 pTemplate->InitialUpdateFrame(pFrame, pDoc, TRUE);
00696                 pFrame->MDIActivate();
00697             }
00698 
00699             // If a splashbox is up then reset it to the front of the z order.
00700             if (pSplashBox != NULL) pSplashBox->SetActiveWindow();
00701         
00702             // Save the view frame's address in the appropriate z-order slot.
00703             ERROR3IF(zPos >= nTotalViews, "Out of range zPos in LoadAppWindowState");
00704             if (zPos < nTotalViews) pzOrder[zPos] = pFrame;
00705             if (fHadFocus) pFocusFrame = pFrame;
00706 
00707             // Argh!! Murder! I can't get the view titles to update properly, no matter what
00708             // I do!  So I'm going to cheat here and if necessary append the view number to
00709             // the frame title.
00710             if (nViewCount == 1)
00711             {
00712                 pFrame->m_nWindow = 0;
00713             }
00714             else
00715             {
00716                 TCHAR szTitle[_MAX_PATH + 32], szNewTitle[_MAX_PATH + 32];
00717                 pFrame->GetWindowText(szTitle, sizeof(szTitle) / sizeof(szTitle[0]));
00718                 ::wsprintf(szNewTitle, TEXT("%s:%lu"), (LPCTSTR) szTitle, (UINT32) nView);
00719                 pFrame->SetWindowText(szNewTitle);
00720                 pFrame->m_nWindow = nView;
00721             }
00722         }
00723 
00724         // OK, now we've finished with the doc delete its sub-key.
00725         CloseRegKey(hDocKey);
00726         DeleteRegKey(hMDIKey, szDocID);
00727     }
00728 
00729     // Restore this flag.
00730     fDontMaximiseViews = FALSE;
00731 
00732     // Check if we had a cataclysmic failure.
00733     if (!fAtLeastOneLoaded)
00734     {
00735         TRACEUSER( "JustinF", _T("Couldn't restore even one doc - wiping MDI key\n"));
00736         DeleteRegKey(hWorkspaceKey, TEXT("MDI"));
00737         CloseRegKey(hWorkspaceKey);
00738         delete[] pzOrder;
00739 
00740         StatusLine::SetDefaultPrefix();
00741         return FALSE;
00742     }
00743     
00744     // All done with the registry.
00745     CloseRegKey(hMDIKey);
00746     CloseRegKey(hWorkspaceKey);
00747 
00748     // OK, now we've finished loading all the docs and creating all their views, set their
00749     // z-order.
00750 //  TRACEUSER( "JustinF", _T("Setting position of views: "));
00751     CWnd* pwndLast = (CWnd*) &CWnd::wndTop;
00752     for (INT32 i = 0; i < nTotalViews; i++)
00753     {
00754         CCamMDIChild* pFrame = pzOrder[i];
00755         if (pFrame != NULL)
00756         {
00757 //          TRACEUSER( "JustinF", _T(" %d"), i + 1);
00758             pFrame->SetWindowPos(pwndLast, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
00759             pwndLast = pFrame;
00760         }
00761     }
00762 
00763 //  TRACEUSER( "JustinF", _T("\n"));
00764 
00765     // Finally, set the focus to the appropriate view, if we found one.
00766     if (pFocusFrame != NULL) pFocusFrame->MDIActivate();
00767 
00768     // Success!
00769     delete[] pzOrder;
00770     StatusLine::SetDefaultPrefix();
00771     return TRUE;
00772 }
00773 
00774 
00775 
00776 /********************************************************************************************
00777 >   BOOL InitAppState()
00778 
00779     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00780     Created:    8/10/95
00781     Returns:    TRUE if successfully initialises the app-state system.
00782     Purpose:    Initialises the app-state system, reading prefs.
00783     SeeAlso:    LoadAppWindowState
00784 ********************************************************************************************/
00785 
00786 BOOL InitAppState()
00787 {
00788     // First, declare this pref.
00789     ERROR2IF(!GetApplication()->DeclareSection(TEXT("Workspace"), 5) ||
00790              !GetApplication()->DeclarePref(TEXT("Workspace"), TEXT("RestoreOnStartup"),
00791                                             &fRestoreWorkspaceOnStartup, FALSE, TRUE),
00792              FALSE,
00793              _R(IDE_BAD_INI_FILE));
00794 
00795 //  TRACEUSER( "JustinF", _T("%s restore workspace on startup\n"),
00796 //            (LPCTSTR) ((fRestoreWorkspaceOnStartup) ? TEXT("Will") : TEXT("Won't")));
00797 
00798     // Success!
00799     return TRUE;
00800 }

Generated on Sat Nov 10 03:48:03 2007 for Camelot by  doxygen 1.4.4