camdoc.cpp

Go to the documentation of this file.
00001 // $Id: camdoc.cpp 1777 2007-07-04 10:37:58Z luke $
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 #include "camtypes.h"
00099 
00100 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00101 //#include "mario.h"
00102 //#include "justin.h"
00103 
00104 #include "nativeop.h"
00105 #include "dbugtree.h"
00106 #include "brushmsg.h"
00107 #include "tmplmngr.h"
00108 
00109 #include "camdoc.h"
00110 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 #include "menuops.h"
00112 #include "camelot.h"
00113 #include "filedlgs.h"
00114 
00115 IMPLEMENT_DYNAMIC_CLASS( CCamDoc, wxDocument )
00116 
00117 // Declare smart memory handling in Debug builds
00118 #define new CAM_DEBUG_NEW
00119 
00120 // Setting this to some document will force all CCamDoc's created by the
00121 // default constructor to attach to m_pForceDocument
00122 Document *CCamDoc::s_pForceDocument = NULL;
00123 BOOL CCamDoc::s_RemoveExistingOnNewDoc = FALSE;
00124 PathName CCamDoc::ms_pathNextTemplateToUse;
00125 
00126 /************************************************************************************
00127 >   CCamDoc::CCamDoc(Document* pKernelDoc = 0)
00128 
00129     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00130     Created:    ages ago
00131     Inputs:     pKernelDoc      ---     the kernel Document to attach to this
00132                                         CCamDoc, or m_pForceDoc, a global override
00133                                         of all default creations.
00134     Purpose:    Creates a CCamDoc, optionally attached to a given pKernelDoc or
00135                 if pKernelDoc is null, a new Document.
00136     Notes:      m_pFor
00137     Scope:      protected
00138     Errors:     May throw an MFC memory exception!
00139 ************************************************************************************/
00140 
00141 CCamDoc::CCamDoc( Document *pKernelDoc /*= NULL*/ )
00142   : m_pKernelDoc( NULL ),
00143     m_fIsReadOnly( false ),
00144     m_fIsACopy( false ),
00145     m_fIsUntouched( false ),
00146     m_bIsModifiable( false ),
00147 #if (_OLE_VER >= 0x200)
00148     m_fExportPreview( true ),
00149     m_fIsVisible( false ),
00150     m_fDoneInitialShow( false ),
00151 #endif
00152     m_lpszInitialZoomOp( NULL ),
00153     m_fDoneNewDoc( false )
00154 {
00155 #if (_OLE_VER >= 0x200)
00156     // For most apps enable compound documents.
00157     EnableCompoundFile();
00158     EnableAutomation();
00159 #endif
00160 
00161     // Graham 22/10/97: Set the template path name as empty
00162     SetTemplate();
00163 
00164     // If the default was passed then use the 'forced' one (which may also
00165     // be null, meaning 'create a Document'.
00166     if( NULL == pKernelDoc )
00167         pKernelDoc = s_pForceDocument;
00168 
00169     // Connect with a ready-made kernel Document type?
00170     if( pKernelDoc )
00171     {
00172         // Attach this CCamDoc to the Document type.
00173         ERROR3IF(pKernelDoc->GetOilDoc(),
00174                     "Document already attached in CCamDoc::CCamDoc");
00175         m_pKernelDoc = pKernelDoc;
00176     }
00177     else
00178     {
00179         // Default - connect to a newly-created standard kernel Document.
00180         m_pKernelDoc = new Document;
00181         if( !m_pKernelDoc )
00182             throw CMemoryException();
00183     }
00184 
00185     // Try to initialise the kernel Document type and attach it to this CCamDoc.
00186     if( !m_pKernelDoc->Init( this ) )
00187     {
00188         // Didn't work - delete the Document object and throw an exception
00189         delete m_pKernelDoc;
00190         throw CMemoryException();
00191     }
00192 
00193     // Initialise the document flags.
00194     SetModifiedFlag(FALSE);
00195 
00196 #if (_OLE_VER >= 0x200)
00197     // All done - now claim the OLE 2.0 libraries.
00198     AfxOleLockApp();
00199 #endif
00200 }
00201 
00202 /************************************************************************************
00203 >   CCamDoc::~CCamDoc()
00204 
00205     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00206     Created:    19/5/93
00207     Purpose:    Destructor - destroys the Document associated with this OIL document.
00208 ************************************************************************************/
00209 
00210 CCamDoc::~CCamDoc()
00211 {
00212     // Get rid of the Document associated with this CCamDoc.
00213 //  wxDocument::SetNoCurrent();
00214     m_pKernelDoc->SetCurrent();
00215     delete m_pKernelDoc;
00216     m_pKernelDoc = NULL;
00217     
00218     // Under OLE 2.0 we must release our claim on the OLE libraries.
00219 #if (_OLE_VER >= 0x200)
00220     AfxOleUnlockApp();
00221 #endif
00222 }
00223 // CCamDoc document command handlers.
00224 
00225 /********************************************************************************************
00226 >   BOOL CCamDoc::GeneralOpenDocument(CCLexFile* pFile, UINT32 nPrefFilter)
00227 
00228     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00229     Created:    3/4/95
00230     Inputs:     pFile           -   the file to load the document from.
00231                 nPrefFilter     -   the preferred filter to use, usually FILTERID_GENERIC.
00232                                     Pass -1 to use the last filter the user chose in a
00233                                     file dialog box.
00234     Returns:    TRUE if the document was opened ok, FALSE if there was a problem
00235     Purpose:    This function will load a document with the name provided to help out the
00236                 OnNewDocument and the OpOpenDocument, since they do mostly the same thing.
00237     SeeAlso:    CCamDoc::OnOpenDocument; CCamDoc::OnNewDocument
00238 ********************************************************************************************/
00239 
00240 bool CCamDoc::GeneralOpenDocument( CCLexFile *pFile, UINT32 nPrefFilter )
00241 {
00242     // We need to make sure that the Current DocView is the same as the Selected DocView here
00243 /*  TRACEUSER( "JustinF", _T("In CCamDoc::GeneralOpenDocument(%p, %u)\n"),
00244                 (LPVOID) pFile, nPrefFilter);
00245 */  DocView            *pDocView = DocView::GetCurrent();
00246     DocView            *pOldSelView = DocView::GetSelected();
00247     if (pDocView != NULL)
00248     {
00249         // There was a current DocView, see if its got anything to do with out new doc
00250         // it should do
00251         if (pDocView->GetDoc() == m_pKernelDoc)
00252         {
00253             // make it the selected view
00254             Document::SetSelectedViewAndSpread( m_pKernelDoc, pDocView, NULL );
00255         }
00256     }
00257 
00258     // Make sure these point to this doc and this view.
00259     m_pKernelDoc->SetCurrent();
00260     if (m_pKernelDoc->GetFirstDocView() != NULL) m_pKernelDoc->GetFirstDocView()->SetCurrent();
00261 
00262     // Tell the Doc we are not importing the file
00263     if (m_pKernelDoc!=NULL) m_pKernelDoc->SetIsImporting(FALSE);
00264 
00265     // Do the load.
00266     BOOL IsImportOK = InvokeNativeFileOp(OPTOKEN_NATIVELOAD, pFile, nPrefFilter);
00267 
00268     // Make sure the colour bar is not left in a mess
00269     //GetMainFrame()->UpdateWindow();
00270 
00271     // Set the flag back to its default value
00272     if (m_pKernelDoc != NULL) m_pKernelDoc->SetIsImporting(TRUE);
00273 
00274     // See if the Import worked OK
00275     if (!IsImportOK)
00276     {
00277         // Find out what the old doc was
00278         Document* pDoc = NULL;
00279         if (pOldSelView != NULL) pDoc = pOldSelView->GetDoc();
00280         
00281         // Set the old document and view up and fail.
00282         Document::SetSelectedViewAndSpread(pDoc, pOldSelView, NULL);
00283         return FALSE;
00284     }
00285 
00286     // Make this document the selected document (this used to be done in document::Init but
00287     // was moved here for technical reasons
00288     Document::SetSelectedViewAndSpread(m_pKernelDoc, 0, 0); 
00289 
00290     // If we had a doc, make sure that the Operation History is emptied out
00291     if (m_pKernelDoc != NULL && !m_pKernelDoc->EmptyOperationHistory()) return FALSE;
00292 
00293     // Seems to have worked (for now).
00294     return TRUE;
00295 }
00296 
00297 /********************************************************************************************
00298 >   BOOL CCamDoc::LoadDefaultDocument()
00299 
00300     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00301     Created:    19/8/96
00302     Returns:    TRUE if successful.
00303     Purpose:    Loads the default document.  Called by CCamDoc::OnNewDocument etc.
00304 ********************************************************************************************/
00305 
00306 bool CCamDoc::LoadDefaultDocument()
00307 {
00308     // If this flags gets set to TRUE it means we have had to 'fake' the embedded doc
00309     // from the normal doc template.  In this case, quarter it's size.
00310 //  TRACEUSER( "JustinF", _T("In CCamDoc::LoadDefaultDocument\n"));
00311 #if (_OLE_VER >= 0x200)
00312     BOOL fQuarterDoc = FALSE;
00313 #endif
00314     
00315     //Graham 22/10/97: First get the path of the template
00316     PathName            pathTemplateToUse = GetTemplate();
00317 
00318     String_256          Path = pathTemplateToUse.GetPath();
00319 
00320     TCHAR              *Filename = NULL;
00321     String_256          Location = pathTemplateToUse.GetLocation( TRUE );
00322     String_256          File = pathTemplateToUse.GetFileName( TRUE );
00323 
00324     // See if the file exists
00325     if (Path != String_256(_T("")));
00326     {
00327         // In braces so file closes when res goes out of scope
00328         CamResource res;
00329         wxFSFile* f = res.OpenwxFSFile((TCHAR *)Path);
00330         if (f)
00331             Filename = (TCHAR*) Path;
00332     }
00333 #if (_OLE_VER >= 0x200)     
00334     else if (IsEmbedded())
00335     {
00336         // Try to load the normal one instead and quarter it's size
00337         File.Load(_R(IDS_DEFAULTDOCNAME));
00338 
00339         Path = Location;
00340         Path += File;
00341 //      TRACEUSER( "JustinF", _T("\t- trying template doc %s\n"), (LPCTSTR) Path);
00342     
00343         // See if the file exists
00344         CFileStatus Status;
00345         if (CFile::GetStatus((TCHAR*) Path, Status) != 0)
00346         {
00347             // It did exist, so set the filename to load to the file we have found
00348             Filename = (TCHAR*) Path;
00349         }
00350 
00351         // Remember to quarter it's size.
00352         fQuarterDoc = TRUE;
00353     }
00354 
00355 #endif
00356 
00357     // Hide the user's preferred filter.
00358 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX)
00359     INT32 nOldVal = BaseFileDialog::SelectedFilter; 
00360     BaseFileDialog::SelectedFilter = 0;
00361 #endif
00362 
00363     CamResource res;
00364     // If we can't find the disk-based template, load the one from resources instead.
00365     CCLexFile          *pFile;
00366     if (Filename)
00367     {
00368         if( wxFile::Exists( Filename ) )
00369             // Found a disk file, use that.
00370             pFile = new CCDiskFile(PathName(Filename), ios::in | ios::binary);
00371         else
00372             // Else we fall back to memory
00373             pFile = res.Open(Filename);
00374     }
00375     else
00376     {
00377         // Previously, Xara X (in Corel Xara times) would load a default template 
00378         // from its resources (defdoc.ppp) when it could not find the real default
00379         // template.  For a variety of reasons, this does not work in Xara X.  The new 
00380         // behaviour shows an error message requesting that the user fix the problem 
00381         // (by saving a new default template).  - Jonathan 4/9/2000
00382         ERROR1(FALSE, _R(IDS_TEMPLATE_NOT_FOUND));
00383     }
00384 
00385     // Check if we managed to allocate a file.
00386     if (!pFile)
00387     {
00388 //      TRACE( _T("Not enough memory for a new file in CCamDoc::LoadDefaultDocument\n"));
00389 //      AfxThrowMemoryException();
00390         return FALSE;
00391     }
00392 
00393     // Was the file opened OK?
00394     if (!pFile->good())
00395     {
00396 //      delete pFile; - Freeing CamResource does this
00397         ERROR1(FALSE, _R(IDT_IMPORT_NOTFOUND));
00398     }
00399     
00400     // Do the load.
00401     m_pKernelDoc->SetTemplateLoading(TRUE);
00402     //  TRACEUSER( "JustinF", _T("\t- about to call CCamDoc::GeneralOpenDocument\n"));
00403     BOOL fOK = GeneralOpenDocument(pFile, FILTERID_GENERIC);
00404 //  delete pFile; - Freeing CamResource does this
00405     m_pKernelDoc->SetTemplateLoading(FALSE);
00406 
00407 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX)
00408     // Restore the user's preferred filter.
00409     BaseFileDialog::SelectedFilter = nOldVal;
00410 #endif
00411 
00412     // Did it work?
00413     if (!fOK)
00414     {
00415 //      TRACE( _T("GeneralOpenDocument failed in DefaultDocumentRequired - dial 999\n"));
00416         return FALSE;
00417     }
00418 
00419 #if (_OLE_VER >= 0x200)
00420 
00421     // Did we load the embedded template from the default doc in resources?
00422     if (fQuarterDoc)
00423     {
00424         // Yes, so quarter the size of the page, to make a neat A6-ish embedded drawing.
00425         // We must set the new page size directly, without generating undo records.  First,
00426         // get the document's first spread, ie. its page.
00427 //      TRACEUSER( "JustinF", _T("\t- quartering size of page as doc is embedded\n"));
00428         Spread* pSpread = GetKernelDoc()->FindFirstSpread();
00429         ERROR2IF(!pSpread, FALSE, "Can't find a Spread in CCamDoc::LoadDefaultDocument");
00430 
00431         // Scale all the objects on the page, if there are any, by a factor of 4.
00432         ERROR2IF(!ScaleContents(0.5, 0.5), FALSE,
00433                     "Can't scale document contents in CCamDoc::LoadDefaultDocument");
00434 
00435         // Get the the page settings that we just loaded.  Only the width and height
00436         // will be changed (and the aspect ratio will be preserved).
00437         PageResizeInfo pri;
00438         ERROR2IF(!pSpread->GetPageSize(&pri.Width, &pri.Height,
00439                                        &pri.Margin, &pri.Bleed,
00440                                        &pri.Dps, &pri.ShowDropShadow),
00441                     FALSE, "GetPageSize failed in CCamDoc::LoadDefaultDocument");
00442 
00443         // Now all that's set-up, resize the spread by a factor of 1/2 x 1/2.
00444         pSpread->SetPageSize(pri.Width / 2, pri.Height / 2,
00445                              pri.Margin, pri.Bleed, pri.Dps, pri.ShowDropShadow);
00446     }
00447 
00448 #endif
00449     // Success!
00450     return true;
00451 }
00452 
00453 /********************************************************************************************
00454 >   PathName CCamDoc::GetTemplate() const
00455 
00456     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
00457     Created:    22/10/97
00458     Returns:    PathName - the template that was used to create this document.
00459     Purpose:    As above
00460     SeeAlso:    CCamDoc::LoadDefaultDocument
00461 ********************************************************************************************/
00462 
00463 PathName CCamDoc::GetTemplate() const
00464 {
00465 #if (_OLE_VER >= 0x200)
00466     //First, is this an embedded document?
00467     if (IsEmbedded())
00468     {
00469         //Yes. So get the default templates path.
00470         PathName pathEmbeddedTemplatePath = GetApplication()->GetTemplatesPath();
00471 
00472         //And add "embedded.xar" on the end
00473         String_256 strEmbeddedTemplateFilename(_R(IDS_DEFAULT_EMBEDDED_DOCNAME));
00474 
00475         pathEmbeddedTemplatePath.SetFileNameAndType(strEmbeddedTemplateFilename);
00476 
00477         return pathEmbeddedTemplatePath;
00478     }
00479     else
00480     {
00481         //No. So return our member variable
00482         return m_pathTemplate;
00483     }
00484 #else
00485     return m_pathTemplate;
00486 #endif
00487 }
00488 
00489 /********************************************************************************************
00490 >   void CCamDoc::SetTemplate(const PathName& pathToSet=PathName())
00491 
00492     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
00493     Created:    22/10/97
00494     Inputs:     pathToSet - the PathName to set as our default template
00495     Purpose:    As above
00496     SeeAlso:    CCamDoc::LoadDefaultDocument
00497 ********************************************************************************************/
00498 
00499 void CCamDoc::SetTemplate( const PathName &pathToSet )
00500 {
00501     m_pathTemplate = pathToSet;
00502 }
00503 
00504 /********************************************************************************************
00505 >   static PathName CCamDoc::GetNextTemplateToUse() const
00506 
00507     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
00508     Created:    22/10/97
00509     Returns:    PathName - the value of ms_pathNextTemplateToUse
00510     Purpose:    To find the path of the next template to use
00511     SeeAlso:    CCamDoc::LoadDefaultDocument
00512 ********************************************************************************************/
00513 
00514 PathName CCamDoc::GetNextTemplateToUse()
00515 {
00516     if (ms_pathNextTemplateToUse.IsValid())
00517     {
00518         wxFSFile * f;
00519         {
00520             // In braces so closes on descope
00521             CamResource res;
00522             f = res.OpenwxFSFile((const TCHAR *)(ms_pathNextTemplateToUse.GetPath()));
00523         }
00524         if (f)
00525         {
00526             return ms_pathNextTemplateToUse;
00527         }
00528     }
00529     
00530     PathName            pathToReturn( CTemplateManager::GetDefaultDrawingTemplate() );
00531     return pathToReturn;
00532 
00533 }
00534 
00535 /********************************************************************************************
00536 >   static void CCamDoc::SetNextTemplateToUse(const PathName& pathToSet) 
00537 
00538     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
00539     Created:    22/10/97
00540     Inputs:     pathToSet - the path of the next template to use
00541     Purpose:    To set the path of the next template to use
00542     SeeAlso:    CCamDoc::LoadDefaultDocument
00543 ********************************************************************************************/
00544 
00545 void CCamDoc::SetNextTemplateToUse(const PathName& pathToSet) 
00546 {
00547     ms_pathNextTemplateToUse=pathToSet;
00548 }
00549 
00550 
00551 
00552 /********************************************************************************************
00553 >   static BOOL CCamDoc::EnableRemoveUntouchedDocs()
00554 
00555     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
00556     Created:    11/10/96
00557     Returns:    TRUE if successful, FALSE otherwise
00558     Purpose:    Enable to idle-time removal of untouched documents.
00559                 Called when the user creates new documents or opens existing documents from
00560                 the highest possible level: menucmds.cpp.
00561 ********************************************************************************************/
00562 
00563 BOOL CCamDoc::EnableRemoveUntouchedDocs()
00564 {
00565 PORTNOTE("other", "Removed idle processing");
00566 #ifndef EXCLUDE_FROM_XARALX
00567     s_fRunIdleProcessing = TRUE;
00568 #endif
00569     return TRUE;
00570 }
00571 
00572 
00573 /********************************************************************************************
00574 >   virtual BOOL CCamDoc::OnNewDocument()
00575 
00576     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00577     Created:    8/3/94
00578     Returns:    TRUE if a new document is OK, FALSE otherwise.
00579     Purpose:    Called by MFC during the processing of a File/New command.  Before
00580                 this is called MFC/kernel have already contructed new instances of
00581                 the CCamDoc / Document classes.  Calls the kernel's Document and
00582                 CCamDoc's base class to do the actual work.
00583     Errors:     -
00584     SeeAlso:    CCamDoc::OnOpenDocument; CCamDoc::OnSaveDocument; CCamDoc::DoNewDocument
00585 ********************************************************************************************/
00586 
00587 bool CCamDoc::OnNewDocument()
00588 {
00589     // Make sure the kernel is in the know.
00590     TRACEUSER( "JustinF", _T("In CCamDoc::OnNewDocument\n"));
00591 //  ASSERT_VALID(this);
00592 
00593     //Graham 22/10/97: First set the template that this document is based on
00594     SetTemplate(GetNextTemplateToUse());
00595 
00596     SetNextTemplateToUse();
00597 
00598 #if (_OLE_VER >= 0x200)
00599     // Make sure the doc is considered 'visible' unless it is embedded.
00600     if (!IsEmbedded()) m_fIsVisible = TRUE;
00601 #endif
00602 
00603     // We must call the base class if OLE & MFC is to work properly.
00604     if (!wxDocument::OnNewDocument())
00605     {
00606         TRACE( _T("CCamDocBase::OnNewDocument failed - that's quite scary, isn't it?\n"));
00607         return FALSE;
00608     }
00609 
00610     // Set the prefix on the status-line.
00611 //  StatusLine::SetPrefix(String_64(_R(IDS_WAIT_CREATING_DOC_PFX)));
00612 
00613     // Get the document's default title prefix, as set from resources by MFC.
00614     m_TitlePrefix = (LPCTSTR) GetTitle();
00615 
00616     // Try to initialise the document.
00617     if (!DoNewDocument())
00618     {
00619         // Failed somehow!
00620         TRACEUSER( "JustinF", _T("\t- DoNewDocument failed in CCamDoc::OnNewDocument\n"));
00621     //  StatusLine::SetDefaultPrefix();
00622         return FALSE;
00623     }
00624 
00625     // New documents can be discarded if they haven't been changed, and they need
00626     // a path name if they are to be saved.  Set the document's flags appropriately.
00627     m_pKernelDoc->MakeJustCreated();
00628     SetOriginalPath(TEXT(""));
00629 
00630     // Templates should also not ask whether they need to be saved in the old format,
00631     // so force this off regardless.
00632     m_pKernelDoc->SetLoadedAsVersion1File(FALSE);
00633 
00634     // Make sure the window titles accurately reflect the state of the document.
00635     UpdateTitle();
00636     if (s_RemoveExistingOnNewDoc)   RemoveExistingDocs();
00637 
00638     m_fIsUntouched = FALSE;             // Mark this document as having been "touched"
00639                                         // by the user (because he's told us to open it)
00640 //  fRunIdleProcessing = TRUE;          // Flag the idle document processor that it should
00641                                         // scan for untouched docs and remove them.
00642 
00643     // Now that the document is stable, everything is selected and ready to go
00644     // we should now broadcast a message to this effect. This is so that things
00645     // like the options system can then update itself in the knowledge that
00646     // everything is fine and fabby rather than just sitting on doc selection
00647     // messages and wondering why it doesn't recieve a last one to say that 
00648     // everything has been set up..
00649     m_pKernelDoc->SetStable(TRUE);
00650     BROADCAST_TO_ALL(DocChangingMsg(m_pKernelDoc, DocChangingMsg::BORNANDSTABLE));
00651 
00652 #if (_OLE_VER >= 0x200)
00653     // Make sure the first view onto this new document zooms to the page bounds.
00654     if (IsServer()) m_lpszInitialZoomOp = OPTOKEN_ZOOMSPREAD;
00655 #endif
00656 
00657     // Tidy up.
00658     m_bIsModifiable = TRUE;
00659     SetModified(FALSE);
00660     UpdateAllViews();
00661 //  StatusLine::SetDefaultPrefix();
00662     return TRUE;
00663 }
00664 
00665 /********************************************************************************************
00666 >   virtual BOOL CCamDoc::DoNewDocument()
00667 
00668     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00669     Created:    3/10/96
00670     Returns:    TRUE if successful.
00671     Purpose:    Called to load the default document etc by CCamDoc::OnNewDocument.  Does
00672                 the actual load of the document data, without changin any flags etc.
00673     SeeAlso:    CCamDoc::OnNewDocument
00674 ********************************************************************************************/
00675 
00676 bool CCamDoc::DoNewDocument()
00677 {
00678     // Set up the kernel.
00679     m_pKernelDoc->SetCurrent();
00680 
00681     // If we've already 'new-ed' this document then bail out now.
00682     if (m_fDoneNewDoc) return TRUE;
00683 
00684     // Try to load the default document.
00685     if (!LoadDefaultDocument()) return FALSE;
00686     m_fDoneNewDoc = TRUE;
00687 
00688 #if (_OLE_VER >= 0x200)
00689     // Embedded docs (OLE or hidden) don't export preview bitmaps.
00690     if (IsEmbedded()) SetExportPreview(FALSE);
00691 #endif
00692 
00693     // Success.
00694     return TRUE;
00695 }
00696 /********************************************************************************************
00697 >   virtual bool CCamDoc::OnSaveDocument(const wxString& filename)
00698 
00699     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00700     Created:    8/3/94
00701     Inputs:     A C string with the directory path / filename of the document.
00702     Returns:    TRUE for a successful save, FALSE otherwise
00703     Purpose:    Saves the document to the specified path.  Calls the kernel
00704                 to do the actual work.
00705     SeeAlso:    CCamDoc::OnNewDocument; CCamDoc::OnOpenDocument; CCamDoc::DoSaveDocument
00706 ********************************************************************************************/
00707 
00708 bool CCamDoc::OnSaveDocument(const wxString& filename)
00709 {
00710     const TCHAR* pcszPathName = filename.c_str();
00711 #ifdef STANDALONE
00712 
00713     // Do nothing on a standalone version
00714     return TRUE;
00715 
00716 #else
00717 
00718 //  ASSERT_VALID(this);
00719 //  ASSERT(pcszPathName == 0 || AfxIsValidString(pcszPathName));
00720 
00721 PORTNOTE("other", "Disabled OLE")
00722 #ifndef EXCLUDE_FROM_XARALX
00723 #if (_OLE_VER >= 0x200)
00724     #ifdef _DEBUG
00725         if (IsUserName("JustinF"))
00726         {
00727             TRACE( _T("In CCamDoc::OnSaveDocument("));  
00728             if (pcszPathName)
00729                 TRACE( _T("FILE %s"), (LPCTSTR) pcszPathName);
00730             else
00731                 TRACE( _T("STORAGE 0x%p"), (LPVOID) m_lpRootStg);   
00732             TRACE( _T(", %s)\n", (LPCTSTR) (m_bSameAsLoad ? TEXT("SAVE"))
00733                                                       : (m_bRemember ? TEXT("SAVE AS")
00734                                                                      : TEXT("SAVE COPY"))));
00735         }
00736     #endif
00737 #endif
00738 
00739 #if (_OLE_VER >= 0x200)
00740     // This patched in from COleLinkingDoc::OnSaveDocument.
00741     BOOL fRemember = m_bRemember;
00742 #endif
00743 
00744     // TO DO: Check if we need to call the base-class, and how.
00745 /*  if (!CCamDocBase::OnSaveDocument(pcszPathName))
00746     {
00747         TRACE( _T("CCamDocBase::OnSaveDocument failed - that's quite scary, isn't it?\n"));
00748         return FALSE;
00749     }
00750 */
00751     // Set the busy prefix.
00752 //  StatusLine::SetPrefix(String_64(_R(IDS_WAIT_SAVING_DOC_PFX)));
00753 #endif
00754     // Try the actual save.
00755     if (!DoSaveDocument(pcszPathName))
00756     {
00757 //      StatusLine::SetDefaultPrefix();
00758         return FALSE;
00759     }
00760 
00761 PORTNOTE("other", "Disabled OLE")
00762 #ifndef EXCLUDE_FROM_XARALX
00763 #if (_OLE_VER >= 0x200)
00764     // Update the moniker/registration if the name has changed.
00765     // Neville 8/8/97 Fix for bug 5592: MFC Assert while saving
00766     // Check that the document is not a copy before trying to do OLE bits
00767     // If its a copy then it should never be an OLE doc.
00768     if (fRemember && m_strMoniker != pcszPathName && !IsACopy())
00769     {
00770         // update the moniker/registration since the name has changed
00771         Revoke();
00772         RegisterIfServerAttached(pcszPathName, TRUE);
00773     }
00774 #endif
00775 #endif
00776     // Close the file, update the flags etc and return success.
00777     if (pcszPathName) SetOriginalPath(TEXT(""));
00778     m_fIsUntouched = FALSE;
00779     SetModified(FALSE);
00780     SetDocumentSaved(true);
00781 
00782 #ifdef __WXMAC__
00783     wxFileName fn(pcszPathName) ;
00784     fn.MacSetDefaultTypeAndCreator() ;
00785 #endif
00786 
00787 //  StatusLine::SetDefaultPrefix();
00788     return TRUE;
00789 
00790 #endif
00791 }
00792 
00793 /********************************************************************************************
00794 >   virtual BOOL CCamDoc::DoSaveDocument(LPCTSTR pcszPathName)
00795 
00796     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00797     Created:    3/10/96
00798     Inputs:     pcszPathName    ---     path to the file to load (NULL means an embedding)
00799     Returns:    TRUE if successful.
00800     Purpose:    Helper function for CCamDoc::OnSaveDocument.  Does the actual saving of
00801                 the data, without disturbing aby flags etc.
00802     SeeAlso:    CCamDoc::OnSaveDocument; CCamDoc::SaveToStorage
00803 ********************************************************************************************/
00804 
00805 bool CCamDoc::DoSaveDocument( const wxString &strPathName )
00806 {
00807     // Create and open the appropriate kind of file.
00808     CCLexFile* pFile = CreateCCFile( strPathName, ios::out | ios::trunc);
00809     if (!pFile) return FALSE;
00810 
00811     // Make sure the kernel is set up.
00812     m_pKernelDoc->SetCurrent();
00813 
00814     // Try to save the document.
00815 // WEBSTER - markn 28/1/97
00816 // Native file saving is to be .web, not .xar
00817 #ifndef WEBSTER
00818     bool                fOK = FALSE != InvokeNativeFileOp( OPTOKEN_NATIVESAVE, pFile, FILTERID_NATIVE );
00819 #else
00820     bool                fOK = FALSE != InvokeNativeFileOp( OPTOKEN_NATIVESAVE, pFile, FILTERID_WEB );
00821 #endif // WEBSTER
00822 
00823     // Did that work?
00824     delete pFile;
00825     return fOK;
00826 }
00827 
00828 bool CCamDoc::OnOpenDocument( const wxString &strFilename )
00829 {
00830 #if (_OLE_VER >= 0x200)
00831     #ifdef _DEBUG
00832         if (IsUserName("JustinF"))
00833         {
00834             TRACE( _T("In CCamDoc::OnOpenDocument("));  
00835             if (pcszPathName)
00836                 TRACE( _T("FILE %s)\n"), (LPCTSTR) pcszPathName);
00837             else
00838                 TRACE( _T("STORAGE 0x%p)\n"), (LPVOID) m_lpRootStg);
00839         }
00840     #endif
00841 #endif
00842 
00843     // Put the kernel in the know.
00844     m_bIsModifiable = FALSE;
00845 
00846 #if (_OLE_VER >= 0x200)
00847     // Make sure the doc is considered 'visible' unless it is embedded.
00848     if (!IsEmbedded()) m_fIsVisible = TRUE;
00849 #endif
00850 
00851     // Remember the selected document, for possible restoration.
00852     DocView* pOldSelView = DocView::GetSelected();
00853 
00854 #if (_OLE_VER >= 0x200)
00855     // If this doc is not embedded then the user will want control after the server session.
00856     extern BOOL Bodge_NoRecentFileList;
00857     if (!IsEmbedded() && !Bodge_NoRecentFileList) AfxOleSetUserCtrl(TRUE);
00858 #endif
00859 
00860     // Set the busy prefix.
00861 //  StatusLine::SetPrefix(String_64(_R(IDS_WAIT_OPENING_DOC_PFX)));
00862 
00863     // Get the title from MFC - we use it as a prefix to the whole title.
00864     m_TitlePrefix = wxFileNameFromPath(strFilename); //GetTitle();
00865 
00866     // Try to open the document.
00867     if( !DoOpenDocument( strFilename ) )
00868     {
00869     #if !defined(EXCLUDE_FROM_RALPH)
00870         // If we failed then because we may have loaded a default document we will
00871         // have to ensure that the selection is put back to what it was before this
00872         // rather than what happens in the GeneralOpenDocument which is to put it back
00873         // to the selection before the function was called. If we don't do this then we
00874         // will loose the selection if the default doc was loaded.
00875         // Find out what the old doc was, if any.
00876         if (Document::GetSelected())
00877         {
00878             // Don't do this if no documents are open ('selected').
00879             Document* pDoc = NULL;
00880             if (pOldSelView != NULL) pDoc = pOldSelView->GetDoc();
00881             Document::SetSelectedViewAndSpread(pDoc, pOldSelView, NULL);
00882         }
00883     #endif
00884 
00885         // Damn, blown it again.
00886 //      StatusLine::SetDefaultPrefix();
00887         return FALSE;
00888     }
00889 
00890 #if (_OLE_VER >= 0x200)
00891     
00892     // Don't try to re-register copies of already registered docs.
00893     if (!IsACopy())
00894     {
00895         // Always register the document before opening it.
00896         Revoke();
00897         if (!RegisterIfServerAttached(pcszPathName, FALSE))
00898         {
00899             // always output a trace (it is just an FYI -- not generally fatal)
00900             TRACEUSER( "JustinF", _T("Warning: unable to register moniker '%s' as running\n"),
00901                         (LPCTSTR) pcszPathName);
00902         }   
00903     }
00904 
00905 #endif
00906 
00907     // Record the path we opened in a preference so it survives sessions
00908     BaseFileDialog::DefaultOpenFilePath = AfxGetApp().GetDocumentManager()->GetLastDirectory();
00909 
00910     SetOriginalPath( strFilename.c_str() );
00911     
00912     if( s_RemoveExistingOnNewDoc )
00913         RemoveExistingDocs();
00914 
00915     m_fIsUntouched = FALSE;             // Mark this document as having been "touched"
00916                                         // by the user (because he's told us to open it)
00917 //  fRunIdleProcessing = TRUE;          // Flag the idle document processor that it should
00918                                         // scan for untouched docs and remove them.
00919 
00920     // Now that the document is stable, everything is selected and ready to go
00921     // we should now broadcast a message to this effect. This is so that things
00922     // like the options system can then update itself in the knowledge that
00923     // everything is fine and fabby rather than just sitting on doc selection
00924     // messages and wondering why it doesn't recieve a last one to say that 
00925     // everything has been set up..
00926     m_pKernelDoc->SetStable( TRUE );
00927     BROADCAST_TO_ALL( DocChangingMsg( m_pKernelDoc, DocChangingMsg::BORNANDSTABLE ) );
00928 
00929 #if (_OLE_VER >= 0x200)
00930 
00931 #ifdef _DEBUG
00932     DocRect drBounds;
00933     GetPageBounds(&drBounds);
00934     TRACEUSER( "JustinF", _T("\t- doc is %ld x %ld HIMETRIC\n"),
00935                 (INT32) CCamSrvrItem::MPtoHM(drBounds.Width()),
00936                 (INT32) CCamSrvrItem::MPtoHM(drBounds.Height()));
00937 #endif
00938 
00939     // Make sure the first view onto this already-existing document *doesn't* auto-zoom.
00940     m_lpszInitialZoomOp = 0;
00941 
00942 #endif
00943 
00944     SetFilename( strFilename, true );
00945     SetTitle(wxFileNameFromPath(strFilename));
00946     Modify(false);
00947     m_savedYet = true;
00948     UpdateAllViews();
00949 
00950     // Tidy up.
00951     m_bIsModifiable = TRUE;
00952     SetModified(FALSE);
00953 
00954 #if defined(_DEBUG)
00955     if ( Error::IsUserName("Gavin") )
00956         DebugTreeDlg::TweeDump( GetKernelDoc() );
00957 #endif
00958 
00959 //  StatusLine::SetDefaultPrefix();
00960     return TRUE;
00961 }
00962 
00963 /********************************************************************************************
00964 >   virtual BOOL CCamDoc::DoOpenDocument(LPCTSTR pcszPathName)
00965 
00966     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00967     Created:    3/10/96
00968     Inputs:     pcszPathName    ---     path to file to open (NULL means an embeddeding).
00969     Returns:    TRUE if successful.
00970     Purpose:    Helper function to CCamDoc::OnOpenDocument.  Does the actual load of the
00971                 data, without disturbing any flags etc.
00972     SeeAlso:    CCamDoc::OnOpenDocument; CCamDoc::LoadFromStorage
00973 ********************************************************************************************/
00974 
00975 bool CCamDoc::DoOpenDocument( const wxString &strFilename )
00976 {
00977     // Create and open the appropriate kind of file.
00978     CCLexFile          *pFile = CreateCCFile( strFilename.c_str(), ios::in );
00979     if (!pFile) return FALSE;
00980 
00981     // Set up the kernel.
00982     m_pKernelDoc->SetCurrent();
00983 
00984     // Try to load the document and it's item, if it's embedded.
00985     bool                fOK = false;
00986     try
00987     {
00988     #ifndef STANDALONE
00989         // Before we open the file we must ask the filter system to work out what filter is
00990         // required to load the file, ask that filter if it requires a default document or not
00991         // and if it says yes then load the default document in. Required because if a file such
00992         // as a bitmap is loaded the user would expect to see this loaded into the default
00993         // document, as this file format defines no document structure, otherwise the default
00994         // constructed document would be used.
00995         // Only returns False if a problem happened in the testing and loading process.
00996         // -- Standalone
00997         // Don't do it on a standalone version otherwise the items get loaded on top of the  
00998         // document with all the info on rather than a blank page.
00999         // Note the selected document before we start anything
01000 //      DocView* pOldSelView = DocView::GetSelected();
01001         if (!DefaultDocumentRequired(pFile, FILTERID_USERCHOICE))
01002         {
01003             TRACE( wxT("DefaultDocumentRequired failed in CCamDoc::OnOpenDocument - doh?\n") );
01004             delete pFile;
01005             return FALSE;
01006         }
01007     #endif
01008         
01009         // Try to load the file.
01010         m_pKernelDoc->SetTemplateLoading(FALSE); // Note that it is not a template being loaded
01011         fOK = GeneralOpenDocument(pFile, FILTERID_USERCHOICE);
01012 
01013     #if (_OLE_VER >= 0x200)
01014         // Embedded docs (OLE or hidden) don't export preview bitmaps.
01015         if (IsEmbedded()) SetExportPreview(FALSE);
01016     #endif
01017     }
01018     catch( ... )
01019     {
01020         // Tidy up.
01021         delete pFile;
01022         return FALSE;
01023     }
01024 
01025     // Did this work?
01026     delete pFile;
01027     return fOK;
01028 }
01029 
01030 /********************************************************************************************
01031 >   BOOL CCamDoc::DefaultDocumentRequired(CCLexFile* pFile, UINT32 nPrefFilter)
01032 
01033     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01034     Created:    12/10/95
01035     Inputs:     pFile           -   file to check
01036     Returns:    TRUE if the process went ok, FALSE if there was a problem
01037     Purpose:    Given the pathname that we have been asked to open and before we actually go
01038                 and open the file, we must ask the filter system to work out what filter is
01039                 required to load the file, ask that filter if it requires a default document
01040                 or not and if it says yes then load the default document in.
01041                 This is required because if a file such as a bitmap is loaded the user would
01042                 expect to see this loaded into the default document, as this file format
01043                 defines no document structure, otherwise the default constructed document
01044                 would be used and this is one that is never seen elsewhere by the user.
01045                 Other file types apart form bitmaps might require the same treatment,
01046                 examples at present are Corel palette files and Windows metafiles.
01047                 Formats which define document structures, such as our native format and the
01048                 EPS formats will be changing the default constructed document given
01049                 information in the format and so there is no point in loading the default
01050                 document. Would cause problems anyway as things like colours would need
01051                 clearing out etc.
01052                 Needs to be done here as otherwise we would be right in the middle of the
01053                 loading process before we decide what filter is required and hence would be
01054                 calling effectively the same code re-enterantly!
01055                 Only returns False if a problem happened in the testing and loading process.
01056         
01057     Errors:     -
01058     SeeAlso:    CCamDoc::GeneralOpenDocument; CCamDoc::OnOpenDocument;
01059                 Filter::IsDefaultDocRequired;
01060 ********************************************************************************************/
01061 
01062 bool CCamDoc::DefaultDocumentRequired( CCLexFile *pFile, UINT32 nPrefFilter )
01063 {
01064 #if defined(EXCLUDE_FROM_RALPH)
01065     return true;
01066 #else
01067 
01068     // NULL pathname implies that we can't do any checking so return immediately
01069     // Shouldn't happen, maybe we should error?
01070 //  TRACEUSER( "JustinF", _T("In CCamDoc::DefaultDocumentRequired(%p)\n"), (LPVOID) pFile);
01071     PathName            pth = pFile->GetPathName();
01072     if (!pth.IsValid())
01073     {
01074 //      TRACEUSER( "JustinF", _T("\t- file has no valid path, assuming it's OK\n"));
01075         return TRUE;
01076     }
01077 
01078     // Find out the position of the filter selected by the user in the open dialog
01079     INT32 SelectedPos = BaseFileDialog::SelectedFilter;
01080 
01081     // Do we know which filter was used (we know nothing about things in the recent file list)
01082     Filter* pFilter = Filter::GetFirst();
01083     if (nPrefFilter != FILTERID_USERCHOICE || SelectedPos == 0)
01084     {
01085         // We know nothing. We will have to go and have a look at all the possibles
01086         // We will find the Filter Family and ask it to try and load the file
01087         // Find the filter that the user chose.
01088         UINT32 nID = (nPrefFilter != FILTERID_USERCHOICE) ? nPrefFilter : FILTERID_GENERIC;
01089         while (pFilter != NULL && pFilter->FilterID != nID)
01090         {
01091             // Try the next filter
01092             pFilter = Filter::GetNext(pFilter);
01093         }
01094     }
01095     else
01096     {
01097         // We know which type of filter the user had selected in the file dialog
01098         // Find the filter that the user chose
01099         while (pFilter != NULL)
01100         {
01101             // This is the filter?
01102             if (pFilter->GetFlags().CanImport && 
01103                 pFilter->pOILFilter->Position == SelectedPos)
01104                     break;
01105 
01106             // Try the next filter
01107             pFilter = Filter::GetNext(pFilter);
01108         }
01109     }
01110     
01111     // Check that the Filter existed
01112     if (pFilter == NULL)
01113     {
01114         // It did not...
01115         TRACE( _T("Can't find filter #%u in CCamDoc::DefaultDocumentRequired\n"),
01116                 (UINT32) nPrefFilter);
01117         InformError(_R(IDT_CANT_FIND_FILTER));
01118         return FALSE;
01119     }
01120 
01121     // Ask the filter or filter family about whether a default document is required.
01122     // If it is a filter family then we will have to work out what filter is actually
01123     // required and hence ask that filter the qeustion.
01124     if (!pFilter->IsDefaultDocRequired(pth.GetPath())) return TRUE;
01125 
01126     //Graham 22/10/97: First set the template that this document is based on
01127     SetTemplate(GetNextTemplateToUse());
01128 
01129     SetNextTemplateToUse();
01130 
01131     // Try to load the default document.
01132     return LoadDefaultDocument();
01133 #endif
01134 }
01135 
01136 
01137 /********************************************************************************************
01138 >   BOOL CCamDoc::RemoveExistingDocs()
01139 
01140     Author:         Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01141     Created:        26/5/95
01142     Returns:        TRUE if successful, FALSE otherwise
01143     Purpose:        Removed existing documents, when a new document is created.
01144 ********************************************************************************************/
01145 
01146 BOOL CCamDoc::RemoveExistingDocs()
01147 {
01148     if (!s_RemoveExistingOnNewDoc ||
01149             Camelot.Documents.GetCount() < 2 ||
01150             AskQuestion(_R(IDS_CLOSEOTHERDOCS), _R(IDS_KEEPDOCS), _R(IDS_CLOSEDOCS), 0, 0, 2, 2) != 2)
01151     {
01152         // Nothing to do.
01153         return TRUE;
01154     }
01155 
01156     // Delete any other documents still associated with this application
01157     Document *pDoc;
01158     Document *pRootDoc = m_pKernelDoc;
01159     Document *pNextDoc = (Document*) Camelot.Documents.GetNext(m_pKernelDoc);
01160 
01161     while (pNextDoc != NULL)
01162     {
01163         if (pNextDoc != m_pKernelDoc)
01164             pNextDoc->GetOilDoc()->OnCloseDocument();   // This will remove it from the list
01165 
01166         // User may have pressed 'Cancel' so we need to check that the doc
01167         // has gone away
01168         pDoc = pNextDoc;
01169         pNextDoc = (Document*) Camelot.Documents.GetNext(pRootDoc);
01170 
01171         if (pNextDoc == pDoc)
01172         {
01173             // User must have pressed 'Cancel ...
01174             // So skip this doc in future
01175             pRootDoc = pDoc;
01176             pNextDoc = (Document*) Camelot.Documents.GetNext(pRootDoc);
01177         }
01178     }
01179 
01180     Document::SetSelectedViewAndSpread(m_pKernelDoc);
01181     DocView::GetSelected()->SetCurrent();
01182     return TRUE;
01183 }
01184 
01185 
01186 /********************************************************************************************
01187 
01188 >   virtual void CCamDoc::SetTitle(LPCTSTR lpszTitle)
01189 
01190     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01191     Created:    27/3/95
01192     Returns:    -
01193     Purpose:    To set a new title for the document. Overide the parent class versions so we
01194                 can do things like send a message to inform people that things have changed.
01195     SeeAlso:    GetKernelTitle(); CDocument::SetTitle();
01196 
01197 ********************************************************************************************/
01198 
01199 void CCamDoc::SetTitle(LPCTSTR lpszTitle)
01200 {
01201 #if !defined(EXCLUDE_FROM_RALPH)
01202     // Make a note of the current document's title
01203     wxString    EntryTitle = GetTitle();
01204 
01205     // Set the new Title Prefix
01206     m_TitlePrefix = String_256(lpszTitle);
01207 
01208     // We now have to go and work out what extra bits we want to appear after the actual
01209     // title, such as Modified, Read Only flags etc.
01210     // Load the suffix separator string.  Clear the string used to build up a suffix to
01211     // the title.
01212     String sep(_R(IDS_DOC_SUFFIX_SEPARATOR));
01213     String_256 sfx;
01214     sfx.Empty();
01215 
01216     // Check the "document is modified" flag.
01217     BOOL fSuffixExists = FALSE;
01218     if (IsModifiable() && !GetKernelDoc()->IsAHiddenDoc() && IsModified())
01219     {
01220         fSuffixExists = TRUE;
01221         sfx += String(_R(IDS_DOC_MODIFIED_MARK));
01222     }
01223 
01224     // Check the "document is read-only" flag.
01225     if (IsReadOnly())
01226     {
01227         if (fSuffixExists)
01228         {
01229             sfx += sep;
01230         }
01231         else
01232         {
01233             fSuffixExists = TRUE;
01234         }
01235         sfx += String(_R(IDS_DOC_READ_ONLY_MARK));
01236     }
01237 
01238     // Check the "document is a copy" flag.
01239     if (IsACopy())
01240     {
01241         if (fSuffixExists)
01242         {
01243             sfx += sep;
01244         }
01245         else
01246         {
01247             fSuffixExists = TRUE;
01248         }
01249         sfx += String(_R(IDS_DOC_COPY_MARK));
01250     }
01251 
01252     // Get the document's title, as looked after by MFC.
01253     String_256 title = m_TitlePrefix;
01254 
01255     // If a suffix exists, format and append the it to the title.
01256     if (fSuffixExists)
01257     {
01258         String_256 tmp;
01259         tmp.MakeMsg(_R(IDS_DOC_SUFFIX_FORMAT), &sfx);
01260         title += tmp;
01261     }
01262 
01263     // Now we have the complete title that we want in the title bar, including
01264     // the name of the document and all the flags, so set it in MFC
01265     wxDocument::SetTitle( (const TCHAR *)title );
01266 
01267     // If the document's title has been changed then broadcast to the kernel to
01268     // let everyone know about the change.
01269     // Do not send it if TitlePrefix is empty as we seem to get some random settings
01270     // during say document opening where we will get people to update with say "[Modified]".
01271     if (!m_TitlePrefix.IsEmpty() && (EntryTitle != GetTitle()))
01272     {
01273         BROADCAST_TO_ALL( DocChangingMsg( m_pKernelDoc, DocChangingMsg::TITLECHANGED ) );
01274     }
01275 #endif
01276 }
01277 
01278 /********************************************************************************************
01279 
01280 >   virtual void CCamDoc::SetPathName(LPCTSTR lpszPathName, BOOL bAddToMRU = TRUE)
01281 
01282     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01283     Created:    27/3/95
01284     Returns:    -
01285     Purpose:    To set a new pathname for the document. Overide the parent class versions so we
01286                 can do things like send a message to inform people that things have changed.
01287     SeeAlso:    GetPathName(); CDocument::SetPathName();
01288 
01289 ********************************************************************************************/
01290 
01291 void CCamDoc::SetPathName(LPCTSTR lpszPathName, BOOL bAddToMRU)
01292 {
01293     // Make a note of the current document's pathname
01294     wxString EntryPathName = GetFilename();
01295 
01296     // Call the parent class form of the function to do the job
01297     wxDocument::SetFilename( lpszPathName, bAddToMRU );
01298 
01299     // If the document's pathname has been changed then broadcast to the kernel to
01300     // let everyone know about the change as this will affect the title of the document.
01301     if (EntryPathName != *lpszPathName)
01302     {
01303         BROADCAST_TO_ALL( DocChangingMsg( m_pKernelDoc, DocChangingMsg::TITLECHANGED ) );
01304     }
01305 }
01306 
01307 /********************************************************************************************
01308 
01309 >   virtual void CCamDoc::SetPathNameEmpty()
01310 
01311     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01312     Created:    27/3/95
01313     Returns:    -
01314     Purpose:    To set a new pathname for the document. Overide the parent class versions so we
01315                 can do things like send a message to inform people that things have changed.
01316     SeeAlso:    GetPathName(); CDocument::SetPathName();
01317 
01318 ********************************************************************************************/
01319 
01320 void CCamDoc::SetPathNameEmpty()
01321 {
01322     SetFilename(_T(""));
01323 }
01324 
01325 /********************************************************************************************
01326 >   void CCamDoc::SetModified(BOOL fState)
01327 
01328     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01329     Created:    2/7/93
01330     Inputs:     A boolean which if TRUE means "mark document as modified"
01331     Purpose:    To tell the document that it has been modified.  While MFC provides an
01332                 implementation of this, it doesn't update the document's title, so
01333                 call this function instead.
01334     SeeAlso:    CDocument::IsModified
01335 ********************************************************************************************/
01336 
01337 void CCamDoc::SetModified( bool fState )
01338 {
01339     // If the docuement cannot be modified (ie. it's internal implementation) then
01340     // ignore this call.
01341     if (!IsModifiable()) return;
01342 
01343 
01344 /*  TRACEUSER( "JustinF", _T("In CCamDoc::SetModified(%s)\n"),
01345                 (LPCTSTR) (fState ? TEXT("TRUE") : TEXT("FALSE")));
01346 */  
01347     // Do stuff only when the doc's state is changed.
01348     if (fState != IsModified())
01349     {
01350         // Set the flag & update the flags in the title
01351         SetModifiedFlag( fState );      
01352         UpdateTitle();
01353     }
01354 
01355     // It can't be "just created" any more
01356     if( fState )
01357         m_fIsUntouched = FALSE;
01358 
01359 #if (_OLE_VER >= 0x200)
01360     // Count this modification (or unmodification) for the idle-time server update if
01361     // the doc is embedded.
01362     if (IsServer()) GetEmbeddedItem()->PostponeUpdate();
01363 
01364     // Don't do any updates for a while
01365     ResetContainerUpdateTimer();
01366 #endif
01367 
01368     // tell the world we have changed something
01369     BROADCAST_TO_ALL(ScreenChangeMsg());
01370     //TRACEUSER( "Diccon", _T("CamDoc::SetModified\n"));
01371 }
01372 
01373 
01374 
01375 /********************************************************************************************
01376 >   void CCamDoc::SetReadOnly(BOOL fState)
01377 
01378     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01379     Created:    2/7/93
01380     Inputs:     A boolean which if TRUE means "mark document as read-only"
01381     Outputs:    -
01382     Returns:    -
01383     Purpose:    To tell the document whether it can be modified or not.
01384     Errors:     -
01385     SeeAlso:    CCamDoc::IsReadOnly
01386 ********************************************************************************************/
01387 
01388 void CCamDoc::SetReadOnly( bool fState )
01389 {
01390     if (fState != IsReadOnly())
01391     {
01392         m_fIsReadOnly = fState;
01393         UpdateTitle();
01394     }
01395 }
01396 
01397 
01398 
01399 /********************************************************************************************
01400 >   void CCamDoc::SetCopy(BOOL fState)
01401 
01402     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01403     Created:    2/7/93
01404     Inputs:     A boolean which if TRUE means "mark document as modified"
01405     Outputs:    -
01406     Returns:    -
01407     Purpose:    To tell the document whether it is a copy of an ineditable document.
01408     Errors:     -
01409     SeeAlso:    CCamDoc::IsACopy
01410 ********************************************************************************************/
01411 
01412 void CCamDoc::SetCopy( bool fState )
01413 {
01414     if (fState != IsACopy())
01415     {
01416         m_fIsACopy = fState;
01417         UpdateTitle();
01418     }
01419 }
01420 
01421 /********************************************************************************************
01422 >   BOOL CCamDoc::IsUntouched() const
01423 
01424     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
01425     Created:    21/6/96
01426     Inputs:     -
01427     Outputs:    -
01428     Returns:    TRUE if this document is untouched by the user. That means the program has
01429                 created the document but the user hasn't modified, edited, operated on it
01430                 or saved it.
01431                 FALSE otherwise.
01432     Purpose:    Provides a safe way to test the document's flags.
01433                 Note there's no equivalent Set function for this flag because only this
01434                 class should ever set its state.
01435     Errors:     -
01436     SeeAlso:    CCamDoc::SetJustCreated
01437 ********************************************************************************************/
01438 
01439 bool CCamDoc::IsUntouched() const
01440 {
01441     return m_fIsUntouched;
01442 }
01443 
01444 /********************************************************************************************
01445 >   BOOL CCamDoc::IsReadOnly() const
01446 
01447     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01448     Created:    15/3/94
01449     Inputs:     -
01450     Outputs:    -
01451     Returns:    TRUE if this document cannot be edited, only browsed.
01452     Purpose:    Provides a safe way to test the document's flags.
01453     Errors:     -
01454     SeeAlso:    CCamDoc::SetReadOnly
01455 ********************************************************************************************/
01456 
01457 bool CCamDoc::IsReadOnly() const
01458 {
01459     return m_fIsReadOnly;
01460 }
01461 
01462 /********************************************************************************************
01463 >   BOOL CCamDoc::IsACopy() const
01464 
01465     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01466     Created:    15/3/94
01467     Inputs:     -
01468     Outputs:    -
01469     Returns:    TRUE if this document is a copy of another (ineditable) document.
01470     Purpose:    Provides a safe way to test the document's flags.
01471     Errors:     -
01472     SeeAlso:    CCamDoc::SetCopy
01473 ********************************************************************************************/
01474 
01475 bool CCamDoc::IsACopy() const
01476 {
01477     return m_fIsACopy;
01478 }
01479 
01480 /********************************************************************************************
01481 >   BOOL CCamDoc::IsModifiable() const
01482 
01483     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01484     Created:    23/09/96
01485     Returns:    TRUE if this document modifiable via SetModified
01486                 FALSE otherwise.
01487     Purpose:    Because of a bodge in Operation::EndOp(), SetModified() is called needlessly.
01488                 So we know whether to pay any attention to IsModified() we can use this
01489 
01490 ********************************************************************************************/
01491 bool CCamDoc::IsModifiable() const
01492 {
01493     return m_bIsModifiable;
01494 }
01495 
01496 /***********************************************************************************************
01497 >   Document* CCamDoc::GetKernelDoc() const
01498 
01499     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01500     Created:    19/5/93
01501     Inputs:     - 
01502     Outputs:    -
01503     Returns:    Pointer to the Document object associated with this object.
01504     Purpose:    Find the Kernel document associated with this Oil document.
01505     Errors:     -
01506     SeeAlso:    -
01507 ***********************************************************************************************/
01508 
01509 Document* CCamDoc::GetKernelDoc() const
01510 {
01511     return m_pKernelDoc;
01512 }
01513 
01514 
01515 
01516 /********************************************************************************************
01517 
01518 >   BOOL CCamDoc::SaveModified()
01519 
01520     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
01521     Created:    30/4/94
01522     Inputs:     -
01523     Outputs:    -
01524     Returns:    TRUE if safe to continue & close document, FALSE if cannot
01525     Purpose:    Prompts user to save document if required. MFCCOPY. Normal MFC uses non-
01526                 UI compliant Yes/No box.
01527     Errors:     -
01528 
01529 ********************************************************************************************/
01530 
01531 bool CCamDoc::OnSaveModified()
01532 {
01533 #ifdef STANDALONE
01534     // Don't prompt in standalone version - we can't save anyway
01535     return TRUE;
01536 #else
01537     // Check if we can dodge this job.  Don't save "hidden" kernel documents, or docs
01538     // that cannot be modified.
01539     if (!IsModifiable() || (GetKernelDoc() && GetKernelDoc()->IsAHiddenDoc()))
01540     {
01541         return true;        // ok to continue
01542     }
01543 
01544 #if (_OLE_VER >= 0x200)
01545     // Don't save (to file) embedded documents, they always save into a storage.
01546     if (IsEmbedded()) return CCamDocBase::SaveModified();
01547 #endif
01548     
01549     // Don't save docs that haven't been changed since last being saved.
01550     if (!IsModified()) return TRUE;
01551 
01552     // Get filename to display in msg.
01553     wxString name = m_documentFile;     // Was: m_strPathName;
01554     if (name.IsEmpty())
01555     {
01556         // No path means untitled, so use the made-up name instead.
01557         name = (const TCHAR*)m_TitlePrefix; 
01558     }
01559     else
01560     {
01561         // Extract the abbreviated path from the full path as held by MFC.
01562         // This involves a bit of string juggling...
01563         String_256 Temp(name);
01564         PathName Path(Temp);
01565         Temp = Path.GetTruncatedPath(20);
01566         name = (TCHAR*)Temp;
01567     }
01568 
01569     // use MakeMsg, so the context-sensitive help will work.
01570     StringBase buf;
01571     if (!buf.Alloc(512))
01572     {
01573         // Out of memory!
01574         ERROR( _R(IDE_NOMORE_MEMORY), false );
01575     }
01576 
01577     // Make the "save changes to <file>" message.
01578     buf.MakeMsg(_R(IDM_SAVEPROMPT), (LPCTSTR) name);
01579 
01580     // Set up the question we want to ask.
01581     ErrorInfo Question;
01582     Question.ErrorMsg = 0;
01583     Question.Button[0] = _R(IDB_SAVE);
01584     Question.Button[1] = _R(IDB_DONTSAVE);
01585     Question.Button[2] = _R(IDB_CANCEL);
01586 //  Question.Button[3] = _R(IDB_HELP);
01587     Question.OK = 1;
01588     Question.Cancel = 3;
01589 
01590     // We use a special title for the dialogue, usually "Closing Document" but if
01591     // Camelot is shutting down then "Exiting Xara Studio".
01592     Question.Title = (Camelot.CamelotIsDying()) ? _R(IDS_EXITING_XSTUDIO_TITLE)
01593                                                 : _R(IDS_CLOSING_DOC_TITLE);
01594 
01595     BOOL Again;
01596     do
01597     {
01598         // Set the error message
01599         Error::SetError( 0, buf, 0 );
01600 
01601         // And ask the question
01602         Again = FALSE;
01603         TRACEUSER( "Andy", _T("Creating SAVE? dialog box\n"));
01604 /*      switch ( AskQuestion( &Question ) )
01605         {
01606             case _R(IDB_CANCEL):
01607                 return FALSE;       // don't continue
01608                 break;
01609 
01610             case _R(IDB_SAVE):
01611                 // If so, either Save or Update, as appropriate
01612                 if (!DoSave(m_strPathName))
01613                     return FALSE;       // don't continue
01614                 
01615                 // fall through . . .
01616 
01617             case _R(IDB_DONTSAVE):
01618                 // If not saving changes, revert the document.
01619 
01620                 // OK, we must clear the modified flag here as the doc is no longer "dirty".
01621                 // If we don't then we will be prompted twice about saving open docs when
01622                 // we process a system shutdown message.
01623                 SetModified(FALSE);
01624                 break;
01625 
01626             default:
01627                 ASSERT(FALSE);
01628                 break;
01629         }
01630 */
01631         UINT32 answer = AskQuestion( &Question );
01632         if (answer==_R(IDB_CANCEL))
01633             return FALSE;       // don't continue
01634 
01635         else if (answer==_R(IDB_SAVE))
01636         {
01637             // If so, either Save or Update, as appropriate
01638             if (!DoSave(GetOriginalPath()))
01639                 return FALSE;       // don't continue
01640             // else doc has been saved so it's no longer "modified"
01641             SetModified(FALSE);
01642         }
01643 
01644         else if (answer==_R(IDB_DONTSAVE))
01645             // If not saving changes, revert the document.
01646 
01647             // OK, we must clear the modified flag here as the doc is no longer "dirty".
01648             // If we don't then we will be prompted twice about saving open docs when
01649             // we process a system shutdown message.
01650             SetModified(FALSE);
01651 
01652         else
01653             ERROR3("Unexpected return from AskQuestion\n");
01654 
01655     }
01656     while (Again);
01657 
01658     return TRUE;    // keep going
01659 #endif
01660     return true;
01661 }
01662 
01663 
01664 /********************************************************************************************
01665 
01666 This overrides the default wxDocument SaveAs behaviour, initially to tell user that save 
01667 doesn't work, but in the longer term it will play host to the real SaveAs code
01668 
01669 ********************************************************************************************/
01670 
01671 bool CCamDoc::SaveAs()
01672 {
01673 //  return wxDocument::SaveAs();
01674     wxDocTemplate *docTemplate = GetDocumentTemplate();
01675     if (!docTemplate)
01676         return false;
01677 
01678 #if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXMAC__)
01679     wxString filter = docTemplate->GetDescription() + wxT(" (") + docTemplate->GetFileFilter() + wxT(")|") + docTemplate->GetFileFilter();
01680 
01681     // Now see if there are some other template with identical view and document
01682     // classes, whose filters may also be used.
01683 
01684     if (docTemplate->GetViewClassInfo() && docTemplate->GetDocClassInfo())
01685     {
01686         wxList::compatibility_iterator node = wxDocManager::GetDocumentManager()->GetTemplates().GetFirst();
01687         while (node)
01688         {
01689             wxDocTemplate *t = (wxDocTemplate*) node->GetData();
01690 
01691             if (t->IsVisible() && t != docTemplate &&
01692                 t->GetViewClassInfo() == docTemplate->GetViewClassInfo() &&
01693                 t->GetDocClassInfo() == docTemplate->GetDocClassInfo())
01694             {
01695                 // add a '|' to separate this filter from the previous one
01696                 if ( !filter.empty() )
01697                     filter << wxT('|');
01698 
01699                 filter << t->GetDescription() << wxT(" (") << t->GetFileFilter() << wxT(") |")
01700                        << t->GetFileFilter();
01701             }
01702 
01703             node = node->GetNext();
01704         }
01705     }
01706 #else
01707     wxString filter = docTemplate->GetFileFilter() ;
01708 #endif
01709 
01710     wxString strPath;
01711     wxString strName;
01712     wxString strExt;
01713 
01714     // If this document already has a path, make Save As default to that path
01715     wxString tmp = GetFilename();
01716     if (!tmp.IsEmpty())
01717     {
01718         wxSplitPath(tmp, &strPath, &strName, &strExt);
01719     }
01720 
01721     if (strPath.IsEmpty())
01722 //      strPath = docTemplate->GetDirectory();
01723         strPath = (LPCTSTR) BaseFileDialog::DefaultSaveFilePath;
01724 
01725     // We want to force the use of the .xar extension...
01726     strExt = docTemplate->GetDefaultExtension();
01727 
01728     // We can't use wxOVERWRITE_PROMPT because is doesn't conform to our UI guidelines
01729     // So we must run that logic ourselves...
01730     BOOL bShowFileSelectorAgain = FALSE;
01731     do
01732     {
01733         wxString title(CamResource::GetText(_R(IDS_SAVEAS)));
01734         tmp = wxFileSelector(title,
01735                             strPath,
01736                             strName,
01737                             strExt,
01738                             filter,
01739                             wxSAVE,
01740                             GetDocumentWindow());
01741 
01742         if (tmp.IsEmpty())
01743             return false;
01744 
01745         if (wxFileExists(tmp))
01746         {
01747             ErrorInfo Info;
01748             Info.ErrorMsg = _R(IDS_SAVEAS_OVERWRITE);
01749             Info.Button[0] = _R(IDS_OVERWRITE);
01750             Info.Button[1] = _R(IDB_SAVEAS);
01751             Info.Button[2] = _R(IDS_CANCEL);
01752 
01753             UINT32 Answer = AskQuestion(&Info);
01754 
01755             if (Answer==_R(IDS_OVERWRITE))
01756             {
01757                 // Just use the name the user selected to overwite the existing file
01758                 bShowFileSelectorAgain = FALSE;
01759             }
01760             else if (Answer== _R(IDB_SAVEAS))
01761             {
01762                 // User wants to save as some other name
01763                 wxSplitPath(tmp, &strPath, &strName, &strExt);
01764                 strName = wxFileNameFromPath(tmp);
01765                 tmp = _T("");
01766                 bShowFileSelectorAgain = TRUE;
01767             }
01768             else if (Answer==_R(IDS_CANCEL))
01769             {
01770                 // User has chosen to abort the operation
01771                 return FALSE;
01772             }
01773             else
01774                 ERROR3("Unknown Answer from AskQuestion");
01775         }
01776     }
01777     while (bShowFileSelectorAgain);
01778 
01779     wxString fileName(tmp);
01780     wxSplitPath(fileName, &strPath, &strName, &strExt);
01781 
01782     if (strExt.IsEmpty())
01783     {
01784         fileName += wxT(".");
01785         fileName += docTemplate->GetDefaultExtension();
01786     }
01787 
01788     SetFilename(fileName);
01789     SetTitle(wxFileNameFromPath(fileName));
01790 
01791     // Notify the views that the filename has changed
01792     wxList::compatibility_iterator node = m_documentViews.GetFirst();
01793     while (node)
01794     {
01795         wxView *view = (wxView *)node->GetData();
01796         view->OnChangeFilename();
01797         node = node->GetNext();
01798     }
01799 
01800     // Files that were not saved correctly are not added to the FileHistory.
01801     if (!OnSaveDocument(m_documentFile))
01802         return false;
01803 
01804     // Record the path we saved in a preference so it survives sessions
01805     BaseFileDialog::DefaultSaveFilePath = strPath;
01806 
01807     // A file that doesn't use the default extension of its document template cannot be opened
01808     // via the FileHistory, so we do not add it.
01809     if (docTemplate->FileMatchesTemplate(fileName))
01810     {
01811         GetDocumentManager()->AddFileToHistory(fileName);
01812     }
01813     else
01814     {
01815         // The user will probably not be able to open the file again, so
01816         // we could warn about the wrong file-extension here.
01817     }
01818 
01819     return true;
01820 }
01821 
01822 
01823 /********************************************************************************************
01824 
01825 >   BOOL CCamDoc::DoSave(LPCTSTR lpszPathName, BOOL bReplace)
01826 
01827     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
01828     Created:    27/1/95
01829     Inputs:     lpszPathName - path name where to save document file
01830                 if 'bReplace' is TRUE will change file name if successful (SaveAs)
01831                 if 'bReplace' is FALSE will not change path name (SaveCopyAs) or clear
01832                 the "dirty" flag.
01833     Returns:    TRUE if it worked, FALSE if not
01834     Purpose:    This is an exact copy of the CDocument version of this function. I had to
01835                 copy it out as I need to change the bit that displays the SaveAs dialog so
01836                 that I could set it to the correct directory and generally change it about
01837                 to meet our requirements. This function ends up calling OnSaveDocument above
01838                 to do the actual saving.
01839 
01840 ********************************************************************************************/
01841 
01842 PORTNOTE("other","CCamDoc::DoSave - Replaced by simpler version")
01843 #ifndef EXCLUDE_FROM_XARALX
01844 bool CCamDoc::DoSave(LPCTSTR lpszPathName, BOOL bReplace)
01845 {
01846 #ifdef STANDALONE
01847     // Do nothing on a standalone version
01848     return true;
01849 #else
01850 
01851     // Get the name to save it as and see if it is empty
01852     bool                SaveAsNewName = false;
01853     wxString            newName = lpszPathName;
01854 
01855     // See if we have loaded this document as an old EPS native format
01856     // If so, then give the user the oppertunity to rename the file so that we don't
01857     // overwrite the original old format document.
01858     // Don't though, if the document is unnamed, so we are going to do a 'save as ...'
01859     // operation anyway.
01860     if( m_pKernelDoc && m_pKernelDoc->IsLoadedAsVersion1File() && !newName.IsEmpty() )
01861     {
01862 #ifndef _DEBUG
01863         // Old EPS format document so ask the user which format to save in
01864         ErrorInfo Info;
01865         Info.ErrorMsg = _R(IDS_OVERWRITEOLDFILE);
01866         Info.Button[0] = _R(IDS_OVERWRITE);
01867         Info.Button[1] = _R(IDB_SAVEAS);
01868         Info.Button[2] = _R(IDS_CANCEL);
01869         UINT32 Answer = AskQuestion(&Info);
01870 #else
01871         UINT32 Answer;
01872         if (!OpConvertFileFormats::IsActive ())
01873         {
01874             // Old EPS format document so ask the user which format to save in
01875             ErrorInfo Info;
01876             Info.ErrorMsg = _R(IDS_OVERWRITEOLDFILE);
01877             Info.Button[0] = _R(IDS_OVERWRITE);
01878             Info.Button[1] = _R(IDB_SAVEAS);
01879             Info.Button[2] = _R(IDS_CANCEL);
01880             Answer = AskQuestion(&Info);
01881         }
01882         else
01883         {
01884             Answer = SaveAsNewName;
01885         }
01886 #endif
01887         if (Answer==_R(IDS_OVERWRITE))
01888             // Rename the new file to make sure we don't overwrite old
01889             SaveAsNewName = FALSE;
01890         else if (Answer== _R(IDB_SAVEAS))
01891             // Rename the new file to make sure we don't overwrite old
01892             SaveAsNewName = TRUE;
01893         else if (Answer==_R(IDS_CANCEL))
01894             // User has chosen to abort the operation
01895             return FALSE;
01896         else
01897             ERROR3("Unknown Answer from AskQuestion");
01898 
01899         // Once we have asked the question ensure that the user is not asked again
01900         // We need to set the loaded flag as FALSE to effectively say that the document
01901         // is now considered version 2.
01902         // In a save as operation, the document will switch to the new name.
01903         // Now Disabled, as cannot set it until actually saved the document as the user may choose
01904         // something like save as and then cancel the file dialog box
01905         //KernelDoc->SetLoadedAsVersion1File(FALSE);
01906     }
01907 
01908     // If the name is empty, i.e. wasn't loaded as a .xar (e.g. open a tiff file) or newly created
01909     // then ask the user for a name i.e. do a 'save as....' operation.
01910     // Also, if we loaded an old format eps xar file and the user has chosen to not overwrite the
01911     // file then we must give them a 'save as....' option.
01912     if (newName.IsEmpty() || SaveAsNewName)
01913     {
01914         // Its empty, so create a default name
01915         CDocTemplate* pTemplate = GetDocTemplate();
01916         ASSERT(pTemplate != NULL);
01917 
01918         newName = m_strPathName;
01919         if (bReplace && newName.IsEmpty())
01920         {
01921             // No path means untitled, so use the made-up name instead.
01922             // This is our stored form of the title before having any items such as ' * '
01923             // or '(Copy)' appended. It is used by the close unsaved document, so warn user code
01924             // so should be reasonably safe.
01925             newName = (const TCHAR*) TitlePrefix;
01926         }
01927 
01928         // we will do it like this instead...
01929         // Set up the dialog
01930         String_256 FilterString(_R(IDS_SAVEFILTERS));
01931 
01932         // Get the filename.
01933         String_256 Str((const char*)newName);
01934 
01935         // If the string is still empty, get a default out
01936         if (Str.IsEmpty()) Str.Load(_R(IDS_DEFAULTFILENAME));
01937 
01938         // Build a pathname out of it
01939         PathName Path(Str);
01940 
01941         // Get some details, ready for the dialog
01942         String_256 LowxString = Path.GetLocation(FALSE);
01943         String_256 NameString = Path.GetFileName();
01944 
01945         // create a dialog and use the path and name of the file if available, or
01946         // use the default path if not.
01947         String_256 DocName = GetKernelDocName();
01948 
01949         // Sorry about the long names, but we are into OS Specific scary stuff here
01950         // Under Windows 95 the OnFileNameOK() function of CFileDialog does not work
01951         // As a Result we have to do the tests ourselves afterwards under win95
01952         // by default we do not need to put the dialog up
01953         BOOL WeNeedToPutSaveAsDialogUpAgain = FALSE;
01954         
01955         // try the dialog
01956         do
01957         {
01958             // Default to only putting the dialog up the once.
01959             WeNeedToPutSaveAsDialogUpAgain = FALSE;
01960 
01961             // Create and display prepare the dialog
01962             SaveFileDialog SaveDialog(FilterString, LowxString, NameString, DocName);
01963             SaveDialog.PrepareDialog();     
01964     
01965             // Display the dialog
01966             TRACE( _T("Display the dialog\n"));
01967             BOOL Result = SaveDialog.OpenAndGetFileName();
01968 
01969             // If they did not click on OK then stop right now
01970             if (!Result)
01971                 return FALSE;
01972 
01973             // Make sure that the file name is OK
01974             // we only need to do this under windows 95, as other OS's will have already done it
01975             // Disable for VC4.0/MFC 4.0 as they have fixed it.
01976         #if _MFC_VER < 0x400
01977             if (IsWin32c())
01978             {
01979                 TRACE( _T("Windows 95, testing for same file name after the event\n"));
01980                 if (!SaveDialog.IsValidFilename()) WeNeedToPutSaveAsDialogUpAgain = TRUE;
01981             }
01982         #endif
01983 
01984             // Get the filename.
01985             wxString TempName(SaveDialog.m_ofn.lpstrFile);
01986             SaveDialog.AppendExtension(&TempName);
01987             Str = String_256(TempName);
01988             Path = PathName(Str);
01989 
01990             // Extract directory name (minus terminating backslash) and remember for next time.
01991             SaveDialog.SetDefaultPath(Path.GetLocation(FALSE));
01992 
01993         } while(WeNeedToPutSaveAsDialogUpAgain);
01994 
01995         // Put the file name into the var set aside for it
01996         newName = (const char*) Str;
01997     
01998     }
01999 
02000         
02001     // Check that the document isn't already open. NOTE: this is only relevant
02002     //  to OLE documents, as attempting to save a document with the same name as
02003     //  an existing, open doc will stuff up the OLE registration code in the 
02004     //  CCamDoc::OnSaveDocument function, after overwriting the file itself...
02005     
02006     BOOL isDocumentOpen = FALSE;
02007 
02008 PORTNOTETRACE("other","CCamDoc::DoSave - remove OLE usage");
02009 #ifndef EXCLUDE_FROM_XARALX
02010 #if (_OLE_VER >= 0x200)
02011 
02012     POSITION pos = AfxGetApp()->GetFirstDocTemplatePosition();
02013 
02014     CDocTemplate::Confidence match = CDocTemplate::noAttempt;
02015     CDocTemplate* pTemplate = NULL;
02016     CDocument* pOpenDocument = NULL;
02017 
02018     // cycle through the document types until we've done them all, or we find that
02019     //  the document is already open.
02020     while ((pos != NULL) && (match != CDocTemplate::yesAlreadyOpen))
02021     {
02022         pTemplate = AfxGetApp()->GetNextDocTemplate(pos);
02023         ASSERT (pTemplate->IsKindOf(RUNTIME_CLASS(CDocTemplate)));
02024 
02025         ASSERT (pOpenDocument == NULL);
02026         match = pTemplate->MatchDocType(newName, pOpenDocument);
02027 
02028             // NOTE: make sure that the match isn't the document that we're editing,
02029             //  otherwise we wouldn't be able to save documents at all...
02030         if (this == pOpenDocument)
02031         {
02032             match =  CDocTemplate::noAttempt;
02033             pOpenDocument = NULL;
02034         }
02035     }
02036 
02037     // Determine whether document is already open or not
02038     if (match == CDocTemplate::yesAlreadyOpen)
02039         isDocumentOpen = TRUE;
02040     else
02041         isDocumentOpen = FALSE;
02042 
02043 #endif      // (OLE_VER >= 0x200)
02044 #endif
02045 
02046     // End 'Already Open' check.
02047 
02048     if (isDocumentOpen == FALSE)
02049     {
02050 
02051         // Make a .bak version of the file here in case the save screws up
02052         // This will be removed after the save, unless they have the keep bak files option in
02053         // Rename the current version of the file to the same with a .bak extension
02054         // get the old filename
02055         String_256 BakFileName(newName);
02056         String_256 OldFileName = BakFileName;
02057         
02058         // Change the extension on NewFileName...
02059         PathName NewPathName = BakFileName;
02060 
02061         // and change its extension
02062         String_256 Extension(_R(IDS_BAKEXTENSION));
02063         NewPathName.SetType(Extension);
02064 
02065         // Go find out where the temp directory is so that we can put the .bak file in there
02066         String_256 TempFileName;
02067         char* pTempName = _tgetenv("TEMP");
02068         if (pTempName!=NULL)
02069         {
02070             TempFileName = String_256(pTempName);
02071             
02072             // See if we have a backslash
02073             String_8 LastChar;
02074             TempFileName.Right(&LastChar, 1);
02075 
02076             // if it isn't a \ then add one
02077             if (LastChar!=String_8("\\"))
02078                 TempFileName += String_8("\\");
02079 
02080             // Add the leaf name to it
02081             TempFileName += NewPathName.GetFileName();
02082             TRACEUSER( "Neville", _T("TEMP file is %s\n"), (const char*)TempFileName);
02083         }
02084 
02085         // Copy the version with the new extension back over the original
02086         BakFileName = NewPathName.GetPath();
02087 
02088         // Get these as strings we can use
02089         TCHAR* pBakName = NULL;
02090         TCHAR* pOldName = (TCHAR*) OldFileName;
02091         
02092         // If the user want .bak files then use a local name,
02093         // otherwise put the bak file in the temp directory
02094         if ((BaseFileDialog::MakeBakFiles) || (pTempName==NULL))
02095             pBakName = (TCHAR*) BakFileName;
02096         else
02097             pBakName = (TCHAR*) TempFileName;
02098 
02099         // make sure they are not the same (ie, let them save files with a .bak extension)
02100         BOOL FileNamesSame = (BakFileName == OldFileName);
02101         if (!FileNamesSame)
02102         {
02103             // Make sure that the .bak version of the file does not exist
02104             // If these do not work (eg the .bak is read-only) then you
02105             // simply will not get your .bak file updated and run the risk
02106             // of loosing your current changes if the save fails.
02107             TRACEUSER( "Neville", _T("Check to see if %s exists\n"), pBakName);
02108             if (_taccess(pBakName, 0)==0)
02109             {
02110                 TRACEUSER( "Neville", _T("deleteing %s\n"), pBakName);
02111                 unlink(pBakName);
02112             }
02113         
02114             // Now rename the original file (but only if the old filename exists)
02115             TRACEUSER( "Neville", _T("Check to see if %s exists\n"), pOldName);
02116             if (_taccess(pOldName, 0)==0)
02117             {
02118                 // Rename the original artwork to a .bak version of the file
02119                 TRACEUSER( "Neville", _T("Renaming %s to %s\n"), pOldName, pBakName);
02120                 INT32 RenameResult = _trename(pOldName, pBakName);
02121 
02122                 // if we fail to rename the file, but the user wants renamed files, complain
02123                 if ((RenameResult!=0) && (BaseFileDialog::MakeBakFiles))
02124                 {
02125                     // There was a problem renaming the file, ask if we want to go on
02126                     ErrorInfo Info;
02127                     Info.ErrorMsg = _R(IDS_RENAMEFAILED);
02128                     Info.Button[0] = _R(IDS_SAVEANYWAY);
02129                     Info.Button[1] = _R(IDS_ABORTSAVE);
02130 
02131                     // If not then stop right away.
02132                     if (AskQuestion(&Info)==_R(IDS_ABORTSAVE))
02133                         return FALSE;
02134                 }
02135             }
02136         }
02137 
02138         // This may take a while ...
02139         String_64 strProgress;
02140         strProgress.MakeMsg(_R(IDS_WAIT_UPDATING_DOC_PFX), (LPCTSTR) GetTitle());
02141         BeginSlowJob( -1, FALSE, NULL );
02142 
02143     #if (_OLE_VER >= 0x200)
02144         // If the document is embedded and this isn't SaveCopyAs then don't export a preview
02145         // bitmap.
02146         BOOL fOldPrev;
02147         if (IsEmbedded() && !bReplace)
02148         {
02149             TRACEUSER( "JustinF", _T("Exporting preview for embedded item in CCamDoc::DoSave\n"));
02150             fOldPrev = SetExportPreview(TRUE);
02151         }
02152     #endif
02153 
02154         // Do the actual saving
02155         BOOL fOK = OnSaveDocument(newName);
02156 
02157     #if (_OLE_VER >= 0x200)
02158         // Restore the original setting if we changed it.
02159         if (IsEmbedded() && !bReplace) SetExportPreview(fOldPrev);
02160     #endif
02161 
02162         // Was the save successful?
02163         if (!fOK)
02164         {
02165             // The save failed here, so tidy up
02166             // be sure to delete the corrupt file
02167             TRACEUSER( "Neville", _T("Save failed, removing %s\n"), newName);
02168             remove(newName);
02169 
02170             // Well, something went a bit wrong there, so copy the old version of the file
02171             // over the top of the rubbish one if we have the .bak version that is
02172             if (!FileNamesSame)
02173             {
02174                 // If the bak file exists, rename it over the original
02175                 TRACEUSER( "Neville", _T("Check to see if %s exists\n"), pBakName);
02176                 if (_taccess(pBakName, 0) == 0)
02177                 {
02178                     TRACEUSER( "Neville", _T("renaming %s to %s\n"), pBakName, pOldName);
02179                     _trename(pBakName, pOldName);
02180                 }
02181             }
02182 
02183             // return that we failed
02184             EndSlowJob();
02185             return FALSE;
02186         }
02187 
02188         // The save worked, so get rid of the bak file if they do not want it
02189         // if we do not want bak file around the place, then get rid of them
02190         if (!BaseFileDialog::MakeBakFiles)
02191         {
02192             TRACEUSER( "Neville", _T("bak files not wanted, getting rid of it\n"));
02193             // Make sure the .bak file was not the real file as well!
02194             if (!FileNamesSame)
02195             {
02196                 // If the bak file exists, delete it
02197                 TRACEUSER( "Neville", _T("Check to see if %s exists\n"), pBakName);
02198                 if (_taccess(pBakName, 0)==0)
02199                 {
02200                     TRACEUSER( "Neville", _T("Deleting %s\n"), pBakName);
02201                     unlink(pBakName);
02202                 }
02203             }       
02204         }
02205 
02206         // Once we have saved the document ok, then ensure that the user is not asked again
02207         if (KernelDoc) KernelDoc->SetLoadedAsVersion1File(FALSE);
02208 
02209         // reset the title and change the document name
02210         if (bReplace)
02211         {
02212             // If we have just changed the name of the document, then get rid of the copy flag
02213             SetCopy(FALSE);
02214         
02215             // We saved the file under a new name, as opposed to a copy of the file, so it is
02216             // no longer "dirty".
02217             SetModified(FALSE);
02218 
02219             // Set the name of the document
02220             SetPathName(newName);
02221         }
02222 
02223         EndSlowJob();
02224         return TRUE;        // success
02225     }       // Document is already open and registered
02226     else
02227     {
02228 //      MessageBox (NULL, _R(IDS_OVERWRITEOPENFILE), NULL, MB_ICONERROR);
02229         UINT32 Answer;
02230         ErrorInfo Info;
02231 
02232         Info.ErrorMsg = _R(IDS_OVERWRITEOPENFILE);
02233         Info.Button[0] = _R(IDS_CANCEL);
02234         Answer = AskQuestion(&Info);
02235 
02236         return FALSE;       // could not open document
02237 
02238     }       // End of isDocumentOpen (OLE registration check)
02239 #endif  // Not standalone (see first few lines)
02240 }
02241 #else
02242 
02243 
02244 bool CCamDoc::DoSave(LPCTSTR lpszPathName, BOOL bReplace)
02245 {
02246 #ifdef STANDALONE
02247     // Do nothing on a standalone version
02248     return true;
02249 #else
02250     PORTNOTETRACE("save", "CCamDoc::DoSave grossly simplified from Xtreme version!");
02251     BOOL bOK = TRUE;
02252 
02253     // Get the name to save it as and see if it is empty
02254     BOOL                SaveAsNewName = false;
02255     wxString            newName = lpszPathName;
02256 
02257     // If the name is empty, i.e. wasn't loaded as a .xar (e.g. open a tiff file) or newly created
02258     // then ask the user for a name i.e. do a 'save as....' operation.
02259     // Also, if we loaded an old format eps xar file and the user has chosen to not overwrite the
02260     // file then we must give them a 'save as....' option.
02261     if (newName.IsEmpty() || SaveAsNewName)
02262     {
02263         SaveAs();
02264     }
02265     else
02266     {
02267         bOK = OnSaveDocument(newName);
02268     }
02269 
02270     return bOK;
02271 #endif
02272 }
02273 #endif
02274 
02275 
02276 /********************************************************************************************
02277 >   virtual void CCamDoc::DeleteContents()
02278 
02279     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02280     Created:    25/3/94
02281     Inputs:     -
02282     Outputs:    -
02283     Returns:    -
02284     Purpose:    Deletes this document's data.  Called by MFC in various situations.
02285     Errors:     -
02286     SeeAlso:    Document::DeleteContents
02287 ********************************************************************************************/
02288 
02289 bool CCamDoc::DeleteContents()
02290 {
02291     m_pKernelDoc->SetCurrent();
02292     m_pKernelDoc->DeleteContents();
02293 
02294     return true;
02295 }
02296 
02297 /********************************************************************************************
02298 >   void CCamDoc::UpdateTitle()
02299 
02300     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02301     Created:    14/3/94
02302     Inputs:     -
02303     Outputs:    -
02304     Returns:    -
02305     Purpose:    Sets the (window) titles of all views onto this document to the
02306                 contained title of the document, plus a suffix if the document has
02307                 been modified (cf. Visual C++ & Word), is read-only, or a copy.
02308     Errors:     -
02309     SeeAlso:    -
02310 ********************************************************************************************/
02311 
02312 void CCamDoc::UpdateTitle()
02313 {
02314     m_pKernelDoc->SetCurrent();
02315 
02316     // Update the title of all views onto this document, and broadcast to the kernel to
02317     // let everyone know about the change, but only if it has actually changed
02318     // This actually sets the title to the same as it is now, but makes it recaluculate all
02319     // 'Modifed' flags on the end
02320     SetTitle( m_TitlePrefix );
02321 
02322     // Notify the views that the filename has changed
02323     wxList::compatibility_iterator node = m_documentViews.GetFirst();
02324     while (node)
02325     {
02326         wxView *view = (wxView *)node->GetData();
02327         view->OnChangeFilename();
02328         node = node->GetNext();
02329     }
02330 }
02331 
02332 /********************************************************************************************
02333 
02334 >   String_256 CCamDoc::GetKernelTitle()
02335 
02336     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
02337     Created:    13/1/95
02338     Returns:    String_256 containing the current document title
02339     Purpose:    Good for finding out the title of the document. If the document has been
02340                 saved as 'Blobby.art' then the title returned will be of the form
02341                 'Blobby.art (Modified)' etc. ie What you would see in the title of a
02342                 non maximised document window.
02343     SeeAlso:    Document::GetTitle()
02344 
02345 ********************************************************************************************/
02346 
02347 String_256 CCamDoc::GetKernelTitle()
02348 {
02349     // First off, get a copy of the string we are after
02350     wxString            CurrentTitle = GetTitle();
02351 
02352     // and put it into a Kernel String_256 and return it
02353     return String_256( CurrentTitle );
02354 }
02355 
02356 
02357 
02358 /********************************************************************************************
02359 
02360 >   String_256 CCamDoc::GetKernelPathName(UINT32 MaxSize = 0)
02361 
02362     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02363     Created:    20/3/95
02364     Inputs:     MaxSize maximum size in characters of the requried pathname.
02365                 Zero indicates return the full pathname, which it defaults to. 
02366     Returns:    String_256 containing the current document pathname
02367     Purpose:    Good for finding out the pathname of the document.
02368     SeeAlso:    Document::GetPathName;
02369     
02370 ********************************************************************************************/
02371 
02372 String_256 CCamDoc::GetKernelPathName(UINT32 MaxSize)
02373 {
02374 #if !defined(EXCLUDE_FROM_RALPH)
02375     // First off, get a copy of the string we are after
02376     wxString            name = GetFilename();
02377 
02378     if( !name.IsEmpty() )
02379     {
02380         // Extract the abbreviated path from the full path as held by MFC.
02381         TCHAR           buf[512];
02382         camStrcpy( buf, name );
02383 PORTNOTE("other","Removed AbbreviateName usage")
02384 #ifndef EXCLUDE_FROM_XARALX
02385         AbbreviateName( buf, (INT32)MaxSize, TRUE );
02386 #endif
02387         name = buf;
02388     }
02389 
02390     // and put it into a Kernel String_256 and return it
02391     String_256 KernelString(name);
02392     return KernelString;
02393 #else
02394     return String_256( GetFilename() );
02395 #endif
02396 }
02397 
02398 
02399 
02400 /********************************************************************************************
02401 
02402 >   String_256 CCamDoc::GetKernelLocation(UINT32 MaxSize = 0)
02403 
02404     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02405     Created:    20/3/95
02406     Inputs:     MaxSize maximum size in characters of the requried location.
02407                 Zero indicates return the full location, which it defaults to. 
02408     Returns:    String_256 containing the current document location
02409     Purpose:    Good for finding out the location of the document. This is the pathname minus
02410                 the filename.
02411     SeeAlso:    Document::GetLocation
02412     
02413 ********************************************************************************************/
02414 
02415 String_256 CCamDoc::GetKernelLocation(UINT32 MaxSize)
02416 {
02417     // First off, get a copy of the string we are after
02418     wxString            name = GetFilename();  //GetPathName();
02419 
02420     // and put it into a Kernel String_256 ready just in case we have to return it
02421     String_256 KernelString(name);
02422 
02423     // if the pathname is blank then return it directly to the caller.
02424     if ( KernelString.IsEmpty() )
02425         return KernelString;
02426         
02427     // We will use the pathname class to try and truncate this to a more reasonable
02428     // pathname if it will not fit into the required space as this knows all about
02429     // what makes up paths etc.
02430     PathName   KernelPathName(KernelString);    // construct the pathname using the string_256
02431 
02432     if (!KernelPathName.IsValid())
02433     {
02434         // There was a problem parsing that pathname, so just return the string
02435         // An error will have been set.
02436         Error::ClearError();
02437         return KernelString;
02438     }
02439     
02440     return KernelPathName.GetTruncatedLocation(MaxSize);
02441 }
02442 
02443 
02444 
02445 /********************************************************************************************
02446 
02447 >   String_256 CCamDoc::GetKernelDocName(BOOL IncludeFileType = TRUE)
02448 
02449     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02450     Created:    27/3/95
02451     Returns:    String_256 containing the current document name.
02452     Purpose:    Good for finding out the name of the document. If the document has been
02453                 saved as 'Blobby.art' then the title returned will be of the form
02454                 'Blobby.art etc. otherwise will be of the form Untitled#1. Similar to what
02455                 the functions GetTitle() and GetKernelTitle() return but is just the document
02456                 name with none of the modified etc.
02457     SeeAlso:    GetKernelTitle(); Document::GetDocName();
02458 
02459 ********************************************************************************************/
02460 
02461 String_256 CCamDoc::GetKernelDocName(BOOL IncludeFileType)
02462 {
02463     // The Title Prefix is just the name of the document without all the 'Modified' bits
02464     // on the end of it. If it isn't, the bug is not here, but elsewhere.
02465     return m_TitlePrefix;
02466 }
02467 
02468 /********************************************************************************************
02469 >   String_256 CCamDoc::GetOriginalPath() const
02470 
02471     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02472     Created:    2/10/95
02473     Returns:    Returns the path to the original file that was used to load this doc if it
02474                 wasn't a .ART native format file, eg. if you "open" a bitmap then Camelot
02475                 makes a default document and imports the bitmap onto it, in this case this
02476                 function will return the path to the bitmap.  This path is set to empty if
02477                 the doc is modified or was created by "new" document.
02478     SeeAlso:    CCamDoc::SetOriginalPath; SaveAppWindowState
02479 ********************************************************************************************/
02480 
02481 String_256 CCamDoc::GetOriginalPath() const
02482 {
02483     // We *don't* set the original path to empty in the IsModified function because
02484     // the user might undo back to the unmodified version!
02485     return (((CCamDoc*) this)->IsModified()) ? String_256(TEXT("")) : m_strOriginalPath;
02486 }
02487 
02488 
02489 
02490 /********************************************************************************************
02491 >   void CCamDoc::SetOriginalPath(const String_256& strPath)
02492 
02493     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02494     Created:    2/10/95
02495     Inputs:     strPath         the path to the original non-native document, eg. a bitmap
02496                                 that was "opened" to make this doc.
02497     Purpose:    Sets the path to the non-native document that this Camelot doc is based on.
02498                 This path should be set to empty if the Camelot doc is no longer equivalent
02499                 to the original non-native file, eg. if the Camelot doc becomes modified,
02500                 or was loaded from a .ART native file, or is new (untitled).
02501     Errors:     -
02502     SeeAlso:    CCamDoc::GetOriginalPath
02503 ********************************************************************************************/
02504 
02505 void CCamDoc::SetOriginalPath(const String_256& strPath)
02506 {
02507 //  TRACEUSER( "JustinF", _T("\tSetting original path to %s\n"), (LPCTSTR) strPath);
02508     m_strOriginalPath = strPath;
02509 }
02510 
02511 /********************************************************************************************
02512 >   virtual CCLexFile* CCamDoc::CreateCCFile(LPCTSTR lpcszPath, INT32 nOpenMode)
02513 
02514     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02515     Created:    19/8/96
02516     Inputs:     lpcszPath   -   path to the disk file to open, or if NULL then open the
02517                                 "CONTENTS" stream of the CCamDoc's root-storage member.
02518                 nOpenMode   -   opening mode, eg. ios::in.  ios::binary is assumed.
02519     Returns:    A pointer to a CCLexFile derivative on the heap that represents the given
02520                 file object, either on disk or in structured storage.  The caller should
02521                 deallocate this file when finished with it.  Returns NULL if there was an
02522                 error (eg. file not found) - if so then the error has already been reported.
02523     Purpose:    CCamDoc::OnOpenDocument and CCamDoc::OnSaveDocument call this to allocate
02524                 a CCLexFile object to load ans save from/to.
02525     SeeAlso:    CCamDoc::OnOpenDocument; CCamDoc::OnSaveDocument
02526 ********************************************************************************************/
02527 
02528 CCLexFile *CCamDoc::CreateCCFile( LPCTSTR lpcszPath, INT32 nOpenMode )
02529 {
02530     // Fix-up the flags.
02531     nOpenMode |= ios::binary;
02532     if (nOpenMode & ios::out) nOpenMode |= ios::trunc;
02533 
02534     // Allocate the appropriate kind of file.
02535     CCLexFile* pFile = 0;
02536     if (lpcszPath)
02537     {
02538         // A path was passed, so open a disk-file on it.
02539         pFile = new CCDiskFile(PathName(lpcszPath), nOpenMode);
02540 //      TRACEUSER( "JustinF", _T("\t- a new CCDiskFile at 0x%p, no sweat\n"), (LPVOID) pFile);
02541     }
02542 
02543 #if (_OLE_VER >= 0x200)
02544 
02545     else
02546     {
02547         // No path was passed, so open the 'native XaraDrawing' stream of CCamDoc's
02548         // m_lpRootStg storage, inherited from CCamDocBase (COleServerDoc).
02549         ERROR2IF(!m_lpRootStg, 0, "No IStorage interface in CCamDoc::CreateCCFile");
02550 
02551         // We have to create or open the stream, depending on whether we are opening for read,
02552         // write, or read/write.
02553         //
02554         // JCF: version 2.0 change - embedded native XaraDrawings no longer have
02555         // version numbers as the native filter handles all versioning itself.
02556         // So we will try to transparently rename on opening any old style streams
02557         // we come across.
02558         LPCWSTR pszStreamName = L"Xara Drawing (native)";
02559         LPSTREAM pIStream;
02560         HRESULT hr;
02561         if (nOpenMode & ios::in)
02562         {
02563             // Loading, so open an existing stream.
02564             ERROR2IF(nOpenMode & ios::out, FALSE,
02565                             "CCamDoc::CreateCCFile: OLE read AND write not implemented");
02566             hr = m_lpRootStg->OpenStream(pszStreamName, 0,
02567                                          STGM_READ | STGM_SHARE_EXCLUSIVE,
02568                                          0, &pIStream);
02569 
02570             // Try the old native format if opening the new stream didn't work.
02571             if (hr == STG_E_FILENOTFOUND)
02572             {
02573                 LPCWSTR pszOldStreamName = L"XaraDrawing 1.5 (Native)";
02574                 hr = m_lpRootStg->OpenStream(pszOldStreamName, 0,
02575                                              STGM_READ | STGM_SHARE_EXCLUSIVE,
02576                                              0, &pIStream);
02577                 
02578                 if (SUCCEEDED(hr))
02579                 {
02580                     // Try to modernise the old stream's name.
02581                     HRESULT hr2 = m_lpRootStg->RenameElement(pszOldStreamName, pszStreamName);
02582                     TRACEUSER( "JustinF", _T("\t- tried to rename v1.5 stream (HRESULT 0x%lX)\n"),
02583                                                     (UINT32) hr2);
02584                     
02585                     // Pass any error along if there's not a good reason for it.
02586                     if (FAILED(hr2) &&
02587                         hr2 != STG_E_DISKISWRITEPROTECTED &&
02588                         hr2 != STG_E_ACCESSDENIED)
02589                             hr = hr2;
02590                 }
02591             }
02592         }
02593         else
02594         {
02595             // If there's a Camelot class factory around then associate this storage with it.
02596             if (m_pFactory) WriteClassStg(m_lpRootStg, m_pFactory->GetClassID());
02597 
02598             // Saving, so create a new stream / truncate an existing stream.
02599             ERROR3IF(!(nOpenMode & ios::out), "No I/O mode in CCamDoc::CreateCCFile");
02600             hr = m_lpRootStg->CreateStream(pszStreamName,
02601                                            STGM_WRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE,
02602                                            0, 0, &pIStream);
02603         }
02604 
02605         // Do we have a valid IStream?
02606         if (FAILED(hr))
02607         {
02608             // No, so report the error and fail.
02609             TRACE( _T("Couldn't open IStream in CCamDoc::CreateCCFile (HRESULT 0x%lX)\n"),
02610                     (UINT32) hr);
02611             InformError(_R(IDE_OPEN_ERROR));
02612             return 0;
02613         }
02614 
02615 #ifdef WEBSTER      
02616         // WEBSTER-Martin-29/12/96
02617         // no accusoft stuff so wrap a boring old CCOleStream around it
02618         pFile = new CCOleStream(pIStream, nOpenMode, filebuf::sh_none);
02619 #else
02620         // Yes, so wrap a CCAccusoftOleStream around it.
02621         pFile = new CCOleAccusoftStream(pIStream, nOpenMode, filebuf::sh_none);
02622 #endif
02623 /*      TRACEUSER( "JustinF", _T("\t- a new CCAccusoftOleStream at 0x%p, take cover!\n"),
02624                     (LPVOID) pFile);
02625 */  }
02626 
02627 #endif
02628 
02629     // Check if we managed to allocate the file.
02630     if (!pFile)
02631     {
02632         // No, so report the error and fail.
02633         InformError( _R(IDE_NOMORE_MEMORY) );
02634         return 0;
02635     }
02636 
02637     // Was the file opened sucessfully?
02638     if (!pFile->isOpen())
02639     {
02640         // Couldn't open the file, so deallocate it.  Any error will have already been
02641         // reported.
02642         delete pFile;
02643         pFile = 0;
02644     }
02645 
02646     // Return the file (or null).
02647     return pFile;
02648 }

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