00001 // $Id: document.cpp 1668 2006-08-04 11:45:17Z alex $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 00099 #include "camtypes.h" 00100 00101 #include <fstream> 00102 //#include <strstream> // this seems to be deprecated 00103 #include <ctype.h> 00104 #include <string> 00105 #include <stdlib.h> // for rand() fn 00106 00107 #include "camdoc.h" 00108 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00109 //#include "docmsgs.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00110 00111 #include "dumbnode.h" 00112 #include "noderect.h" 00113 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00114 #include "lineattr.h" 00115 #include "colcontx.h" 00116 //#include "doccolor.h" 00117 //#include "colourix.h" 00118 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00119 //#include "readeps.h" 00120 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00121 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00122 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00123 #include "csrstack.h" 00124 #include "grid.h" 00125 #include "nodedoc.h" 00126 #include "chapter.h" 00127 #include "page.h" 00128 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00129 #include "wrkrect.h" 00130 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00131 //#include "msg.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00132 #include "sprdmsg.h" 00133 #include "layer.h" 00134 #include "insertnd.h" 00135 //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00136 #include "camview.h" 00137 //#include "native.h" // The new designed native filter, used for v2 00138 #include "nativeps.h" // The old style EPS native filter, used in v1.1 00139 #include "saveeps.h" 00140 #include "zoomops.h" 00141 #include "qualops.h" 00142 #include "ai_eps.h" 00143 #include "ai_epsrr.h" 00144 #include "fontlist.h" 00145 #include "fontman.h" 00146 #include "progress.h" 00147 #include "bmpcomp.h" 00148 #include "ralphdoc.h" 00149 #include "camelot.h" // For SafeRender Critical section stuff 00150 //#include "clipint.h" 00151 #include "nodedoc.h" 00152 #include "ngsentry.h" 00153 #include "opnudge.h" 00154 #include "ophist.h" 00155 #include "cutop.h" 00156 00157 //#include "ralphvw.h" 00158 #include "vstate.h" 00159 00160 DECLARE_SOURCE("$Revision: 1668 $"); 00161 00162 CC_IMPLEMENT_DYNAMIC(Document, BaseDocument) 00163 CC_IMPLEMENT_DYNAMIC(DocChangingMsg, Msg) 00164 CC_IMPLEMENT_DYNAMIC(SpreadMsg, Msg) 00165 CC_IMPLEMENT_DYNAMIC(TranspModeMsg, Msg) 00166 CC_IMPLEMENT_DYNAMIC(SafeRenderPointer, CCObject) 00167 00168 // Declare smart memory handling in Debug builds 00169 #define new CAM_DEBUG_NEW 00170 00171 const MILLIPOINT PageWidth = ( 8 * 72000); 00172 const MILLIPOINT PageHeight = (11 * 72000); 00173 00174 // Default page size/position. 00175 const MILLIPOINT Gap = 72000L; 00176 const MILLIPOINT PasteBoardWidth = PageWidth + (Gap * 2); 00177 const MILLIPOINT PasteBoardHeight = PageHeight + (Gap * 2); 00178 const MILLIPOINT DefBleedSize = 72000L/4; 00179 00180 00181 Document* Document::Current = NULL; 00182 Document* Document::Selected = NULL; 00183 00184 Spread* Document::pGlobalSelSpread = NULL; 00185 00186 BOOL Document::fRestoreViewOnImport = TRUE; 00187 00188 00189 static String_256 ClipboardNameText(TEXT("Clipboard")); 00190 00191 // the default nudge size for our documents .... 00192 // NOTE: if you change this, you should also update the hard-coded value within: 00193 // GeneralRecordHandler::HandleTagNudeSizeRecord (). I could move this to the .h; but I can't 00194 // be bothered .... 00195 const UINT32 DEFAULT_NUDGE_SIZE = 2835; 00196 00197 00198 00199 /*********************************************************************************************** 00200 00201 > Document::Document(BOOL IsAHiddenDoc = FALSE) 00202 00203 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00204 Created: 19/5/93 00205 Inputs: IsAHiddenDoc - FALSE for a normal document (see below) 00206 TRUE for a hidden document (including clipboards, etc) 00207 00208 Purpose: Constructor. Initialises the link to the OIL document. 00209 00210 Notes: You MUST call Document::Init after Creation of the document, to fill in 00211 the defaults and build the document tree root. 00212 00213 HIDDEN DOCUMENTS 00214 A hidden document is one which is not shown to the user in any UI. 00215 Hidden docs are used mainly for clipboard (and OLE) data transfer operations. 00216 00217 Note that if you pass in (pCCamDoc = NULL) then the document is forced to be hidden. 00218 SeeAlso IsAHiddenDoc() and IsNotAHiddenDoc() in document.h 00219 00220 The InternalClipboard is now based upon Document. It creates a Hidden Document. 00221 Generally nobody should care about this, but some bits of code might have to be 00222 careful of the differences. Use IsAClipboard() to check if the doc is really a 00223 clipboard. Note also that Clipboard documents do not broadcast DocChangingMsgs. 00224 00225 Errors: None. 00226 SeeAlso: Document::Init; InternalClipboard; BaseDocument 00227 00228 ***********************************************************************************************/ 00229 00230 Document::Document(BOOL bIsAHiddenDoc) 00231 : BaseDocument(bIsAHiddenDoc), 00232 OilDoc(0) 00233 { 00234 // NB. Make sure all the Document stuff is set up before calling routines which 00235 // might interrogate the Document object. 00236 00237 // Set the default state of the flags. 00238 DocFlags.LayerMultilayer = FALSE; 00239 DocFlags.LayerAllVisible = FALSE; 00240 DocFlags.SaveWithUndo = TRUE; 00241 00242 // Set the times 00243 CreationTime = ::time(NULL); 00244 LastSaveTime = 0; 00245 00246 // Set up default bleed offset 00247 BleedOffset = DefBleedSize; 00248 00249 // Set up our array of default colour contexts by copying the 'global' array 00250 ColourContext::GetGlobalDefaults( &DefaultColourContexts ); 00251 00252 // Add this document to the list of all documents in Camelot 00253 #ifdef RALPH 00254 Camelot.Documents.AddHead(this); 00255 #else 00256 if (IsNotAHiddenDoc()) 00257 { 00258 Camelot.Documents.AddHead(this); 00259 } 00260 #endif 00261 00262 // Set this document to be the current one 00263 this->SetCurrent(); 00264 00265 NodesInTree = 0; 00266 00267 // Initialise pointers to sensible values (they are set up in the Init() function) 00268 OpHistory = 0; 00269 AttributeMgr = 0; 00270 m_pSetSentinel = 0; 00271 pDocUnitList = 0; 00272 pSelSpread = 0; 00273 00274 IsARalph = FALSE; 00275 pRalphDocument =NULL; 00276 Viewmode = DOCUMENT_VIEW; 00277 00278 // Always keep this flag TRUE except when Loading New Files in 00279 DocIsImporting = TRUE; 00280 00281 // Always keep this False unless loading a template document 00282 DocTemplateLoading = FALSE; 00283 00284 // Make sure that the loaded as old version file is set to a known state 00285 LoadedAsVersion1File = FALSE; 00286 00287 m_docNudge = DEFAULT_NUDGE_SIZE; 00288 SetBitmapSmoothing(TRUE); 00289 m_DuplicationOffset = DocCoord(OpDuplicate::DuplicatePlacementX, OpDuplicate::DuplicatePlacementY); 00290 00291 // Document is not yet "born and stable". 00292 m_fStable = FALSE; 00293 } 00294 00295 00296 00297 /******************************************************************************************** 00298 00299 > BOOL Document::Init(CCamDoc* pOilDoc) 00300 00301 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00302 Created: 20/7/93 00303 Inputs: pOilDoc --- the CCamDoc to attach this Document too 00304 Returns: TRUE if the document initialised ok, FALSE otherwise. 00305 Purpose: Sets up the document tree. At the moment it fills it with test data 00306 (paths etc) but in future only the initial tree nodes will be set up. 00307 When the document has been completely initialised, it becomes the 00308 selected and current document: DocChangingMsg message broadcasts will 00309 occur (in the order BORN, CURRENT, SELECTED). 00310 00311 Notes: This now also sets up the default list of indexed (named) colours which 00312 the user can base their document upon [in the BaseDocument Init method]. 00313 These should be set up from a default document (or whatever) in future. 00314 00315 Errors: Out of memory. 00316 SeeAlso: ReadEPSData; Document::Document; 00317 Document::SetSelectedViewAndSpread; Document::SetCurrent 00318 00319 ********************************************************************************************/ 00320 00321 BOOL Document::Init(CCamDoc* pOilDoc) 00322 { 00323 // Ralph has a NULL oildoc... 00324 #ifndef RALPH 00325 ERROR2IF(OilDoc, FALSE, "Document already attached to a CCamDoc in Document::Init"); 00326 #endif 00327 OilDoc = pOilDoc; 00328 00329 NodeDocument* Doc; 00330 EndDocument* End; 00331 00332 // Make this the current document - NOTE! no broadcast as of 22/7/94 00333 SetCurrent(); 00334 00335 // Set the busy cursor . . . 00336 BeginSlowJob(-1, FALSE); 00337 00338 // First, call the base class Init method to set up for us. 00339 // This creates the StartDocument, NodeDocument, & EndDocument, and sets up 00340 // a default colour list and other doc components. 00341 if (!BaseDocument::Init()) return InitFailed(); 00342 00343 // Check that the document is OK 00344 ERROR3IF(GetFirstNode() == NULL,"StartDoc not found"); 00345 Doc = (NodeDocument*)GetFirstNode()->FindNext(); 00346 ERROR3IF(Doc == NULL, "NodeDocument not found"); 00347 End = (EndDocument*)Doc->FindNext(); 00348 ERROR3IF(End == NULL, "EndDocument not found"); 00349 00350 // Make the doc unit list 00351 pDocUnitList = new DocUnitList; 00352 if (pDocUnitList == NULL || !pDocUnitList->MakeDefaultUnits()) 00353 return(InitFailed()); 00354 00355 // Create the Operation history for the document 00356 OpHistory = new OperationHistory; 00357 if (OpHistory == NULL) 00358 return(InitFailed()); 00359 00360 // Create the attribute manager for the document 00361 AttributeMgr = new AttributeManager; 00362 if (AttributeMgr == NULL || !AttributeMgr->InitInstance()) 00363 return(InitFailed()); 00364 00365 // Build the basic tree structure (Chapter, spread, layer) 00366 if (!InitTree(Doc)) 00367 return(InitFailed()); 00368 00369 if (IsNotAHiddenDoc()) 00370 { 00371 // Broadcast a message to all that there's a new document on the block . . . 00372 BROADCAST_TO_ALL(DocChangingMsg(this, DocChangingMsg::BORN)); 00373 } 00374 00375 // Add the default attributes as Nodes at the start of the tree 00376 // The clipboard document does not need default attributes, as things copied into it 00377 // are always kept attribute complete. But now that we're importing into the clipboard, 00378 // it is a very good idea to have safe defaults lying about. 00379 InitDefaultAttributeNodes(); 00380 00381 // Take the hourglass off 00382 EndSlowJob(); 00383 00384 return(TRUE); 00385 } 00386 00387 00388 00389 /******************************************************************************************** 00390 00391 > BOOL Document::InitTree(NodeDocument *RootNode) 00392 00393 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00394 Created: 23/4/95 00395 00396 Inputs: RootNode - points at the basic NodeDocument from which the main documet 00397 tree hangs. 00398 00399 Returns: TRUE if it succeeds, FALSE if it failed (in which case you should 00400 call InitFailed() and possibly InformError()) 00401 00402 Purpose: Called by Document::Init to initialise the document tree structure. 00403 00404 Mainly intended for use by the internal clipboard in order to delete 00405 and recreate the standard tree whenever it is wiped - I've done this 00406 here dso that any chnages to the normal document layout will also affect 00407 the clipboard document in an appropriate manner. 00408 00409 Errors: Lack of memory might make 'new' fail 00410 00411 SeeAlso: Document::Init 00412 00413 ********************************************************************************************/ 00414 00415 BOOL Document::InitTree(NodeDocument* pRootNode) 00416 { 00417 if (pRootNode == NULL || !pRootNode->IsNodeDocument()) 00418 { 00419 ERROR3("This doc's NodeDocument is NULL or isn't really a NodeDocument"); 00420 return(FALSE); 00421 } 00422 00423 // Temporary bodge to construct example document tree for Target 1. 00424 Chapter* pChapter = new Chapter(pRootNode, LASTCHILD); 00425 if (pChapter == 0) return FALSE; 00426 00427 // Create the sentinel node for all object names within the chapter, and a 00428 // child NodeBarProperty. 00429 m_pSetSentinel = new NodeSetSentinel(pChapter, FIRSTCHILD); 00430 if (m_pSetSentinel == 0) return FALSE; 00431 NodeBarProperty* pbp = new NodeBarProperty(m_pSetSentinel, LASTCHILD); 00432 if (pbp == 0) return FALSE; 00433 00434 // Create a rectangle for the pasteboard 00435 DocRect PasteRect(MinDocCoord + 0x10000, 00436 MaxDocCoord - 0x10000 - 1 * PasteBoardHeight, 00437 MinDocCoord + 0x10000 + 2 * PasteBoardWidth, 00438 MaxDocCoord - 0x10000); 00439 00440 // Create the spread 00441 Spread *pSpread = new Spread(pChapter, FIRSTCHILD, PasteRect); 00442 if (pSpread == NULL) return FALSE; 00443 00444 // Create the default page and grid (JustinF says: even if we are a hidden document) 00445 if (!pSpread->CreateDefaultPageAndGrid(TRUE)) return FALSE; 00446 00447 // Create the Insertion node which must always live as a last child of the selected 00448 // spreads active layer. The Insertion node holds a pointer to this document so that 00449 // if for whatever reason the InsertionNode is destroyed (eg. Delete layer) then 00450 // we can Inform this document and it can NULLIFY the InsertPos pointer. 00451 InsertPos = new InsertionNode(this); 00452 if (InsertPos == NULL) return FALSE; 00453 InsertPos->AttachNode(pSpread, LASTCHILD); 00454 00455 return TRUE; 00456 } 00457 00458 00459 00460 /******************************************************************************************** 00461 00462 > BOOL Document::InitDefaultAttributeNodes() 00463 00464 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00465 Created: 22/06/94 00466 Inputs: - 00467 Outputs: - 00468 Returns: TRUE if the default attributes have been added to the tree OK 00469 FALSE if we run out of memory. 00470 00471 Purpose: This function adds the document's default attributes as nodes at the start 00472 of the tree (i.e. as first children of the NodeDocument). 00473 00474 The Attribute optimisation routines will not work if the document does 00475 not contain the default attributes. 00476 00477 Note: This function must be called after the initial document structure has 00478 been set up and all default attributes have been registered. 00479 00480 00481 Errors: The Out Of Memory Error is set if we run out of memory, FALSE is returned 00482 in this situation. 00483 00484 00485 ********************************************************************************************/ 00486 00487 BOOL Document::InitDefaultAttributeNodes() 00488 { 00489 ENSURE(AttributeMgr != NULL, "Attribute Manager pointer is NULL"); 00490 00491 // Find out the number of default attributes 00492 UINT32 NumDefaultAttribs = AttributeMgr->GetNumAttributes(); 00493 ENSURE(NumDefaultAttribs != 0, "The document has no default attributes"); 00494 00495 AttributeEntry* DefaultAttribs = AttributeMgr->GetDefaultAttributes(); 00496 00497 if (DefaultAttribs == NULL) 00498 return FALSE; 00499 00500 // ---------------------------------------------------------------------------------------- 00501 // Try and find the NodeDocument node - to which the attributes will be added 00502 00503 Node* TreeRoot; 00504 00505 ENSURE(TreeStart != NULL, "The initial tree structure has not been initialised"); 00506 00507 TreeRoot = TreeStart->FindNext(); 00508 00509 ENSURE(TreeRoot != NULL, "Can't find NodeDocument"); 00510 ENSURE(TreeRoot->GetRuntimeClass() == CC_RUNTIME_CLASS(NodeDocument), "Alien tree structure"); 00511 00512 // ---------------------------------------------------------------------------------------- 00513 // Create a NodeAttribute for each of the default attributes and add them into the 00514 // tree as first children of the NodeDocument. 00515 00516 for(UINT32 i=0; i<NumDefaultAttribs; i++) 00517 { 00518 ENSURE(DefaultAttribs[i].pAttr != NULL, "Default attribute is NULL"); 00519 00520 Node* NodeAttr = DefaultAttribs[i].pAttr->MakeNode(); 00521 00522 if (NodeAttr != NULL) 00523 { 00524 // Add the Attribute as a first child of the NodeDocument. Note that we suppress 00525 // the transparency check for default attributes. 00526 NodeAttr->AttachNode(TreeRoot, FIRSTCHILD, FALSE); 00527 00528 NodeAttribute* pNa = (NodeAttribute*)NodeAttr; 00529 if(pNa->IsLinkedToNodeGeometry()) 00530 { 00531 pNa->NewlyCreatedDefaultAttr((NodeDocument*)TreeRoot); 00532 } 00533 } 00534 } 00535 00536 // ---------------------------------------------------------------------------------------- 00537 00538 // Default attribute array no longer required so we can safely delete it 00539 CCFree(DefaultAttribs); 00540 return TRUE; 00541 } 00542 00543 00544 00545 /******************************************************************************************** 00546 00547 > BOOL Document::ReInit() 00548 00549 Author: Chris_Parks (Xara Group Ltd) <camelotdev@xara.com> 00550 Created: 16/4/96 00551 Returns: Init ok 00552 Purpose: Calls InitFailed to delete the Tree and various others and follows this with 00553 an Init to put the Document back into a virgin state 00554 Not used just yet... 00555 Errors: 00556 00557 ********************************************************************************************/ 00558 00559 BOOL Document::ReInit() 00560 { 00561 // RALPH 00562 InitFailed(); 00563 return Init(OilDoc); 00564 00565 /* 00566 TreeStart->CascadeDelete(); 00567 ERROR3IF(GetFirstNode() == NULL,"StartDoc not found"); 00568 NodeDocument *Doc = (NodeDocument*)GetFirstNode()->FindNext(); 00569 return InitTree(Doc); 00570 */ 00571 00572 // return TRUE; 00573 00574 } 00575 00576 00577 00578 /******************************************************************************************** 00579 00580 > BOOL Document::InitFailed(void) 00581 00582 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00583 Created: 8/12/94 00584 Returns: FALSE 00585 00586 Purpose: Called by Document::Init when it fails; encapsulates all necessary 00587 tidying up, and then returns FALSE so that it can be called as part 00588 of the final return statement. 00589 Replaces some completely unnecessary goto code. 00590 00591 SeeAlso: Document::Init 00592 00593 ********************************************************************************************/ 00594 00595 BOOL Document::InitFailed(void) 00596 { 00597 if (TreeStart != 0) 00598 { 00599 TreeStart->CascadeDelete(); 00600 delete TreeStart; 00601 m_pSetSentinel = 0; 00602 } 00603 00604 if (OpHistory != 0) 00605 { 00606 delete OpHistory; 00607 OpHistory = 0; 00608 } 00609 00610 if (AttributeMgr != 0) 00611 { 00612 delete AttributeMgr; 00613 AttributeMgr = 0; 00614 } 00615 00616 if (pDocUnitList != 0) 00617 { 00618 delete pDocUnitList; 00619 pDocUnitList = 0; 00620 } 00621 00622 EndSlowJob(); 00623 return(FALSE); 00624 } 00625 00626 00627 00628 /*********************************************************************************************** 00629 00630 > Document::~Document() 00631 00632 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00633 Created: 19/5/93 00634 Purpose: Destructor. Deletes the whole document tree of this object, and all memory 00635 is returned to the heaps whence it came. The busy cursor is displayed while 00636 this is happening. 00637 00638 ***********************************************************************************************/ 00639 00640 Document::~Document() 00641 { 00642 // Set the busy cursor . . . 00643 BeginSlowJob(-1, FALSE); 00644 00645 #ifndef RALPH 00646 // Broadcast to everyone that this document is a dead duck. 00647 if (IsNotAHiddenDoc()) 00648 #endif 00649 { 00650 // Document no longer stable. 00651 SetStable(FALSE); 00652 BROADCAST_TO_ALL(DocChangingMsg(this, DocChangingMsg::ABOUTTODIE)); 00653 } 00654 00655 00656 #ifdef _DEBUG 00657 // DocViews should be closed before Documents, so all render regions for this document 00658 // should have been deleted - make sure they have. 00659 Camelot.DeleteRenderRegions(this); 00660 #endif 00661 00662 #ifndef RALPH 00663 // Remove Document from list of all documents 00664 if (IsNotAHiddenDoc()) 00665 #endif 00666 { 00667 Camelot.Documents.RemoveItem(this); 00668 00669 // Is this the last document in the program? 00670 BOOL ThisIsTheLastDoc = (Camelot.Documents.GetHead() == NULL); 00671 00672 if (ThisIsTheLastDoc) 00673 { 00674 // There are no more documents, so ensure that the system is in the correct state. 00675 00676 // If the system is working correctly, then the following should be true: 00677 // If Current != NULL, Current must be this document 00678 // If Selected != NULL, Selected must be this document 00679 // We will ensure this is the case in debug builds 00680 00681 ENSURE((Current == NULL) || (Current == this),"Current document is garbage"); 00682 ENSURE((Selected == NULL) || (Selected == this),"Selected document is garbage"); 00683 00684 // Reset Current and Selected document and DocView 00685 SetNoCurrent(); 00686 SetNoSelectedViewAndSpread(); 00687 00688 DocView::SetNoCurrent(); 00689 // DocView::SetNoSelected(); -- now done in SetNoSelectedViewAndSpread(), above 00690 00691 } 00692 else 00693 { 00694 // Make sure that Current and Selected do not refer to the dying document 00695 if (this == Current) SetNoCurrent(); 00696 if (this == Selected) SetNoSelectedViewAndSpread(); 00697 00698 // This special test added to fix a problem whereby current doc was being set to null 00699 // above and hence causing unit display problems (ERROR2s) in the selector tool when 00700 // opening a bitmap had been aborted. 18/9/96 Neville 00701 if (Selected != NULL && Current == NULL) Current = Selected; 00702 } 00703 } 00704 00705 // Delete all DocViews attached to document 00706 DocViews.DeleteAll(); 00707 00708 #ifndef RALPH 00709 // Broadcast to everyone that this document is a dead duck. 00710 if (IsNotAHiddenDoc()) 00711 { 00712 BROADCAST_TO_ALL(DocChangingMsg(this, DocChangingMsg::KILLED)); 00713 } 00714 #endif 00715 // Destroy the operation history. This must get destroyed before the tree is destroyed 00716 if (OpHistory != NULL) 00717 delete (OpHistory); 00718 00719 // Destroy the attribute manager 00720 if (AttributeMgr != NULL) 00721 delete (AttributeMgr); 00722 00723 // Destroy the list of units in this document 00724 if (pDocUnitList != NULL) 00725 delete (pDocUnitList); 00726 00727 // All done... 00728 EndSlowJob(); 00729 00730 // Note that the tree is deleted in the base class destructor 00731 } 00732 00733 00734 00735 /******************************************************************************************** 00736 > BOOL Document::IsModified() const 00737 00738 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00739 Created: 23/3/94 00740 Inputs: - 00741 Outputs: - 00742 Returns: Returns TRUE if the document has been modified since last being saved. 00743 Purpose: Tests the "Modified" flag. 00744 Errors: - 00745 SeeAlso: CCamDoc::IsModified 00746 ********************************************************************************************/ 00747 00748 BOOL Document::IsModified() const 00749 { 00750 if (OilDoc) 00751 return OilDoc->IsModified(); 00752 00753 return(FALSE); 00754 } 00755 00756 00757 00758 /******************************************************************************************** 00759 > BOOL Document::IsReadOnly() const 00760 00761 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00762 Created: 23/3/94 00763 Inputs: - 00764 Outputs: - 00765 Returns: Returns TRUE if the document is read-only, ie. cannot be modified. 00766 Purpose: Tests the "Read Only" flag. 00767 Errors: - 00768 SeeAlso: CCamDoc::IsReadOnly 00769 ********************************************************************************************/ 00770 00771 BOOL Document::IsReadOnly() const 00772 { 00773 if (OilDoc) 00774 return OilDoc->IsReadOnly(); 00775 00776 return(FALSE); 00777 } 00778 00779 00780 00781 /******************************************************************************************** 00782 > BOOL Document::IsACopy() const 00783 00784 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00785 Created: 23/3/94 00786 Inputs: - 00787 Outputs: - 00788 Returns: Returns TRUE if the document is a copy of another document. 00789 Purpose: Tests the "Copy" flag. 00790 Errors: - 00791 SeeAlso: CCamDoc::IsACopy 00792 ********************************************************************************************/ 00793 00794 BOOL Document::IsACopy() const 00795 { 00796 if (OilDoc) 00797 return OilDoc->IsACopy(); 00798 00799 return(FALSE); 00800 } 00801 00802 00803 00804 /******************************************************************************************** 00805 > void Document::SetModified(BOOL fState = TRUE) 00806 00807 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00808 Created: 23/3/94 00809 Inputs: - 00810 Outputs: - 00811 Returns: - 00812 Purpose: Sets (or clears) the "document is modified" flag. 00813 Errors: - 00814 SeeAlso: CCamDoc::SetModified 00815 ********************************************************************************************/ 00816 00817 void Document::SetModified(BOOL fState /* = TRUE */) 00818 { 00819 if (OilDoc) 00820 OilDoc->SetModified( fState != FALSE ); 00821 } 00822 00823 /******************************************************************************************** 00824 > void Document::IsLoadedAsVersion1File() const 00825 00826 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00827 Created: 30/7/96 00828 Inputs: - 00829 Outputs: - 00830 Returns: - 00831 Purpose: Returns the current state of the IsLoadedAsVersion1File flag. 00832 Flag to say that the document was loaded as a version 1 file 00833 and so the user needs to be given the option of saving it in this form 00834 when the document is saved 00835 ********************************************************************************************/ 00836 00837 BOOL Document::IsLoadedAsVersion1File() const 00838 { 00839 return LoadedAsVersion1File; 00840 } 00841 00842 /******************************************************************************************** 00843 > BOOL Document::ISetLoadedAsVersion1File(BOOL NewState) 00844 00845 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00846 Created: 30/7/96 00847 Inputs: New state of the flag required 00848 Outputs: - 00849 Returns: Old state of the flag 00850 Purpose: Sets a new current state of the IsLoadedAsVersion1File flag. 00851 Flag to say that the document was loaded as a version 1 file 00852 and so the user needs to be given the option of saving it in this form 00853 when the document is saved 00854 ********************************************************************************************/ 00855 00856 BOOL Document::SetLoadedAsVersion1File(BOOL NewState) 00857 { 00858 BOOL OldState = LoadedAsVersion1File; 00859 LoadedAsVersion1File = NewState; 00860 return OldState; 00861 } 00862 00863 00864 00865 00866 00867 /******************************************************************************************** 00868 > BOOL Document::CreateDragTargets() 00869 00870 Author: Chris_Parks (Xara Group Ltd) <camelotdev@xara.com> 00871 Created: 22/1/95 00872 Inputs: - 00873 Outputs: - 00874 Returns: - 00875 Purpose: Calls all (OILY) views to create their drag targets. 00876 Errors: - 00877 SeeAlso: CCamDoc::SetModified 00878 ********************************************************************************************/ 00879 00880 BOOL Document::CreateDragTargets(DragInformation * DragInfo) 00881 { 00882 if (IsNotAClipboard()) 00883 { 00884 DocView * Ptr= (DocView*) DocViews.GetHead(); 00885 CCamView* TheView; 00886 00887 while(Ptr) 00888 { 00889 TheView = Ptr->GetConnectionToOilView(); 00890 if(TheView) 00891 TheView->CreateDragTarget(DragInfo); 00892 Ptr= (DocView*) DocViews.GetNext(Ptr); 00893 } 00894 } 00895 return TRUE; 00896 } 00897 00898 00899 00900 /******************************************************************************************** 00901 00902 > String_256 Document::GetTitle() const 00903 00904 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00905 Created: 15/3/94 00906 Returns: A String_256 that holds the document title 00907 Purpose: Returns the Title of the document. The title is the text that appears in the 00908 documents windows (when it is not maximised). For example 'Untitled #1' or 00909 'Untitled #1 (Modified)' or even 'Blobby.art (Modified)'. 00910 SeeAlso: Document::GetProducer; Document::GetComment; CCamDoc::GetKernelTitle 00911 00912 ********************************************************************************************/ 00913 00914 String_256 Document::GetTitle() const 00915 { 00916 if (OilDoc) 00917 return OilDoc->GetKernelTitle(); 00918 00919 return(ClipboardNameText); 00920 } 00921 00922 00923 /******************************************************************************************** 00924 00925 > String_256 Document::GetDocName(BOOL IncludeFileType = TRUE) const 00926 00927 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00928 Created: 27/3/95 00929 Inputs: IncludeFileType - TRUE if the filetype is required. Defaults to TRUE. 00930 Returns: A String_256 that holds the document name 00931 Purpose: Returns the name of the document. The name will be the first part of the title 00932 which is the text that appears in the document windows (when it is not maximised). For example 'Untitled #1' or 00933 'Untitled #1 (Modified)' or even 'Blobby.art (Modified)'. 00934 SeeAlso: Document::GetTitle(); CCamDoc::GetKernelTitle(); CCamDoc::GetKernelDocName(); 00935 SeeAlso: Document::GetProducer; Document::GetComment; 00936 00937 ********************************************************************************************/ 00938 00939 String_256 Document::GetDocName(BOOL IncludeFileType) const 00940 { 00941 if (OilDoc) 00942 return OilDoc->GetKernelDocName(IncludeFileType); 00943 00944 return(ClipboardNameText); 00945 } 00946 00947 00948 /******************************************************************************************** 00949 00950 > String_256 Document::GetPathName(UINT32 MaxSize = 0) const 00951 00952 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00953 Created: 20/3/95 00954 Inputs: MaxSize - This is the size we have to fit the pathname into. 00955 Defaults to zero , meaning all off the pathname. 00956 Returns: A String_256 that holds the pathname for the document. 00957 Purpose: Returns the pathname of the document. 00958 SeeAlso: CCamDoc::GetKernelPathName; PathName::GetTruncatedPathName; 00959 SeeAlso: Document::GetLocation; CCamDoc::GetTruncatedLocation; 00960 00961 ********************************************************************************************/ 00962 00963 String_256 Document::GetPathName(UINT32 MaxSize) const 00964 { 00965 if (OilDoc) 00966 return OilDoc->GetKernelPathName(MaxSize); 00967 00968 return(ClipboardNameText); 00969 } 00970 00971 /******************************************************************************************** 00972 00973 > String_256 Document::GetLocation(UINT32 MaxSize = 0) const 00974 00975 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00976 Created: 20/3/95 00977 Inputs: MaxSize - This is the size we have to fit the pathname into. 00978 Defaults to zero , meaning all off the pathname. 00979 Returns: A String_256 that holds the location for the document. 00980 Purpose: Returns the location of the document, which is the pathname with no filename. 00981 SeeAlso: CCamDoc::GetKernelLocation; PathName::GetTruncatedLocation; 00982 SeeAlso: Document::GetPathName; CCamDoc::GetKernelPathName; 00983 00984 ********************************************************************************************/ 00985 00986 String_256 Document::GetLocation(UINT32 MaxSize) const 00987 { 00988 if (OilDoc) 00989 return OilDoc->GetKernelLocation(MaxSize); 00990 00991 return(ClipboardNameText); 00992 } 00993 00994 00995 /******************************************************************************************** 00996 > const String_256& Document::GetProducer() const 00997 00998 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00999 Created: 15/3/94 01000 Inputs: - 01001 Outputs: - 01002 Returns: A reference to the (constant) producer's name of this document. 01003 Purpose: 01004 Errors: - 01005 SeeAlso: Document::GetTitle; Document::GetComment 01006 ********************************************************************************************/ 01007 01008 const String_256& Document::GetProducer() const 01009 { 01010 return Producer; 01011 } 01012 01013 01014 01015 /******************************************************************************************** 01016 > const String_256& Document::GetComment() const 01017 01018 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01019 Created: 15/3/94 01020 Inputs: - 01021 Outputs: - 01022 Returns: A reference to the (constant) producer's name of this document. 01023 Purpose: Getting the time the document was created. 01024 Errors: - 01025 SeeAlso: Document::GetTitle; Document::GetProducer 01026 ********************************************************************************************/ 01027 01028 const String_256& Document::GetComment() const 01029 { 01030 return Comment; 01031 } 01032 01033 01034 01035 /******************************************************************************************** 01036 > void Document::SetComment(String_256* NewComment) 01037 01038 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01039 Created: 31/8/94 01040 Inputs: A pointer to the new comment string. 01041 Outputs: - 01042 Returns: - 01043 Purpose: Setting the document's comment string. 01044 Errors: - 01045 SeeAlso: Document::GetComment 01046 ********************************************************************************************/ 01047 01048 void Document::SetComment(String_256* NewComment) 01049 { 01050 Comment = *NewComment; 01051 } 01052 01053 01054 01055 /******************************************************************************************** 01056 > const time_t& Document::GetCreationTime() const 01057 01058 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01059 Created: 31/08/94 01060 Inputs: - 01061 Outputs: - 01062 Returns: A reference to the time of the document's creation. 01063 Purpose: 01064 Errors: - 01065 SeeAlso: Document::GetLastSaveTime 01066 ********************************************************************************************/ 01067 01068 const time_t& Document::GetCreationTime() const 01069 { 01070 return CreationTime; 01071 } 01072 01073 01074 01075 /******************************************************************************************** 01076 > const time_t& Document::GetLastSaveTime() const 01077 01078 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01079 Created: 31/08/94 01080 Inputs: - 01081 Outputs: - 01082 Returns: A reference to the time of the document's creation. Will be 0 if the 01083 document is unsaved. 01084 Purpose: Getting the time the document was last saved. 01085 Errors: - 01086 SeeAlso: Document::GetCreationTime 01087 ********************************************************************************************/ 01088 01089 const time_t& Document::GetLastSaveTime() const 01090 { 01091 return LastSaveTime; 01092 } 01093 01094 01095 01096 /******************************************************************************************** 01097 > void Document::SetLastSaveTime() const 01098 01099 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01100 Created: 1/09/94 01101 Inputs: - 01102 Outputs: - 01103 Returns: - 01104 Purpose: Call on saving a document. Sets the document's last saved time. 01105 Errors: - 01106 SeeAlso: Document::GetLastSaveTime 01107 ********************************************************************************************/ 01108 01109 void Document::SetLastSaveTime() 01110 { 01111 LastSaveTime = ::time(NULL); 01112 } 01113 01114 /******************************************************************************************** 01115 > void Document::SetLastSaveTime(time_t) 01116 01117 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01118 Created: 30/7/96 01119 Inputs: - 01120 Outputs: - 01121 Returns: - 01122 Purpose: Allows setting of the document's last saved time. 01123 Errors: - 01124 SeeAlso: Document::GetLastSaveTime 01125 ********************************************************************************************/ 01126 01127 void Document::SetLastSaveTime(time_t NewTime) 01128 { 01129 LastSaveTime = NewTime; 01130 } 01131 01132 /******************************************************************************************** 01133 > void Document::SetCreationTime(time_t) 01134 01135 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01136 Created: 30/7/96 01137 Inputs: - 01138 Outputs: - 01139 Returns: - 01140 Purpose: Allows setting of the document's creation time. 01141 Errors: - 01142 SeeAlso: Document::GetLastSaveTime 01143 ********************************************************************************************/ 01144 01145 void Document::SetCreationTime(time_t NewTime) 01146 { 01147 CreationTime = NewTime; 01148 } 01149 01150 /******************************************************************************************** 01151 > void Document::MakeJustCreated() 01152 01153 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01154 Created: 11/5/95 01155 Inputs: - 01156 Outputs: Sets member variables 01157 Returns: - 01158 Purpose: Resets member variables of the document so it abbears as if the document has 01159 just been created (eg CreationTime is set to the current time) 01160 Errors: - 01161 SeeAlso: - 01162 ********************************************************************************************/ 01163 void Document::MakeJustCreated() 01164 { 01165 LastSaveTime = 0; // Zero means not saved 01166 CreationTime = ::time(NULL); 01167 } 01168 01169 01170 01171 /******************************************************************************************** 01172 01173 > void Document::InsertNewNode( Node* NewNode, DocCoord* Point ) 01174 01175 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 01176 Created: 3/9/93 01177 Inputs: NewNode - A Pointer to the New node to be inserted 01178 pDestSpread - pointer to the spread which this new node should be 01179 inserted, If this is NULL then the object is inserted 01180 on the selected spread. 01181 01182 Purpose: Inserts the Node into the Document at the position specified. 01183 The node is added to the active layer on this spread 01184 SeeAlso: Document::FindEnclosingChapter(); Document::FindEnclosingPage() 01185 01186 ********************************************************************************************/ 01187 01188 void Document::InsertNewNode( Node* NewNode, Spread *pDestSpread ) 01189 { 01190 SetCurrent(); 01191 01192 Node *pNode; 01193 01194 // Most of the time we will be inserting onto the selected spread 01195 // So find out what this is. 01196 01197 if ((pDestSpread == NULL) || (pDestSpread == Document::GetSelectedSpread())) 01198 { 01199 // We need to insert the node onto the selected spread. This is very quick because we 01200 // keep an Insertion node there. 01201 pNode = GetInsertionPosition(); 01202 ENSURE(pNode != NULL, "Could not find insertion position in Document::InsertNewNode()"); 01203 // Attach the node to the left of the insertion node 01204 NewNode -> AttachNode( pNode, PREV ); 01205 01206 } 01207 else 01208 { 01209 // This is assuming that we are inserting into the non-selected spread and so does 01210 // not use the insertion position. Unfortunately, there is a chance that this MAY happen 01211 // as the selected spread may be in a different document and so we are inserting into a 01212 // single spread document with an insertion node. The code below will insert AFTER the 01213 // insertion node and so will be in an illegal position. We really should check this!!! 01214 // As we are close to release I will put an error 3 in just in case. Neville 24/9/96 01215 TRACE( _T("\aDocument::InsertNewNode inserting into the unselected spread. Is this correct?\n") ); 01216 01217 pNode = pDestSpread->FindActiveLayer(); 01218 ENSURE(pNode != NULL, "Could not find layer in Document::InsertNewNode()"); 01219 // Attach this node to the tree at this point 01220 NewNode -> AttachNode( pNode, LASTCHILD ); 01221 } 01222 } 01223 01224 01225 01226 /*********************************************************************************************** 01227 01228 DocView *Document::GetSpareDocView() 01229 01230 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 01231 Created: 19/5/93 01232 01233 Inputs: - 01234 Outputs: - 01235 Returns: NULL, or a spare DocView 01236 01237 Purpose: Looks for a DocView with no attached OilView, so we can recycle it 01238 01239 Errors: None. 01240 01241 ***********************************************************************************************/ 01242 01243 DocView* Document::GetSpareDocView() 01244 { 01245 if (IsNotAClipboard()) 01246 { 01247 DocView *View = (DocView *) DocViews.GetHead(); 01248 01249 while (View != NULL) 01250 { 01251 CCamView *pCamView = View->GetConnectionToOilView(); 01252 if (pCamView == NULL) return View; 01253 View = (DocView *) DocViews.GetNext(View); 01254 } 01255 } 01256 01257 return NULL; // No free views found 01258 } 01259 01260 01261 01262 /*********************************************************************************************** 01263 01264 > DocView* Document::GetNewDocView() 01265 01266 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 01267 Created: 19/5/93 01268 01269 Inputs: -