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 }