clipint.cpp

Go to the documentation of this file.
00001 // $Id: clipint.cpp 1282 2006-06-09 09:46:49Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 /*
00099 //*/
00100 // Camelot's Internal clipboard
00101 
00102 
00103 #include "camtypes.h"
00104 
00105 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 #include "chapter.h"
00107 //#include "clipext.h"  // External (oil) clipboard stuff
00108 #include "clipint.h"    // Internal clipboard stuff
00109 //#include "group.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 #include "layer.h"
00111 //#include "simon.h"
00112 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 #include "colourix.h"
00114 #include "collist.h"
00115 #include "cliptype.h"
00116 
00117 #include "camdoc.h"
00118 #include "optspage.h"   // for PageResizeInfo page settings
00119 
00120 #include <math.h>       // for floor()
00121 
00122 #include "nodetxts.h"   //To add text to the clipboard
00123 #include "nodedoc.h"
00124 //#include "srvritem.h" //for justin's clever "add-text-to-the-clipboard" function
00125 
00126 //#include "will2.h"
00127 //#include "mario.h"
00128 //#include "justin3.h"
00129 
00130 #include "bmpcomp.h"    // BitmapList
00131 
00132 DECLARE_SOURCE("$Revision: 1282 $"); 
00133 
00134 
00135 CC_IMPLEMENT_DYNAMIC(InternalClipboard, Document)
00136 CC_IMPLEMENT_MEMDUMP(InternalClipboardFormat, CC_CLASS_MEMDUMP)
00137 
00138 #define new CAM_DEBUG_NEW
00139 
00140 
00141 InternalClipboard* InternalClipboard::pInstance = 0;
00142 InternalClipboard* InternalClipboard::pOther = 0;
00143 
00144 
00145 
00146 /********************************************************************************************
00147 
00148 >   InternalClipboard::InternalClipboard(InternalClipboard::ID id, BOOL fHide = TRUE)
00149 
00150     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00151     Created:    5/7/94
00152 
00153     Purpose:    InternalClipboard constructor. 
00154 
00155 ********************************************************************************************/
00156 
00157 InternalClipboard::InternalClipboard(InternalClipboard::ID id, BOOL fHide)
00158   : Document(fHide),
00159     pClipboardRange(new Range),
00160     ClipOp(FALSE),
00161     m_id(id)
00162 {
00163     // Empty.
00164 }
00165 
00166 
00167 /********************************************************************************************
00168 
00169 >   virtual InternalClipboard::~InternalClipboard(); // Destructor
00170 
00171     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00172     Created:    5/7/94
00173 
00174     Purpose:    InternalClipboard destructor
00175 
00176 ********************************************************************************************/
00177 
00178 InternalClipboard::~InternalClipboard()
00179 {
00180     delete pClipboardRange;
00181     pClipboardRange = 0;
00182 }
00183 
00184 
00185 
00186 /********************************************************************************************
00187 >   static InternalClipboard::ID InternalClipboard::GetCurrentID()
00188 
00189     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00190     Created:    13/10/96
00191     Returns:    The ID of the 'current' clipboard, the one return by Instance().
00192 ********************************************************************************************/
00193 
00194 InternalClipboard::ID InternalClipboard::GetCurrentID()
00195 {
00196     return pInstance->m_id;
00197 }
00198 
00199 
00200 
00201 /********************************************************************************************
00202 
00203 >   static BOOL InternalClipboard::Initialise()                  
00204 
00205     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00206     Created:    15/8/94
00207 
00208     Purpose:    This method creates the one and only instance of the InternalClipboard and
00209                 then initialises it. Called by main3.cpp
00210 
00211 ********************************************************************************************/
00212 
00213 BOOL InternalClipboard::Initialise()                 
00214 {
00215     // Create the clipboards.
00216     if (!(pInstance = new InternalClipboard(InternalClipboard::CLIPBOARD))) return FALSE;
00217 
00218     if (!(pOther = new InternalClipboard(InternalClipboard::DRAGDROP)))
00219     {
00220         delete pInstance;
00221         return FALSE;
00222     }
00223 
00224 //  if (!CCamDoc::Create(pInstance))
00225 PORTNOTE("other", "Clipboard doc should be hidden")
00226     CCamDoc* pOilDoc1 = new CCamDoc(pInstance);
00227     if (pOilDoc1 == NULL)
00228     {
00229         delete pInstance;
00230         delete pOther;
00231         return FALSE;
00232     }
00233 
00234 //  if (!CCamDoc::Create(pOther))
00235 PORTNOTE("other", "Clipboard doc should be hidden")
00236     CCamDoc* pOilDoc2 = new CCamDoc(pOther);
00237     if (pOilDoc2 == NULL)
00238     {
00239         delete pInstance->GetOilDoc();
00240         delete pOther;
00241         return FALSE;
00242     }
00243 
00244     pInstance->OriginalCentreLock = TRUE;
00245      
00246     return TRUE;
00247 }
00248 
00249 
00250 
00251 /********************************************************************************************
00252 
00253 >   BOOL InternalClipboard::Init(CCamDoc* pOilDoc)
00254 
00255     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00256     Created:    15/8/94
00257     
00258     Inputs:     pOilDoc - the CCamDoc to attach the cliboard to, if any.
00259     
00260     Returns:    FALSE if it failed
00261 
00262     Purpose:    This method initialises the Internal clipboard.
00263                 It is an internal method, called by Initialise()
00264                 It calls down to Document::Init, then adds an insertion Layer node to the
00265                 bottom of the basic doc tree.
00266 
00267     SeeAlso:    InternalClipboard::Initialise(); Document::Init; Document::InitTree
00268 
00269 ********************************************************************************************/
00270 
00271 BOOL InternalClipboard::Init(CCamDoc* pOilDoc)
00272 {
00273     if (!Document::Init(pOilDoc)) return FALSE;
00274 
00275     Node *pSpread = FindFirstSpread();
00276     ERROR3IF(pSpread == NULL, "No Spread in document!");
00277 
00278     Node *InsPos = pSpread->FindFirstChild();
00279     ERROR3IF(InsPos == NULL, "No Spread-child in document!");
00280 
00281     // Now scan the children of the first spread until we find a layer, or run out of nodes
00282     while (InsPos != NULL && !InsPos->IsLayer())
00283         InsPos = InsPos->FindNext();
00284 
00285     if (InsPos == NULL)     // No Layer, so we'd better add one for ourselves
00286     {
00287         String_256 LayerID = String_256(_R(IDS_K_CLIPINT_LAYERNAME));
00288         Layer *pLayer = new Layer(pSpread, LASTCHILD, LayerID);
00289         ERRORIF(!pLayer, _R(IDE_NOMORE_MEMORY), InitFailed())
00290     }
00291 
00292     OriginalCentreLock = TRUE;
00293 
00294     // Sucess.
00295     return(TRUE);;
00296 }
00297 
00298 
00299 
00300 /********************************************************************************************
00301 
00302 >   static void InternalClipboard::Deinit()                  
00303 
00304     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00305     Created:    15/8/94
00306 
00307     Purpose:    This method destroys the InternalClipboard
00308                 It is called by main.cpp on shutdown
00309                 (and now by CCamDocTemplate::CloseAllDocuments immediately prior to shutdown)
00310 
00311     Notes:      This code may be called multiple times without problems. Please keep it that way.
00312 
00313 ********************************************************************************************/
00314 
00315 void InternalClipboard::Deinit()
00316 {
00317     // Make sure the clipboards are empty.
00318     // Sort out the main clipboard first
00319     Clear();
00320 
00321     // Now sort out the alternate clipborad
00322     Swap();
00323     Clear();
00324     Swap();
00325     
00326     if (pInstance)
00327     {
00328         delete pInstance->GetOilDoc();
00329         pInstance = 0;
00330     }
00331 
00332     if (pOther)
00333     {
00334         delete pOther->GetOilDoc();
00335         pOther = 0;
00336     }
00337 }
00338 
00339 
00340 
00341 /********************************************************************************************
00342 
00343 >   static void InternalClipboard::Swap()
00344 
00345     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00346     Created:    29/9/96
00347     Purpose:    Swaps the two internal clipboards, pInstance and pOther.  Used to allow
00348                 drag'n'drop operations to happen without disturbing the internal
00349                 clipboard.
00350     Errors:     -
00351     SeeAlso:    -
00352 
00353 ********************************************************************************************/
00354 
00355 void InternalClipboard::Swap()
00356 {
00357     InternalClipboard* pcb = pInstance;
00358     pInstance = pOther;
00359     pOther = pcb;
00360 }
00361 
00362 
00363 
00364 /********************************************************************************************
00365 
00366 >   static Layer *InternalClipboard::GetInsertionLayer()
00367 
00368     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (recoded from Simon's for new clipboard document layout)
00369     Created:    23/4/95 (21/7/94)
00370 
00371     Returns:    A pointer to the layer which is the parent of all objects placed on the 
00372                 clipboard
00373 
00374     Purpose:    Returns a pointer to the clipboard's layer node which is the parent of all
00375                 nodes which get added to the clipboard. 
00376 
00377     Errors:     ERROR3 and returns NULL if an internal consistency check fails
00378 
00379 ********************************************************************************************/
00380 
00381 Layer* InternalClipboard::GetInsertionLayer()
00382 {
00383     // Is there a tree (this gets called during destruction, which is a real pain).
00384     if (!pInstance || !pInstance->GetFirstNode())
00385     {
00386         TRACEUSER( "JustinF", _T("No first node in InternalClipboard::GetInsertionLayer\n"));
00387         return 0;
00388     }
00389 
00390     // Get the first spread
00391     Node* pSpread = pInstance->FindFirstSpread();
00392     ERROR3IF(pSpread == NULL, "No spread found in clipboard doc");
00393 
00394     // Get the spread's first child...
00395     Node *InsPos = pSpread->FindFirstChild();
00396     ERROR3IF(InsPos == NULL, "No spread-child found in clipboard doc");
00397 
00398     // And now search across until we find the first layer
00399     while (InsPos != NULL && !InsPos->IsLayer())
00400         InsPos = InsPos->FindNext();
00401 
00402     ERROR3IF(InsPos == NULL, "No insertion layer found in clipboard doc");
00403     return (Layer*) InsPos;
00404 }
00405 
00406 
00407 
00408 /********************************************************************************************
00409 
00410 >   void InternalClipboard::Clear();                                                                         
00411 
00412     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00413     Created:    21/7/94
00414 
00415     Purpose:    Deletes the contents of the internal clipboard
00416 
00417 ********************************************************************************************/
00418 
00419 void InternalClipboard::Clear()
00420 {
00421     Layer* Root = GetInsertionLayer();
00422     if (Root == NULL || Root->FindFirstChild() == NULL)
00423         return;     // The clipboard is empty already
00424 
00425     // The clipboard range is no longer valid
00426     if (pInstance->pClipboardRange) delete pInstance->pClipboardRange;
00427 
00428     // An empty range. We need to create this cos the operation could fail
00429     pInstance->pClipboardRange = new Range;
00430 
00431     // Delete all objects in clipboard
00432     Root->DeleteChildren(Root->FindFirstChild());
00433 
00434 
00435     // Ensure that the top level of the tree has bounding rect caches invalidated,
00436     // as we' ve just vaped the entire subtree below it
00437     Root->InvalidateBoundingRect();
00438 
00439   // We can't do this at the moment because by the time we're called it seems the component
00440   // copy is already under way, and so we're well screwed
00441 
00442     // Destroy and re-initialise the doc-components (to chuck away unneeded stuff)
00443 //  DestroyDocComponents(); 
00444 //  if (!InitDocComponents())
00445 //  {
00446 //      ERROR3("DocComponent initialisation failed in InternalClipboard::ClearClipboard");
00447 //  }
00448 
00449     // Instead, we are really only concerned about stacks of colours building up, so
00450     // we'll just delete any *unused* IndexedColours from the document's list. (Some colours
00451     // are kept in-use by the attribute manager and stuff...)
00452 
00453     // First, all named colours (styles)
00454     ColourList *ColList = pInstance->GetIndexedColours();
00455     IndexedColour *Ptr = (IndexedColour *) ColList->GetHead();
00456     IndexedColour *Next;
00457     while (Ptr != NULL)
00458     {
00459         Next = (IndexedColour *) ColList->GetNext((ListItem*)Ptr);
00460         if (!Ptr->IsInUse())
00461         {
00462             // Remove this colour from the list
00463             ColList->RemoveItem(Ptr);
00464 
00465             // Ensure this is not in use as a parent of other colours
00466             ColList->RemoveLinksToColour(Ptr);
00467 
00468             // And vape it
00469             delete Ptr;
00470         }
00471 
00472         Ptr = Next;
00473     }
00474 
00475     // Now all unnamed colours (locals)
00476     List *Locals = ColList->GetUnnamedColours();
00477     Ptr = (IndexedColour *) Locals->GetHead();
00478     while (Ptr != NULL)
00479     {
00480         Next = (IndexedColour *) Locals->GetNext(Ptr);
00481         if (!Ptr->IsInUse())
00482         {
00483             // Remove this colour from the list
00484             Locals->RemoveItem(Ptr);
00485 
00486             // And vape it (locals can't be parent colours, so no need to
00487             // RemoveLinksToColour() for them)
00488             delete Ptr;
00489         }
00490 
00491         Ptr = Next;
00492     }
00493 
00494     // Now do the same for this document's bitmap list
00495     BitmapList *pBmpList = pInstance->GetBitmapList();
00496     if (pBmpList)
00497     {
00498         ListItem* pItem = pBmpList->GetHead();
00499         ListItem* pNextItem;
00500         while (pItem)
00501         {
00502             pNextItem = pBmpList->GetNext(pItem);
00503 
00504             KernelBitmap* pBmpItem = (KernelBitmap*)pItem;
00505             // check if it is the default bitmap, if so then leave in the list
00506             if (!pBmpItem->IsDefaultBitmap())
00507             {           
00508                 pBmpList->RemoveItem(pBmpItem);
00509                 delete pBmpItem;
00510             }
00511 
00512             pItem = pNextItem;
00513         }
00514     }
00515 }
00516 
00517 
00518 
00519 /********************************************************************************************
00520 
00521 >   static BOOL InternalClipboard::AttrsHaveChanged()
00522 
00523     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00524     Purpose:    This function should be called if the attributes of the Internal clipboard
00525                 have changed in some way. eg. if a bitmap has been deleted.  It destroys
00526                 the cache of common attributes.
00527 
00528 ********************************************************************************************/
00529 
00530 void InternalClipboard::AttrsHaveChanged()
00531 {
00532     if (pInstance && pInstance->pClipboardRange)
00533     {
00534         pInstance->pClipboardRange->AttrsHaveChanged();
00535     }
00536 }
00537 
00538 
00539 
00540 /********************************************************************************************
00541 
00542 >   BOOL InternalClipboard::CopyObjects(Range& RangeToCopy, Operation * pOp)
00543 
00544     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00545     Created:    21/7/94
00546     Inputs:     RangeToCopy: The objects to copy to the clipboard
00547 
00548     Returns:    FALSE if we could not copy 
00549 
00550     Purpose:    Copies a range of objects to the clipboard, all previous clipboard contents
00551                 are deleted. If the copy fails the clipboard is emptied and FALSE returned.
00552                 It can be called via CALL_WITH_FAIL.
00553 
00554     SeeAlso:    InternalClipboard::CopyComponentData()
00555 
00556 ********************************************************************************************/
00557 
00558 
00559 
00560 BOOL InternalClipboard::CopyObjects(Range& RangeToCopy, Operation * pOp)
00561 {
00562      // Delete the current contents of the clipboard
00563     pInstance->ClipOp = TRUE;
00564     Clear();
00565     
00566     // All objects to be copied to the clipboard need to be made attribute complete or else
00567     // they may loose important attributes. This is especially true of objects within groups.
00568 
00569     if (!(RangeToCopy.MakeAttributeComplete(TRUE,FALSE,TRUE)))
00570         return(FALSE); // Failed
00571 
00572     BOOL Failed = FALSE;  // until we know better
00573 
00574     Node* Root = GetInsertionLayer(); 
00575     ENSURE(Root != NULL, "Root of clipboard is NULL"); 
00576 
00577     if (!Root->CopyComplexRange(RangeToCopy))
00578     {
00579         Failed = TRUE;
00580         Clear();    // Tidy up
00581         ERROR3("Failed to copy objects");
00582     }
00583 
00584 // Matt (+Karim, + MarkH + loads of other people I whined to) - 02/02/2001
00585 // Removed David McClarnon's fix for 'copy-inside on bevelled blends' as it causes the operation history to
00586 // reference the object in the clipboard - which is deleted when the clipboard is changed !!! -> AccessViolation-ahoy!
00587 /*
00588     // call post duplicate on all nodes
00589     Node * pChildNode = Root->FindFirstDepthFirst();
00590 
00591     while (pChildNode && pChildNode != Root)
00592     {
00593         if (pChildNode->IsAnObject())
00594         {
00595             if (pOp != NULL)
00596             {
00597                 if (pOp->IS_KIND_OF(UndoableOperation))
00598                 {
00599                     ((NodeRenderableInk *)pChildNode)->PostDuplicate((UndoableOperation *)pOp);
00600                 }
00601                 else
00602                 {
00603                     if (!pChildNode->IsABaseTextClass())
00604                         ((NodeRenderableInk *)pChildNode)->PostDuplicate(NULL);
00605                 }
00606             }
00607         }
00608 
00609         pChildNode = pChildNode->FindNextDepthFirst(Root);
00610     }
00611 */
00612     // We now need to optimise the attributes on all objects copied to the clipboard
00613     if (!Failed)
00614     {
00615         Node* FirstNode = pInstance->GetFirstNode();
00616         ERROR3IF(!FirstNode, "Cannot find first clipboard node"); 
00617         if (FirstNode)
00618         {
00619             Node* Root = FirstNode->FindNext(); 
00620             ERROR3IF(!Root, "Clipboard has no root");
00621             ERROR3IF(!(IS_A(Root, NodeDocument)), "This should be the root of the clipboard"); 
00622             if (Root)
00623             { 
00624                 if (!Root->OptimiseAttributes())
00625                 {
00626                     Failed = TRUE; 
00627                     Clear(); 
00628                 }
00629             } 
00630         } 
00631     
00632     }
00633  
00634         
00635     // Ensure that the top level of the tree has bounding rect caches invalidated,
00636     // as we've just plugged an entire new subtree in!
00637     ((Layer *)Root)->InvalidateBoundingRect();
00638 
00639     // We now need to Normalise the attributes of all objects copied
00640     RangeToCopy.NormaliseAttributes(FALSE,TRUE); 
00641 
00642     pInstance->ClipOp = FALSE;
00643     return (!Failed); 
00644 } 
00645 
00646 
00647 
00648 
00649 
00650 /********************************************************************************************
00651 
00652 >   BOOL InternalClipboard::CopyComponentData(BaseDocument* pSrcDoc)
00653 
00654     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00655     Created:    21/7/94
00656     Inputs:     pSrcDoc: The source document
00657 
00658     Returns:    FALSE if the component data has not successfuly been copied accross. In this
00659                 situation AbortComponentCopy gets called. 
00660                  
00661     Purpose:    This function should get called after CopyObjects has been called. It asks
00662                 all objects to copy accross their component data to the clipboard. It can
00663                 be called via CALL_WITH_FAIL.
00664 
00665 ********************************************************************************************/
00666 
00667 BOOL InternalClipboard::CopyComponentData(BaseDocument* pSrcDoc)
00668 {
00669     if (IsEmpty(FALSE))
00670     {
00671         // The CopyObjects either was not called, or failed
00672         ERROR3("InternalClipboard::CopyComponentData called when clipboard is empty!");
00673         return(FALSE);
00674     }
00675     
00676     // Scan all clipboard nodes
00677     Node* Root = GetInsertionLayer();
00678     Node* Current = Root->FindFirstDepthFirst();
00679     while (Current != NULL)
00680     {
00681         // Ask the current node if it would copy it's data to the relevant DocComponents
00682         if (Current->IsKindOf(CC_RUNTIME_CLASS(NodeRenderable)))
00683         {
00684             if (!((NodeRenderable*) Current)->CopyComponentData(pSrcDoc, pInstance))
00685             {
00686                 // No luck
00687                 pInstance->AbortComponentCopy();    // Cancel all data which has been copied
00688                 Clear();        // Tidy up
00689                 return FALSE; 
00690             }
00691         }
00692 
00693         Current = Current->FindNextDepthFirst(Root); 
00694     }
00695 
00696     return TRUE; // Success
00697 }
00698 
00699 
00700 
00701 /********************************************************************************************
00702 
00703 >   DocRect InternalClipboard::GetObjectsBounds()
00704 
00705     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00706     Created:    28/7/94
00707 
00708     Returns:    The bounds of all objects in the clipboard
00709 
00710     Purpose:    For finding the bounds of all objects in the clipboard
00711 
00712 ********************************************************************************************/
00713 
00714 DocRect InternalClipboard::GetObjectsBounds()
00715 {
00716     DocRect Bounds;
00717 
00718     ERROR3IF(IsEmpty(FALSE), "InternalClipboard::GetObjectsBounds called when CB is empty");
00719 
00720     Node* CurrentNode = GetInsertionLayer()->FindFirstChild();
00721     while (CurrentNode  != NULL)
00722     {
00723         if (CurrentNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableBounded)))
00724         {
00725             Bounds = Bounds.Union(
00726                 ( ((NodeRenderableBounded*)CurrentNode)->GetBoundingRect(TRUE, FALSE)) );
00727         }
00728         CurrentNode = CurrentNode->FindNext();
00729     }
00730 
00731     return Bounds;
00732 }
00733 
00734 
00735 
00736 /********************************************************************************************
00737 
00738 >   static BOOL InternalClipboard::CopyInProgress(void)
00739 
00740     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00741     Created:    19/4/95
00742 
00743     Returns:    TRUE if we are currently busy copying
00744 
00745     Purpose:    Allows external entities to determine if they were called during a
00746                 clipboard copy operation.
00747 
00748 ********************************************************************************************/
00749 
00750 BOOL InternalClipboard::CopyInProgress()
00751 {
00752     return pInstance->ClipOp;
00753 }
00754 
00755 
00756 /********************************************************************************************
00757 
00758 >   static BOOL InternalClipboard::IsEmpty(BOOL AskExternalClipboard = TRUE)
00759 
00760     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00761     Created:    19/4/95
00762 
00763     Inputs:     AskExternalClipboard - if TRUE, this method will tell you if there is ANY
00764                 data available for pasting. If FALSE, it simply checks if the internal
00765                 clipboard (esentially an internal cache) is empty. ONLY the external clipboard
00766                 (or internal calls in this class) should ever pass in FALSE for this parameter!
00767 
00768     Returns:    TRUE if the clipboard is empty (no data to paste)
00769                 FALSE if the clipboard is non-empty (there is data available to paste)
00770 
00771     Purpose:    To determine if there is anything currently stored on the internal clipboard
00772 
00773     Notes:      If there is no internal clipboard, it will return TRUE
00774 
00775 ********************************************************************************************/
00776 
00777 BOOL InternalClipboard::IsEmpty(BOOL AskExternalClipboard)
00778 {
00779     if (pInstance == NULL)
00780         return(TRUE);
00781 
00782     Layer *templayer = pInstance->GetInsertionLayer();
00783     if (!templayer) {   ERROR3("Can't get clipboard insertion layer!"); return TRUE; }
00784 
00785     Node* n = templayer->FindFirstChild();
00786     BOOL Empty = (n == NULL);
00787 
00788     if (Empty && AskExternalClipboard)
00789     {
00790 PORTNOTE("extclipboard", "Removed use of External Clipboard")
00791 #ifndef EXCLUDE_FROM_XARALX
00792         // We're empty, so ask the External clipboard if it can supply us with data
00793         ExternalClipboard *Clipboard = ExternalClipboard::GetExternalClipboard();
00794 
00795         if (Clipboard == NULL)
00796             return(TRUE);
00797 
00798         return(Clipboard->IsEmpty());
00799 #else
00800         return TRUE;
00801 #endif
00802     }
00803 
00804     return(Empty);
00805 }
00806 
00807 
00808 
00809 /********************************************************************************************
00810 
00811 >   BOOL InternalClipboard::PrepareForCopy(void)
00812 
00813     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00814     Created:    19/4/95
00815 
00816     Returns:    TRUE if the clipboard is ready to accept new data
00817                 FALSE if the copy must be aborted
00818 
00819     Purpose:    To ready the clipboard for a cut/copy operation (copy data TO the clipboard).
00820                 This will interact with the external clipboard in order to claim the global
00821                 clipboard, and readies the clipboard for use.
00822 
00823     Notes:      After you have copied data to the clipboard, you MUST call CopyCompleted
00824 
00825     SeeAlso:    InternalClipboard::CopyCompleted; InternalClipboard::PrepareForPaste;
00826                 ExternalClipboard::PrepareForCopy
00827 
00828 ********************************************************************************************/
00829 
00830 BOOL InternalClipboard::PrepareForCopy(void)
00831 {
00832     Clear();
00833 PORTNOTE("extclipboard", "Removed use of External Clipboard")
00834 #ifndef EXCLUDE_FROM_XARALX
00835     ExternalClipboard* pcb = ExternalClipboard::GetExternalClipboard();
00836     return pcb ? pcb->PrepareForCopy() : FALSE;
00837 #else
00838     return TRUE;
00839 #endif
00840 }
00841 
00842 
00843 
00844 /********************************************************************************************
00845 
00846 >   BOOL InternalClipboard::CopyCompleted(void)
00847 
00848     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00849     Created:    19/4/95
00850 
00851     Returns:    TRUE if all went well
00852                 FALSE if the copy failed in some way
00853 
00854     Purpose:    Tells the InternalClipboard that you have finished copying data to it.
00855                 This interacts with the external clipboard in order to make the new data
00856                 available to the outside world.
00857 
00858     Notes:      Before starting to copy data to the clipboard you MUST call PrepareForCopy
00859 
00860     SeeAlso:    InternalClipboard::PrepareForCopy; ExternalClipboard::CopyCompleted
00861 
00862 ********************************************************************************************/
00863 
00864 BOOL InternalClipboard::CopyCompleted(void)
00865 {
00866     if (IsEmpty(FALSE))
00867     {
00868         ERROR3("That copy wasn't much fun - the clipboard's still empty!");
00869         return(FALSE);
00870     }
00871 
00872 PORTNOTE("extclipboard", "Removed use of External Clipboard")
00873 #ifndef EXCLUDE_FROM_XARALX
00874     ExternalClipboard *Clipboard = ExternalClipboard::GetExternalClipboard();
00875     if (Clipboard == NULL) return(FALSE);
00876 
00877     if (Clipboard->CopyCompleted())
00878     {
00879 #endif
00880         // Objects have successfully been moved to clipboard. Perform neccessary processing
00881         if (!pInstance->OnNewClipboardObjects()) InformError();
00882         return TRUE; 
00883 #ifndef EXCLUDE_FROM_XARALX
00884     }   
00885     else
00886     {
00887         return FALSE;
00888     }
00889 #endif
00890 }
00891 
00892 
00893 
00894 /********************************************************************************************
00895 
00896 >   BOOL InternalClipboard::PrepareForPaste(BOOL* ExternalSource = NULL)
00897 
00898     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00899     Created:    19/4/95
00900 
00901     Outputs:    ExternalSource: When the function returns TRUE, ExternalSource will be TRUE
00902                                 if the data has come from the external clipboard, and
00903                                 FALSE if not.
00904 
00905     Returns:    TRUE if the clipboard is ready to provide data for pasting
00906                 FALSE if the paste must be aborted (nothing to paste)
00907 
00908     Purpose:    To ready the clipboard for a paste operation (copy data FROM the clipboard).
00909                 This may interact with the external clipboard in order to provide the
00910                 necessary data.
00911 
00912     Notes:      After copying data from the clipboard you MUST call PasteCompleted
00913 
00914     SeeAlso:    InternalClipboard::PasteCompleted; InternalClipboard::PrepareForCopy;
00915                 ExternalClipboard::PrepareForPaste
00916 
00917 ********************************************************************************************/
00918 
00919 BOOL InternalClipboard::PrepareForPaste(BOOL* ExternalSource)
00920 {
00921     if (ExternalSource)
00922         *ExternalSource = FALSE;   // Until we know better
00923 
00924     pInstance->OriginalCentreLock = TRUE;                       // Don't allow centre to be reset
00925 
00926     // If we are empty, then we'll have to go and look outside for something to put onto
00927     // the internal clipboard.
00928     if (IsEmpty(FALSE))
00929     {
00930 PORTNOTE("extclipboard", "Removed use of External Clipboard")
00931 #ifndef EXCLUDE_FROM_XARALX
00932         ExternalClipboard *Clipboard = ExternalClipboard::GetExternalClipboard();
00933         if (Clipboard == NULL || !Clipboard->PrepareForPaste())
00934             return(FALSE);
00935 
00936         // Optimise attributes on the clipboard
00937         Node* FirstNode = pInstance->GetFirstNode();
00938         ERROR3IF(!FirstNode, "Cannot find first clipboard node"); 
00939         if (FirstNode)
00940         {
00941             Node* Root = FirstNode->FindNext(); 
00942             ERROR3IF(!Root, "Clipboard has no root");
00943             ERROR3IF(!(IS_A(Root, NodeDocument)), "This should be the root of the clipboard"); 
00944             if (Root && !Root->OptimiseAttributes()) return FALSE;
00945         }
00946 
00947         // Objects successfully transferred to clipboard. Perform neccessary processing
00948         if (!pInstance->OnNewClipboardObjects()) InformError();
00949         
00950         pInstance->OriginalCentreLock = FALSE;                      // Allow centre to be reset on first Paste
00951 
00952         // Data has come from external clipboard 
00953         if (ExternalSource) *ExternalSource = TRUE;
00954 #endif
00955     }
00956 
00957     return(TRUE);
00958 }
00959 
00960 
00961 
00962 /********************************************************************************************
00963 
00964 >   BOOL InternalClipboard::PasteCompleted(void)
00965 
00966     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00967     Created:    19/4/95
00968 
00969     Returns:    TRUE if all went well
00970                 FALSE if the paste failed in some way
00971 
00972     Purpose:    Tells the InternalClipboard that you have finished copying data from it.
00973                 This provides interaction with the external clipboard.
00974 
00975     Notes:      Before starting to copy data to the clipboard you MUST call PrepareForCopy
00976 
00977     SeeAlso:    InternalClipboard::PrepareForPaste; ExternalClipboard::PasteCompleted
00978 
00979 ********************************************************************************************/
00980 
00981 BOOL InternalClipboard::PasteCompleted(void)
00982 {
00983     if (IsEmpty(FALSE))
00984     {
00985         ERROR3("That paste wasn't much fun - the clipboard's empty now!");
00986     }
00987 
00988 PORTNOTE("extclipboard", "Removed use of External Clipboard")
00989 #ifndef EXCLUDE_FROM_XARALX
00990     ExternalClipboard *Clipboard = ExternalClipboard::GetExternalClipboard();
00991 
00992     if (Clipboard == NULL)
00993         return(FALSE);
00994 
00995     return(Clipboard->PasteCompleted());
00996 #else
00997     return TRUE;
00998 #endif
00999 }
01000 
01001 
01002 
01003 /********************************************************************************************
01004 
01005 >   static void InternalClipboard::DescribeContents(String_64 *Result);
01006 
01007     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01008     Created:    21/5/95
01009 
01010     Outputs:    Result will be filled in with either a blank string, or a description of the
01011                 current internal clipboard contents. 
01012 
01013     Purpose:    To determine the description of the clipboard contents
01014 
01015     Notes:      Redirects the call to the external clipboard, as it has a better idea 
01016                 of the overall picture.
01017 
01018     SeeAlso:    ExternalClipboard::DescribeContents
01019 
01020 ********************************************************************************************/
01021 
01022 void InternalClipboard::DescribeContents(String_64 *Result)
01023 {
01024     ERROR3IF(Result == NULL, "Illegal NULL param");
01025 PORTNOTE("extclipboard", "Removed use of External Clipboard")
01026 #ifndef EXCLUDE_FROM_XARALX
01027     ExternalClipboard::DescribeContents(Result);
01028 #else
01029     static String_64 strDesc = String_64(_T("No description (see InternalClipboard::DescribeContents)"));
01030     Result = &strDesc;
01031 #endif
01032 }
01033 
01034 
01035 
01036 /********************************************************************************************
01037 
01038 >   static void InternalClipboard::DescribeContentsInternal(String_64* Result);
01039 
01040     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01041     Created:    21/5/95
01042 
01043     Outputs:    Result will be filled in with either a blank string, or a description of the
01044                 current internal clipboard contents. 
01045 
01046     Purpose:    To determine the description of the clipboard contents
01047 
01048     Notes:      Internal version of this call, for the external clipboard only.
01049 
01050     SeeAlso:    InternalClipboard::DescribeContents
01051 
01052 ********************************************************************************************/
01053 
01054 void InternalClipboard::DescribeContentsInternal(String_64* Result)
01055 {
01056     ERROR3IF(Result == NULL, "Illegal NULL param");
01057 
01058     *Result = TEXT("");
01059     if (IsEmpty(FALSE)) return;
01060 
01061     // --- Scan the document tree to determine the description. Note that this should be
01062     // done by calling a range, except that the code is in SelRange, so I've rewritten it here
01063     // to save myself half a day's delay waiting for a range.h rebuild when I can't afford it...
01064 
01065     Node* Subtree = GetInsertionLayer();
01066     if (Subtree == NULL)
01067         return;
01068 
01069     Range ClipRange(Subtree->FindFirstChild(), Subtree->FindLastChild(),
01070                         RangeControl(TRUE,TRUE,TRUE,TRUE));
01071 
01072     String_256 Description;
01073     Node* Current = ClipRange.FindFirst();
01074     if (Current == NULL) return;
01075 
01076     // Implementation
01077     Node* FirstInRange = Current; 
01078     CCRuntimeClass* NodeType = Current->GetRuntimeClass();  
01079     
01080     // --------------------------------------------------------------------------------
01081     // Determine if there is more than one type of object selected
01082 
01083     BOOL OneTypeOfObject = TRUE;                          // TRUE if range contains only
01084                                                           // one type of object. 
01085     do
01086     {   
01087         if (Current->GetRuntimeClass() != NodeType)       // Range contains more than one
01088                                                           // type of object
01089         {
01090             // Current object is not the same type as the first so we know there is more
01091             // than one type of object.
01092             OneTypeOfObject = FALSE;
01093             break;
01094         }
01095 
01096         Current = ClipRange.FindNext(Current);
01097     }     
01098     while (Current);
01099     
01100     UINT32 NumObjectsInRange = ClipRange.Count();                    // Count is cached
01101     ERROR3IF(NumObjectsInRange <= 0, "No objects selected"); 
01102 
01103     if (OneTypeOfObject)
01104     {
01105         // All objects in the selection are of the same type
01106 
01107         String_32 Name;
01108         BOOL UseClassToDescribe = TRUE;
01109 
01110         NodeGroup* FirstGroup = NULL; 
01111 
01112         if (FirstInRange->GetRuntimeClass() == CC_RUNTIME_CLASS(NodeGroup))
01113         {
01114             UseClassToDescribe = FALSE; 
01115             // If all selected groups have the same name then the name is used in the 
01116             // description
01117             FirstGroup = (NodeGroup*)FirstInRange;
01118             NodeGroup* CurrentGroup = FirstGroup;
01119             Name = CurrentGroup->GetName(); 
01120             if (!(Name.IsEmpty()))
01121             {
01122                 do
01123                 {
01124                     CurrentGroup=(NodeGroup*)ClipRange.FindNext(CurrentGroup); 
01125             
01126                     if (CurrentGroup != NULL)
01127                     {
01128                         if (CurrentGroup->GetName() != Name)
01129                         {
01130                             // A group has been found with a different name. Stop the search and
01131                             // use the class to describe the selection.
01132                             UseClassToDescribe = TRUE; 
01133                             break;                  
01134                         }
01135                     }
01136 
01137                 } while (CurrentGroup != NULL); 
01138             }
01139             else
01140             {
01141                 UseClassToDescribe = TRUE;
01142             }
01143         }
01144         if (UseClassToDescribe)
01145         {
01146             Description = (FirstInRange->Describe(NumObjectsInRange>1));                                   
01147         }
01148         else 
01149         {
01150             // Use the group name to describe the selection
01151             ERROR3IF(FirstGroup == NULL, "FirstGroup should be the first selected group"); 
01152             if (NumObjectsInRange > 1)
01153             {
01154                 Description = SelRange::Pluralise(FirstGroup->GetName()); 
01155             }
01156             else
01157             {
01158                 Description = FirstGroup->GetName();
01159             }
01160         }
01161     }
01162     else
01163     {
01164         // There must be more than one type of selected objects
01165         ERROR3IF(NumObjectsInRange <= 1, "Only a single object is in range"); 
01166         // Cos there are multiple objects of different types we describe them as 'objects'
01167         Description = String(_R(IDS_OBJECTS));  
01168     }
01169 
01170     Description.Left(Result, 63);
01171 }
01172 
01173 
01174 
01175 /********************************************************************************************
01176 
01177 >   BOOL InternalClipboard::OnNewClipboardObjects()
01178 
01179     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
01180     Created:    6/9/95
01181     Returns:    FALSE if something has gone wrong. An InformError should be called if this
01182                 occurs. The Cut/Copy/Paste Operation being performed should not be aborted though. 
01183 
01184     Purpose:    This fn will be called whenever data has successfuly been transfered to 
01185                 the InternalClipboard. i.e. After a Cut, Copy, or (paste from External Clipboard)
01186         
01187     
01188     Scope:      private
01189 
01190 ********************************************************************************************/
01191 
01192 BOOL InternalClipboard::OnNewClipboardObjects()
01193 {
01194     // Set the bounds of the spread containing the objects to the bounds of the objects.
01195     Spread* pSpread = FindFirstSpread();
01196     ERROR2IF(!pSpread, FALSE, "No first Spread in InternalClipboard::OnNewClipboardObjects");
01197 
01198     // Calculate the bounds of all the objects on the spread (this code is based on
01199     // Spread::GetPageVisibleBounds, ie. the function that Zoom to Drawing uses).
01200     DocRect drBounds;
01201     drBounds.MakeEmpty();
01202 
01203     // Search through all the children of the spread, looking for layers.
01204     Layer* pLayer = pSpread->FindFirstLayer();
01205     while (pLayer)
01206     {
01207         // We ignore the guide layers, which always have an empty bounding box
01208         // (according to Mark Neves!)
01209         if (!pLayer->IsGuide())
01210         {
01211             // Include the bounds of the objects on this layer.
01212             drBounds = drBounds.Union(pLayer->GetBoundingRect());
01213         }
01214 
01215         // And onto the next layer ...
01216         pLayer = pLayer->FindNextLayer();
01217     }
01218 
01219     // If the bounds aren't empty then set the page size to be those bounds, so the
01220     // page is the smallest size that encloses the objects it contains.
01221     if (!drBounds.IsEmpty())
01222     {
01223         // Remember the centre of the bounds of the objects, so Paste-In-Place will
01224         // still work.
01225         dcCentre.x = drBounds.lo.x + drBounds.Width() / 2;
01226         dcCentre.y = drBounds.lo.y + drBounds.Height() / 2;
01227 
01228         // Now convert to document coordinates.
01229         pSpread->SpreadCoordToDocCoord(&drBounds);
01230 
01231         // Work out the new dimensions of the page.
01232 /*      MILLIPOINT mpWidth  = drBounds.Width();
01233         MILLIPOINT mpHeight = drBounds.Height();
01234         
01235         // Inflate the size of the page by 5% to give a pleasing border around the objects.
01236         const double fpInflate = 1.024695076596;
01237         mpWidth  = (MILLIPOINT) floor(mpWidth  *  fpInflate + 0.5);
01238         mpHeight = (MILLIPOINT) floor(mpHeight *  fpInflate + 0.5);
01239 */
01240 
01241 PORTNOTE("other", "Removed use of CCamDoc::SetPageSize")
01242 #ifndef EXCLUDE_FROM_XARALX
01243 //#if (_OLE_VER >= 0x200)       
01244         // Resize the page to just surround the objects, but don't scale the objects
01245         // by the same amount.
01246         ERROR2IF(!GetOilDoc()->SetPageSize(mpWidth, mpHeight, FALSE),
01247                  FALSE, "SetPageSize failed in InternalClipboard::OnNewClipboardObjects");
01248 //#endif
01249 #endif
01250 
01251         // Discard any undo information in this clipboard document.
01252         EmptyOperationHistory();
01253     }
01254 #ifdef _DEBUG
01255     else
01256     {
01257         // This should be investigated if you see this TRACE.  Perhaps because the selection
01258         // consisted of invisible layers?
01259         TRACE( _T("Warning: no bounds for SetPageSize in InternalClipboard::OnNewClipboardObjects (?)\n"));
01260     }
01261 #endif
01262 
01263     // Currently this routine creates a new Range of objects on the clipboard
01264     delete pClipboardRange;
01265     pClipboardRange = NULL; 
01266 
01267     // Find the first child of the clipboard's layer
01268     Node* pNode = Node::FindFirstChapter(this);  
01269     NodeRenderableInk* pInkNode = NULL;
01270     if (pNode) pNode = ((Chapter*) pNode)->FindFirstSpread(); 
01271     if (pNode) pNode = ((Spread*) pNode)->FindFirstLayer();
01272     if (pNode)
01273     {
01274         pInkNode = (NodeRenderableInk*)pNode->FindFirstChild(CC_RUNTIME_CLASS(NodeRenderableInk));
01275         while (pInkNode!=NULL && !pInkNode->CanSelectAsCompoundParent())
01276         {
01277             if (pInkNode->IsCompoundClass() && ((NodeCompound*)pInkNode)->GetInkNodeFromController())
01278                 pInkNode = ((NodeCompound*)pInkNode)->GetInkNodeFromController();
01279             else
01280                 pInkNode = (NodeRenderableInk*)pInkNode->FindFirstChild(CC_RUNTIME_CLASS(NodeRenderableInk));
01281         }
01282     }
01283 
01284     ERROR3IF(!pInkNode, "InternalClipboard::OnNewClipboardObjects, Where has the clipboard gone ??");
01285     if (!pInkNode) return FALSE; // What else can we do ?
01286     
01287     // Try to create a range of all objects.
01288     pClipboardRange = new Range(pInkNode, NULL, RangeControl(TRUE, TRUE));
01289     return pClipboardRange != 0;
01290 }
01291 
01292 
01293 
01294 /********************************************************************************************
01295 >   DocCoord InternalClipboard::GetOriginalCentrePoint()
01296 
01297     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01298     Created:    13/10/96
01299     Returns:    The original centre point of the objects on the clipboard before they were
01300                 copied.
01301     Purpose:    Paste-in-place centres the objects when they are pasted at this point.
01302     SeeAlso:    InternalClipboard::OnNewClipboardObjects;
01303 ********************************************************************************************/
01304 
01305 DocCoord InternalClipboard::GetOriginalCentrePoint()
01306 {
01307     return pInstance->dcCentre;
01308 }
01309 
01310 
01311 
01312 
01313 /********************************************************************************************
01314 >   void InternalClipboard::SetOriginalCentrePoint(DocCoord NewCentre)
01315 
01316     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
01317     Created:    13/10/96
01318     Input:      NewCentre   A position that the caller would like to record as being the
01319                             "original centre" of the objects on the clipboard.
01320     Returns:    -
01321     Purpose:    Paste-in-place centres the objects when they are pasted at this point.
01322                 Reset the centre point but only do so when the centre point is unlocked.
01323     SeeAlso:    InternalClipboard::OnNewClipboardObjects, OpPaste::DoPasteStandard;
01324 ********************************************************************************************/
01325 
01326 void InternalClipboard::SetOriginalCentrePoint(DocCoord NewCentre)
01327 {
01328     if (!pInstance->OriginalCentreLock)
01329     {
01330         pInstance->dcCentre = NewCentre;
01331         pInstance->OriginalCentreLock = TRUE;
01332     }
01333 }
01334 
01335 /********************************************************************************************
01336 >   void InternalClipboard::CopyText(TCHAR* pcBuffer)
01337 
01338     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>, liberally copied from BodgeTextMap::HandleImport
01339     Created:    24/4/97
01340     Input:      pcBuffer    The text to copy on to the clipboard
01341     Returns:    -
01342     Purpose:    Copies the text on to the clipboard (by converting it
01343                 to a text object).
01344     SeeAlso:    TextStory::CreateFromChars, BodgeTextMap::HandleImport
01345 ********************************************************************************************/
01346 
01347 BOOL InternalClipboard::CopyText(TCHAR* pcBuffer)
01348 {
01349 PORTNOTE("other", "InternalClipboard::CopyText disabled due to use of CCamSrvrItem")
01350 #ifndef EXCLUDE_FROM_XARALX
01351     //We need to tell CCamSrvrItem that what we are about to put on the clipboard 
01352     //should be treated as text
01353 
01354     //To do this, we call RenderProprietary Formats, which sets a flag. The
01355     //returned value will be the old state of this flag, which we must remember
01356     //cos otherwise Justin will beat me up
01357     BOOL fOldState = CCamSrvrItem::RenderProprietaryFormats(FALSE);
01358 
01359     //If we have some text
01360     if (pcBuffer != NULL && pcBuffer[0] != '\0')
01361     {
01362         //Create a text story, which we position arbitarily on the clipboard
01363         TextStory* pTextStory=TextStory::CreateFromChars(DocCoord(100,100), pcBuffer,
01364                     NULL, InternalClipboard::Instance(), NULL, TRUE);
01365 
01366         if (pTextStory!=NULL)
01367         {
01368             //Prepare to copy...this will clear the clipboard
01369             PrepareForCopy();
01370     
01371             // Attach the text story to the clipboard
01372             pTextStory->AttachNode(InternalClipboard::GetInsertionLayer(), LASTCHILD);
01373             pTextStory->NormaliseAttributes();
01374 
01375             // And format the text story properly
01376             pTextStory->FormatAndChildren(NULL,FALSE,FALSE);
01377 
01378             CopyCompleted();
01379 
01380             //And reset the old state of the flag
01381             CCamSrvrItem::RenderProprietaryFormats(fOldState);
01382 
01383             return(TRUE);
01384         }
01385 
01386         // We failed, so clear the clipboard
01387         InternalClipboard::Clear();
01388 
01389         //And reset the old state of the flag
01390         CCamSrvrItem::RenderProprietaryFormats(fOldState);
01391 
01392         return FALSE;
01393     }
01394 #endif
01395 
01396     return FALSE;
01397         
01398 }
01399 
01400 
01401 
01402 

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