document.cpp

Go to the documentation of this file.
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:     - 
01270     Outputs:    -
01271     Returns:    -
01272                  
01273     Purpose:    Returns a new DocView for the client.  If any unconnected views already exist
01274                 for this document, the first is returned.  Otherwise a new DocView is created
01275                 and returned.
01276                 If a new DocView is obtained, it becomes the 'current' DocView before
01277                 it is returned to the caller.
01278                
01279     Errors:     None.
01280                                                                  
01281 ***********************************************************************************************/
01282 
01283 DocView* Document::GetNewDocView()
01284 {
01285     // Is there a spare view knocking about?
01286     DocView *pDocView = GetSpareDocView();
01287     
01288     if (pDocView != NULL)
01289         // Yes - so return it.
01290         return pDocView;
01291 
01292     if (IsAClipboard())
01293     {
01294         TRACEUSER( "Jason",_T("\n\nXX Attempting to add a DocView to a clipboard!\n") );
01295     }
01296     else
01297     {
01298         // No views spare - create a new one connected to this document...
01299         pDocView = new DocView(this);
01300     
01301         if (pDocView != NULL)
01302         {
01303             if (pDocView->Init())
01304                 DocViews.AddTail(pDocView);     // link it into the DocView list ...
01305             else
01306             {
01307                 delete pDocView;
01308                 pDocView=NULL;
01309             }
01310         }
01311 
01312         // Make it the current DocView
01313         pDocView->SetCurrent();
01314     }
01315 
01316     // ...and return this new view to the caller.       
01317     return pDocView;
01318 }
01319 
01320 
01321 
01322 void Document::OnDocViewDying(DocView *pDocViewToDelete)
01323 {
01324     // Look for this DocView in the list
01325     DocView *pDocView = (DocView *) DocViews.GetHead();
01326     
01327     // Traverse List of DocViews 
01328     while (pDocView != NULL)
01329     {
01330         // Is this the DocView that is closing down?
01331         if (pDocView == pDocViewToDelete)
01332         {
01333             // Yes - remove it from the list and return
01334             DocViews.RemoveItem(pDocView);
01335             return;
01336         }
01337 
01338         // Try the next one
01339         pDocView = (DocView *) DocViews.GetNext(pDocView);
01340     }
01341 }
01342 
01343 
01344 
01345 /***********************************************************************************************
01346 >   void Document::ShowViewScrollers(BOOL fIsVisible)
01347     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01348     Created:    2/11/94
01349     Inputs:     -
01350     Outputs:    -
01351     Returns:    -
01352     Purpose:    Show or Hide Scollers on all Views
01353     SeeAlso:    -
01354 *********************************************************************************************/
01355 
01356 void Document::ShowViewScrollers(BOOL fIsVisible)
01357 {
01358     if (IsNotAClipboard())
01359     {
01360         DocView* pDocView = (DocView*) DocViews.GetHead();
01361         while (pDocView != NULL)
01362         {
01363             pDocView->ShowViewScrollers(fIsVisible);
01364             pDocView = (DocView *) DocViews.GetNext(pDocView);
01365         }
01366     }
01367 }
01368 
01369 /***********************************************************************************************
01370 >   void Document::ShowViewRulers(BOOL fIsVisible)
01371     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com> 
01372     Created:    2/11/94
01373     Inputs:     -
01374     Outputs:    -
01375     Returns:    -
01376     Purpose:    Show or Hide Rulers all Views
01377     SeeAlso:    -
01378 *********************************************************************************************/
01379 
01380 void Document::ShowViewRulers(BOOL fIsVisible)
01381 {
01382 #if !defined(EXCLUDE_FROM_RALPH)
01383     if (IsNotAClipboard())
01384     {
01385         DocView* pDocView = (DocView*) DocViews.GetHead();
01386         while (pDocView != NULL)
01387         {
01388             pDocView->ShowViewRulers(fIsVisible);
01389             pDocView = (DocView *) DocViews.GetNext(pDocView);
01390         }
01391     }
01392 #endif
01393 }
01394 
01395 /***********************************************************************************************
01396 
01397 >   CCamDoc* Document::GetOilDoc() const
01398 
01399     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01400     Created:    19/5/93
01401     
01402     Inputs:     - 
01403     Outputs:    -
01404     Returns:    NULL or a pointer to the CCamDoc object associated with this object.
01405 
01406     Purpose:    Find the Oil document associated with the Document.
01407 
01408     Notes:      IMPORTANT: Clipboard Documents may NOT have an attached OilDoc -> will return NULL
01409 
01410     Errors:     None.
01411                                                                  
01412 ***********************************************************************************************/
01413 
01414 CCamDoc* Document::GetOilDoc() const
01415 {
01416     return OilDoc;
01417 }
01418 
01419 
01420 
01421 /***********************************************************************************************
01422 
01423 >   static Document* Document::GetCurrent()
01424 
01425     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01426     Created:    21/5/93
01427     
01428     Inputs:     - 
01429     Outputs:    -
01430     Returns:    Pointer to the current Document object.
01431                  
01432     Purpose:    Find the current Document object.
01433                
01434     Errors:     None.
01435                                                                  
01436 ***********************************************************************************************/
01437 
01438 Document* Document::GetCurrent()
01439 {
01440 #ifdef RALPH
01441 
01442     if(::GetCurrentThreadId() == RalphDocument::GetImportingThreadID())
01443     {
01444         //TRACEUSER( "Richard", _T("+++++ GetCurrent called from Load Thread\n"));
01445         return RalphDocument::GetImportingDoc();
01446     }
01447 #endif
01448     //TRACEUSER( "Richard", _T(">>> Document::GetCurrent returning Current\n"));
01449     return Current;
01450 }
01451 
01452 
01453 
01454 /***********************************************************************************************
01455 
01456 >   static Document* Document::GetSelected()
01457 
01458     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01459     Created:    21/5/93
01460     
01461     Inputs:     - 
01462     Outputs:    -
01463     Returns:    Pointer to the selected Document object.
01464                  
01465     Purpose:    Find the selected Document object.
01466                
01467     Errors:     None.
01468                                                                  
01469 ***********************************************************************************************/
01470 
01471 Document* Document::GetSelected()
01472 {
01473 #ifdef RALPH
01474     // if we are being called from the load thread return the current load thread document
01475     if(::GetCurrentThreadId() == RalphDocument::GetImportingThreadID())
01476     {
01477         //TRACEUSER( "Richard", _T("+++++ GetSelected called from Load Thread\n"));
01478         return RalphDocument::GetImportingDoc();
01479     }
01480 #endif
01481     //TRACEUSER( "Richard", _T(">>> Document::GetSelected returning Selected\n"));
01482     return Selected;
01483 }
01484 
01485 
01486     
01487 /***********************************************************************************************
01488 
01489 >   void Document::SetCurrent()
01490     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01491     Created:    21/5/93
01492     Inputs:     - 
01493     Outputs:    -
01494     Returns:    -
01495     Purpose:    Make this object be the 'current' document.  
01496                 **** Changed 22/7/94 by MarkN ****
01497                 Does NOT broadcasts a message to all that this is happening any more.
01498     Errors:     None.
01499                                                                  
01500 ***********************************************************************************************/
01501 
01502 void Document::SetCurrent()
01503 {
01504 #ifdef RALPH
01505     // if we are being called from the load thread just ignore 
01506     if(::GetCurrentThreadId() == RalphDocument::GetImportingThreadID())
01507         return ;
01508 #endif
01509     Current = this;
01510 }
01511 
01512 
01513 
01514 /***********************************************************************************************
01515 
01516 >   static void Document::SetNoCurrent()
01517 
01518     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01519     Created:    21/5/93
01520     
01521     Inputs:     - 
01522     Outputs:    -
01523     Returns:    -
01524                  
01525     Purpose:    Set the current document pointer to be NULL, i.e., there is no current
01526                 document object.
01527                 **** Changed 22/7/94 by MarkN ****
01528                 Does NOT broadcasts a message to all that this is happening any more.
01529                
01530     Errors:     None.
01531                                                                  
01532 ***********************************************************************************************/
01533 
01534 void Document::SetNoCurrent()
01535 {
01536 #ifdef RALPH
01537     // if we are being called from the load thread just ignore 
01538     if(::GetCurrentThreadId() == RalphDocument::GetImportingThreadID())
01539         return ;
01540 #endif
01541     Current = NULL;
01542 }
01543 
01544 
01545 
01546 /***********************************************************************************************
01547 
01548 >   void Document::SetNoSelectedViewAndSpread(void)
01549 
01550     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01551     Created:    13/2/95
01552     
01553     Inputs:     -
01554     Outputs:    -
01555     Returns:    -
01556                  
01557     Purpose:    To set the Selected Document, DocView, and Spread.
01558                 This sets all three of these entities to NULL - no selected entity.
01559 
01560                 These 3 items are interlinked - changing the spread may mean changing
01561                 to a different document and view - these changes can cause several messages
01562                 (DocChangingMsg, SpreadMsg, etc) to be broadcast, so they must be treated
01563                 as a single indivisble operation, which only broadcasts the necessary
01564                 messages when the entrie state has been changed.
01565 
01566     Notes:      If the Selected docuemnt changes, a DocChangingMsg (SELCHANGED) will be 
01567                 broadcast, with pOldDoc == the last selected Doc, and pNewDoc == the new
01568                 selected document. Either/both of pOldDoc and pNewDoc may be NULL!
01569 
01570                 If the Selected DocView changes, a DocViewMsg (SELCHANGED) will be broadcast,
01571                 with the pOldDocView and pNewDocView fields indicating the old and new DocViews.
01572 
01573                 If the Selected spread changes, a SpreadMsg (SELCHANGED) will be broadcast.
01574                 pOldSpread and pNewSpread will point at the spreads involved.
01575 
01576                 This does NOT affect the Current doc.
01577 
01578 ***********************************************************************************************/
01579 
01580 void Document::SetNoSelectedViewAndSpread(void)
01581 {
01582     TRACEUSER("Gerry", _T("Document::SetNoSelectedViewAndSpread"));
01583 #ifdef RALPH
01584     // if we are being called from the load thread just ignore 
01585     if(::GetCurrentThreadId() == RalphDocument::GetImportingThreadID())
01586         return ;
01587 #endif
01588     // Remember if each of the selected things has chnaged as a result of this call
01589     Document    *OldSelDocument = Selected;
01590     DocView     *OldSelView     = DocView::GetSelected();
01591     Spread      *OldSelSpread   = pGlobalSelSpread;
01592 
01593     // Tell those that care that the selected view is about to become null.
01594     BROADCAST_TO_ALL(DocViewMsg(OldSelView, NULL, DocViewMsg::SELABOUTTOCHANGE));
01595 
01596     // --- Set no selected spread
01597     pGlobalSelSpread = NULL;
01598     if (Selected != NULL)
01599         Selected->pSelSpread = NULL;
01600 
01601     // --- Set no selected document
01602     Selected = NULL;
01603 
01604     // --- Set no selected docview
01605     DocView::SetSelectedInternal(NULL);
01606 
01607 
01608     // --- And broadcast appropriate message(s)
01609     if (Selected != OldSelDocument)
01610     {
01611         BROADCAST_TO_ALL(DocChangingMsg(OldSelDocument, NULL,
01612                                         DocChangingMsg::SELCHANGED));
01613     }
01614 
01615     if (DocView::GetSelected() != OldSelView)
01616     {
01617         DocView::SendSelectedMessage(OldSelView, DocView::GetSelected());
01618     }
01619 
01620     if (pGlobalSelSpread != OldSelSpread)
01621     {
01622         BROADCAST_TO_ALL(SpreadMsg(OldSelSpread, NULL,
01623                             SpreadMsg::SELCHANGED));
01624     }
01625 
01626     // Ensure any delayed Selection message broadcasts are sent now
01627     GetApplication()->FindSelection()->BroadcastAnyPendingMessages();
01628 }
01629 
01630 
01631 
01632 /***********************************************************************************************
01633 
01634 >   static void Document::SetSelectedViewAndSpread(Document *TheDocument = NULL,
01635                                                     DocView *TheView = NULL,
01636                                                     Spread *TheSpread = NULL);
01637 
01638     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01639     Created:    13/2/95
01640     
01641     Inputs:     TheDocument - NULL, or a pointer to the document to make selected
01642                 TheView - NULL, or the docview for TheDocument which should be made selected
01643                 TheSpread - NULL or the Spread in TheDocument which should be made selected
01644 
01645     Outputs:    -
01646     Returns:    -
01647                  
01648     Purpose:    To set the Selected Document, DocView, and Spread.
01649 
01650                 These 3 items are interlinked - changing the spread may mean changing
01651                 to a different document and view - these changes can cause several messages
01652                 (DocChangingMsg, SpreadMsg, etc) to be broadcast, so they must be treated
01653                 as a single indivisble operation, which only broadcasts the necessary
01654                 messages when the entrie state has been changed.
01655 
01656     Notes:      If any of the parameters are NULL, sensible defaults (The currently selected
01657                 document, the currently selected or first docview of that document, and
01658                 the currently selected or first spread of that document, respectively) will
01659                 be used.
01660 
01661                 If the Selected document changes, a DocChangingMsg (SELCHANGED) will be 
01662                 broadcast, with pOldDoc == the last selected Doc, and pNewDoc == the new
01663                 selected document. Either/both of pOldDoc and pNewDoc may be NULL.
01664 
01665                 If the Selected DocView changes, a DocViewMsg (SELCHANGED) will be broadcast,
01666                 with the pOldDocView and pNewDocView fields indicating the old and new DocViews.
01667 
01668                 If the Selected spread changes, a SpreadMsg (SELCHANGED) will be broadcast.
01669                 pOldSpread and pNewSpread will point at the spreads involved.
01670                
01671                 This also sets CurrentDoc to equal the Selected Doc. Ths state should
01672                 remain true during the broadcast of the DocChanging Message.
01673 
01674     Errors:     ERROR2's will be generated if the parameters are incompatible (TheView
01675                 must be a view onto TheDocuemnt; TheSpread must lie within TheDocument)
01676 
01677 ***********************************************************************************************/
01678 
01679 void Document::SetSelectedViewAndSpread(Document *TheDocument,
01680                                             DocView *TheView,
01681                                             Spread *TheSpread)
01682 {
01683 //  TRACEUSER("Gerry", _T("Document::SetSelectedViewAndSpread(0x%08x, 0x%08x, 0x%08x)"), TheDocument, TheView, TheSpread);
01684 #ifdef RALPH
01685     // if we are being called from the load thread just ignore 
01686     if(::GetCurrentThreadId() == RalphDocument::GetImportingThreadID())
01687         return ;
01688 #endif
01689     // We must remember if each of the selected things has changed as a result of this call
01690     Document    *OldSelDocument = Selected;
01691     DocView     *OldSelView     = DocView::GetSelected();
01692     Spread      *OldSelSpread   = pGlobalSelSpread;
01693 
01694     // Ensure that all parameters are valid pointers
01695     if (TheDocument == NULL)
01696         TheDocument = Selected;
01697 
01698     if (TheDocument == NULL)
01699     {
01700         // The caller is obviously trying to set the selected spread/view when there is
01701         // no valid document around
01702         ERROR3("Can't set selected spread/view when there is no selected doc!");
01703         return;
01704     }
01705 
01706     if (TheView == NULL)
01707     {
01708         // The caller supplied no docview - try the selected docview, and if that is not
01709         // in the document becoming selected, then use the first view for the sel doc.
01710         TheView = DocView::GetSelected();
01711         if (TheView == NULL || TheView->GetDoc() != TheDocument)
01712             TheView = (DocView *) TheDocument->DocViews.GetHead();
01713     }
01714 
01715     if (TheSpread == NULL)
01716     {
01717         // The caller specified no spread - Try the globally selected spread, then the
01718         // document's memory of the selected spread, and finally, the first spread in the
01719         // document.
01720         if (pGlobalSelSpread != NULL && SpreadBelongsToDoc(TheDocument, pGlobalSelSpread))
01721             TheSpread = pGlobalSelSpread;
01722         else
01723         {
01724             if (TheDocument->pSelSpread != NULL)
01725                 TheSpread = TheDocument->pSelSpread;
01726             else
01727                 TheSpread = TheDocument->FindFirstSpread();
01728         }
01729     }
01730 
01731 
01732     // Tell those that care that the selected view is about to change
01733     if (TheView!=OldSelView)
01734     {
01735         BROADCAST_TO_ALL(DocViewMsg(OldSelView, OldSelView, DocViewMsg::SELABOUTTOCHANGE));
01736     }
01737 
01738     // --- Set the new selected document, and also update CurrentDoc to be this one
01739     // (so that CurrentDoc points at selected while the broadcast goes around)
01740     Selected = TheDocument;
01741     Selected->SetCurrent();
01742 
01743     OpNudge::SetNudgeStep (Selected->GetDocNudge ());   // CGS:  since documents now store the nudge
01744 
01745     // --- Set the new selected DocView
01746     DocView::SetSelectedInternal(TheView);
01747 
01748     // --- Set the new selected spread
01749     ERROR3IF(TheSpread != NULL && !SpreadBelongsToDoc(Selected, TheSpread),
01750                 "Selected spread should be in the Selected Doc!");
01751     pGlobalSelSpread = TheSpread;
01752     if (Selected != NULL)
01753         Selected->pSelSpread = TheSpread;
01754 
01755 
01756     // --- Now, check if any have changed, and broadcast appropriate messages
01757     if (Selected != OldSelDocument)
01758     {
01759         BROADCAST_TO_ALL(DocChangingMsg(OldSelDocument, Selected,
01760                             DocChangingMsg::SELCHANGED));
01761     }
01762 
01763     if (DocView::GetSelected() != OldSelView)
01764     {
01765         DocView::SendSelectedMessage(OldSelView, DocView::GetSelected());
01766     }
01767 
01768     if (pGlobalSelSpread != OldSelSpread)
01769     {
01770         BROADCAST_TO_ALL(SpreadMsg(OldSelSpread, pGlobalSelSpread,
01771                             SpreadMsg::SELCHANGED));
01772     }
01773 
01774     // Ensure any delayed Selection message broadcasts are sent now
01775     GetApplication()->FindSelection()->BroadcastAnyPendingMessages();
01776 }
01777 
01778 
01779     
01780 /***********************************************************************************************
01781 
01782 >   void Document::SetSelected()
01783 
01784     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>/ MarkN
01785     Created:    21/5/93
01786     
01787     Inputs:     - 
01788     Outputs:    -
01789     Returns:    -
01790                  
01791     Purpose:    THIS METHOD IS DEFUNCT! DO NOT CALL IT!
01792                 Use Document::SetSelectedViewAndSpread() instead
01793                 (This call is currently indirected to that one, and gives TRACE warnings)
01794     
01795                 Make this object be the 'selected' document object.
01796 
01797                 It sets the selected spread to be a relevent spread in this document.
01798                 If there is a change in selected spread as a result, a SpreadMsg::SELCHANGED
01799                 message is broadcast.
01800 
01801                 A message is broadcast called SELCHANGED. On receipt of this message, pOldDoc is the one 
01802                 being deselected, and pNewDoc is the one being selected,
01803                 NOTE!! pOldDoc and/or pNewDoc can be NULL!!!
01804                
01805                 This does NOT effect the Current doc.
01806 
01807                 If the new selected document is not the document associated with the selected
01808                 DocView, then DocView::SetNoSelected() is called. This is because the selected
01809                 DocView must be a view onto the selected document.
01810 
01811     Errors:     None.
01812                                                                  
01813 ***********************************************************************************************/
01814 
01815 #if 0
01816 
01817 void Document::SetSelected()
01818 {
01819 #if FALSE
01820 /*
01821     // Defunct code - see below for replacement code
01822     if (Selected == this) return;
01823     Document* pOldDoc = Selected;
01824 
01825     Selected = this;
01826 
01827     // The selected document has changed, so ensure that the selected DocView belongs to the new
01828     // selected document
01829     // This is based on the rule that the selected DocView MUST be a view onto the selected document
01830     DocView* pSelDocView = DocView::GetSelected();
01831     if ((pSelDocView != NULL) && (pSelDocView->GetDoc() != Selected))
01832         DocView::SetNoSelected();
01833 
01834     if (pSelSpread == NULL)
01835         pSelSpread = FindFirstSpread();
01836 
01837     BROADCAST_TO_ALL(DocChangingMsg(pOldDoc,Selected,DocChangingMsg::DocState::SELCHANGED));
01838     Document::SetSelectedSpread(pSelSpread);
01839 */
01840 #else
01841 
01842     // Now just indirects to the centralised Doc/DocView/Spread selector
01843     TRACE( _T("WARNING: Illegal call to defunct Document::SetSelected\n"));
01844     Document::SetSelectedViewAndSpread(this, NULL, NULL);
01845 
01846 #endif
01847 }
01848 
01849 #endif
01850 
01851 
01852 /***********************************************************************************************
01853 
01854 >   static void Document::SetNoSelected()
01855 
01856     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01857     Created:    21/5/93
01858     
01859     Inputs:     - 
01860     Outputs:    -
01861     Returns:    -
01862                  
01863     Purpose:    THIS METHOD IS DEFUNCT! DO NOT CALL IT!
01864                 Use Document::SetNoSelectedViewAndSpread() instead
01865                 (This call is currently indirected to that one, and gives TRACE warnings)
01866     
01867                 Set the selected document pointer to be NULL, i.e., there is no selected
01868                 document object. 
01869                 This does NOT effect the Current doc.
01870 
01871                 **** Changed 22/7/94 by MarkN ****
01872                 A new message is broadcast that combines the SELECTED and UNSELECTED messages
01873                 in one called SELCHANGED. On receipt of this message, pOldDoc is the one being
01874                 deselected, and pNewDoc is the one being selected,
01875                 NOTE!! pOldDoc and/or pNewDoc can be NULL!!!
01876                
01877     Errors:     None.
01878                                                                  
01879 ***********************************************************************************************/
01880 
01881 #if 0
01882 
01883 void Document::SetNoSelected()
01884 {
01885 #if FALSE
01886 /*
01887     if (Selected == NULL) return;
01888     Document* pOldDoc = Selected;
01889 
01890     Selected = NULL;
01891     Document::SetSelectedSpread(NULL);
01892 
01893     BROADCAST_TO_ALL(DocChangingMsg(pOldDoc,NULL,DocChangingMsg::DocState::SELCHANGED));
01894 */
01895 #else
01896 
01897     TRACE( _T("WARNING: Illegal call to defunct Document::SetNoSelected\n"));
01898     Document::SetNoSelectedViewAndSpread();
01899 
01900 #endif
01901 }                    
01902 
01903 #endif
01904 
01905 
01906 /***********************************************************************************************
01907 
01908 >   static void Document::SetSelectedSpread(Spread* pNewSelSpread)
01909 
01910     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01911     Created:    3/8/94
01912     Inputs:     pNewSelSpread = ptr to the spread that is the new selected spread
01913     Outputs:    -
01914     Returns:    -
01915     Purpose:    THIS METHOD IS DEFUNCT! DO NOT CALL IT!
01916                 Use Document::SetSelectedViewAndSpread() instead
01917                 (This call is currently indirected to that one, and gives TRACE warnings)
01918     
01919                 Sets the global instance of the selected spread. 
01920                 pNewSelSpread must be a spread belonging to the selected document.
01921     Errors:     -
01922     SeeAlso:    -
01923 
01924 ***********************************************************************************************/
01925 
01926 #if 0
01927 
01928 void Document::SetSelectedSpread(Spread* pNewSelSpread)
01929 {
01930 #if FALSE
01931 /*
01932     // if no change return
01933     if (pGlobalSelSpread == pNewSelSpread) return;
01934 
01935     Spread* pOldSelSpread = pGlobalSelSpread;
01936 
01937     if (Selected == NULL && pNewSelSpread == NULL)
01938         // If there's no selected document, then there's no selected spread
01939         pGlobalSelSpread = NULL;
01940     else
01941     {
01942         // Make sure there is at least a selected doc
01943         ENSURE(Selected != NULL,"Can't set selected spread if there isn't a selected document");
01944 
01945         // if there's a new sel spread, ensure it belongs to the selected doc
01946         if (pNewSelSpread != NULL)
01947         {
01948             ENSURE(SpreadBelongsToDoc(Selected,pNewSelSpread),"Trying to set the selected spread which doesn't belong to the selected doc.");
01949         }
01950 
01951         // We've ensured that there's a selected doc, and the new sel spread belongs to it
01952 
01953         pGlobalSelSpread     = pNewSelSpread;
01954         Selected->pSelSpread = pNewSelSpread;
01955     }
01956 
01957     // Clear all current selections, and remove the blobs
01958     //NodeRenderableInk::DeselectAll();
01959 
01960     // Inform the SelRange that it has changed, get it to broadcast
01961     //GetApplication()->FindSelection()->Update(TRUE); 
01962 
01963     BROADCAST_TO_ALL(SpreadMsg(pOldSelSpread,pNewSelSpread,SpreadMsg::SpreadReason::SELCHANGED));
01964 */
01965 #else
01966 
01967     TRACE( _T("WARNING: Illegal call to defunct Document::SetSelectedSpread\n"));
01968     Document::SetSelectedViewAndSpread(Selected, NULL, pNewSelSpread);
01969 
01970 #endif
01971 
01972 }
01973 
01974 #endif
01975 
01976 
01977 
01978 /***********************************************************************************************
01979 
01980 >   static Spread *Document::GetSelectedSpread()
01981 
01982     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01983     Created:    3/8/94
01984     Inputs:     -
01985     Outputs:    -
01986     Returns:    The selected spread in the system
01987     Purpose:    Returns the selected spread
01988     Errors:     -
01989     SeeAlso:    -
01990 
01991 ***********************************************************************************************/
01992 
01993 Spread *Document::GetSelectedSpread()
01994 {
01995 #ifdef RALPH
01996     // if we are being called from the load thread return the first spread in the current load
01997     // thread document
01998     if(::GetCurrentThreadId() == RalphDocument::GetImportingThreadID())
01999     {
02000         //TRACEUSER( "Richard", _T("+++++ GetSelectedSpread called from Load Thread\n"));
02001         return RalphDocument::GetImportingDoc()->FindFirstSpread();
02002     }
02003 #endif
02004     //TRACEUSER( "Richard", _T(">>> Document::GetSelectedSpread returning pGlobalSelSpread\n"));
02005     return (pGlobalSelSpread);
02006 }
02007 
02008 
02009 
02010 /***********************************************************************************************
02011 
02012 >   static BOOL Document::SpreadBelongsToDoc(Document* pDoc,Spread* pSpread)
02013 
02014     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02015     Created:    3/8/94
02016     Inputs:     pDoc    = ptr to a document
02017                 pSpread = ptr to a spread
02018     Outputs:    -
02019     Returns:    TRUE if pSpread is a child of the NodeDocument belonging to pDoc
02020                 FALSE otherwise
02021     Purpose:    Tests to see if the spread belongs to the document
02022     Errors:     -
02023     SeeAlso:    -
02024 
02025 ***********************************************************************************************/
02026 
02027 BOOL Document::SpreadBelongsToDoc(Document* pDoc,Spread* pSpread)
02028 {
02029     if (pDoc == NULL) return FALSE;
02030 
02031     // Find pDoc's first node
02032     Node* pNode = pDoc->GetFirstNode();
02033     ENSURE(pNode != NULL,"No first node!");
02034 
02035     // The next node should be the NodeDocument node
02036     pNode = pNode->FindNext();
02037     ENSURE(pNode != NULL,"No next node!");
02038     ENSURE(pNode->GetRuntimeClass() == CC_RUNTIME_CLASS(NodeDocument),"Next node is not a NodeDocument");
02039 
02040     // pNode should now point to pDoc's NodeDocument node
02041 
02042     // Find pSpread's parent NodeDocument node
02043     Node* pParentNodeDoc = pSpread->FindParent(CC_RUNTIME_CLASS(NodeDocument));
02044     ENSURE(pParentNodeDoc != NULL,"The spread has no NodeDocument parent");
02045 
02046     // Return TRUE if pSpread's parent NodeDocument node == pDoc's NodeDocument node
02047 
02048     return ((pParentNodeDoc == pNode) && (pNode != NULL) && (pParentNodeDoc != NULL));
02049 }
02050 
02051 
02052 
02053 /***********************************************************************************************
02054 
02055 >   Spread* Document::FindFirstSpread()
02056 
02057     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02058     Created:    3/8/94
02059     Inputs:     -
02060     Outputs:    -
02061     Returns:    The first spread in this document.  A document always has at least one spread
02062     Purpose:    Finds the first spread in this document.
02063     Errors:     -
02064     SeeAlso:    -
02065 
02066 ***********************************************************************************************/
02067 
02068 Spread* Document::FindFirstSpread()
02069 {
02070     Node* pNode = GetFirstNode();
02071     ERROR3IF(pNode == NULL,"Document::FindFirstSpread No first node!");
02072     if (pNode == NULL)
02073         return NULL;
02074 
02075     pNode = pNode->FindNext();
02076     if (pNode != NULL)
02077     {
02078         ERROR3IF(pNode->GetRuntimeClass() != CC_RUNTIME_CLASS(NodeDocument),"Next node is not a NodeDocument");
02079         pNode = pNode->FindFirstChild();
02080         if (pNode != NULL)
02081         {
02082             if (pNode->GetRuntimeClass() != CC_RUNTIME_CLASS(Chapter))
02083                 pNode = pNode->FindNext(CC_RUNTIME_CLASS(Chapter));
02084             if (pNode != NULL)
02085             {
02086                 pNode = pNode->FindFirstChild();
02087                 if (pNode != NULL)
02088                 {
02089                     if (pNode->GetRuntimeClass() != CC_RUNTIME_CLASS(Spread))
02090                         pNode = pNode->FindNext(CC_RUNTIME_CLASS(Spread));
02091 
02092                     ERROR3IF(pNode == NULL,"Can't find a spread as a child of Chapter");
02093                 }
02094                 else
02095                     ERROR3("No child of Chapter node");
02096             }
02097             else
02098                 ERROR3("Can't find a chapter as a child of NodeDocument");
02099         }
02100         else
02101             ERROR3("No child of NodeDocument node");
02102     }
02103     else
02104         ERROR3("No next node!");
02105 
02106     return ((Spread*)pNode);
02107 }
02108 
02109 
02110 
02111 /***********************************************************************************************
02112 
02113 >   void Document::GetExtents(DocCoord* Lo, DocCoord* Hi, DocRect* Extent, View *pView)
02114 
02115     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02116     Created:    28/5/93
02117     Inputs:     pView - the View to pixelise the extents to.
02118     Outputs:    Lo, Hi - the extents of the document.
02119     Returns:    -
02120     Purpose:    Find the extents of the document.  These are in DocCoords - Lo is the
02121                 bottom-left corner of the last chapter, and Hi is the top-right corner
02122                 of the first chapter.
02123     Errors:     -
02124     SeeAlso:    -
02125 
02126 ***********************************************************************************************/
02127 
02128 void Document::GetExtents(DocCoord* Lo, DocCoord* Hi, DocRect* Extent, View *pView)
02129 {
02130     NodeDocument* DocNode = (NodeDocument*) TreeStart->FindNext();
02131     
02132     // Just to be on the safe side
02133     ENSURE(DocNode->IsKindOf(CC_RUNTIME_CLASS(NodeDocument)),
02134                     "Document.cpp: This node is not a NodeDocument");
02135     
02136     *Lo = DocNode->LoExtent();
02137     *Hi = DocNode->HiExtent();
02138     *Extent = DocNode->GetPasteboardRect(TRUE, pView);
02139 }
02140 
02141 
02142 
02143 /***********************************************************************************************
02144 
02145 >   void Document::UpdateExtents(const DocCoord& Lo, const DocCoord& Hi)
02146 
02147     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02148     Created:    29/5/93
02149     Inputs:     Lo, Hi - the new Extents in document coordinates.
02150     Outputs:    -
02151     Returns:    -
02152     Purpose:    Change the document extents.  This will only be done by objects of class
02153                 NodeDocument.  All related DocViews are informed of the change.
02154     Errors:     -
02155     SeeAlso:    NodeDocument
02156     SeeAlso:    GetExtents
02157 
02158 ***********************************************************************************************/
02159 
02160 void Document::UpdateExtents(const DocCoord& Lo, const DocCoord& Hi)
02161 {
02162     DocView *pView = (DocView*) DocViews.GetHead();
02163 
02164     // Scan list of all DocView of this Document    
02165     while (pView != NULL)
02166     {
02167         // Inform DocView of the new document extent.
02168         pView->SetExtent(Lo, Hi);
02169         pView = (DocView*) DocViews.GetNext(pView);
02170     }
02171 }   
02172 
02173 
02174 
02175 /********************************************************************************************
02176 
02177 >   OperationHistory& Document::GetOpHistory()
02178 
02179     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
02180     Created:    1/7/93
02181     Inputs:     -
02182     Outputs:    -
02183     Returns:    A reference to the documents operation history
02184     Purpose:    For finding the documents operation history
02185     Errors:     -
02186     SeeAlso:    -
02187 
02188 ********************************************************************************************/
02189 
02190 OperationHistory& Document::GetOpHistory()
02191 {
02192     return (*OpHistory);
02193 }
02194 
02195 
02196 
02197 /********************************************************************************************
02198 
02199 >   BOOL Document::EmptyOperationHistory()
02200 
02201     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
02202     Created:    6/4/95
02203     Returns:    TRUE if the Operation History was empied ok, FALSE if there is a problem
02204     Purpose:    This function deletes the operation history, destroying everything in it.
02205                 It then creates a new empty Operation History and sets it up ready for use.
02206                 This function was really created to allow the New and Open Document options
02207                 to get rid of the undo that is created by the file importing.
02208 
02209 ********************************************************************************************/
02210 
02211 BOOL Document::EmptyOperationHistory()
02212 {
02213     // If there was no Operation History in the first place, then there is a problem
02214     if (OpHistory==NULL)
02215         return FALSE;
02216 
02217     // Before we delete th history find out what its maximum size is
02218     UINT32 MaxSize = OpHistory->GetMaxSize();
02219 
02220     // There is an Operation History, so toast it
02221     delete OpHistory;
02222     OpHistory = NULL;
02223 
02224     // Now try and replace it with a new one
02225     OpHistory = new OperationHistory(MaxSize);
02226     
02227     // If we did not get the memory to create a new one, then fail
02228     if (OpHistory==NULL)
02229         return FALSE;
02230 
02231     // We now have a nice new empty operation history, so return happy
02232     return TRUE;
02233 }
02234 
02235 
02236 
02237 /********************************************************************************************
02238 
02239 >   AttributeManager& GetAttributeMgr() const; 
02240 
02241     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
02242     Created:    1/7/93
02243     Inputs:     -
02244     Outputs:    -
02245     Returns:    A reference to the documents operation history
02246     Purpose:    For finding the documents operation history
02247     Errors:     -
02248     SeeAlso:    -
02249 
02250 ********************************************************************************************/
02251 
02252 AttributeManager& Document::GetAttributeMgr() const
02253 {
02254     ENSURE(AttributeMgr != NULL,
02255                 "Pointer to Attribute Manager is NULL in Document::GetAttributeMgr()");
02256     return (*AttributeMgr); 
02257 }
02258 
02259 
02260 
02261 
02262 /********************************************************************************************
02263 
02264 >   BOOL Document::IsMultilayer()
02265 
02266     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02267     Created:    11/8/94
02268     Inputs:     -
02269     Outputs:    -
02270     Returns:    TRUE if the multilayer flag for the document is set. FALSE otherwise
02271     Purpose:    Interogate the multilayer status of this document
02272     Errors:     -
02273     SeeAlso:    -
02274 
02275 ********************************************************************************************/
02276 
02277 BOOL Document::IsMultilayer()
02278 {
02279     return (DocFlags.LayerMultilayer != 0);
02280 }
02281 
02282 /********************************************************************************************
02283 
02284 >   BOOL Document::IsAllVisible()
02285 
02286     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02287     Created:    11/8/94
02288     Inputs:     -
02289     Outputs:    -
02290     Returns:    TRUE if the "all visible" flag for the document is set. FALSE otherwise
02291     Purpose:    Interogate the "all visible" status of this document
02292     Errors:     -
02293     SeeAlso:    -
02294 
02295 ********************************************************************************************/
02296 
02297 BOOL Document::IsAllVisible()
02298 {
02299     return (DocFlags.LayerAllVisible != 0);
02300 }
02301 
02302 /********************************************************************************************
02303 
02304 >   void Document::SetMultilayer(BOOL state)
02305 
02306     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02307     Created:    11/8/94
02308     Inputs:     state = TRUE or FALSE
02309     Outputs:    -
02310     Returns:    -
02311     Purpose:    Lets you set the state of the multilayer document flag
02312     Errors:     -
02313     SeeAlso:    -
02314 
02315 ********************************************************************************************/
02316 
02317 void Document::SetMultilayer(BOOL state)
02318 {
02319     DocFlags.LayerMultilayer = state;
02320 }
02321 
02322 /********************************************************************************************
02323 
02324 >   void Document::SetAllVisible(BOOL state)
02325 
02326     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02327     Created:    11/8/94
02328     Inputs:     state = TRUE or FALSE
02329     Outputs:    -
02330     Returns:    -
02331     Purpose:    Lets you set the state of the "all visible" document flag
02332     Errors:     -
02333     SeeAlso:    -
02334 
02335 ********************************************************************************************/
02336 
02337 void Document::SetAllVisible(BOOL state)
02338 {
02339     DocFlags.LayerAllVisible = state;
02340 }
02341 
02342 /********************************************************************************************
02343 
02344 >   NodeAttribute* Document::GetDefaultAttr(CCRuntimeClass* RequiredAttr)
02345 
02346     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02347     Created:    25/10/93
02348     Inputs:     RequiredAttr - the type of attribute to look for.
02349     Returns:    Pointer to the default attribute node, or NULL if the attribute was not 
02350                 found.
02351     Purpose:    Finds the default attribute node for a document, given the attribute class
02352                 to look for.  For instance, to find out the default line width for a
02353                 document: MonoOn
02354                 
02355                 AttrLineWidth *pAttr = pDoc->GetDefaultAttr(CC_RUNTIME_CLASS(AttrLineWidth));
02356                 MonoOff
02357 
02358 ********************************************************************************************/
02359 
02360 NodeAttribute* Document::GetDefaultAttr(CCRuntimeClass* RequiredAttr)
02361 {
02362     // Search for line width attribute as a child of the NodeDocument.
02363     Node *pNode = TreeStart->FindNext();
02364     
02365     if (pNode == NULL)
02366     {
02367         // Error in document tree
02368         return NULL;
02369     }
02370     
02371     if (!pNode->IsKindOf(CC_RUNTIME_CLASS(NodeDocument)))
02372     {
02373         // Error in document tree
02374         return NULL;
02375     }
02376     
02377     // Find the attribute in question
02378     for (pNode = pNode->FindFirstChild();
02379          pNode != NULL;
02380          pNode = pNode->FindNext())
02381     {
02382         if (pNode->IsKindOf(RequiredAttr))
02383             return (NodeAttribute *) pNode;
02384     }
02385     
02386     // Required attribute was not found - just return NULL
02387     return NULL;
02388 }
02389 
02390 /********************************************************************************************
02391 >   NodeSetSentinel* Document::GetSetSentinel() const
02392 
02393     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02394     Created:    30/11/93
02395     Returns:    A (cached) pointer to the document's NodeSetSentinel node.
02396     SeeAlso:    NameGallery; NodeSetSentinel; Document::InitTree
02397 ********************************************************************************************/
02398 
02399 NodeSetSentinel* Document::GetSetSentinel() const
02400 {
02401     ERROR3IF(m_pSetSentinel == 0, "Document::GetSetSentinel: no NodeSetSentinel");
02402     return m_pSetSentinel;
02403 }
02404 
02405 
02406 
02407 /********************************************************************************************
02408 
02409 >   static void Document::IncCurrentNodeCount()
02410 
02411     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02412     Created:    30/11/93
02413     Inputs:     -
02414     Outputs:    -
02415     Returns:    -
02416     Purpose:    Adds one to the NodesInTree counter of the Current Document object, if it
02417                 exists.  Called by the constructors of class Node.
02418     Errors:     -
02419     SeeAlso:    Document::DecCurrentNodeCount; Document::NodesInDocument
02420 
02421 ********************************************************************************************/
02422 
02423 void Document::IncCurrentNodeCount()
02424 {
02425     if (Current) Current->NodesInTree++;
02426 }
02427 
02428 
02429 
02430 /********************************************************************************************
02431 
02432 >   static void Document::DecCurrentNodeCount()
02433 
02434     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02435     Created:    30/11/93
02436     Inputs:     -
02437     Outputs:    -
02438     Returns:    -
02439     Purpose:    Decrements the node counter in the current Document, if there is one.
02440                 Called by the destructor of class Node.
02441     Errors:     -
02442     SeeAlso:    Document::IncCurrentNodeCount; Document::NodesInDocument
02443 
02444 ********************************************************************************************/
02445 
02446 void Document::DecCurrentNodeCount()
02447 {
02448     if (Current) Current->NodesInTree--;
02449 }
02450 
02451 
02452 
02453 /********************************************************************************************
02454 
02455 >   void Document::DeleteContents()
02456 
02457     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02458     Created:    25/3/94
02459     Inputs:     -
02460     Outputs:    -
02461     Returns:    -
02462     Purpose:    None. Nothing. Does not do anything. And don't even think about making it
02463                 do anything!
02464     Errors:     -
02465     SeeAlso:    CCamDoc::DeleteContents
02466 
02467 ********************************************************************************************/
02468 
02469 void Document::DeleteContents()
02470 {
02471     // This function does nothing because MFC calls it in a completely brain-damaged way.
02472     // It calls it when the document is about to be destroyed, and ALSO calls it just
02473     // after a new document has just been created. Fabby eh? Those boys from Redmond strike 
02474     // again!  (Tim)
02475 
02476     // DON'T make it do anything!
02477 }
02478 
02479 
02480 
02481 
02482 /********************************************************************************************
02483 
02484 >   void Document::ForceRedraw(FRDocViewFunc pFunc)
02485 
02486     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02487     Created:    29/4/94
02488     Inputs:     pFunc = ptr to func to equire whether a particular DocView should be redrawn
02489     Purpose:    Calls DocView::ForceRedraw() for each DocView attached to this
02490                 Document.  i.e. This forces a *complete* redraw for the whole document in
02491                 all views attached to it.
02492     SeeAlso:    DocView::ForceRedraw
02493 
02494 ********************************************************************************************/
02495 
02496 void Document::ForceRedraw(FRDocViewFunc pFunc)
02497 {
02498     ListItem* pItem = DocViews.GetHead();
02499     while (pItem != NULL)
02500     {
02501         BOOL ok = TRUE;
02502         DocView* pDocView = (DocView*)pItem;
02503 
02504         if (pFunc != NULL)
02505             ok = pFunc(pDocView);
02506 
02507         if (ok)
02508         {
02509             // Pass TRUE to DocView::ForceRedraw() so that we force an immediate update of
02510             // the paper, because this function is used when something pretty fundamental has
02511             // changed in the document, quite often related to spreads/pages etc.
02512             ((DocView*) pItem)->ForceRedraw(TRUE);
02513         }
02514 
02515         pItem = DocViews.GetNext(pItem);
02516     }
02517 }
02518 
02519 
02520 
02521 /********************************************************************************************
02522 >   void Document::ForceRedraw(WorkRect& forceRect)
02523 
02524     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02525     Created:    29/4/94
02526     Inputs:     A WorkRect bounding the area to be redrawn
02527     Outputs:    -
02528     Returns:    -
02529     Purpose:    Calls DocView::ForceRedraw(WorkRect&) for each DocView attached to
02530                 this Document.
02531     Errors:     -
02532     SeeAlso:    DocView::ForceRedraw
02533 ********************************************************************************************/
02534 
02535 void Document::ForceRedraw(WorkRect& forceRect)
02536 {
02537     ListItem* pItem = DocViews.GetHead();
02538     while (pItem != NULL)
02539     {
02540         ((DocView*) pItem)->ForceRedraw(forceRect);
02541         pItem = DocViews.GetNext(pItem);
02542     }
02543 }
02544 
02545 
02546 
02547 /********************************************************************************************
02548 >   void Document::ForceRedraw(Spread* pSpread, DocRect spreadRect, BOOL Accumulate = FALSE, Node* pInvalidNode = NULL, BOOL bAutoRelease = TRUE)
02549 
02550     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02551     Created:    29/4/94
02552     Inputs:     A pointer to a spread and the area within that spread to redraw.
02553     Outputs:    -
02554     Returns:    -
02555     Purpose:    Calls DocView::ForceRedraw(Spread*, DocRect) for each DocView
02556                 attached to this Document.
02557     Errors:     -
02558     SeeAlso:    DocView::ForceRedraw
02559 ********************************************************************************************/
02560 
02561 void Document::ForceRedraw(Spread* pSpread, DocRect spreadRect, BOOL Accumulate, Node* pInvalidNode, BOOL bAutoRelease)
02562 {
02563     // If the caller has told us about a node that has become invalid (probably causing this redraw)
02564     // Then make sure it doesn't hold on to any cached rendering before we force the redraw
02565     if (pInvalidNode && bAutoRelease)
02566     {
02567         if (pInvalidNode->IsAnObject()) ((NodeRenderableInk*)pInvalidNode)->ReleaseCached(TRUE, TRUE);
02568     }
02569 
02570     ListItem* pItem = DocViews.GetHead();
02571     while (pItem != NULL)
02572     {
02573         ((DocView*) pItem)->ForceRedraw(pSpread, spreadRect, Accumulate, pInvalidNode);
02574         pItem = DocViews.GetNext(pItem);
02575     }
02576 }
02577 
02578 /********************************************************************************************
02579 
02580 >   void Document::FlushRedraw()
02581 
02582     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02583     Created:    22/12/94
02584     Purpose:    Calls DocView::FlushRedraw() for each DocView
02585                 attached to this Document.
02586     SeeAlso:    DocView::FlushRedraw
02587 
02588 ********************************************************************************************/
02589 
02590 void Document::FlushRedraw()
02591 {
02592     ListItem* pItem = DocViews.GetHead();
02593     while (pItem != NULL)
02594     {
02595         ((DocView*) pItem)->FlushRedraw();
02596         pItem = DocViews.GetNext(pItem);
02597     }
02598 }
02599 
02600 
02601 
02602 /********************************************************************************************
02603 >   void Document::HandleNodeDeletion(Node* pNode)
02604 
02605     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02606     Created:    29/4/94
02607     Inputs:     A WorkRect bounding the area to be redrawn
02608     Outputs:    -
02609     Returns:    -
02610     Purpose:    Calls DocView::ForceRedraw(WorkRect&) for each DocView attached to
02611                 this Document.
02612     Errors:     -
02613     SeeAlso:    DocView::ForceRedraw
02614 ********************************************************************************************/
02615 
02616 void Document::HandleNodeDeletion(Node* pNode)
02617 {
02618     ListItem* pItem = DocViews.GetHead();
02619     while (pItem != NULL)
02620     {
02621         ((DocView*) pItem)->HandleNodeDeletion(pNode);
02622 
02623         pItem = DocViews.GetNext(pItem);
02624     }
02625 }
02626 
02627 
02628 
02629 /********************************************************************************************
02630 
02631 >   InsertionNode* Document::GetInsertionPosition(); 
02632 
02633     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
02634     Created:    18/7/94
02635     Returns:    The Insertion position. This will be the InsertionNode (Insert as a Previous 
02636                 child of this)
02637     Purpose:    This function should be called to find the position in the document where a
02638                 new object should be inserted. The object should always be inserted as a previous
02639                 child of the InsertionNode which is returned.
02640     SeeAlso:    UndoableOperation::DoInsertNewNode
02641 
02642 ********************************************************************************************/
02643 
02644 InsertionNode* Document::GetInsertionPosition()
02645 {
02646     // Is the Insertion node in the corrrect spread ?
02647     Spread* SelSpread = Document::GetSelectedSpread();
02648     ENSURE(SelSpread != NULL, "The selected spread is NULL");
02649     
02650     // I think it's ok to search for the active layer here cos there is not likely
02651     // to be zillions of layers.
02652     Layer* SelActiveLyr = SelSpread->FindActiveLayer(); 
02653     ENSURE(SelActiveLyr != NULL, "Could not find active layer on selected spread"); 
02654     
02655     Node* InsertLyr = NULL;  // The layer containing the InsertionNode. If one
02656                              // exists. See the InsertionNode's destructor.
02657     if (InsertPos)
02658     {
02659         ERROR3IF(InsertPos->FindNext(), "InsertionNode is not the last node on a layer"); 
02660         InsertLyr = InsertPos->FindParent();
02661         // In a retail if the InsertPos' parent is NULL then we will survive this
02662         ERROR3IF(!InsertLyr, "The Insertion node's parent has been deleted"); 
02663         // If the parent of the Insertion node is not a Layer then there is probably
02664         // cause for concern. Not very likely this.
02665         ENSURE(InsertLyr->GetRuntimeClass() == CC_RUNTIME_CLASS(Layer), "Parent of insertion node is not a layer");
02666     }
02667     else
02668     {
02669         // Weve lost our Insertion Node. Create a new one
02670         InsertPos = new InsertionNode(this);
02671         if (!InsertPos)
02672         {
02673             return NULL; // Not v. likely
02674         }
02675     }
02676 
02677     if (SelActiveLyr != ((Layer*)InsertLyr))
02678     {
02679         // The InsertionNode should be moved
02680         // this is the slow bit, but it will only happen when the selected spread 
02681         // changes.
02682         InsertPos->MoveNode(SelActiveLyr, LASTCHILD);   
02683     }
02684     // otherwise the InsertPos is in the correct position
02685     return InsertPos;
02686 } 
02687 
02688 
02689 
02690 /********************************************************************************************
02691 
02692 >   void Document::ResetInsertionPosition()
02693 
02694     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02695     Created:    18/08/94
02696     Purpose:    Forces the insertion node to move to the end of the layer that it is
02697                 currently on.  This is used by the filters so they can insert an 
02698                 arbitrary number of nodes into the tree without worryng about the insertion 
02699                 position being updated every time and then it can just update it at the end 
02700                 using this function.
02701     SeeAlso:    Document::GetInsertionPosition
02702 
02703 ********************************************************************************************/
02704 
02705 void Document::ResetInsertionPosition()
02706 {
02707     // Is the Insertion node in the correct spread ?
02708     Spread* SelSpread = Document::GetSelectedSpread();
02709     if (SelSpread==NULL)
02710     {
02711         SelSpread = FindFirstSpread();
02712         if (SelSpread==NULL)
02713         {
02714             ERROR3("Fialed to ResetInsertPosition(), unable to find a spread in this document");
02715             return;
02716         }
02717     }
02718     
02719     // I think it's ok to search for the active layer here cos there is not likely
02720     // to be zillions of layers.
02721     Layer* pSelActiveLyr = SelSpread->FindActiveLayer();
02722     if ( pSelActiveLyr )
02723     {
02724         ERROR3IF(pSelActiveLyr == NULL, "Could not find active layer on selected spread"); 
02725 
02726         //Node* InsertLyr = InsertPos->FindParent();
02727 
02728         //ENSURE(InsertLyr->GetRuntimeClass() == CC_RUNTIME_CLASS(Layer), 
02729         //  "Parent of insertion node is not a layer")
02730 
02731         if (InsertPos == NULL)
02732             GetInsertionPosition();
02733 
02734         // The InsertionNode should be moved
02735         if (InsertPos != NULL && pSelActiveLyr != NULL)
02736             InsertPos->MoveNode(pSelActiveLyr, LASTCHILD);
02737 
02738     /*
02739         Node* pInsertPosNode = GetInsertionPosition();
02740 
02741         ERROR3IF(pInsertPosNode == NULL,"Can't get hold of the insert node");
02742 
02743         // The InsertionNode should be moved
02744         if (pInsertPosNode != NULL)
02745             pInsertPosNode->MoveNode(SelActiveLyr, LASTCHILD);
02746     */
02747     }
02748 }
02749 
02750 
02751 
02752 /********************************************************************************************
02753 >   static BOOL Document::ReadPrefs()
02754 
02755     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02756     Created:    5/1/95
02757     Inputs:     -
02758     Outputs:    -
02759     Returns:    TRUE if successful.
02760     Purpose:    Reads preferences for the Document class from the program's .INI file.
02761     Errors:     -
02762     SeeAlso:    InitKernel
02763 ********************************************************************************************/
02764 
02765 BOOL Document::ReadPrefs()
02766 {
02767     if (Camelot.DeclareSection(TEXT("Preferences"), 1))
02768     {
02769         Camelot.DeclarePref(TEXT("Preferences"), TEXT("RemoveExistingDocs"),
02770                                &CCamDoc::s_RemoveExistingOnNewDoc, FALSE, TRUE);
02771     }
02772     return TRUE;
02773 }
02774 
02775 
02776 /********************************************************************************************
02777 
02778 >   BOOL Document::EPSStartImport(EPSFilter *pFilter)
02779 
02780     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02781     Created:    03/08/94
02782     Inputs:     pFilter - the EPS filter that is being used to import a file.
02783     Returns:    TRUE if the document was able to prepare for importing;
02784                 FALSE if not (e.g. out of memory)
02785     Purpose:    Inform the document that an EPS import is about to start.
02786     SeeAlso:    DocComponent
02787 
02788 ********************************************************************************************/
02789 
02790 BOOL Document::EPSStartImport(EPSFilter *pFilter)
02791 {
02792     return TRUE;
02793 }
02794 
02795 /********************************************************************************************
02796 
02797 >   void Document::EPSEndImport(EPSFilter *pFilter, BOOL Success)
02798 
02799     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02800     Created:    03/08/94
02801     Inputs:     pFilter - the EPS filter that is being used to import a file.
02802                 Success - TRUE => The import was successful;
02803                          FALSE => The import failed - abandon any changes.
02804     Purpose:    Inform the document that an EPS import has just finished.
02805     SeeAlso:    DocComponent
02806 
02807 ********************************************************************************************/
02808 
02809 void Document::EPSEndImport(EPSFilter *pFilter, BOOL Success)
02810 {
02811 }
02812 
02813 /********************************************************************************************
02814 
02815 >   BOOL Document::EPSStartExport(EPSFilter *pFilter)
02816 
02817     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02818     Created:    03/08/94
02819     Returns:    TRUE if the document was able to prepare for exporting;
02820                 FALSE if not (e.g. out of memory)
02821     Inputs:     pFilter - the EPS filter that is being used to export a file.
02822     Purpose:    Inform the document that an EPS export is about to start.
02823     SeeAlso:    DocComponent
02824 
02825 ********************************************************************************************/
02826 
02827 BOOL Document::EPSStartExport(EPSFilter *pFilter)
02828 {
02829     return TRUE;
02830 }
02831 
02832 /********************************************************************************************
02833 
02834 >   void Document::EPSEndExport(EPSFilter *pFilter)
02835 
02836     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02837     Created:    03/08/94
02838     Inputs:     pFilter - the EPS filter that is being used to import a file.
02839     Purpose:    Inform the document that an EPS export has just finished.
02840     SeeAlso:    DocComponent
02841 
02842 ********************************************************************************************/
02843 
02844 void Document::EPSEndExport(EPSFilter *pFilter)
02845 {
02846 }
02847 
02848 
02849 /********************************************************************************************
02850 
02851 >   BOOL Document::WriteEPSProlog ( EPSFilter *pFilter )
02852 
02853     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02854     Created:    01/08/94
02855     Inputs:     pFilter - the EPS filter that is being used to export a file.
02856     Returns:    TRUE if the Prolog for this document was written out successfully;
02857                 FALSE if not (e.g. out of disk space etc)
02858     Purpose:    Write out the EPS prolog for this document, using the EPS
02859                 filter object supplied. 
02860                 (The base class does nothing except return TRUE)
02861 
02862     SeeAlso:    Document::WriteEPSSetup; 
02863                 Document::WriteEPSComments;
02864                 Document::ProcessEPSComment; 
02865                 DocComponent; 
02866                 EPSFilter
02867 
02868 ********************************************************************************************/
02869 
02870 BOOL Document::WriteEPSProlog ( EPSFilter *pFilter )
02871 {
02872     // This function is only called from the AIEPS render region.
02873     EPSExportDC *pDC = pFilter->GetExportDC ();
02874     AIExportProlog ( pDC );
02875 
02876     return TRUE;
02877 }
02878 
02879 /********************************************************************************************
02880 
02881 >   BOOL Document::WriteEPSFonts(EPSFilter *pFilter)
02882 
02883     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02884     Created:    20/4/95
02885     Inputs:     pFilter - the EPS filter that is being used to export a file.
02886     Returns:    TRUE if the fonts for this document was written out successfully;
02887                 FALSE if not (e.g. out of disk space etc)
02888     Purpose:    Write out the EPS fonts for this document, using the EPS
02889                 filter object supplied.
02890                 (The base class does nothing except return TRUE)
02891 
02892     SeeAlso:    Document::WriteEPSProlog; 
02893                 Document::WriteEPSComments;
02894                 Document::ProcessEPSComment; 
02895                 DocComponent; 
02896                 EPSFilter
02897 
02898 ********************************************************************************************/
02899 
02900 BOOL Document::WriteEPSFonts(EPSFilter *pFilter)
02901 {
02902     if ( (pFilter->IS_KIND_OF(CamelotNativeEPSFilter)) ||
02903          (pFilter->IS_KIND_OF(AIEPSFilter))
02904        )
02905     {
02906         EPSExportDC *pDC = pFilter->GetExportDC();
02907 
02908         String_64 FontName;
02909         String_64 EFont;
02910         INT32 Style;
02911         FontList CurFontList;
02912         BOOL first=TRUE;
02913 
02914         if (!CurFontList.Build(this))
02915             return FALSE;
02916 
02917         FontListItem* pItem = CurFontList.GetFirstItem();
02918         while (pItem)
02919         {
02920             FontName = pItem->GetFontName();
02921             Style = pItem->GetFontStyle();
02922             // Graeme (31-3-00) - Map the encoded name onto the PS font name.
02923             FONTMANAGER->EncodeAndMapFontName(FontName, EFont, Style);
02924 
02925             if (first)
02926                 pDC->OutputToken(_T("%%DocumentFonts:"));
02927             else
02928                 pDC->OutputToken(_T("%%+"));    
02929 
02930             pDC->OutputToken((TCHAR*)EFont);
02931             pDC->OutputNewLine();
02932         
02933             first=FALSE;
02934             pItem = CurFontList.GetNextItem(pItem); 
02935         }
02936     }
02937     return TRUE;
02938 }
02939 
02940 /********************************************************************************************
02941 
02942 >   BOOL Document::WriteEPSResources(EPSFilter *pFilter)
02943 
02944     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02945     Created:    20/4/95
02946     Inputs:     pFilter - the EPS filter that is being used to export a file.
02947     Returns:    TRUE if the resources for this document was written out successfully;
02948                 FALSE if not (e.g. out of disk space etc)
02949     Purpose:    Write out the EPS resources for this document, using the EPS
02950                 filter object supplied.
02951                 (The base class does nothing except return TRUE)
02952 
02953     SeeAlso:    Document::WriteEPSProlog; 
02954                 Document::WriteEPSComments;
02955                 Document::ProcessEPSComment; 
02956                 DocComponent; 
02957                 EPSFilter
02958 
02959 ********************************************************************************************/
02960 
02961 BOOL Document::WriteEPSResources(EPSFilter *pFilter)
02962 {
02963     // Graeme (24/3/00) - Removed the IsKindOf ( AIEPSFilter ) calls because this is now
02964     // only called from the AI render region.
02965     EPSExportDC *pDC = pFilter->GetExportDC();
02966 
02967     pDC->OutputToken(_T("%%DocumentNeededResources:"));
02968 
02969     AIExportResources(pDC,TRUE);
02970 
02971     return TRUE;
02972 }
02973 
02974 
02975 /********************************************************************************************
02976 
02977 >   BOOL Document::WriteEPSSetup(EPSFilter *pFilter)
02978 
02979     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02980     Created:    01/08/94
02981     Inputs:     pFilter - the EPS filter that is being used to export a file.
02982     Returns:    TRUE if the Prolog for this document was written out successfully;
02983                 FALSE if not (e.g. out of disk space etc)
02984     Purpose:    Write out the EPS setup for this document, using the EPS
02985                 filter object supplied.
02986                 (The base class does nothing except return TRUE)
02987 
02988     SeeAlso:    Document::WriteEPSProlog; 
02989                 Document::WriteEPSComments;
02990                 Document::ProcessEPSComment; 
02991                 DocComponent; 
02992                 EPSFilter
02993 
02994 ********************************************************************************************/
02995 
02996 BOOL Document::WriteEPSSetup(EPSFilter *pFilter)
02997 {
02998     // only do something if the filter is an Illustrator one
02999     if (pFilter->IS_KIND_OF(AIEPSFilter))
03000     {
03001         EPSExportDC *pDC = pFilter->GetExportDC();
03002 
03003         ExportTextSetup(pFilter);
03004         AIExportExtras(pDC);
03005         AIExportCharEncoding(pDC);
03006         AIExportFontEncoding(pDC);
03007     }
03008     return TRUE;
03009 }
03010 
03011 
03012 
03013 /********************************************************************************************
03014 
03015 >   BOOL Document::WriteEPSComments(EPSFilter *pFilter)
03016 
03017     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03018     Created:    01/08/94
03019     Inputs:     pFilter - the EPS filter that is being used to export a file.
03020     Outputs:    -
03021     Returns:    TRUE if the EPS comments for this document were written out successfully;
03022                 FALSE if not (e.g. out of disk space etc)
03023     Purpose:    Write out any comments that need to be in the initial batch of EPS
03024                 comments (i.e. before the %%EndComments line), using the specified EPS
03025                 Filter object.
03026                 (The base class does nothing except return TRUE)
03027 
03028     SeeAlso:    Document::WriteEPSSetup; 
03029                 Document::WriteEPSProlog;
03030                 Document::ProcessEPSComment; 
03031                 DocComponent; 
03032                 EPSFIlter
03033 
03034 ********************************************************************************************/
03035 
03036 BOOL Document::WriteEPSComments(EPSFilter *pFilter)
03037 {
03038     // only do something if the filter is a Native one
03039     if (pFilter->IS_KIND_OF(CamelotNativeEPSFilter))
03040     {
03041         // NOTE: If you add something new then ensure you export it at the end of the list.
03042         // This is because older versions of the program (1.0b and before) will stop
03043         // processing at unknown comments and can cause immense problems.           
03044 
03045         // Output the colour table in ArtWorks format.
03046         EPSExportDC *pDC = pFilter->GetExportDC();
03047 
03048         // The Page List comment:
03049         pDC->OutputToken(_T("%%DocumentInfo"));
03050         pDC->OutputNewLine();
03051 
03052         // Export the Units. These should really be saved out as early as possible
03053         // as other things (such as the grid settings) can make use of them.
03054         ExportUnitInfo(pDC);
03055 
03056         // Export the page layout
03057         ExportPageInfo(pDC);
03058 
03059         // The Document Comment comment:
03060         ExportDocumentComment(pDC);
03061 
03062         // Now save out the Views ScaleFactor and Scroll Offsets
03063         ExportViewInfo(pDC);
03064 
03065         // Now save out the State vars of the view
03066         ExportStateInfo(pDC);
03067 
03068         // Save out the View Quality
03069         ExportQualityInfo(pDC);
03070 
03071         // Grid settings
03072         ExportGridInfo(pDC);
03073 
03074         // View flags (always on top, maximised etc)
03075         ExportFlagInfo(pDC);
03076 
03077         // Export the date info
03078         ExportDateInfo(pDC);
03079 
03080         // Export the undo info (document history)
03081         ExportUndoInfo(pDC);
03082 
03083         // These were all exported in version 1.00b of Studio 
03084         // These are new ones after the this release version.
03085         
03086         // Export the default units. Must be saved after the user units as we
03087         // might have defined a user unit as the default.
03088         ExportDefaultUnitsInfo(pDC);
03089         
03090         //Export the ruler and scroller visible states
03091         // removed by Chris 27/10/95
03092         // Ruler/Scroller state now set only from a global preference
03093         // see ImportRulerState();
03094         //ExportRulerState(pDC);
03095 
03096         // export the origin info - must be output after grid and page info as they both
03097         // reset the origin so must both be imported before the origin is finally set
03098         ExportOriginInfo(pDC);
03099     }
03100 
03101     return TRUE;
03102 }
03103 
03104 /********************************************************************************************
03105 
03106 >   BOOL Document::WriteEPSTrailer(EPSFilter *pFilter)
03107 
03108     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
03109     Created:    19/4/94
03110     Inputs:     pFilter - the EPS filter that is being used to export a file.
03111     Returns:    TRUE if the Trailer for this document was written out successfully;
03112                 FALSE if not (e.g. out of disk space etc)
03113     Purpose:    Write out the EPS trailer for this document, using the EPS
03114                 filter object supplied.
03115                 (The base class does nothing except return TRUE)
03116 
03117     SeeAlso:    Document::WriteEPSProlog; 
03118                 Document::WriteEPSComments;
03119                 Document::ProcessEPSComment; 
03120                 DocComponent; 
03121                 EPSFilter
03122 
03123 ********************************************************************************************/
03124 
03125 BOOL Document::WriteEPSTrailer(EPSFilter *pFilter)
03126 {
03127     // only do something if the filter is an Illustrator one
03128     if (pFilter->IS_KIND_OF(AIEPSFilter))
03129     {
03130         EPSExportDC *pDC = pFilter->GetExportDC();
03131         AIExportTrailer(pDC);
03132     }   
03133     ExportTextTrailer(pFilter);
03134 
03135     return TRUE;
03136 }
03137 
03138 
03139 
03140 /********************************************************************************************
03141 
03142 >   BOOL ReadNextNumber(INT32* Number, TCHAR* Comment, INT32* Offset)
03143 
03144     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
03145     Created:    15/2/95
03146     Inputs:     Comment - The string we are reading from
03147                 Offset - the offset into the string that we start from
03148     Outputs:    Number - holds the number in the string if the function returns TRUE
03149                 Offset - Holds the offset to just after the number in the string if the
03150                 function returns TRUE
03151     Returns:    TRUE if it worked, FALSE if it could not find a number
03152     Purpose:    Called by Document::ProcessEPSComment to help tidy up the code a little.
03153                 This actually just reads a number out of a string.
03154 
03155 ********************************************************************************************/
03156 
03157 BOOL ReadNextNumber(INT32* Number, TCHAR* Comment, INT32* Offset)
03158 {
03159     INT32& i = *Offset;
03160     BOOL IsNegative = FALSE;
03161 
03162     // Skip till we get to the first number
03163     while (!isdigit(Comment[i]) && (Comment[i] != 0) && (Comment[i]!='-'))
03164         i++;
03165 
03166     if (Comment[i]=='-')
03167     {
03168         // Negative number
03169         IsNegative = TRUE;
03170         i++;
03171     }
03172 
03173     // Read in the number
03174     if (isdigit(Comment[i]))
03175     {
03176         // get the Number
03177         *Number=0;
03178         camSscanf(&(Comment[i]),_T("%d"),Number);
03179 
03180         // Set the sign
03181         if (IsNegative)
03182             *Number = -(*Number);
03183 
03184         // Skip to the next number
03185         while (isdigit(Comment[i]))
03186             i++;
03187 
03188         // finished
03189         return TRUE;
03190     }
03191 
03192     // Failed
03193     return FALSE;
03194 }
03195 
03196 /********************************************************************************************
03197 
03198 >   BOOL ReadNextNumber(UINT32* Number, TCHAR* Comment, INT32* Offset)
03199 
03200     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
03201     Created:    07/07/95
03202     Inputs:     Comment - The string we are reading from
03203                 Offset - the offset into the string that we start from
03204     Outputs:    Number - holds the number in the string if the function returns TRUE
03205                 Offset - Holds the offset to just after the number in the string if the
03206                 function returns TRUE
03207     Returns:    TRUE if it worked, FALSE if it could not find a number
03208     Purpose:    Called by Document::ProcessEPSComment to help tidy up the code a little.
03209                 This actually just reads a number out of a string.
03210 
03211 ********************************************************************************************/
03212 
03213 BOOL ReadNextNumber(UINT32* Number, TCHAR* Comment, INT32* Offset)
03214 {
03215     INT32& i = *Offset;
03216 
03217     // Skip till we get to the first number
03218     while (!isdigit(Comment[i]) && (Comment[i] != 0))
03219         i++;
03220 
03221     // Read in the number
03222     if (isdigit(Comment[i]))
03223     {
03224         // get the Number
03225         *Number=0;
03226         camSscanf(&(Comment[i]),_T("%ud"),Number);
03227 
03228         // Skip to the next number
03229         while (isdigit(Comment[i]))
03230             i++;
03231 
03232         // finished
03233         return TRUE;
03234     }
03235 
03236     // Failed
03237     return FALSE;
03238 }
03239 
03240 
03241 
03242 /********************************************************************************************
03243 
03244 >   BOOL ReadNextNumber(double* Number, TCHAR* Comment, INT32* Offset)
03245 
03246     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
03247     Created:    15/2/95
03248     Inputs:     Comment - The string we are reading from
03249                 Offset - the offset into the string that we start from
03250     Outputs:    Number - holds the number in the string if the function returns TRUE
03251                 Offset - Holds the offset to just after the number in the string if the
03252                 function returns TRUE
03253     Returns:    TRUE if it worked, FALSE if it could not find a number
03254     Purpose:    Called by Document::ProcessEPSComment to help tidy up the code a little.
03255                 This actually just reads a number out of a string.
03256 
03257 ********************************************************************************************/
03258 
03259 BOOL ReadNextNumber(double* Number, TCHAR* Comment, INT32* Offset)
03260 {
03261     INT32& i = *Offset;
03262 
03263     // Skip till we get to the first number
03264     while (camIsspace(Comment[i]) && (Comment[i]!=0))
03265         i++;
03266 
03267     // Read in the number
03268     if (!camIsspace(Comment[i]))
03269     {
03270         // get the Number
03271         *Number=0.0;
03272         camSscanf(&(Comment[i]),_T("%lf"),Number);
03273 
03274         // Skip to the next number
03275         while (!camIsspace(Comment[i]))
03276             i++;
03277 
03278         // finished
03279         return TRUE;
03280     }
03281 
03282     // Failed
03283     return FALSE;
03284 }
03285 
03286 
03287 /********************************************************************************************
03288 
03289 >   BOOL GetNextString(StringBase* pString, INT32 MaxLen, TCHAR* Comment, INT32* Offset))
03290 
03291     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
03292     Created:    28/3/95
03293     Inputs:     MaxLen - the max length of the output string
03294                 Comment - The string we are reading from
03295                 Offset - the offset into the string that we start from
03296     Outputs:    pString - Holds the string
03297                 Offset - Holds the offset to just after the number in the string if the
03298                 function returns TRUE
03299     Returns:    TRUE if it worked, FALSE if it could not find a string
03300     Purpose:    Called by Document::ProcessEPSComment to help tidy up the code a little.
03301                 This actually just reads a string out of a string.
03302 
03303 ********************************************************************************************/
03304 
03305 BOOL ReadNextString(StringBase* pString, INT32 MaxLen, TCHAR* Comment, INT32* Offset)
03306 {
03307     INT32& i = *Offset;
03308     TCHAR TempStr[256];
03309 
03310     // Skip till we get to the start of the string (Which is the '(' char)
03311     while ((Comment[i]!='(') && (Comment[i]!=0))
03312         i++;
03313 
03314     // ok, read the string in
03315     if (Comment[i]=='(')
03316     {
03317         // Eat the open bracket
03318         i++;
03319 
03320         // Start to copy the string
03321         TCHAR Ch;
03322         INT32 Dst = 0;
03323         do
03324         {
03325             // Get this char and store it
03326             Ch = Comment[i];
03327             TempStr[Dst] = Ch;
03328             Dst++;
03329             i++;
03330             
03331             if (Ch=='\\')
03332             {
03333                 // This is the escape char, so store the char that follows it,
03334                 // but do not change the value of Ch or it may think that the comment is ending
03335                 TempStr[Dst-1] = Comment[i];
03336                 i++;
03337             } 
03338         } while (((Ch!=0) && (Ch!=')')) || (Dst==MaxLen-1));
03339 
03340         // Terminate the string
03341         TempStr[Dst-1] = 0;
03342 
03343         // Copy the string into the StringBase
03344         pString->Empty();
03345         *pString += (TCHAR*)TempStr;
03346         return TRUE;
03347     }
03348 
03349     // if we get here, we did not extract the string
03350     return FALSE;
03351 }
03352 
03353 
03354 
03355 /********************************************************************************************
03356 
03357 >   ProcessEPSResult Document::ProcessEPSComment(EPSFilter *pFilter, 
03358                                                  const TCHAR *pComment)
03359 
03360     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03361     Created:    01/08/94
03362     Inputs:     pFilter - the EPS filter that is being used to import a file.
03363                 pComment - read only buffer containing  - This EPS comment is not recognised by the document.
03364                 EPSCommentSy the whole EPS comment to parse.
03365     Returns:    EPSCommentUnknown ntaxError - This EPS comment was recognised by this document
03366                                         but it contained an error.
03367                 EPSCommentSystemError - This EPS comment was recognised by this document
03368                                         but a system error occured that was not caused
03369                                         directly by the comment, e.g. out of memory.
03370                 EPSCommentOK          - This EPS comment was recognised as a legal comment by 
03371                                         this document, and was processed successfully.
03372     Purpose:    Process an EPS comment found in the file, if it 'belongs' to the
03373                 document.  If it does not, then the document should return EPSCommentUnknown, 
03374                 and the comment will be passed on to the document components.
03375                 If the function returns EPSCommentOK, and the next line in the file starts 
03376                 with "%%+", i.e. an EPS/PostScript continuation comment, then this will be
03377                 passed to this document immediately, without trying any of the document 
03378                 components first.  This allows items such a colour lists
03379                 to be imported easily, as they are usually specified on multiple lines in
03380                 the file, using "%%+" comments.
03381                 (The base class does nothing - it returns EPSCommentUnknown)
03382 
03383     SeeAlso:    Document::EndOfEPSComment; 
03384                 Document::WriteEPSProlog; 
03385                 Document::WriteEPSSetup; 
03386                 Document::WriteEPSComments; 
03387                 DocComponent; 
03388                 ProcessEPSResult;
03389                 EPSFIlter
03390 
03391 ********************************************************************************************/
03392 
03393 ProcessEPSResult Document::ProcessEPSComment(EPSFilter *pFilter, 
03394                                              const TCHAR *pComment)
03395 {
03396     // OK, to begin with, set the current doc and view to this doc and it's first view.
03397     SetCurrent();
03398     if (GetFirstDocView() != NULL){
03399         GetFirstDocView()->SetCurrent();
03400     }
03401     if ((pFilter->IS_KIND_OF(CamelotNativeEPSFilter)) && !IsImporting())
03402     {
03403         // Take a copy of the comment
03404         TCHAR Comment[256];
03405         camStrcpy(Comment, pComment);
03406 
03407         // Look for Document info
03408         if (camStrncmp(pComment, _T("%%NativePageList"), 16) == 0)
03409         {
03410             // Found the page description table
03411             return EPSCommentOK;
03412         }
03413         else if (camStrncmp(pComment, _T("%%DocumentInfo"), 14) == 0)
03414         {
03415             // Found the page description table
03416             // Set the Documents Comment to nothing
03417             String_256 Empty("");
03418             SetComment(&Empty);
03419 
03420             return EPSCommentOK;
03421         }
03422         else if (camStrncmp(pComment, _T("%%+"), 3) == 0)
03423         {
03424             // Assume we do not know about this comment until we can prove that we do.
03425             //
03426             // NOTE: If you add something new then ensure you export it at the end of the list.
03427             // This is because older versions of the program (1.0b and before) will stop
03428             // processing at unknown comments and can cause immense problems.           
03429 
03430             ProcessEPSResult Result = EPSCommentUnknown;
03431             TCHAR InfoType = pComment[3];
03432             switch (InfoType)
03433             {
03434                 // The Document Info Comment (as seen in the Document Info dialog in the File menu)
03435                 case 'c' :
03436                 {
03437                     Result = ImportDocumentComment(Comment);
03438                     break;
03439                 }
03440 
03441                 // Read in the Creation and Last Saved dates
03442                 case 'd' :
03443                 {
03444                     Result = ImportDateInfo(Comment);
03445                     break;
03446                 }
03447 
03448                 // Read in the View Flags
03449                 case 'f':
03450                 {
03451                     break;
03452                 }
03453 
03454                 // Read in the Grid Settings
03455                 case 'g':
03456                 {
03457                     Result = ImportGridInfo(Comment);
03458                     break;
03459                 }
03460 
03461                 // Read in the Grid Settings
03462                 case 'o':
03463                 {
03464                     Result = ImportOriginInfo(Comment);
03465                     break;
03466                 }
03467 
03468                 // Document history which is the specified undo size
03469                 case 'h':
03470                 {
03471                     Result = ImportUndoInfo(Comment);
03472                     break;
03473                 }
03474 
03475                 // Page Description
03476                 case 'p' :
03477                 {
03478                     // load in the new page layout
03479                     Result = ImportPageInfo(Comment);
03480 
03481                     // adjust the page origin to match the new page.
03482                     pFilter->ResetImportOrigin();
03483                     break;
03484                 }
03485 
03486                 // Read in the View Quality Settings
03487                 case 'q':
03488                 {
03489                     // Load in the new view quality
03490                     Result = ImportQualityInfo(Comment);
03491 
03492 #if !defined(EXCLUDE_FROM_RALPH)
03493                     // update all the view quality sliders
03494                     QualitySliderDescriptor::Update();
03495 #endif
03496                     break;
03497                 }
03498 
03499                 // The DocView State Info (Grid on/off, Snapping on/off etc)
03500                 case 's' :
03501                 {
03502                     Result = ImportStateInfo(Comment);
03503                     break;
03504                 }
03505 
03506                 // The Unit settings
03507                 case 'u' :
03508                 {
03509                     Result = ImportUnitInfo(Comment);
03510                     break;
03511                 }
03512 
03513                 // The default display unit settings
03514                 case 'U' :
03515                 {
03516                     Result = ImportDefaultUnitsInfo(Comment);
03517                     break;
03518                 }
03519                 
03520                 // The Ruler and Scroller visible state
03521                 case 'r' :
03522                 {
03523                     //Result = ImportRulerState(Comment);
03524                     // removed by Chris 27/10/95
03525                     // just ignore this token now
03526                     // Ruler/Scroller state now set only from a global preference
03527                     Result = EPSCommentOK;
03528                     break;
03529                 }
03530             
03531                 // The View Setting (Scale Factor, Scroll offsets etc)
03532                 case 'v' :
03533                 {
03534                     Result = ImportViewInfo(Comment);
03535                     break;
03536                 }
03537 
03538                 default :
03539                 {
03540                     Result = EPSCommentUnknown;
03541                     break;
03542                 }
03543             }
03544 
03545             // Result will hold the result of any processing of this continuation comment
03546             return Result;
03547         }
03548     }
03549     else if (pFilter->IS_KIND_OF(CamelotNativeEPSFilter))
03550     {
03551         // Importing a native file - we need to get the page origin so that the filter
03552         // can position the objects correctly.
03553 
03554         // Take a copy of the comment
03555         TCHAR Comment[256];
03556         camStrcpy(Comment, pComment);
03557 
03558         // Look for Document info
03559         if (camStrncmp(pComment, _T("%%NativePageList"), 16) == 0)
03560         {
03561             // Found the page description table
03562             return EPSCommentOK;
03563         }
03564         else if (camStrncmp(pComment, _T("%%DocumentInfo"), 14) == 0)
03565         {
03566             // Found the page description table
03567             // Set the Documents Comment to nothing
03568             String_256 Empty("");
03569             SetComment(&Empty);
03570 
03571             return EPSCommentOK;
03572         }
03573         else if (camStrncmp(pComment, _T("%%+"), 3) == 0)
03574         {
03575             // Default to recognising this comment - all we care about is extracting the page origin.
03576             ProcessEPSResult Result = EPSCommentOK;
03577             TCHAR InfoType = pComment[3];
03578             if (InfoType == 'p')
03579             {
03580                 // Set the default version
03581                 INT32 Version = -1;
03582 
03583                 // Where in the comment to start looking from (skip over %%+p)
03584                 INT32 i = 4;
03585 
03586                 // Read in the version number
03587                 if (!ReadNextNumber(&Version, Comment, &i))
03588                     return EPSCommentSyntaxError;
03589 
03590                 // Descide what to do based on the version number
03591                 switch (Version)
03592                 {
03593                     case 0 :
03594                     {
03595                         // Version 0 expects to find the following infomation
03596                         // Width, Height, Margin, Bleed, Dps, ShowDropShadow
03597                         // Get something to put all the numbers into
03598                         MILLIPOINT Dummy, Margin;
03599 
03600                         // Read in the Width of the page
03601                         if (!ReadNextNumber(&Dummy, Comment, &i))
03602                             return EPSCommentSyntaxError;
03603 
03604                         // Read in the Height of the page
03605                         if (!ReadNextNumber(&Dummy, Comment, &i))
03606                             return EPSCommentSyntaxError;
03607 
03608                         // Read in the Margin of the page
03609                         if (!ReadNextNumber(&Margin, Comment, &i))
03610                             return EPSCommentSyntaxError;
03611 
03612                         // Ok, we've got the margin, so tell the EPS filter about it.
03613                         DocCoord NewOrigin(Margin, Margin);
03614                         pFilter->ResetImportOrigin(NewOrigin);
03615                     }                 
03616 
03617                     // Unknown version
03618                     default:
03619                     {
03620                         // Here we have got a version number we do not know how to process
03621                         // so just ignore this comment happy. we will say that the comment
03622                         // was OK as an error is technically wrong in this case
03623                     }
03624                 }
03625             }
03626 
03627             // Result will hold the result of any processing of this continuation comment
03628             return Result;
03629         }
03630     }
03631 
03632     return EPSCommentUnknown;
03633 }
03634 
03635 
03636 /********************************************************************************************
03637 
03638 >   void Document::EndOfEPSComment(EPSFilter *pFilter)
03639 
03640     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03641     Created:    02/08/94
03642     Inputs:     pFilter - the EPS filter that is being used to import a file.
03643     Purpose:    Informs the document that the comment it has been decoding has
03644                 now finished, and it should take whatever action required to act on
03645                 the comment.
03646                 This call is made even for single-line comments, because by the nature of
03647                 DSC comments, it is not known until the next comment starts or a
03648                 non-comment line is encountered that the comment is over and is not
03649                 multi-line.
03650 
03651     SeeAlso:    Document::ProcessEPSComment; 
03652                 Document::WriteEPSProlog; 
03653                 Document::WriteEPSSetup; 
03654                 Document::WriteEPSComments;
03655                 DocComponent; EPSFilter
03656 
03657 ********************************************************************************************/
03658 
03659 void Document::EndOfEPSComment(EPSFilter *pFilter)
03660 {
03661 }
03662 
03663 /********************************************************************************************
03664 
03665 >   INT32 Document::GetSizeOfExport(Filter *pFilter)
03666 
03667     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03668     Created:    27/01/95
03669     Inputs:     pFilter - the export filter that will be used.
03670     Returns:    An approximation of the size of data that will be exported by this
03671                 document, in terms of nodes. (see NodeRenderable::GetSizeOfExport).
03672     Purpose:    Find out how many nodes will be exported when this document is exported.
03673                 The node can use the filter to find out how it will be exported.
03674                 NB. This is virtual - the default implementation just returns 1 - only
03675                     override if this is not accurate.
03676     SeeAlso:    Node::NeedsToExport; Node::ExportRender; NodeRenderable::GetSizeOfExport
03677 
03678 ********************************************************************************************/
03679 INT32 Document::GetSizeOfExport( Filter * )
03680 {
03681     // Default value is one node...
03682     return 1;
03683 }
03684 
03685 /********************************************************************************************
03686 >   DocView* Document::GetTopmostView() const
03687 
03688     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03689     Created:    5/10/96
03690     Returns:    A pointer to the DocView of this Document that is top-most in the Z-order
03691                 window list.  It's the view onto this document that was last worked in
03692                 by the user.  Returns NULL if this document has no visible views.
03693     Purpose:    Finds out which of this Document's DocViews is 'selected'.
03694     SeeAlso:    CCamDoc::SetPageSize
03695 ********************************************************************************************/
03696 
03697 DocView* Document::GetTopmostView() const
03698 {
03699     // Search through all the views onto this document.
03700     DocView* pvTop = 0;
03701     INT32 zTop = -1;
03702     for (DocView* pv = GetFirstDocView(); pv; pv = GetNextDocView(pv))
03703     {
03704         // Is this view above our current highest?
03705         if (pv->pVState && pv->pVState->zPos > zTop)
03706         {
03707             // It is, so remember it as the new highest.
03708             zTop = pv->pVState->zPos;
03709             pvTop = pv;
03710         }
03711     }
03712 
03713     // Return the highest, if any.
03714     return pvTop;
03715 }
03716 
03717 
03718 
03719 /********************************************************************************************
03720 
03721 >   MILLIPOINT Document::GetBleedOffset()   const
03722 
03723     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03724     Created:    14/12/94
03725     Inputs:     -
03726     Outputs:    -
03727     Returns:    The current size in millipoints of this Document's bleed area.
03728     Purpose:    For getting the Document's bleed area size. 
03729     Errors:     -
03730     SeeAlso:    SetBleedOffset();
03731 
03732 ********************************************************************************************/
03733 
03734 MILLIPOINT Document::GetBleedOffset() const
03735 {
03736     return BleedOffset;
03737 } 
03738 
03739 /********************************************************************************************
03740 
03741 >   BOOL Document::SetBleedOffset(MILLIPOINT Bleed)
03742 
03743     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03744     Created:    14/12/94
03745     Inputs:     -
03746     Outputs:    -
03747     Returns:    The current size in millipoints of this document's bleed area.
03748     Purpose:    For setting a new value for the Document's bleed area size. 
03749     Errors:     -
03750     SeeAlso:    Document::GetBleedOffset();
03751 
03752 ********************************************************************************************/
03753 
03754 BOOL Document::SetBleedOffset(MILLIPOINT Bleed)
03755 {
03756     BleedOffset = Bleed;    // set up new bleed value
03757     
03758     return TRUE;
03759 } 
03760 
03761 
03762 
03763 
03764 /********************************************************************************************
03765 
03766 >   BOOL Document::ExportPageInfo(EPSExportDC *pDC)
03767 
03768     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
03769     Created:    21/3/95
03770     Inputs:     pDC - The DC to render to
03771     Returns:    TRUE
03772     Purpose:    Exports a Document Info continuation comment that describes the page layout.
03773                 It takes the following form :-
03774                 %%+p VersionNum
03775                 if VersionNum is zero then the following will be on the rest of the line
03776                 Width Height Margin Bleed DPS(1 for yes, 0 for no) ShowDropShadow(1 for yes, 0 for no)
03777 
03778 ********************************************************************************************/
03779 
03780 BOOL Document::ExportPageInfo(EPSExportDC *pDC)
03781 {
03782     // Find the first spread to get the page info from
03783     // Don't use the selected spread as it breaks save all
03784     // do don't do Spread* pSpread = GetSelectedSpread();
03785     Node *pANode = GetFirstNode()->FindNext()->FindFirstChild();
03786     while ((pANode != NULL) && (!pANode->IsKindOf(CC_RUNTIME_CLASS(Chapter))))
03787         pANode = pANode->FindNext();
03788         
03789     ERROR2IF(!pANode->IsKindOf(CC_RUNTIME_CLASS(Chapter)),
03790         FALSE, "Document::Export(something)(): Could not find Chapter");
03791 
03792     Chapter *pChapter = (Chapter *) pANode;
03793     
03794     // pSpread is a child of pChapter
03795     Spread *pSpread = (Spread *) pChapter->FindFirstChild();
03796     ERROR2IF(!pSpread->IsKindOf(CC_RUNTIME_CLASS(Spread)),
03797         FALSE, "Document::Export(something)(): Could not find Spread");
03798 
03799     // get something to put all the page info into
03800     TCHAR Buffer[256];
03801     MILLIPOINT Width, Height;
03802     MILLIPOINT Margin, Bleed;
03803     BOOL Dps, ShowDropShadow;
03804     INT32 Version = 0;
03805 
03806     // and go and get all the page info
03807     BOOL Worked = pSpread->GetPageSize(&Width, &Height, &Margin, &Bleed, &Dps, &ShowDropShadow);
03808 
03809     // If it worked, we had better try and output some info
03810     if (Worked)
03811     {
03812         // Build a string with all the data in it
03813         camSprintf(Buffer, _T("%d %d %d %d %d %d %d"), Version, (INT32)Width, (INT32)Height, (INT32)Margin, (INT32)Bleed, Dps, ShowDropShadow);
03814 
03815         // Output the line to the file
03816         pDC->OutputToken(_T("%%+p"));
03817         pDC->OutputToken(Buffer);
03818         pDC->OutputNewLine();
03819     }
03820 
03821     return TRUE;
03822 }
03823 
03824 
03825 /********************************************************************************************
03826 
03827 >   BOOL Document::ExportDocumentComment(EPSExportDC *pDC)
03828 
03829     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
03830     Created:    21/3/95
03831     Inputs:     pDC - The DC to render to
03832     Returns:    TRUE
03833     Purpose:    Will export as many Document Info continuation comments as are needed to
03834                 save out the whole comment. Each continuation comment takes the form as follows :-
03835                 %%+c CommentHere
03836                 Each line will not have more that about 100 chars of comment on it (they will
03837                 all be simple joined together when importing). If there is a new line char
03838                 in the comment the continuation comment will end at that point, but the last
03839                 char of the continuation comment will be ^.
03840 
03841 ********************************************************************************************/
03842 
03843 BOOL Document::ExportDocumentComment(EPSExportDC *pDC)
03844 {
03845 #if !defined(EXCLUDE_FROM_RALPH)
03846     // Save this out in 200 Char lines, using many continuation comments if needed
03847     String_256 Comment = GetComment();
03848     INT32 StrLength = Comment.Length();
03849     
03850     // Go though the string splitting it up as needed
03851     TCHAR OneLine[256];
03852     TCHAR Buffer[256];
03853     camStrcpy(Buffer, (TCHAR*)Comment);
03854 
03855     // vars to keep track of where we are
03856     INT32 Src = 0;
03857     INT32 Dest = 0;
03858     
03859     // Loop through the string they have entered and split it up into lines of text
03860     while (Src<StrLength)
03861     {
03862         // should we write this out (ie have we hit a new line)
03863         if ((Buffer[Src]=='\n') || (Buffer[Src]=='\r') || (Dest>100))
03864         {
03865             // deal with it being the CR.
03866             if ((Buffer[Src]=='\n') || (Buffer[Src]=='\r'))
03867             {
03868                 OneLine[Dest] = '^';
03869                 Dest++;
03870             }
03871 
03872             // Skim till we find something that is not a CR
03873             while ((Buffer[Src]=='\n') || (Buffer[Src]=='\r'))
03874                 Src++;
03875 
03876             // Output the line
03877             if (Dest>0)
03878             {
03879                 OneLine[Dest] = 0;
03880                 pDC->OutputToken(_T("%%+c"));
03881                 pDC->OutputToken(OneLine);
03882                 pDC->OutputNewLine();
03883                 Dest = 0;
03884             }
03885         }
03886 
03887         // Lets have this char
03888         OneLine[Dest] = Buffer[Src];
03889         Dest++;
03890         Src++;
03891     }
03892 
03893     // Output the last line
03894     if (Dest>0)
03895     {
03896         OneLine[Dest] = 0;
03897         pDC->OutputToken(_T("%%+c"));
03898         pDC->OutputToken(OneLine);
03899         pDC->OutputNewLine();
03900         Dest = 0;
03901     }
03902 #endif
03903     return TRUE;
03904 }
03905 
03906 /********************************************************************************************
03907 
03908 >   BOOL Document::ExportRulerState(EPSExportDC *pDC)
03909 
03910     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
03911     Created:    21/3/95
03912     Inputs:     pDC - The DC to render to
03913     Returns:    TRUE
03914     Purpose:    Exports the View Settings continuation comment (part of the Document Info
03915                 comment). It has the following form
03916                 %%+r VersionNum(0) ScrollersVisible RulersVisible
03917                 
03918 
03919 ********************************************************************************************/
03920 
03921 BOOL Document::ExportRulerState(EPSExportDC *pDC)
03922 {
03923     // A buffer
03924 
03925     // Find the view to get the info from
03926     // don't do DocView* pView = DocView::GetSelected(); as it breaks save all
03927     DocView* pView = GetFirstDocView(); 
03928     if (this==Document::GetSelected()) pView = DocView::GetSelected();
03929 
03930     if (pView!=NULL)
03931     {
03932         INT32 Version =0;
03933         // Export it
03934         pDC->OutputToken(_T("%%+r"));
03935         // buffer the version number,ruler and scroller state
03936         TCHAR Buffer[256];
03937         camSprintf(Buffer, _T("%d %ld %ld"), Version, pView->AreScrollersVisible(),pView->AreRulersVisible());
03938         pDC->OutputToken(Buffer);
03939         pDC->OutputNewLine();
03940     }
03941 
03942     return TRUE;
03943 }
03944 
03945 
03946 
03947 /********************************************************************************************
03948 
03949 >   BOOL Document::ExportViewInfo(EPSExportDC *pDC)
03950 
03951     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
03952     Created:    21/3/95
03953     Inputs:     pDC - The DC to render to
03954     Returns:    TRUE
03955     Purpose:    Exports the View Settings continuation comment (part of the Document Info
03956                 comment). It has the following form
03957                 %%+v VersionNum(1) XScrollOffset YScrollOffset ScaleFactor Active
03958                 DrawingScale RealScale.
03959                 ScaleFactor is represented 1000 times the actual scale factor. eg when the 
03960                 document is viewed at 100% the scale factor is 1.0. This is export as 1000.
03961                 200% would be 2000 etc. Active is a flag to say if the Document Scale Factor
03962                 is active or not. It is followed by the Drawing and Real scales in the document
03963 
03964 ********************************************************************************************/
03965 
03966 BOOL Document::ExportViewInfo(EPSExportDC *pDC)
03967 {
03968     // A buffer
03969     TCHAR Buffer[256];
03970 
03971     // Find the view to get the info from
03972     // don't do DocView* pView = DocView::GetSelected(); as it breaks save all
03973     DocView* pView = GetFirstDocView(); 
03974     if (this==Document::GetSelected()) pView = DocView::GetSelected();
03975 
03976     if (pView!=NULL)
03977     {
03978         // Find out the Scroll Offsets and the Scale Factor
03979         WorkCoord ScrollOffsets = pView->GetScrollOffsets();
03980         INT32 XOffset = ScrollOffsets.x;
03981         INT32 YOffset = ScrollOffsets.y;
03982         double ScaleFactor = pView->GetViewScale().MakeDouble();
03983         INT32 Version = 1;
03984 
03985         // Find the spread that we are saving
03986         // Find the first spread to get the page info from
03987         // Don't use the selected spread as it breaks save all
03988         // do don't do Spread* pSpread = GetSelectedSpread();
03989         Node *pANode = GetFirstNode()->FindNext()->FindFirstChild();
03990         while ((pANode != NULL) && (!pANode->IsKindOf(CC_RUNTIME_CLASS(Chapter))))
03991             pANode = pANode->FindNext();
03992         
03993         ERROR2IF(!pANode->IsKindOf(CC_RUNTIME_CLASS(Chapter)),
03994             FALSE, "Document::Export(something)(): Could not find Chapter");
03995 
03996         Chapter *pChapter = (Chapter *) pANode;
03997     
03998         // pSpread is a child of pChapter
03999         Spread *pSpread = (Spread *) pChapter->FindFirstChild();
04000         ERROR2IF(!pSpread->IsKindOf(CC_RUNTIME_CLASS(Spread)),
04001             FALSE, "Document::Export(something)(): Could not find Spread");
04002 
04003         if (pSpread != NULL)
04004         {
04005             DimScale* pDimScale = pSpread->GetPtrDimScale();
04006             if (pDimScale != NULL)
04007             {
04008                 // Find out if it is active
04009                 BOOL Active = pDimScale->IsActive();
04010 
04011                 // Find out about the scale factor strings
04012                 String_32 DrawingScale = pDimScale->GetDrawingScaleStr();
04013                 String_32 RealScale = pDimScale->GetRealScaleStr();
04014 
04015                 // Build the comment for the scroll offsets etc
04016                 camSprintf(Buffer, _T("%d %d %d %d %d"), Version, XOffset, YOffset, (INT32)(ScaleFactor*1000), Active);
04017 
04018                 // Export it
04019                 pDC->OutputToken(_T("%%+v"));
04020                 pDC->OutputToken(Buffer);
04021                 pDC->OutputString(DrawingScale);
04022                 pDC->OutputString(RealScale);
04023                 pDC->OutputNewLine();
04024             }
04025         }
04026     }
04027 
04028     return TRUE;
04029 }
04030 
04031 
04032 /********************************************************************************************
04033 
04034 >   BOOL Document::ExportStateInfo(EPSExportDC *pDC)
04035 
04036     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
04037     Created:    21/3/95
04038     Inputs:     pDC - The DC to render to
04039     Returns:    TRUE
04040     Purpose:    Part of the Document Info comment. This is document state information 
04041                 It takes the following form :-
04042                 %%+s VersionNum 
04043                 Version 0 comment lines follows this with 
04044                 ShowGrid SnapToGrid SnapToMagObjects SnapToObjects ForeBackMode (and zero
04045                 as a dummy value, see comments in the function).
04046                 Each of the values is a flag and will hold either 0 for FALSE or 1 for TRUE
04047 
04048 ********************************************************************************************/
04049 
04050 BOOL Document::ExportStateInfo(EPSExportDC *pDC)
04051 {
04052     // A buffer
04053     TCHAR Buffer[512];
04054 
04055     // Find the view to get the info from
04056     // don't do DocView* pView = DocView::GetSelected(); as it breaks save all
04057     DocView* pView = GetFirstDocView(); 
04058     if (this==Document::GetSelected()) pView = DocView::GetSelected();
04059 
04060     if (pView!=NULL)
04061     {
04062         INT32 Version = 1;
04063 
04064         // Find all the State flags for version 0
04065         BOOL ShowGrid           = pView->GetShowGridState();
04066         BOOL SnapToGrid         = pView->GetSnapToGridState();
04067         BOOL SnapToMagObjects   = pView->GetSnapToMagObjectsState();
04068         BOOL SnapToObjects      = pView->GetSnapToObjectsState();
04069         BOOL ForeBackMode       = pView->GetForeBackMode();
04070 
04071         // Find all the State flags for version 1
04072         BOOL ShowGuides         = pView->GetShowGuidesState();
04073         BOOL SnapToGuides       = pView->GetSnapToGuidesState();
04074         BOOL Multilayer         = IsMultilayer();
04075         BOOL AllLayersVisible   = IsAllVisible();
04076 
04077         // Init the buffer with the version numbet
04078         camSprintf(Buffer,_T("%d "),Version);
04079 
04080         // Build the comment string
04081         switch (Version)
04082         {
04083             case 1:
04084                 // Write verison 1 flags (*Note* the space after the last '%d' - this is important)
04085                 camSprintf( Buffer + camStrlen( Buffer ), _T("%d %d %d %d "), ShowGuides, SnapToGuides, 
04086                     Multilayer, AllLayersVisible);
04087                 // Fall through for version 0 flags
04088 
04089             case 0:
04090                 // Note: There was a bug here - the format string had six %ds but
04091                 // only five parameters. There were only supposed to be five parameters
04092                 // so the sixth %d was a typo, not noticed by the compiler (or anyone
04093                 // who looked at the output and should have wondered what that random
04094                 // number was at the end of the line.
04095 
04096                 // In order to reduce the possibility of bugs, I'm instituting a dummy
04097                 // sixth parameter, and altering the code that reads it in.
04098 
04099                 camSprintf( Buffer + camStrlen( Buffer ), _T("%d %d %d %d %d %d"), ShowGrid, SnapToGrid, 
04100                     SnapToMagObjects, SnapToObjects, ForeBackMode, 0);
04101                 break;  // Stop here. Version 0 was the first
04102         
04103             default:
04104                 ERROR3_PF(("Dont know how to write this version for the state flags %d",Version));
04105                 break;
04106         }
04107 
04108         // Export it
04109         pDC->OutputToken(_T("%%+s"));
04110         pDC->OutputToken(Buffer);
04111         pDC->OutputNewLine();
04112     }
04113 
04114     return TRUE;
04115 }
04116 
04117 
04118 /********************************************************************************************
04119 
04120 >   BOOL Document::ExportQualityInfo(EPSExportDC *pDC)
04121 
04122     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
04123     Created:    21/3/95
04124     Inputs:     pDC - The DC to render to
04125     Returns:    TRUE
04126     Purpose:    Part of the Document Info comment. It takes the following form :-
04127                 %%+q VersionNum(0) ViewQuality.
04128                 ViewQuality is the numerical value of the view Quality
04129     SeeAlso:    Quality
04130 
04131 ********************************************************************************************/
04132 
04133 BOOL Document::ExportQualityInfo(EPSExportDC *pDC)
04134 {
04135     // A buffer
04136     TCHAR Buffer[256];
04137 
04138     // Find the view to get the info from
04139     // don't do DocView* pView = DocView::GetSelected(); as it breaks save all
04140     DocView* pView = GetFirstDocView(); 
04141     if (this==Document::GetSelected()) pView = DocView::GetSelected();
04142 
04143     if (pView!=NULL)
04144     {
04145         // Find out what the View Quality is...
04146         INT32 ViewQuality = pView->RenderQuality.GetQuality();
04147         INT32 Version = 0;
04148 
04149         // Build the Comment
04150         camSprintf(Buffer, _T("%d %d"), Version, ViewQuality);
04151 
04152         // Export it
04153         pDC->OutputToken(_T("%%+q"));
04154         pDC->OutputToken(Buffer);
04155         pDC->OutputNewLine();
04156     }
04157 
04158     return TRUE;
04159 }
04160 
04161 
04162 /********************************************************************************************
04163 
04164 >   BOOL Document::ExportGridInfo(EPSExportDC *pDC)
04165 
04166     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
04167     Created:    21/3/95
04168     Inputs:     pDC - The DC to render to
04169     Returns:    -
04170     Purpose:    
04171 
04172 ********************************************************************************************/
04173 
04174 BOOL Document::ExportGridInfo(EPSExportDC *pDC)
04175 {
04176     // A buffer
04177     TCHAR Buffer[256];
04178 
04179     // Start off from the default spread
04180     // Find the first spread to get the page info from
04181     // Don't use the selected spread as it breaks save all
04182     // do don't do Spread* pSpread = GetSelectedSpread();
04183     Node *pANode = GetFirstNode()->FindNext()->FindFirstChild();
04184     while ((pANode != NULL) && (!pANode->IsKindOf(CC_RUNTIME_CLASS(Chapter))))
04185         pANode = pANode->FindNext();
04186         
04187     ERROR2IF(!pANode->IsKindOf(CC_RUNTIME_CLASS(Chapter)),
04188         FALSE, "Document::Export(something)(): Could not find Chapter");
04189 
04190     Chapter *pChapter = (Chapter *) pANode;
04191     
04192     // pSpread is a child of pChapter
04193     Spread *pSpread = (Spread *) pChapter->FindFirstChild();
04194     ERROR2IF(!pSpread->IsKindOf(CC_RUNTIME_CLASS(Spread)),
04195         FALSE, "Document::Export(something)(): Could not find Spread");
04196 
04197     if (pSpread!=NULL)
04198     {
04199         // Find the first child of the spread
04200         Node* pNode = pSpread->FindFirstChild();
04201         while (pNode!=NULL)
04202         {
04203             // For each of the child nodes of the spread, we will check to see if it is a Node Grid
04204             if (pNode->IS_KIND_OF(NodeGrid))
04205             {
04206                 // Get the Node Grid
04207                 NodeGrid* pGrid = (NodeGrid*) pNode;
04208 
04209                 // Only do this if this is the default Grid.
04210                 // That means that it is the full size grid that is toggled
04211                 // from the Show grid thing.
04212                 if (pGrid->IsDefault())
04213                 {
04214                     // This version of the grid saving info is zero
04215                     INT32 Version = 0;
04216                 
04217                     // Go and get the numbers out of the grid
04218                     // BODGE - old builds (hence docs) save the grid spacing in divisions and units but don't
04219                     // account for unit scaling, so as not to change doc format new docs do the same so we must
04220                     // read the grid 'Divisions' with scaling turned off - yuk!
04221                     BOOL Scale=FALSE;
04222                     double   Divisions    = pGrid->GetDivisions(Scale);
04223                     UnitType Unit         = pGrid->GetUnits(Scale);
04224                     UINT32     SubDivisions = pGrid->GetSubdivisions();
04225                     GridType TypeOfGrid   = pGrid->GetGridType();
04226 
04227                     // Build the Comment
04228                     camSprintf(Buffer, _T("%d %f %d %d %d"), Version, Divisions, SubDivisions, (INT32)Unit, (INT32)TypeOfGrid);
04229 
04230                     // Export it
04231                     pDC->OutputToken(_T("%%+g"));
04232                     pDC->OutputToken(Buffer);
04233                     pDC->OutputNewLine();
04234 
04235                     // once we have found a grid and saved it, then we want to stop.
04236                     // This version only saves the default grid.
04237                     return TRUE;
04238                 }
04239             }
04240 
04241             // Oh well, that node was not a grid, so lets see if the next one is
04242             pNode = pNode->FindNext();
04243         }
04244     }
04245 
04246     // Did not save a grid...
04247     return FALSE;
04248 }
04249 
04250 
04251 /********************************************************************************************
04252 >   BOOL Document::ExportOriginInfo(EPSExportDC *pDC)
04253 
04254     Author:     Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
04255     Created:    11/10/95
04256     Inputs:     pDC - The DC to render to
04257     Returns:    FALSE if fails
04258     Purpose:    Export grid/user origin
04259     Note:       Should be exported after grid and page info as when importing,
04260                 these both reset the origin to the origin of the page
04261 ********************************************************************************************/
04262 
04263 BOOL Document::ExportOriginInfo(EPSExportDC *pDC)
04264 {
04265     // find the first (and currently) only spread
04266 PORTNOTE("spread", "Multi-spread warning!")
04267     Spread* pSpread = FindFirstSpread();
04268     ERROR2IF(pSpread==NULL,FALSE,"Document::ExportOriginInfo() - could not find spread");
04269     NodeGrid* pDefaultGrid = pSpread->FindFirstDefaultGridInSpread();
04270     ERROR2IF(pDefaultGrid==NULL,FALSE,"Document::ExportOriginInfo() - could not find default grid");
04271 
04272     // read the grid (user) origin
04273     DocCoord Origin(0,0);
04274     pDefaultGrid->GetOrigin(&Origin.x, &Origin.y);
04275 
04276     // Build the Comment
04277     TCHAR Buffer[256];  // a buffer
04278     INT32 Version = 0;
04279     camSprintf(Buffer, _T("%d %d %d"), Version, Origin.x, Origin.y);
04280 
04281     // Export it
04282     pDC->OutputToken(_T("%%+o"));
04283     pDC->OutputToken(Buffer);
04284     pDC->OutputNewLine();
04285 
04286     return TRUE;
04287 }
04288 
04289 
04290 /********************************************************************************************
04291 
04292 >   BOOL Document::ExportFlagInfo(EPSExportDC *pDC)
04293 
04294     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
04295     Created:    21/3/95
04296     Inputs:     pDC - The DC to render to
04297     Returns:    -
04298     Purpose:    
04299 
04300 ********************************************************************************************/
04301 
04302 BOOL Document::ExportFlagInfo(EPSExportDC *pDC)
04303 {
04304     return TRUE;
04305 }
04306 
04307 
04308 
04309 /********************************************************************************************
04310 
04311 >   BOOL Document::ExportUnitInfo(EPSExportDC *pDC)
04312 
04313     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
04314     Created:    28/3/95
04315     Inputs:     pDC - The DC to export the Units to
04316     Returns:    TRUE
04317     Purpose:    Saves out all the user defined units.
04318                 These are saved in version 0 comments lines, 1 unit per line.
04319                 The default units being used for page and fonts are exported in:-
04320     SeeAlso:    ExportDefaultUnitsInfo;
04321 
04322 ********************************************************************************************/
04323 
04324 BOOL Document::ExportUnitInfo(EPSExportDC *pDC)
04325 {
04326 #if !defined(EXCLUDE_FROM_RALPH)
04327     // A buffer
04328     #define EUI_BUFFER_SIZE 256
04329     TCHAR Buffer[EUI_BUFFER_SIZE];
04330 
04331     // If there is no valid DocUnit list in this document then give up
04332     if (pDocUnitList==NULL)
04333         return FALSE;
04334 
04335     // Find the first relevant unit in the list
04336     Unit* pUnit = (Unit*)pDocUnitList->GetHead();
04337 
04338     while (pUnit!=NULL)
04339     {
04340         // HACK: Export pixel units for compatibiility with old camelot. 
04341         // Really need version control
04342         // Although somewhat crypticly coded this is handled as PIXELS has a NOTYPE base unit
04343         if (pUnit->IsDefault() && (pUnit->GetUnitType() != PIXELS))
04344         {
04345             // Find the next unit in the list
04346             pUnit = (Unit*)pDocUnitList->GetNext(pUnit);
04347             continue;
04348         }
04349 
04350         // OK, we have a unit, so save out its info
04351         // Extract the values
04352         INT32 Version = 0;
04353         MILLIPOINT Size = (MILLIPOINT) pUnit->GetMillipoints();
04354         UnitType BaseUnit = pUnit->GetBaseUnitType();
04355         double Numerator;
04356         double Denominator;
04357         // default units can have NOTYPE so supply sensible values
04358         if (BaseUnit == NOTYPE)     
04359         {
04360             BaseUnit = MILLIPOINTS; // complains in previous camelots if NOTYPE used...
04361             Numerator = 0.0;        // set gibberish numerator so can be picked up in import
04362             Denominator = 1.2;      // use this for version number in which units first appeared
04363         }
04364         else
04365         {
04366             Numerator = pUnit->GetBaseNumerator();
04367             ERROR3IF(Numerator == 0.0, "Document::ExportUnitInfo() - Numerator == 0.0");
04368             Denominator = pUnit->GetBaseDenominator();
04369         }
04370         BOOL IsPrefix = pUnit->IsPrefix();
04371 
04372         String_32 UnitToken = pUnit->GetToken();
04373         String_32 UnitName = pUnit->GetSpecifier();
04374 
04375         // Build the Comment
04376         INT32 nBytes = camSnprintf(Buffer, EUI_BUFFER_SIZE, _T("%d %ld %d %f %f %d"), Version, Size, (INT32)BaseUnit, Numerator, Denominator, IsPrefix);
04377         if (nBytes > EUI_BUFFER_SIZE - 1)
04378         {
04379             ERROR3("Document::ExportUnitInfo - nBytes > EUI_BUFFER_SIZE - 1");
04380             return FALSE;
04381         }
04382         // Export it
04383         pDC->OutputToken(_T("%%+u"));
04384         pDC->OutputToken(Buffer);
04385         pDC->OutputString(UnitToken);
04386         pDC->OutputString(UnitName);
04387         pDC->OutputNewLine();
04388         // Find the next unit in the list
04389         pUnit = (Unit*)pDocUnitList->GetNext(pUnit);
04390     }
04391 
04392 #endif  
04393     return TRUE;
04394 }
04395 
04396 /********************************************************************************************
04397 
04398 >   BOOL Document::ExportDefaultUnitsInfo(EPSExportDC *pDC)
04399 
04400     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04401     Created:    4/9/95
04402     Inputs:     pDC - The DC to export the Units to
04403     Returns:    TRUE
04404     Purpose:    Saves out the user default units for displaying things like page units and
04405                 font units to the user.
04406                 These are saved in version 0 comments lines followed by a string for the
04407                 page units and a string for the font units. Must come after the user units
04408                 section as the default might be one of these user units.
04409                 The usert unit definitions are exported in:-
04410     SeeAlso:    ExportUnitInfo;
04411                 
04412 ********************************************************************************************/
04413 
04414 BOOL Document::ExportDefaultUnitsInfo(EPSExportDC *pDC)
04415 {
04416 #if !defined(EXCLUDE_FROM_RALPH)
04417     // If there is no valid DocUnit list in this document then give up
04418     if (pDocUnitList != NULL)
04419     {
04420         // A buffer
04421         TCHAR Buffer[256];
04422 
04423         // Now output the default units being used for page and fonts
04424         // We will save all this out as version 1 information, this is deemed to be all
04425         // the standard units info
04426         // Cannot use the units field as on earlier versions of Studio, before 1.00b,
04427         // it will be imported as a new user unit with the default settings.
04428         INT32 Version = 0;
04429 
04430         // Get the current default settings
04431         UnitType PageUnits   = pDocUnitList->GetPageUnits();    // The units used to display page measurements
04432         UnitType FontUnits   = pDocUnitList->GetFontUnits();    // The units to display font measurements
04433 
04434         // Find out the full names for these units
04435         String_32 PageUnitToken = pDocUnitList->GetToken(PageUnits);
04436         String_32 FontUnitToken = pDocUnitList->GetToken(FontUnits);
04437 
04438         // Build the Comment
04439         camSnprintf(Buffer, 256, _T("%d"), Version);
04440 
04441         // Export the font and pages units as a line of info
04442         pDC->OutputToken(_T("%%+U"));
04443         pDC->OutputToken(Buffer);
04444         pDC->OutputString(PageUnitToken);
04445         pDC->OutputString(FontUnitToken);
04446         pDC->OutputNewLine();
04447     }
04448 #endif
04449     return TRUE;
04450 }
04451 
04452 
04453 /********************************************************************************************
04454 
04455 >   BOOL Document::ExportDateInfo(EPSExportDC *pDC)
04456 
04457     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
04458     Created:    28/3/95
04459     Inputs:     pDC - the dc to export to
04460     Returns:    TRUE
04461     Purpose:    exports a continuation comment that holds the Last Saved Date and the
04462                 Creation Date. It takes the follwoing form :-
04463                 %%+d Version(0) CreationDate LastSavedDate 
04464 
04465 ********************************************************************************************/
04466 
04467 BOOL Document::ExportDateInfo(EPSExportDC *pDC)
04468 {
04469     // A buffer
04470     TCHAR Buffer[256];
04471 
04472     // Set the last saved date to now
04473     SetLastSaveTime();
04474 
04475     // Find out what they are
04476     time_t Creation =  GetCreationTime();
04477     time_t LastSaved = GetLastSaveTime();
04478 
04479     // Make a string out of them
04480     camSprintf(Buffer, _T("%d %ld %ld"), 0, Creation, LastSaved);
04481 
04482     // Export them
04483     pDC->OutputToken(_T("%%+d"));
04484     pDC->OutputToken(Buffer);
04485     pDC->OutputNewLine();
04486     return TRUE;
04487 }
04488 
04489 /********************************************************************************************
04490 
04491 >   BOOL Document::ExportTextSetup(EPSFilter* pFilter)
04492 
04493     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
04494     Created:    20/4/95
04495     Inputs:     pFilter - the EPS filter that is being used to export a file.
04496     Returns:    TRUE if the text setup for this document was written out successfully;
04497                 FALSE if not (e.g. out of disk space etc)
04498     Purpose:    
04499 
04500 ********************************************************************************************/
04501 
04502 BOOL Document::ExportTextSetup(EPSFilter* pFilter)
04503 {
04504     if ( (pFilter->IS_KIND_OF(CamelotNativeEPSFilter)) ||
04505          (pFilter->IS_KIND_OF(AIEPSFilter))
04506        )
04507     {
04508         // Output the colour table in ArtWorks format.
04509         EPSExportDC *pDC = pFilter->GetExportDC();
04510 
04511         String_64 FontName;
04512         String_64 EFont;
04513         INT32 Style;
04514         FontList CurFontList;
04515 
04516         if (!CurFontList.Build(this))
04517             return FALSE;
04518 
04519         FontListItem* pItem = CurFontList.GetFirstItem();
04520         while (pItem)
04521         {
04522             FontName = pItem->GetFontName();
04523             Style = pItem->GetFontStyle();
04524             // Graeme (31-3-00) - Map the encoded name onto the PS font name.
04525             FONTMANAGER->EncodeAndMapFontName(FontName, EFont, Style);
04526 
04527             // The Page List comment:
04528             pDC->OutputToken(_T("%%IncludeFont:"));
04529             pDC->OutputToken((TCHAR*)EFont);
04530             pDC->OutputNewLine();
04531         
04532             pItem = CurFontList.GetNextItem(pItem); 
04533         }
04534     }
04535 
04536     return TRUE;
04537 }
04538 
04539 
04540 
04541 /********************************************************************************************
04542 
04543 >   BOOL Document::ExportTextTrailer(EPSFilter* pFilter)
04544 
04545     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
04546     Created:    20/4/95
04547     Inputs:     pFilter - the EPS filter that is being used to export a file.
04548     Returns:    TRUE if the text trailer for this document was written out successfully;
04549                 FALSE if not (e.g. out of disk space etc)
04550     Purpose:    
04551 
04552 ********************************************************************************************/
04553 
04554 BOOL Document::ExportTextTrailer(EPSFilter* pFilter)
04555 {
04556     return TRUE;
04557 }
04558 
04559 /********************************************************************************************
04560 
04561 >   BOOL Document::ExportUndoInfo(EPSExportDC *pDC)
04562 
04563     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
04564     Created:    06/07/95
04565     Inputs:     pDC - The DC to render to
04566     Returns:    TRUE
04567     Purpose:    Exports a Document Info continuation comment that describes the document's 
04568                 OperationHistory size.
04569                 It takes the following form :-
04570                 %%+h VersionNum
04571                 if VersionNum is zero then the following will be on the rest of the line
04572                 Size(bytes)
04573 
04574 ********************************************************************************************/
04575 
04576 BOOL Document::ExportUndoInfo(EPSExportDC *pDC)
04577 {
04578     // Find the size of the operation history
04579     UINT32 Size = GetOpHistory().GetMaxSize();
04580 
04581     // get something to put the operation history size info into
04582     TCHAR Buffer[256];
04583     INT32 Version = 0;
04584 
04585     // Build a string with all the data in it
04586     camSprintf(Buffer, _T("%d %lu"), Version, Size);
04587 
04588     // Output the line to the file
04589     pDC->OutputToken(_T("%%+h"));
04590     pDC->OutputToken(Buffer);
04591     pDC->OutputNewLine();
04592     return TRUE;
04593 }
04594 
04595 
04596 /********************************************************************************************
04597 
04598 >   BOOL Document::AIExportResources(EPSExportDC *pDC, BOOL first)
04599 
04600     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
04601     Created:    20/4/95
04602     Inputs:     pDC - the dc to export to
04603     Returns:    TRUE
04604     Purpose:    Export an Illustrator standard needed resources
04605 
04606 ********************************************************************************************/
04607 
04608 BOOL Document::AIExportResources(EPSExportDC *pDC, BOOL first)
04609 {
04610     if (!first)
04611         pDC->OutputToken(_T("%%+"));
04612 
04613     // Graeme (28-3-00) - I've updated these to bring them in line with the procset
04614     // definitions from Fireworks 3 and CorelDraw 9. These have upgraded the file
04615     // to AI version 7.0, and should hopefully offer gradient fill support.
04616     pDC->OutputToken ( _T("procset Adobe_level2_AI5 1.2 0 ") );         pDC->OutputNewLine ();
04617     pDC->OutputToken ( _T("%%+ procset Adobe_packedarray 2.0 0") );     pDC->OutputNewLine ();
04618     pDC->OutputToken ( _T("%%+ procset Adobe_ColorImage_AI6 1.1 0") );  pDC->OutputNewLine ();
04619     pDC->OutputToken ( _T("%%+ procset Adobe_cshow 2.0 8") );           pDC->OutputNewLine ();
04620     pDC->OutputToken ( _T("%%+ procset Adobe_cmykcolor 1.1 0") );       pDC->OutputNewLine ();
04621     pDC->OutputToken ( _T("%%+ procset Adobe_customcolor 1.0 0") );     pDC->OutputNewLine ();
04622     pDC->OutputToken ( _T("%%+ procset Adobe_typography_AI5 1.0 1") );  pDC->OutputNewLine ();
04623     pDC->OutputToken ( _T("%%+ procset Adobe_pattern_AI3 1.0 1") );     pDC->OutputNewLine ();
04624     pDC->OutputToken ( _T("%%+ procset Adobe_Illustrator_AI5 1.2 0") ); pDC->OutputNewLine (); 
04625     return TRUE;
04626 }
04627 
04628 
04629 /********************************************************************************************
04630 
04631 >   BOOL Document::AIExportProlog(EPSExportDC *pDC)
04632 
04633     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
04634     Created:    20/4/95
04635     Inputs:     pDC - the dc to export to
04636     Returns:    TRUE
04637     Purpose:    Export an Illustrator standard prolog
04638 
04639 ********************************************************************************************/
04640 
04641 BOOL Document::AIExportProlog(EPSExportDC *pDC)
04642 {
04643     pDC->OutputToken(_T("%%IncludeResource: procset Adobe_level2_AI5 1.2 0"));          pDC->OutputNewLine();
04644     pDC->OutputToken(_T("%%IncludeResource: procset Adobe_packedarray 2.0 0"));         pDC->OutputNewLine();
04645     pDC->OutputToken(_T("%%IncludeResource: procset Adobe_ColorImage_AI6 1.1 0"));      pDC->OutputNewLine();
04646     pDC->OutputToken(_T("%%IncludeResource: procset Adobe_cshow 2.0 8"));               pDC->OutputNewLine();
04647     pDC->OutputToken(_T("%%IncludeResource: procset Adobe_cmykcolor 1.1 0"));           pDC->OutputNewLine();
04648     pDC->OutputToken(_T("%%IncludeResource: procset Adobe_customcolor 1.0 0"));         pDC->OutputNewLine();
04649     pDC->OutputToken(_T("%%IncludeResource: procset Adobe_typography_AI5 1.1 0"));      pDC->OutputNewLine();
04650     pDC->OutputToken(_T("%%IncludeResource: procset Adobe_pattern_AI3 1.0 1"));         pDC->OutputNewLine();
04651     pDC->OutputToken(_T("%%IncludeResource: procset Adobe_Illustrator_AI5 1.2 0"));     pDC->OutputNewLine();
04652     return TRUE;
04653 }
04654 
04655 
04656 /********************************************************************************************
04657 
04658 >   BOOL Document::AIExportCharEncoding(EPSExportDC *pDC)
04659 
04660     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
04661     Created:    20/4/95
04662     Inputs:     pDC - the dc to export to
04663     Returns:    TRUE
04664     Purpose:    Export an Illustrator compatible character encoding vector but only in 
04665                 EPS format.
04666 
04667 ********************************************************************************************/
04668 
04669 BOOL Document::AIExportCharEncoding(EPSExportDC *pDC)
04670 {
04671     // Temporarily output an inline encoding. This should really be read from a file.
04672     pDC->OutputToken(_T("[")); pDC->OutputNewLine();
04673     pDC->OutputToken(_T("39/quotesingle 96/grave 128/Adieresis/Aring/Ccedilla/Eacute/Ntilde/Odieresis")); pDC->OutputNewLine();
04674     pDC->OutputToken(_T("/Udieresis/aacute/agrave/acircumflex/adieresis/atilde/aring/ccedilla/eacute")); pDC->OutputNewLine();
04675     pDC->OutputToken(_T("/egrave/ecircumflex/edieresis/iacute/igrave/icircumflex/idieresis/ntilde")); pDC->OutputNewLine();
04676     pDC->OutputToken(_T("/oacute/ograve/ocircumflex/odieresis/otilde/uacute/ugrave/ucircumflex")); pDC->OutputNewLine();
04677     pDC->OutputToken(_T("/udieresis/dagger/degree/cent/sterling/section/bullet/paragraph/germandbls")); pDC->OutputNewLine();
04678     pDC->OutputToken(_T("/registered/copyright/trademark/acute/dieresis/.notdef/AE/Oslash")); pDC->OutputNewLine();
04679     pDC->OutputToken(_T("/.notdef/plusminus/.notdef/.notdef/yen/mu/.notdef/.notdef")); pDC->OutputNewLine();
04680     pDC->OutputToken(_T("/.notdef/.notdef/.notdef/ordfeminine/ordmasculine/.notdef/ae/oslash")); pDC->OutputNewLine();
04681     pDC->OutputToken(_T("/questiondown/exclamdown/logicalnot/.notdef/florin/.notdef/.notdef")); pDC->OutputNewLine();
04682     pDC->OutputToken(_T("/guillemotleft/guillemotright/ellipsis/.notdef/Agrave/Atilde/Otilde/OE/oe")); pDC->OutputNewLine();
04683     pDC->OutputToken(_T("/endash/emdash/quotedblleft/quotedblright/quoteleft/quoteright/divide")); pDC->OutputNewLine();
04684     pDC->OutputToken(_T("/.notdef/ydieresis/Ydieresis/fraction/currency/guilsinglleft/guilsinglright")); pDC->OutputNewLine();
04685     pDC->OutputToken(_T("/fi/fl/daggerdbl/periodcentered/quotesinglbase/quotedblbase/perthousand")); pDC->OutputNewLine();
04686     pDC->OutputToken(_T("/Acircumflex/Ecircumflex/Aacute/Edieresis/Egrave/Iacute/Icircumflex")); pDC->OutputNewLine();
04687     pDC->OutputToken(_T("/Idieresis/Igrave/Oacute/Ocircumflex/.notdef/Ograve/Uacute/Ucircumflex")); pDC->OutputNewLine();
04688     pDC->OutputToken(_T("/Ugrave/dotlessi/circumflex/tilde/macron/breve/dotaccent/ring/cedilla")); pDC->OutputNewLine();
04689     pDC->OutputToken(_T("/hungarumlaut/ogonek/caron")); pDC->OutputNewLine();
04690     pDC->OutputToken(_T("TE"));
04691     pDC->OutputNewLine();
04692     return TRUE;
04693 }
04694 
04695 
04696 /********************************************************************************************
04697 
04698 >   BOOL Document::AIExportFontEncoding(EPSExportDC *pDC)
04699 
04700     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
04701     Created:    20/4/95
04702     Inputs:     pDC - the dc to export to
04703     Returns:    TRUE
04704     Purpose:    Export an Illustrator compatible font encodings but only in EPS format.
04705 
04706 ********************************************************************************************/
04707 
04708 BOOL Document::AIExportFontEncoding(EPSExportDC *pDC)
04709 {
04710 #if !defined(EXCLUDE_FROM_RALPH)
04711     // need to enumerate all fonts for this encodeing
04712     String_64 FName;
04713     INT32 Style;
04714     FontList CurFontList;
04715 
04716     if (!CurFontList.Build(this))
04717         return FALSE;
04718 
04719     FontListItem* pItem = CurFontList.GetFirstItem();
04720     while (pItem)
04721     {
04722         FName = pItem->GetFontName();
04723         Style = pItem->GetFontStyle();
04724         AIExportFontEncoding(pDC,FName,Style);
04725         
04726         pItem = CurFontList.GetNextItem(pItem); 
04727     }
04728 #endif
04729     return TRUE;
04730 }
04731 
04732 
04733 /********************************************************************************************
04734 
04735 >   BOOL Document::AIExportFontEncoding(EPSExportDC *pDC, String_64& FontName, INT32 Style)
04736 
04737     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
04738     Created:    20/4/95
04739     Inputs:     pDC - the dc to export to
04740                 FontName - a reference to a font name
04741                 Style - a font style
04742                         b0 = 1 bold
04743                         b1 = 1 italic 
04744     Returns:    TRUE
04745     Purpose:    Export an Illustrator compatible font encoding but only in EPS format.
04746 
04747 ********************************************************************************************/
04748 
04749 BOOL Document::AIExportFontEncoding(EPSExportDC *pDC, String_64& FontName, INT32 Style)
04750 {
04751     String_64 EFont;
04752 
04753     // Graeme (31-3-00) - Map the encoded name onto the PS font name.
04754     FONTMANAGER->EncodeAndMapFontName(FontName, EFont, Style);
04755 
04756     String_256 Line(_T("%AI3_BeginEncoding: _"));
04757 
04758     Line+=(TCHAR*)EFont;
04759     Line+=_T(" ");
04760     Line+=(TCHAR*)EFont;
04761     pDC->OutputToken((TCHAR*)Line);
04762     pDC->OutputNewLine();
04763 
04764     Line=_T("[/_");
04765     Line+=(TCHAR*)EFont;
04766     Line+=_T("/");
04767     Line+=(TCHAR*)EFont;
04768     Line+=_T(" 0 0 1 TZ");
04769     pDC->OutputToken((TCHAR*)Line);
04770     pDC->OutputNewLine();
04771 
04772     Line=_T("%AI3_EndEncoding");
04773     pDC->OutputToken((TCHAR*)Line);
04774     pDC->OutputNewLine();
04775     return TRUE;
04776 }
04777 
04778 
04779 /********************************************************************************************
04780 
04781 >   BOOL Document::AIExportExtras(EPSExportDC *pDC)
04782 
04783     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
04784     Created:    20/4/95
04785     Inputs:     pDC - the dc to export to
04786     Returns:    TRUE
04787     Purpose:    Export an Illustrator compatible trailer
04788 
04789 ********************************************************************************************/
04790 
04791 BOOL Document::AIExportExtras(EPSExportDC *pDC)
04792 {
04793     pDC->OutputToken(_T("Adobe_level2_AI5 /initialize get exec"));      pDC->OutputNewLine();
04794     pDC->OutputToken(_T("Adobe_packedarray /initialize get exec"));     pDC->OutputNewLine();
04795     pDC->OutputToken(_T("Adobe_ColorImage_AI6  /initialize get exec")); pDC->OutputNewLine();
04796     pDC->OutputToken(_T("Adobe_cshow /initialize get exec"));           pDC->OutputNewLine();
04797     pDC->OutputToken(_T("Adobe_cmykcolor /initialize get exec"));       pDC->OutputNewLine();
04798     pDC->OutputToken(_T("Adobe_customcolor /initialize get exec"));     pDC->OutputNewLine();
04799     
04800         // ChrisG (31/10/00) Changed typography line to match Illustrator and CorelDraw.
04801         //  This allows photoshop to import the file correctly.
04802     pDC->OutputToken(_T("Adobe_Illustrator_AI5_vars Adobe_Illustrator_AI5"));
04803     pDC->OutputToken(_T("Adobe_typography_AI5 /initialize get exec"));  pDC->OutputNewLine();
04804         // End of typography output.
04805 
04806     pDC->OutputToken(_T("Adobe_pattern_AI3 /initialize get exec"));     pDC->OutputNewLine();
04807     pDC->OutputToken(_T("Adobe_Illustrator_AI5 /initialize get exec")); pDC->OutputNewLine();
04808     return TRUE;
04809 }
04810 
04811 /********************************************************************************************
04812 
04813 >   BOOL Document::AIExportTrailer(EPSExportDC *pDC)
04814 
04815     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
04816     Created:    20/4/95
04817     Inputs:     pDC - the dc to export to
04818     Returns:    TRUE
04819     Purpose:    Export an Illustrator compatible trailer
04820 
04821 ********************************************************************************************/
04822 
04823 BOOL Document::AIExportTrailer(EPSExportDC *pDC)
04824 {
04825     pDC->OutputToken(_T("Adobe_Illustrator_AI5 /terminate get exec"));  pDC->OutputNewLine();
04826     pDC->OutputToken(_T("Adobe_level2_AI5 /terminate get exec"));       pDC->OutputNewLine();
04827     pDC->OutputToken(_T("Adobe_packedarray /terminate get exec"));      pDC->OutputNewLine();
04828     pDC->OutputToken(_T("Adobe_ColorImage_AI6 /terminate get exec"));   pDC->OutputNewLine();
04829     pDC->OutputToken(_T("Adobe_cshow /terminate get exec"));            pDC->OutputNewLine();
04830     pDC->OutputToken(_T("Adobe_cmykcolor /terminate get exec"));        pDC->OutputNewLine();
04831     pDC->OutputToken(_T("Adobe_customcolor /terminate get exec"));      pDC->OutputNewLine();
04832     pDC->OutputToken(_T("Adobe_typography_AI5 /terminate get exec"));   pDC->OutputNewLine();
04833     pDC->OutputToken(_T("Adobe_pattern_AI3 /terminate get exec"));      pDC->OutputNewLine();
04834     return TRUE;
04835 }
04836 
04837 
04838 /********************************************************************************************
04839 
04840 >   BOOL Document::ImportPageInfo()
04841 
04842     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
04843     Created:    21/3/95
04844     Returns:    TRUE if the import worked, FALSE means that there was a problem.
04845     Purpose:    Tries to import the page info. This function only returns FALSE if there
04846                 was an actual error in the file that needs reporting.
04847 
04848 ********************************************************************************************/
04849 
04850 ProcessEPSResult Document::ImportPageInfo(TCHAR* Comment)
04851 {
04852     // Set the default version
04853     INT32 Version = -1;
04854 
04855     // Where in the comment to start looking from (skip over %%+p)
04856     INT32 i = 4;
04857 
04858     // Read in the version number
04859     if (!ReadNextNumber(&Version, Comment, &i))
04860         return EPSCommentSyntaxError;
04861 
04862     // Descide what to do based on the version number
04863     switch (Version)
04864     {
04865         case 0 :
04866         {
04867             // Version 0 expects to find the following infomation
04868             // Width, Height, Margin, Bleed, Dps, ShowDropShadow
04869             // Get something to put all the numbers into
04870             MILLIPOINT Width, Height;
04871             MILLIPOINT Margin, Bleed;
04872             BOOL Dps, ShowDropShadow;
04873             Width = Height = 0;
04874 
04875             // Read in the Width of the page
04876             if (!ReadNextNumber(&Width, Comment, &i))
04877                 return EPSCommentSyntaxError;
04878 
04879             // Read in the Height of the page
04880             if (!ReadNextNumber(&Height, Comment, &i))
04881                 return EPSCommentSyntaxError;
04882 
04883             // Read in the Margin of the page
04884             if (!ReadNextNumber(&Margin, Comment, &i))
04885                 return EPSCommentSyntaxError;
04886 
04887             // Read in the Bleed of the page
04888             if (!ReadNextNumber(&Bleed, Comment, &i))
04889                 return EPSCommentSyntaxError;
04890 
04891             // Read in the DPS of the page
04892             INT32 TempNum;
04893             if (!ReadNextNumber(&TempNum, Comment, &i))
04894                 return EPSCommentSyntaxError;
04895 
04896             // Copy it to the bool
04897             Dps = (BOOL) TempNum;
04898 
04899             // Read in the Drop shadow state of the page
04900             if (!ReadNextNumber(&TempNum, Comment, &i))
04901                 return EPSCommentSyntaxError;
04902 
04903             // Copy it to the bool
04904             ShowDropShadow = (BOOL) TempNum;
04905 
04906             // Find the spread to change
04907             Spread* pSpread = GetSelectedSpread();
04908             if (pSpread == NULL)
04909                 return EPSCommentSystemError;
04910 
04911             // Ask the pages to change themselves
04912             BOOL Worked = FALSE;
04913             if ((Width>0) && (Height>0))
04914             {
04915                 Worked = pSpread->SetPageSize(Width, Height, Margin, Bleed, Dps, ShowDropShadow);
04916             }
04917         }                 
04918 
04919         // Unknown version
04920         default:
04921         {
04922             // Here we have got a version number we do not know how to process
04923             // so just ignore this comment happy. we will say that the comment
04924             // was OK as an error is technically wrong in this case
04925         }
04926     }
04927 
04928     // if we get here, then everything went smoothly so return Happy
04929     return EPSCommentOK;
04930 }
04931 
04932 
04933 /********************************************************************************************
04934 
04935 >   ProcessEPSResult Document::ImportDocumentComment(TCHAR* Comment)
04936 
04937     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
04938     Created:    21/3/95
04939     Inputs:     Comment - The EPS comment that we have to process
04940     Returns:    ProcessEPSResult - the result of the import - see ProcessEPSComment()
04941     Purpose:    
04942 
04943 ********************************************************************************************/
04944 
04945 ProcessEPSResult Document::ImportDocumentComment(TCHAR* Comment)
04946 {
04947     // Check that this comment line ended in a CR
04948     size_t  StrLength = camStrlen( Comment );
04949     
04950     // If the string was too long, then mark it as an error
04951     if (StrLength>=254)
04952         return EPSCommentSyntaxError;
04953 
04954     // check to see if this line should have a CR in it
04955     if (Comment[StrLength-1]==_T('^'))
04956     {
04957         Comment[StrLength-1] = _T('\r');
04958         Comment[StrLength] = _T('\n');
04959         Comment[StrLength+1] = 0;
04960     }
04961 
04962     // append this line to the document comment
04963     String_256          DocComment( GetComment() );
04964     String_256          NewComment( Comment + 5 );
04965     DocComment += NewComment;
04966     
04967     // Set the comment back into the document and say that all went well
04968     SetComment(&DocComment);
04969 
04970     return EPSCommentOK;
04971 }
04972 
04973 
04974 /********************************************************************************************
04975 
04976 >   ProcessEPSResult Document::ImportViewInfo(TCHAR* Comment)
04977 
04978     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
04979     Created:    21/3/95
04980     Inputs:     Comment - The EPS comment that we have to process
04981     Returns:    ProcessEPSResult - the result of the import - see ProcessEPSComment()
04982     Purpose:    
04983 
04984 ********************************************************************************************/
04985 
04986 ProcessEPSResult Document::ImportViewInfo(TCHAR* Comment)
04987 {
04988 #if !defined(EXCLUDE_FROM_RALPH)
04989     INT32 Version = -1;
04990     INT32 i = 4;
04991 
04992     // Read in the Version Number
04993     if (!ReadNextNumber(&Version, Comment, &i))
04994         return EPSCommentSyntaxError;
04995 
04996     // Act on the version number
04997     switch (Version)
04998     {
04999         case 0 :
05000         case 1 :    // Version 1 is the same, only it has some extra info at the end
05001         {
05002             INT32 XOffset = 0;
05003             INT32 YOffset = 0;
05004             INT32 ScaleFactor = 1000;
05005 
05006             // Read in the Version Number
05007             if (!ReadNextNumber(&XOffset, Comment, &i))
05008                 return EPSCommentSyntaxError;
05009 
05010             // Read in the Version Number
05011             if (!ReadNextNumber(&YOffset, Comment, &i))
05012                 return EPSCommentSyntaxError;
05013 
05014             // Read in the Version Number
05015             if (!ReadNextNumber(&ScaleFactor, Comment, &i))
05016                 return EPSCommentSyntaxError;
05017 
05018             // Adjust the scale factor by a factor of 1000
05019             // go via a double to avoid getting negative scales when ScaleFactor > 32k
05020             FIXED16 RealScale = ((double)ScaleFactor) / 1000.0;
05021 
05022             // See if we have a View to change
05023 //          DocView* pView = DocView::GetSelected();
05024             DocView* pView = GetFirstDocView();
05025             if (pView != NULL && fRestoreViewOnImport)
05026             {
05027                 // Set the view for the following code.  The zoom ops work on the current
05028                 // view, as do the coordinate conversion functions.
05029                 ERROR3IF(pView != DocView::GetCurrent(),
05030                             "DocView::Current is screwed in Document::ImportViewInfo");
05031                 pView->SetCurrent();
05032 
05033                 // Change the view scale
05034                 pView->SetViewScale(RealScale);
05035 
05036                 // Change the scroll offsets
05037                 WorkCoord TopCorner(XOffset, YOffset);
05038                 pView->SetScrollOffsets(TopCorner, FALSE);
05039 
05040                 // Update the button bar
05041                 OpZoomComboDescriptor::Update();
05042             }
05043 
05044             // Deal with the Version 1 bits
05045             if (Version==1)
05046             {
05047                 // The params we will read in
05048                 INT32 Active;
05049                 String_32 DrawingScale;
05050                 String_32 RealScale;
05051 
05052                 // Find the DimScale to set
05053                 DimScale* pDimScale = NULL;
05054                 Spread* pSpread = GetSelectedSpread();
05055                 if (pSpread!=NULL)
05056                     pDimScale = pSpread->GetPtrDimScale();
05057                 
05058                 if (pDimScale!=NULL)
05059                 {
05060                     // Read in the Version Number
05061                     if (!ReadNextNumber(&Active, Comment, &i))
05062                         return EPSCommentSyntaxError;
05063 
05064                     // And set the active state of the scaleing
05065                     pDimScale->SetActiveState(Active);
05066 
05067                     // And read in the two scaling strings
05068                     if (!ReadNextString(&DrawingScale, 32, Comment, &i))
05069                         return EPSCommentSyntaxError;
05070 
05071                     // Set the Drawing Scale
05072                     BOOL Worked = pDimScale->SetDrawingScaleStr(DrawingScale);
05073                     
05074                     if (!ReadNextString(&RealScale, 32, Comment, &i))
05075                         return EPSCommentSyntaxError;
05076 
05077                     // Set the real scale
05078                     if (Worked)
05079                         Worked = pDimScale->SetRealScaleStr(RealScale);
05080 
05081                     // Set the scale factor using the new strings
05082                     if (Worked)
05083                         pDimScale->SetScaleFactor();
05084                     // None of the the above functions report errors if there were problems
05085                     // should really inform the user about the problem using _R(IDW_BADDOCUMENTSCALE) in nev.h/rc
05086                 }
05087             }
05088 
05089             break;
05090         }
05091 
05092         default :
05093         {
05094             break;
05095         }
05096     }
05097 #endif  
05098     return EPSCommentOK;
05099 }
05100 
05101 
05102 /********************************************************************************************
05103 
05104 >   ProcessEPSResult Document::ImportStateInfo(TCHAR* Comment)
05105 
05106     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
05107     Created:    21/3/95
05108     Inputs:     Comment - The EPS comment that we have to process
05109     Returns:    ProcessEPSResult - the result of the import - see ProcessEPSComment()
05110     Purpose:    Imports state information.
05111                 Version 0 holds view state information such as:-
05112                     grid showing and snap to grid
05113                     magnetic snap to objects
05114                     foregound background redraw modes. 
05115 
05116 ********************************************************************************************/
05117 
05118 ProcessEPSResult Document::ImportStateInfo(TCHAR* Comment)
05119 {
05120 #if !defined(EXCLUDE_FROM_RALPH)
05121     // The version of the state info and the read position in the string
05122     INT32 Version = -1;
05123     INT32 i = 4;
05124 
05125     // Find the first DocView (if there is one)
05126     DocView* pFirstView = GetFirstDocView();
05127 
05128     // Read in the Version Number
05129     if (!ReadNextNumber(&Version, Comment, &i))
05130         return EPSCommentSyntaxError;
05131 
05132     // Act on the version number
05133     switch (Version)
05134     {
05135         case 1 : 
05136         {
05137             INT32 ShowGuides            = TRUE;
05138             INT32 SnapToGuides      = TRUE;
05139             INT32 Multilayer            = FALSE;
05140             INT32 AllLayersVisible  = FALSE;
05141 
05142             // Read the ShowGuides flag
05143             if (!ReadNextNumber(&ShowGuides, Comment, &i))
05144                 return EPSCommentSyntaxError;
05145 
05146             // Read the SnapToGuides flag
05147             if (!ReadNextNumber(&SnapToGuides, Comment, &i))
05148                 return EPSCommentSyntaxError;
05149 
05150             // Read the Multilayer flag
05151             if (!ReadNextNumber(&Multilayer, Comment, &i))
05152                 return EPSCommentSyntaxError;
05153 
05154             // Read the AllLayersVisible flag
05155             if (!ReadNextNumber(&AllLayersVisible, Comment, &i))
05156                 return EPSCommentSyntaxError;
05157 
05158 // In viewer leave these alone
05159 #ifndef STANDALONE
05160             // Now try and set the values in the view
05161             if (pFirstView != NULL)
05162             {
05163                 // Set all the flags to either TRUE or FALSE
05164                 pFirstView->SetShowGuidesState(ShowGuides?TRUE:FALSE);
05165                 pFirstView->SetSnapToGuidesState(SnapToGuides?TRUE:FALSE);
05166 
05167                 SetMultilayer(Multilayer?TRUE:FALSE);
05168                 SetAllVisible(AllLayersVisible?TRUE:FALSE);
05169             }
05170 #endif
05171         }
05172         // Fall through for version 0 flags
05173 
05174         case 0 :
05175         {
05176             INT32 ShowGrid = FALSE;
05177             INT32 SnapToGrid = FALSE;
05178             INT32 SnapToMagObjects = FALSE;
05179             INT32 SnapToObjects = FALSE;
05180             INT32 ForeBackMode = FALSE;
05181 
05182             // Read the Grid visible flag
05183             if (!ReadNextNumber(&ShowGrid, Comment, &i))
05184                 return EPSCommentSyntaxError;
05185 
05186             // Snap to Grids yes/no
05187             if (!ReadNextNumber(&SnapToGrid, Comment, &i))
05188                 return EPSCommentSyntaxError;
05189 
05190             // Snap to Magnetic Objects yes/no
05191             if (!ReadNextNumber(&SnapToMagObjects, Comment, &i))
05192                 return EPSCommentSyntaxError;
05193 
05194             // Snap to Objects yes/no
05195             if (!ReadNextNumber(&SnapToObjects, Comment, &i))
05196                 return EPSCommentSyntaxError;
05197 
05198             // Background rendering yes/no
05199             if (!ReadNextNumber(&ForeBackMode, Comment, &i))
05200                 return EPSCommentSyntaxError;
05201 
05202             // Read in the dummy sixth value. This is necessary because
05203             // a printf function had too many %ds in it for the output
05204             // so the program always outputs a random value after the
05205             // rest of them. We have to skip it, just in case.
05206             // Notice that we ignore any errors - if the dummy value is not there, 
05207             // who cares?
05208             INT32 dummy = 0;
05209             ReadNextNumber(&dummy, Comment, &i);
05210             
05211 // In viewer leave these alone
05212 #ifndef STANDALONE
05213             // Now try and set the values in the view
05214             if (pFirstView != NULL)
05215             {
05216                 // Set all the flags to either TRUE or FALSE
05217                 pFirstView->SetShowGridState(ShowGrid?TRUE:FALSE);
05218                 pFirstView->SetSnapToGridState(SnapToGrid?TRUE:FALSE);
05219                 pFirstView->SetSnapToMagObjectsState(SnapToMagObjects?TRUE:FALSE);
05220                 pFirstView->SetSnapToObjectsState(SnapToObjects?TRUE:FALSE);
05221                 pFirstView->SetForeBackMode(ForeBackMode?TRUE:FALSE);
05222             }
05223 #endif
05224             break;
05225         }
05226 
05227 
05228         // Unknown version number
05229         default:
05230         {
05231             // This is not an error, as this would stop the file from loading.
05232             // We will just ignore this little section of information
05233             break;
05234         }
05235     }
05236 #endif
05237     return EPSCommentOK;
05238 }
05239 
05240 
05241 /********************************************************************************************
05242 
05243 >   ProcessEPSResult Document::ImportQualityInfo(TCHAR* Comment)
05244 
05245     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
05246     Created:    21/3/95
05247     Inputs:     Comment - The EPS comment that we have to process
05248     Returns:    ProcessEPSResult - the result of the import - see ProcessEPSComment()
05249     Purpose:    
05250 
05251 ********************************************************************************************/
05252 
05253 ProcessEPSResult Document::ImportQualityInfo(TCHAR* Comment)
05254 {
05255 #if !defined(EXCLUDE_FROM_RALPH)
05256     // The version of the state info and the read position in the string
05257     INT32 Version = -1;
05258     INT32 i = 4;
05259 
05260     // Read in the Version Number
05261     if (!ReadNextNumber(&Version, Comment, &i))
05262         return EPSCommentSyntaxError;
05263 
05264     // Act on the version number
05265     switch (Version)
05266     {
05267         case 0 :
05268         {
05269             // The View Quality - default to something sensible
05270             INT32 ViewQuality = 100;
05271 
05272             // Read in the Version Number
05273             if (!ReadNextNumber(&ViewQuality, Comment, &i))
05274                 return EPSCommentSyntaxError;
05275 
05276             // OK, we got the view quality ok, so try and set it
05277 //          DocView* pView = DocView::GetSelected();
05278             DocView* pView = GetFirstDocView();
05279             if (pView!=NULL)
05280             {
05281                 // Actually set the quality in the view
05282                 /*BOOL Worked = */pView->RenderQuality.SetQuality((INT32)ViewQuality);
05283             }
05284 
05285             break;
05286         }
05287 
05288         default:
05289         {
05290             break;
05291         }
05292     }
05293 #endif
05294     return EPSCommentOK;
05295 }
05296 
05297 
05298 /********************************************************************************************
05299 
05300 >   ProcessEPSResult Document::ImportGridInfo(TCHAR* Comment)
05301 
05302     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
05303     Created:    21/3/95
05304     Inputs:     Comment - The EPS comment that we have to process
05305     Returns:    ProcessEPSResult - the result of the import - see ProcessEPSComment()
05306     Purpose:    Imports the global grid that covers the whole spread
05307 
05308 ********************************************************************************************/
05309 
05310 ProcessEPSResult Document::ImportGridInfo(TCHAR* Comment)
05311 {
05312 #if !defined(EXCLUDE_FROM_RALPH)
05313     // The version of the state info and the read position in the string
05314     INT32 Version = -1;
05315     INT32 i = 4;
05316 
05317     // Read in the Version Number
05318     if (!ReadNextNumber(&Version, Comment, &i))
05319         return EPSCommentSyntaxError;
05320 
05321     // Act on the version number
05322     switch (Version)
05323     {
05324         case 0 :
05325         {
05326             double Divisions;
05327             INT32 SubDiv, Units, Type;
05328             UINT32 SubDivisions;
05329             UnitType Unit;
05330             GridType TypeOfGrid;
05331             
05332             // Read in the Divisions
05333             if (!ReadNextNumber(&Divisions, Comment, &i))
05334                 return EPSCommentSyntaxError;
05335 
05336             // read in the sub-divisions
05337             if (!ReadNextNumber(&SubDiv, Comment, &i))
05338                 return EPSCommentSyntaxError;
05339 
05340             // Read in the unit
05341             if (!ReadNextNumber(&Units, Comment, &i))
05342                 return EPSCommentSyntaxError;
05343 
05344             // Read in the type of grid
05345             if (!ReadNextNumber(&Type, Comment, &i))
05346                 return EPSCommentSyntaxError;
05347 
05348             // Put everything into the correct types
05349             SubDivisions = (UINT32)SubDiv;
05350             Unit = (UnitType)Units;
05351             TypeOfGrid = (GridType) Type;           
05352 
05353             // Get rid of the old grid, if there was one
05354             // and find out where the page corner is, so that the origin of the grid can be set
05355             BOOL FoundPage = FALSE;
05356             DocCoord Corner(0,0);
05357             Spread* pSpread = GetSelectedSpread();
05358             if (pSpread!=NULL)
05359             {
05360                 // Find the first child of the spread
05361                 Node* pNode = pSpread->FindFirstChild();
05362                 while (pNode!=NULL)
05363                 {
05364                     // Go find the next node now
05365                     Node* pNext = pNode->FindNext();
05366 
05367                     // For each of the child nodes of the spread, we will check to see if it is a Node Grid
05368                     if (pNode->IS_KIND_OF(NodeGrid))
05369                     {
05370                         // This is a grid all right, so toast it
05371                         pNode->CascadeDelete();
05372                         delete pNode;               
05373                     }
05374 
05375                     // see if it is a page
05376                     if ((!FoundPage) && (pNode->IS_KIND_OF(Page)))
05377                     {
05378                         // We have found one, so stop looking
05379                         FoundPage = TRUE;
05380 
05381                         // Find out the coord of the bottom corner
05382                         DocRect PageRect = ((Page*)pNode)->GetPageRect();
05383                         Corner = PageRect.LowCorner();
05384                     }
05385 
05386                     // Find the next node
05387                     pNode = pNext;
05388                 }
05389 
05390                 // Set all the global variables - What a load of B********
05391                 NodeGrid::SetDefaultDivisions(Divisions);
05392                 NodeGrid::SetDefaultSubdivisions(SubDivisions);
05393                 NodeGrid::SetDefaultUnits(Unit);
05394                 NodeGrid::SetDefaultGridType(TypeOfGrid);
05395 
05396                 // Make a grid
05397                 // BODGE - old builds (hence docs) save the grid spacing in divisions and units but don't
05398                 // account for unit scaling, so as not to change doc format new docs do the same so we must
05399                 // set the grid with scaling turned off - yuk!
05400                 BOOL Scale=FALSE;
05401                 NodeGrid::MakeDefaultGrid(pSpread, Scale);
05402 
05403                 // Set the origin to 0,0 for now
05404                 if (FoundPage)
05405                 {
05406                     // Find the first child of the spread
05407                     Node* pNode = pSpread->FindFirstChild();
05408                     while (pNode!=NULL)
05409                     {
05410                         // For each of the child nodes of the spread, we will check to see if it is a Node Grid
05411                         if (pNode->IS_KIND_OF(NodeGrid))
05412                             // This is a grid all right, so Set its origin
05413                             ((NodeGrid*)pNode)->SetOrigin(Corner.x, Corner.y);
05414 
05415                         // Find the next node
05416                         pNode = pNode->FindNext();
05417                     }
05418                 }
05419             }
05420             break;
05421         }
05422 
05423         default:
05424         {
05425             break;
05426         }
05427     }
05428 #endif  
05429     return EPSCommentOK;
05430 }
05431 
05432 
05433 /********************************************************************************************
05434 >   ProcessEPSResult Document::ImportOriginInfo(TCHAR* Comment)
05435 
05436     Author:     Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
05437     Created:    11/10/95
05438     Inputs:     Comment - The EPS comment that we have to process
05439     Returns:    ProcessEPSResult - the result of the import
05440     Purpose:    Imports the spread grid/user origin
05441     Note:       The origin should already have been set up to the page origin when importing
05442                 the grid (ie already has a sensible default if the origin import fails)
05443                 Also since the origin does not affect the look of the doc, if possible
05444                 don't abort importing if an error is encountered so the doc can be recovered
05445 ********************************************************************************************/
05446 
05447 ProcessEPSResult Document::ImportOriginInfo(TCHAR* Comment)
05448 {
05449 #if !defined(EXCLUDE_FROM_RALPH)
05450     // find the selected spread in the doc, and it's default grid
05451     Spread* pSpread = GetSelectedSpread();
05452     ERROR2IF(pSpread==NULL,EPSCommentOK,"Document::ImportOriginInfo() - could not find first spread in doc");
05453     NodeGrid* pDefaultGrid = pSpread->FindFirstDefaultGridInSpread();
05454     ERROR2IF(pDefaultGrid==NULL,EPSCommentOK,"Document::ImportOriginInfo() - could not find default grid");
05455 
05456     // init read position in string - ie after "%%+o"
05457     INT32 i = 4;
05458 
05459     // Read in the Version Number
05460     INT32 Version = -1;
05461     if (!ReadNextNumber(&Version, Comment, &i))
05462         return EPSCommentSyntaxError;
05463 
05464     // Act on the version number
05465     switch (Version)
05466     {
05467         case 0 :
05468         {
05469             // Read in the origin
05470             DocCoord Origin(0,0);
05471             if (!ReadNextNumber(&Origin.x, Comment, &i))
05472                 return EPSCommentSyntaxError;
05473             if (!ReadNextNumber(&Origin.y, Comment, &i))
05474                 return EPSCommentSyntaxError;
05475 
05476             // set the grid (and user) origin
05477             pDefaultGrid->SetOrigin(Origin.x,Origin.y);
05478             break;
05479         }
05480 
05481         default: ERROR2(EPSCommentOK,"Document::ImportOriginInfo() - unknown origin version");
05482     }
05483 #endif
05484     
05485     return EPSCommentOK;
05486 }
05487 
05488 
05489 /********************************************************************************************
05490 
05491 >   ProcessEPSResult Document::ImportRulerState(TCHAR* Comment)
05492 
05493     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
05494     Created:    21/3/95
05495     Inputs:     Comment - The EPS comment that we have to process
05496     Returns:    ProcessEPSResult - the result of the import - see ProcessEPSComment()
05497     Purpose:    
05498 
05499 ********************************************************************************************/
05500 
05501 ProcessEPSResult Document::ImportRulerState(TCHAR* Comment)
05502 {
05503 #if !defined(EXCLUDE_FROM_RALPH)
05504     INT32 Version = -1;
05505     INT32 i = 4;
05506     // Read in the Version Number
05507     if (!ReadNextNumber(&Version, Comment, &i))
05508         return EPSCommentSyntaxError;
05509 
05510     switch (Version)
05511     {
05512         case 0 :
05513         {
05514         
05515             INT32 ScrollerState =1;
05516             INT32 RulerState =0;
05517             // Read in the Version Number
05518             if (!ReadNextNumber(&ScrollerState, Comment, &i))
05519                 return EPSCommentSyntaxError;
05520             if (!ReadNextNumber(&RulerState, Comment, &i))
05521                 return EPSCommentSyntaxError;
05522             
05523             // See if we have a View to change
05524 //          DocView* pView = DocView::GetSelected();
05525             DocView* pView = GetFirstDocView();
05526             
05527             // we use default visibility states if this is a new file
05528             // (ie. we are not opening an existing file )
05529             // this flag is set in CCamDoc::OnNewDocument()
05530             // see also CCamDoc::OnOpenDocument()
05531             if(CCamView::GetUseVisibleDefaults())
05532             {
05533                 ScrollerState = CCamView::GetDefaultScrollersState();
05534                 RulerState = CCamView::GetDefaultRulersState();
05535             }
05536         
05537             if (pView != NULL)
05538             {
05539                 pView->ShowViewScrollers((BOOL)ScrollerState);
05540                 pView->ShowViewRulers((BOOL)RulerState);
05541             }
05542             break;
05543         }
05544 
05545         default :
05546         {
05547             break;
05548         }
05549     }
05550 #endif  
05551 
05552     return EPSCommentOK;
05553 }
05554 
05555 
05556 /********************************************************************************************
05557 
05558 >   ProcessEPSResult Document::ImportFlagInfo(TCHAR* Comment)
05559 
05560     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
05561     Created:    21/3/95
05562     Inputs:     Comment - The EPS comment that we have to process
05563     Returns:    ProcessEPSResult - the result of the import - see ProcessEPSComment()
05564     Purpose:    
05565 
05566 ********************************************************************************************/
05567 
05568 ProcessEPSResult Document::ImportFlagInfo(TCHAR* Comment)
05569 {
05570     return EPSCommentOK;
05571 }
05572 
05573 
05574 /********************************************************************************************
05575 
05576 >   ProcessEPSResult Document::ImportUnitInfo(TCHAR* Comment)
05577 
05578     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
05579     Created:    28/3/95
05580     Inputs:     Comment - The comment line to process
05581     Returns:    EPSCommentSyntaxError if there was a systax error in the comment
05582                 EPSCommentOK if the comment was processed ok
05583     Purpose:    Imports a continuation comment with details about a user defined unit on it
05584                 There is 1 unit per comment. This comment always creates a new user unit
05585                 in version prior to Studio 1.00b, code updated to not do this 4/9/95.
05586 
05587 ********************************************************************************************/
05588 
05589 ProcessEPSResult Document::ImportUnitInfo(TCHAR* Comment)
05590 {
05591     // If there is no valid DocUnit list in this document then give up
05592     ERROR3IF(pDocUnitList==NULL,"Document::ImportUnitInfo null pDocUnitList");
05593     if (pDocUnitList==NULL)
05594         return EPSCommentOK;
05595 
05596     // Set up some variables.
05597     // The version of the state info and the read position in the string
05598     INT32 Version = -1;
05599     INT32 i = 4;
05600 
05601     // Read in the Version Number
05602     if (!ReadNextNumber(&Version, Comment, &i))
05603         return EPSCommentSyntaxError;
05604 
05605     // Act on the version number
05606     switch (Version)
05607     {
05608         case 0 :
05609         {
05610             // We need to make a new unit
05611             // Older code had this outside the version loop so you cannot use the 'u'
05612             // comment field for other unit field without creating a new unit in older
05613             // versions e.g. viewer 1.00 and Studio 1.00b and before. 
05614 
05615             // Read in values & validate them before creating the unit
05616 
05617             INT32 Size;
05618             INT32 BaseUnit;
05619             double Numerator;
05620             double Denominator;
05621             INT32 IsPrefix;
05622             String_64 TokenStr;
05623             String_64 SpecifierStr;
05624                 
05625             // Read in the Millipoint size of the unit
05626             if (!ReadNextNumber(&Size, Comment, &i))
05627                 return EPSCommentSyntaxError;
05628 
05629             // Read in the base UnitType
05630             if (!ReadNextNumber(&BaseUnit, Comment, &i))
05631                 return EPSCommentSyntaxError;
05632 
05633             // Read in the unit Numerator
05634             if (!ReadNextNumber(&Numerator, Comment, &i))
05635                 return EPSCommentSyntaxError;
05636 
05637             // Read in the unit Denominator
05638             if (!ReadNextNumber(&Denominator, Comment, &i))
05639                 return EPSCommentSyntaxError;
05640 
05641             // Read in whether the  unit specifier is prefixed (0 == FALSE)
05642             if (!ReadNextNumber(&IsPrefix, Comment, &i))
05643                 return EPSCommentSyntaxError;
05644 
05645             // Finally read in the string values
05646             if (!ReadNextString(&TokenStr, 32, Comment, &i))
05647                 return EPSCommentSyntaxError;
05648 
05649             // Read in the specifier string
05650             if (!ReadNextString(&SpecifierStr, 32, Comment, &i))
05651                 return EPSCommentSyntaxError;
05652 
05653             // Throw away units that have been exported for compatibility with older versions (see ExportUnitInfo())
05654             if (Numerator == 0.0 && Denominator <= 2.0) break;
05655 
05656             Unit* pNewUnit = NULL;
05657             if (!pDocUnitList->MakeNewUnit(&pNewUnit, TRUE))
05658                 return EPSCommentSystemError;
05659 
05660             // Set the values in the units up
05661             pNewUnit->SetMillipoints((double)Size);
05662             pNewUnit->SetBaseUnitType((UnitType) BaseUnit);
05663             pNewUnit->SetBaseNumerator(Numerator);
05664             pNewUnit->SetBaseDenominator(Denominator);
05665             pNewUnit->SetPrefixState((BOOL)IsPrefix);
05666             // Set the token
05667             pNewUnit->SetToken(TokenStr);
05668             // Set the Specifier
05669             pNewUnit->SetSpecifier(SpecifierStr);
05670 
05671             break;
05672         }
05673 
05674         default:
05675         {
05676             // Do nothing with unknown versions as this means info we know nothing about.
05677             // Do not error though as this might be bad.
05678             break;
05679         }
05680     }
05681 
05682     return EPSCommentOK;
05683 }
05684 
05685 /********************************************************************************************
05686 
05687 >   ProcessEPSResult Document::ImportDefaultUnitsInfo(TCHAR* Comment)
05688 
05689     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
05690     Created:    4/9/95
05691     Inputs:     Comment - The comment line to process
05692     Returns:    EPSCommentSyntaxError if there was a systax error in the comment
05693                 EPSCommentOK if the comment was processed ok
05694     Purpose:    Imports a continuation comment with details about the default units which
05695                 are going to be used for showing page and font measurements.
05696                 Cannot use units as on older version will always create a new user unit for
05697                 each ++u found..
05698 
05699 ********************************************************************************************/
05700 
05701 ProcessEPSResult Document::ImportDefaultUnitsInfo(TCHAR* Comment)
05702 {
05703 // In viewer leave these alone as not useful
05704 #ifndef STANDALONE
05705 
05706     // If there is no valid DocUnit list in this document then give up
05707     ERROR3IF(pDocUnitList==NULL,"Document::ImportDefaultUnitsInfo null pDocUnitList");
05708     if (pDocUnitList==NULL)
05709         return EPSCommentOK;
05710 
05711     // Set up some variables.
05712     // The version of the state info and the read position in the string
05713     INT32 Version = -1;
05714     INT32 i = 4;
05715 
05716     // Read in the Version Number
05717     if (!ReadNextNumber(&Version, Comment, &i))
05718         return EPSCommentSyntaxError;
05719 
05720     // Act on the version number
05721     switch (Version)
05722     {
05723         case 0 :
05724         {
05725             // Read in the string values which define the units to use
05726             // First the page units, the units used to display page measurements
05727             String_64 PageUnitsStr;
05728             if (!ReadNextString(&PageUnitsStr, 32, Comment, &i))
05729                 return EPSCommentSyntaxError;
05730 
05731             // Then the font units, the units to display font measurements
05732             String_64 FontUnitsStr;
05733             if (!ReadNextString(&FontUnitsStr, 32, Comment, &i))
05734                 return EPSCommentSyntaxError;
05735 
05736             // Find the unit in the list, if present, otherwise will return NOTYPE
05737             UnitType PageUnits   = pDocUnitList->FindUnitTypeFromToken(PageUnitsStr);
05738             UnitType FontUnits   = pDocUnitList->FindUnitTypeFromToken(FontUnitsStr);   
05739 
05740             // Set the new current default settings, if valid units were found
05741             if (PageUnits != NOTYPE)
05742                 pDocUnitList->SetPageUnits(PageUnits);
05743             if (FontUnits!= NOTYPE)
05744                 pDocUnitList->SetFontUnits(FontUnits);
05745 
05746             break;
05747         }
05748 
05749         default:
05750         {
05751             // Do nothing with unknown versions as this means info we know nothing about.
05752             // Do not error though as this might be bad.
05753             break;
05754         }
05755     }
05756 #endif
05757 
05758     return EPSCommentOK;
05759 }
05760 
05761 /********************************************************************************************
05762 
05763 >   ProcessEPSResult Document::ImportDateInfo(TCHAR* Comment)
05764 
05765     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
05766     Created:    28/3/95
05767     Inputs:     Comment - The Comment that we have to process
05768     Returns:    EPSCommentOK
05769     Purpose:    Reads in the Last saved Date and Creation Date from the file.
05770 
05771 ********************************************************************************************/
05772 
05773 ProcessEPSResult Document::ImportDateInfo(TCHAR* Comment)
05774 {
05775 #if !defined(EXCLUDE_FROM_RALPH)
05776     // The version of the state info and the read position in the string
05777     INT32 Version = -1;
05778     INT32 i = 4;
05779 
05780     // Read in the Version Number
05781     if (!ReadNextNumber(&Version, Comment, &i))
05782         return EPSCommentSyntaxError;
05783 
05784     // Act on the version number
05785     switch (Version)
05786     {
05787         case 0 :
05788         {
05789             INT32 Creation, LastSaved;
05790 
05791             // Read in the Creation Date
05792             if (!ReadNextNumber(&Creation, Comment, &i))
05793                 return EPSCommentSyntaxError;
05794 
05795             // Read in the Last Saved Date
05796             if (!ReadNextNumber(&LastSaved, Comment, &i))
05797                 return EPSCommentSyntaxError;
05798 
05799             // Set the vars in the document
05800             CreationTime = (time_t)Creation;
05801             LastSaveTime = (time_t)LastSaved;
05802             break;
05803         }
05804 
05805         default:
05806         {
05807             break;
05808         }
05809     }
05810 #endif
05811 
05812     return EPSCommentOK;
05813 }
05814 
05815 /********************************************************************************************
05816 
05817 >   ProcessEPSResult Document::ImportUndoInfo(TCHAR* Comment)
05818 
05819     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
05820     Created:    06/07/95
05821     Inputs:     Comment - The Comment that we have to process
05822     Returns:    EPSCommentOK
05823     Purpose:    Reads in the Last saved operation history size from the file.
05824 
05825 ********************************************************************************************/
05826 
05827 ProcessEPSResult Document::ImportUndoInfo(TCHAR* Comment)
05828 {
05829     // The version of the state info and the read position in the string
05830     INT32 Version = -1;
05831     INT32 i = 4;
05832 
05833     // Read in the Version Number
05834     if (!ReadNextNumber(&Version, Comment, &i))
05835         return EPSCommentSyntaxError;
05836 
05837     // Act on the version number
05838     switch (Version)
05839     {
05840         case 0 :
05841         {
05842             UINT32 UndoSize;
05843 
05844             // Read the size for the operation history
05845             if (!ReadNextNumber(&UndoSize, Comment, &i))
05846                 return EPSCommentSyntaxError;
05847 
05848             // Minimum size = 1K
05849             if (UndoSize < 1024)
05850                 UndoSize = 1024;
05851 
05852             // Set the size of the Operation History in
05853             // the document.
05854             GetOpHistory().SetNewMaxSize(UndoSize);
05855 
05856             break;
05857         }
05858 
05859         default:
05860         {
05861             break;
05862         }
05863     }
05864 
05865     return EPSCommentOK;
05866 }
05867 
05868 
05869 
05870 /********************************************************************************************
05871 
05872 >   BOOL Document::IsImporting()
05873 
05874     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
05875     Created:    28/3/95
05876     Returns:    TRUE if the document is importing a file as apposed to Opening a file
05877     Purpose:    Helps work out if the document is in the process of opening an existing
05878                 file or if it is importing data into itself. Called during the reading
05879                 of the Document Info section of the .art files. All the DocInfo section
05880                 is ignored if the file is actually being imported.
05881 
05882 ********************************************************************************************/
05883 
05884 BOOL Document::IsImporting()
05885 {
05886     return DocIsImporting;
05887 }
05888 
05889 
05890 /********************************************************************************************
05891 
05892 >   void Document::SetIsImporting(BOOL NewIsImporting)
05893 
05894     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
05895     Created:    28/3/95
05896     Inputs:     NewIsImporting - The new state of the importing flag
05897     Purpose:    Sets the IsImporting flag for the document
05898 
05899 ********************************************************************************************/
05900 
05901 void Document::SetIsImporting(BOOL NewIsImporting)
05902 {
05903     // Set the flag to either TRUE or FALSE
05904     if (NewIsImporting)
05905         DocIsImporting = TRUE;
05906     else
05907         DocIsImporting = FALSE;
05908 }
05909 
05910 /********************************************************************************************
05911 
05912 >   BOOL Document::IsTemplateLoading()
05913 
05914     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> Humprhys
05915     Created:    6/8/97
05916     Returns:    TRUE if the document is importing a file as apposed to Opening a file
05917     Purpose:    Helps work out if the document being opened or imported is a default or
05918                 template document.
05919                 At present, used in Webster to check if we need to use layers or not. Template
05920                 documents are allowed to have layers. Non-template docs are not.
05921     SeeAlso:    
05922 
05923 ********************************************************************************************/
05924 
05925 BOOL Document::IsTemplateLoading()
05926 {
05927     return DocTemplateLoading;
05928 }
05929 
05930 /********************************************************************************************
05931 
05932 >   void Document::SetTemplateLoading(BOOL NewTemplateLoading)
05933 
05934     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> Humprhys
05935     Created:    6/8/97
05936     Inputs:     NewTemplateLoading - The new state of the template loading flag
05937     Purpose:    Sets the TemplateLoading flag for the document
05938 
05939 ********************************************************************************************/
05940 
05941 void Document::SetTemplateLoading(BOOL NewTemplateLoading)
05942 {
05943     // Set the flag to either TRUE or FALSE
05944     if (NewTemplateLoading)
05945         DocTemplateLoading = TRUE;
05946     else
05947         DocTemplateLoading = FALSE;
05948 }
05949 
05950 /********************************************************************************************
05951 >   static void Document::ShouldRestoreViewOnImport(BOOL fNewState)
05952 
05953     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
05954     Created:    12/10/95
05955     Inputs:     fNewState           new value of the flag
05956     Purpose:    Sets/clears a flag that if TRUE will ask this document to restore the view
05957                 saved within the doc, if FALSE it won't bother.  Normally we want the
05958                 view saved in the doc to be restore, but if we are restoring the entire
05959                 workspace then this is dealt with elsewhere.
05960     Errors:     -
05961     SeeAlso:    Document::ImportViewInfo; LoadAppWindowState
05962 ********************************************************************************************/
05963 
05964 void Document::ShouldRestoreViewOnImport(BOOL fNewState)
05965 {
05966     fRestoreViewOnImport = fNewState;
05967 }
05968 
05969 
05970 
05971 
05972 /***********************************************************************************************
05973 
05974 >   Document::GetDocFontUnits()
05975 
05976     Author:     Chris_Parks (Xara Group Ltd) <camelotdev@xara.com>
05977     Created:    6/5/95
05978     Returns:    Returns Font UnitType for this document
05979     Purpose:    return Font Units for this document
05980                 default to COMP_POINTS if no unit list available
05981 
05982 *************************************************************************************************/                               
05983 
05984 UnitType Document::GetDocFontUnits()
05985 {   
05986     if(pDocUnitList)
05987         return pDocUnitList->GetFontUnits();
05988     else
05989         return COMP_POINTS;
05990 }
05991 
05992 
05993 /***********************************************************************************************
05994 
05995 >   BitmapList* Document::GetBitmapList()
05996 
05997     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05998     Created:    20/8/96
05999     Returns:    Returns this document's bitmap list
06000     Purpose:    Gets the bitmap list from this documents doc component
06001 
06002 *************************************************************************************************/                               
06003 
06004 BitmapList* Document::GetBitmapList()
06005 {
06006     // Find this documents BitmapListComponent
06007     DocComponent* DocBitmapList = 
06008             GetDocComponent(CC_RUNTIME_CLASS(BitmapListComponent));
06009 
06010     ERROR2IF(DocBitmapList == NULL, FALSE, "Couldn't find document bitmap list");
06011     if (DocBitmapList == NULL)
06012         return NULL;
06013 
06014     // Now get the actual bitmap list
06015     return ((BitmapListComponent*)DocBitmapList)->GetBitmapList();
06016 }
06017 
06018 
06019 
06020 /********************************************************************************************
06021 
06022 >   BOOL Document::SetDocNudge (UINT32 newVal)
06023 
06024     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
06025     Created:    31/8/2000
06026     Inputs:     newVal - the new documents nudge size
06027     Returns:    -
06028     Purpose:    Sets the documents nudge size
06029     Errors:     -
06030     SeeAlso:    -
06031 
06032 ********************************************************************************************/
06033 
06034 BOOL Document::SetDocNudge (UINT32 newVal)
06035 {
06036     m_docNudge = newVal;
06037     OpNudge::SetNudgeStep (m_docNudge);     // I need to call this directly to get camelot to
06038                                             // use the new value.
06039     return (TRUE);
06040 }
06041 
06042 
06043 
06044 /***********************************************************************************************
06045 
06046 >   INT32 Document::GetNumLayers() const
06047 
06048     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
06049     Created:    8/7/97
06050     Returns:    -
06051     Purpose:    Counts the layers in this document.
06052 
06053                 This function assumes there is only one spread in the document, so 
06054                 it will fail if we ever implement multiple spread documents (chuckle).
06055 
06056 *************************************************************************************************/                               
06057 
06058 INT32 Document::GetNumLayers()
06059 {
06060     //Find the first spread in the document
06061 PORTNOTE("spread", "Multi-spread warning!")
06062     Spread* pSpread = FindFirstSpread();
06063 
06064     //Now find the first layer in that spread
06065     Layer* pLayer = NULL;
06066     if (pSpread != NULL)
06067         pLayer = pSpread->FindFirstLayer();
06068 
06069     //And count the layers
06070     INT32 iCount = 0;
06071 
06072     while (pLayer != NULL)
06073     {
06074         iCount++;
06075         pLayer=pLayer->FindNextLayer();
06076     }
06077 
06078     return iCount;
06079 }
06080 
06081 /***********************************************************************************************
06082 
06083 >   BOOL Document::IsAnimated() const
06084 
06085     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
06086     Created:    27/10/97
06087     Returns:    -
06088     Purpose:    Finds whether this document is an animation. 
06089 
06090                 We assume the document is an animation if it contains one or more
06091                 frame layers
06092 
06093 *************************************************************************************************/                               
06094 
06095 BOOL Document::IsAnimated()
06096 {
06097     //Find the first spread in the document
06098 PORTNOTE("spread", "Multi-spread warning!")
06099     Spread* pSpread = FindFirstSpread();
06100 
06101     //Find the first frame layer in that spread
06102     Layer * pFrame = pSpread->FindFirstFrameLayer();
06103 
06104     //If there is one, return TRUE. Otherwise return FALSE
06105     return !(pFrame==NULL);
06106     
06107     
06108 }
06109 
06110 
06111 
06112 
06113 /***********************************************************************************************
06114 
06115 >   Progressive Rendering
06116 
06117 *************************************************************************************************/                               
06118 
06119 /***********************************************************************************************
06120 
06121 >   Node* Document::GetLastSafeNodeToRender()
06122 
06123     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
06124     Created:    6/9/96
06125     Purpose:    Returns a reference to the document's 'Safe render pointer'
06126 
06127 *************************************************************************************************/                               
06128 
06129 SafeRenderPointer& Document::GetSafeRenderPointer()
06130 {
06131     return TheSafeRenderPointer;
06132 }
06133 
06134 
06135 /***********************************************************************************************
06136 
06137 >   SafeRenderPointer::SafeRenderPointer()
06138 
06139     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
06140     Created:    6/9/96
06141     Purpose:    Constructs a SafeRenderPointer object
06142 
06143 *************************************************************************************************/                               
06144 
06145 SafeRenderPointer::SafeRenderPointer()
06146 {
06147     m_bPointerValid = TRUE;
06148     pLastSafeNodeToRender = NULL;
06149 }
06150 
06151 /***********************************************************************************************
06152 
06153 >   SafeRenderPointer::~SafeRenderPointer()
06154 
06155     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
06156     Created:    6/9/96
06157     Purpose:    Destroys a SafeRenderPointer object
06158 
06159 *************************************************************************************************/                               
06160 
06161 SafeRenderPointer::~SafeRenderPointer()
06162 {
06163     // Empty.
06164 }
06165 
06166 /***********************************************************************************************
06167 
06168 >   BOOL SafeRenderPointer::UpdateLastSafeNode(Node* pNewNode)
06169 
06170     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
06171     Created:    6/9/96
06172     Purpose:    Updates the last safe node that can be rendered
06173 
06174 *************************************************************************************************/                               
06175 
06176 BOOL SafeRenderPointer::UpdateLastSafeNode(Node* pNewNode)
06177 {
06178     ERROR2IF(!m_bPointerValid, FALSE, "Trying to set safe pointer when it's invalid.");
06179 
06180 #ifdef RALPH
06181 
06182     if ((!pLastSafeNodeToRender) && pNewNode)
06183     {
06184         NodeDocument* pNodeDoc = (NodeDocument*) pNewNode->FindParent(CC_RUNTIME_CLASS(NodeDocument)); 
06185         ASSERT (pNodeDoc); 
06186         if (pNodeDoc)
06187         {
06188             Document* TheDoc = (Document*)pNodeDoc->GetParentDoc();
06189             ASSERT(TheDoc); 
06190             if (TheDoc)
06191             {
06192                 RalphDocument* pRalphDoc = TheDoc->GetRalphDoc(); 
06193                 if (pRalphDoc)
06194                 {
06195                     RalphView * pRalphView = pRalphDoc->GetRalphView();
06196                     if(pRalphView)
06197                     {
06198                     /*  OpZoomDescriptor::FakeZoomToRect(&(pRalphDoc->GetViewportRect()));
06199                         pRalphView->SetSafeToDraw(TRUE);
06200                     */
06201                         //Beep(1500,15);
06202 
06203                         SendMessage(pRalphView->GetSafeHwnd(),WM_ZOOMTORECT,NULL,(INT32)(pRalphDoc->GetViewportRect()));
06204                     }
06205                 }
06206             }
06207         }
06208     }
06209 
06210 #endif
06211 
06212     // Make sure this pointer cannot be accessed by other threads
06213     // while we update it
06214 //  CCamApp::EnterSafeRenderCriticalSection();
06215     
06216 //  TRACEUSER( "Will", _T("Thread %d is setting safe node to %x\n"), GetCurrentThreadId(), pNewNode);
06217     pLastSafeNodeToRender = pNewNode;
06218 
06219     // Ok, it's safe for other threads to access us now
06220 //  CCamApp::ExitSafeRenderCriticalSection();
06221     return TRUE;
06222 }
06223 
06224 /***********************************************************************************************
06225 
06226 >   Node* SafeRenderPointer::GetLastSafeNode()
06227 
06228     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
06229     Created:    6/9/96
06230     Purpose:    Returns a pointer to the last safe node that can be rendered
06231 
06232 *************************************************************************************************/                               
06233 
06234 Node* SafeRenderPointer::GetLastSafeNode()
06235 {
06236     if (!m_bPointerValid)
06237         return NULL;
06238 
06239     Node* pSafeNode = NULL;
06240 
06241     // Make sure this pointer cannot be updated by another thread while we read it
06242 //  CCamApp::EnterSafeRenderCriticalSection();
06243 
06244     pSafeNode = pLastSafeNodeToRender;
06245 //  TRACEUSER( "Will", _T("Thread %d is reading safe node as %x\n"), GetCurrentThreadId(), pSafeNode);
06246 
06247     // Ok, it's safe for other threads to update it now
06248 //  CCamApp::ExitSafeRenderCriticalSection();
06249 
06250     return pSafeNode;
06251 }
06252 
06253 /***********************************************************************************************
06254 
06255 >   void SafeRenderPointer::SetPointerValid()
06256 
06257     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
06258     Created:    6/9/96
06259     Purpose:    Sets the pointer as being valid
06260 
06261 *************************************************************************************************/                               
06262 
06263 void SafeRenderPointer::SetPointerValid()
06264 {
06265 //  TRACEUSER( "Will", _T("Thread %d is setting safe node ptr as VALID\n"), GetCurrentThreadId());
06266     m_bPointerValid = TRUE;
06267 }
06268 
06269 /***********************************************************************************************
06270 
06271 >   void SafeRenderPointer::SetPointerInValid()
06272 
06273     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
06274     Created:    6/9/96
06275     Purpose:    Sets the pointer as being invalid
06276 
06277 *************************************************************************************************/                               
06278 
06279 void SafeRenderPointer::SetPointerInValid()
06280 {
06281 //  TRACEUSER( "Will", _T("Thread %d is setting safe node ptr as INVALID\n"), GetCurrentThreadId());
06282     m_bPointerValid = FALSE;
06283 }
06284 
06285 /***********************************************************************************************
06286 
06287 >   BOOL SafeRenderPointer::IsPointerValid()
06288 
06289     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
06290     Created:    6/9/96
06291     Purpose:    Returns whether or not the pointer is valid
06292 
06293 *************************************************************************************************/                               
06294 
06295 BOOL SafeRenderPointer::IsPointerValid()
06296 {
06297     return m_bPointerValid;
06298 }

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