prnmks.cpp

Go to the documentation of this file.
00001 // $Id: prnmks.cpp 1320 2006-06-14 14:39:32Z 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 // Author  : Mike
00100 // Created : 23/07/96
00101 // Purpose : The PrintMarks Manager and all its helper classes.
00102 //           This manager handles the caching and rendering of print marks
00103 //           within a document. PrintMarks are generally only used for typesetting
00104 
00105 /*
00106 */
00107 
00108 #include "camtypes.h"
00109 //#include "node.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 #include "prnmks.h"
00112 //#include "group.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 #include "fileutil.h"
00114 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00115 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00116 //#include "opdesc.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00117 #include "nativeop.h"
00118 #include "layer.h"
00119 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00120 #include "page.h"
00121 //#include "nodeattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00122 #include "colormgr.h"
00123 #include "prnmkcom.h"
00124 #include "qualattr.h"
00125 //#include "matrix.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00126 #include "dbugtree.h"
00127 //#include "paths.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00128 #include "cctime.h"
00129 #include "nodetxts.h"
00130 #include "nodetxtl.h"
00131 #include "colplate.h"
00132 #include "printctl.h"
00133 #include "fontman.h"
00134 #include "psrndrgn.h"
00135 #include "psdc.h"
00136 //#include "printstr.h"
00137 #include <stdlib.h>
00138 
00139 CC_IMPLEMENT_MEMDUMP(LoadPrintMarks, LoadDirect);
00140 CC_IMPLEMENT_MEMDUMP(PrintMarksMan, CC_CLASS_MEMDUMP);
00141 CC_IMPLEMENT_MEMDUMP(PrintMarksCache, CC_CLASS_MEMDUMP);
00142 CC_IMPLEMENT_MEMDUMP(PrintMark, CC_CLASS_MEMDUMP);
00143 CC_IMPLEMENT_DYNCREATE(MarkPosition, ListItem);
00144 CC_IMPLEMENT_DYNCREATE(PrintMarkItem, ListItem);
00145 CC_IMPLEMENT_MEMDUMP(MarkFormatRegion, CC_CLASS_MEMDUMP);
00146 CC_IMPLEMENT_DYNCREATE(PageRect, ListItem);
00147 CC_IMPLEMENT_DYNAMIC(PageRectList, List);
00148 
00149 DECLARE_SOURCE("$Revision: 1320 $");
00150 
00151 #define new CAM_DEBUG_NEW
00152 
00153 
00154 /*****************************************************************************************
00155 
00156 >   MarkFormat::MarkFormat()
00157 
00158     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00159     Created:    23/07/96
00160     Purpose:    Construct a Mark format object
00161 
00162 *****************************************************************************************/
00163 
00164 MarkFormat::MarkFormat()
00165 {
00166     Top = Middle = Bottom = FALSE;
00167     Left = Centre = Right = FALSE;
00168 }
00169 
00170 BOOL MarkFormat::IsValid() const
00171 {
00172     return (Top || Middle || Bottom || Left || Centre || Right);
00173 }
00174 
00175 void MarkFormat::MakeValid()
00176 {
00177     Centre = Middle = TRUE;
00178     Top = Bottom = Left = Right = FALSE;
00179 }
00180 
00181 INT32 operator==(const MarkFormat& x, const MarkFormat& y)
00182 {
00183     return ( (x.Centre == y.Centre) &&
00184              (x.Middle == y.Middle) &&
00185              (x.Left   == y.Left)   &&
00186              (x.Right  == y.Right)  &&
00187              (x.Top    == y.Top)    &&
00188              (x.Bottom == y.Bottom)
00189             );
00190 }
00191 
00192 
00193 
00194 /*****************************************************************************************
00195 
00196 >   BYTE MarkFormat::GetAsFlagByte(void)
00197 
00198     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00199     Created:    6/9/96
00200 
00201     Returns:    A Byte with bits set for each of the mark formats available
00202 
00203     Purpose:    Fill in a mark format object from a "flags byte"
00204                 Used for native file load/save
00205 
00206     SeeAlso:    MarkFormat::SetFromFlagByte
00207 
00208 *****************************************************************************************/
00209 
00210 BYTE MarkFormat::GetAsFlagByte(void)
00211 {
00212     BYTE Flags = 0;
00213 
00214     if (Left)   Flags |= 0x01;
00215     if (Centre) Flags |= 0x02;
00216     if (Right)  Flags |= 0x04;
00217     if (Top)    Flags |= 0x08;
00218     if (Middle) Flags |= 0x10;
00219     if (Bottom) Flags |= 0x20;
00220 
00221     return(Flags);
00222 }
00223 
00224 
00225 
00226 /*****************************************************************************************
00227 
00228 >   void MarkFormat::SetFromFlagByte(BYTE Flags)
00229 
00230     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00231     Created:    6/9/96
00232 
00233     Inputs:     Flags - A Byte with bits set for each of the mark formats available
00234 
00235     Purpose:    Fill in a mark format object from a "flags byte"
00236                 Used for native file load/save
00237 
00238     SeeAlso:    MarkFormat::GetAsFlagByte
00239 
00240 *****************************************************************************************/
00241 
00242 void MarkFormat::SetFromFlagByte(BYTE Flags)
00243 {
00244     Left    = (Flags & 0x01) ? TRUE : FALSE;
00245     Centre  = (Flags & 0x02) ? TRUE : FALSE;
00246     Right   = (Flags & 0x04) ? TRUE : FALSE;
00247     Top     = (Flags & 0x08) ? TRUE : FALSE;
00248     Middle  = (Flags & 0x10) ? TRUE : FALSE;
00249     Bottom  = (Flags & 0x20) ? TRUE : FALSE;
00250 }
00251 
00252 
00253 
00254 
00255 
00256 /*****************************************************************************************
00257 
00258 >   MarkPosition::MarkPosition()
00259 
00260     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00261     Created:    23/07/96
00262     Purpose:    Construct a mark position object
00263 
00264 *****************************************************************************************/
00265 
00266 MarkPosition::MarkPosition()
00267 {
00268     Initialise();
00269 }
00270 
00271 
00272 /*****************************************************************************************
00273 
00274 >   void MarkPosition::Initialise()
00275 
00276     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00277     Created:    23/07/96
00278     Purpose:    Initialise all the local variables in this mark position
00279 
00280 *****************************************************************************************/
00281 
00282 void MarkPosition::Initialise()
00283 {
00284     Region = MarkRegion_TopLeft;
00285 }
00286 
00287 
00288 /*****************************************************************************************
00289 
00290 >   BOOL MarkPosition::IsEqualTo(const MarkPosition* pOther) const
00291 
00292     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00293     Created:    23/07/96
00294     Inputs:     pOther = a pointer to a mark position to match
00295     Returns:    TRUE if pOther is identical to this mark
00296                 FALSE if not
00297     Purpose:    Check whether another mark position is identical to this one
00298 
00299 *****************************************************************************************/
00300 
00301 BOOL MarkPosition::IsEqualTo(const MarkPosition* pOther) const
00302 {
00303     ERROR2IF(pOther==NULL, FALSE, "NULL pointer passed to MarkPosition::IsEqualTo");
00304     return ( (Region == pOther->Region) &&
00305              (Format == pOther->Format)
00306            );
00307 }
00308 
00309 
00310 /*****************************************************************************************
00311 
00312 >   PrintMark::PrintMark
00313 
00314     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00315     Created:    23/07/96
00316     Purpose:    Construct a new print mark
00317 
00318 *****************************************************************************************/
00319 
00320 PrintMark::PrintMark()
00321 {
00322     MarkIsCustom    = FALSE;
00323     IDByte          = 0;
00324     Type            = MarkType_Unknown;
00325     Orientation     = MO_None;
00326     OnAsDefault     = FALSE;
00327 }
00328 
00329 
00330 /*****************************************************************************************
00331 
00332 >   virtual PrintMark::~PrintMark()
00333 
00334     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00335     Created:    23/07/96
00336     Purpose:    virtual destructor, destroys all instances of the 'MarkPositions' list
00337 
00338 *****************************************************************************************/
00339 
00340 PrintMark::~PrintMark()
00341 {
00342     MarkPosition* pMarkPos;
00343     while ((pMarkPos=(MarkPosition*)MarkPositions.RemoveTail()))
00344         delete pMarkPos;
00345 }
00346 
00347 
00348 
00349 /*****************************************************************************************
00350 
00351 >   void PrintMark::SetMarkMenuText(const String_256* pMenuText)
00352 
00353     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00354     Created:    23/07/96
00355     Inputs:     pMenuText = a pointer to a string containing the textual description of 
00356                             the print mark, (may be used in menus).
00357     Purpose:    Set this print mars menu text
00358 
00359 *****************************************************************************************/
00360 
00361 void PrintMark::SetMarkMenuText(const String_256* pMenuText)
00362 {
00363     ERROR3IF(pMenuText==NULL,"ERROR ERROR, NULL pointer passed to SetMarkMenuText");
00364     if (pMenuText!=NULL)
00365         MenuText = (*pMenuText);
00366 }
00367 
00368 
00369 /*****************************************************************************************
00370 
00371 >   String_256 PrintMark::GetMarkMenuText() const
00372 
00373     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00374     Created:    23/07/96
00375     Inputs:     -
00376     Returns:    This print marks textual description
00377     Purpose:    Return the menu text string saved in this print mark
00378 
00379 *****************************************************************************************/
00380 
00381 String_256 PrintMark::GetMarkMenuText() const
00382 {
00383     return MenuText;
00384 }
00385 
00386 
00387 /*****************************************************************************************
00388 
00389 >   void PrintMark::AddNewPosition(MarkPosition* pNewMarkPos)
00390 
00391     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00392     Created:    23/07/96
00393     Inputs:     pNewMarkPos, a pointer to a new mark position
00394     Returns:    This print marks textual description
00395     Purpose:    Return the menu text string saved in this print mark
00396 
00397 *****************************************************************************************/
00398 
00399 void PrintMark::AddNewPosition(MarkPosition* pNewMarkPos)
00400 {
00401     ERROR3IF(pNewMarkPos==NULL,"NULL MarkPosition pointer passed to AddNewPosition");
00402     if (pNewMarkPos)
00403     {
00404         if (!FindMarkPosition(pNewMarkPos))
00405             MarkPositions.AddTail(pNewMarkPos);
00406     }
00407 }
00408 
00409 /*****************************************************************************************
00410 
00411 >   BOOL PrintMark::FindMarkPosition(const MarkPosition* pSearchMark, MarkPosition** pFoundMark=NULL) const
00412 
00413     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00414     Created:    23/07/96
00415     Inputs:     pSearchMark = a pointer to a print mark to search for
00416                 pFoundMark, a pointer to a pointer to be set on exit. This defaults to null
00417                 when we're only interested in whether the mark exists or not.
00418 
00419     Outputs:    pFoundMark set to a pointer to the print mark in the cache if we find it
00420                 pFoundMark set to NULL if no match found
00421                                     
00422     Returns:    TRUE if there is a mark in the cache identical to this search mark
00423                 FALSE if there isn't
00424     Purpose:    Check the cache to see if there's a mark already in it which matches
00425                 pSearchMark. You can get the pointer to this cached mark by using pFoundMark
00426 
00427 *****************************************************************************************/
00428 
00429 BOOL PrintMark::FindMarkPosition(const MarkPosition* pSearchMark, MarkPosition** pFoundMark) const
00430 {
00431     ERROR3IF(pSearchMark==NULL,"PrintMark::FindMarkPosition passed a NULL search mark pointer");
00432     if (pSearchMark)
00433     {
00434         MarkPosition* pMarkPos = GetFirstPosition();
00435         while (pMarkPos)
00436         {
00437             // Check to see if this exists
00438             if (pSearchMark->IsEqualTo(pMarkPos))
00439             {
00440                 if (pFoundMark!=NULL)
00441                     (*pFoundMark=pMarkPos);
00442                 return TRUE;
00443             }
00444             pMarkPos = GetNextPosition(pMarkPos);
00445         }
00446     }
00447     if (pFoundMark!=NULL)
00448         (*pFoundMark=NULL);
00449     return FALSE;
00450 }
00451 
00452 /*****************************************************************************************
00453 
00454 >   BOOL PrintMark::IsSimilarTo(const PrintMark* pOther) const
00455 
00456     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00457     Created:    23/07/96
00458     Inputs:     pOther, a pointer to another print mark
00459     Returns:    TRUE if this print mark is similar to pOther.
00460                 FALSE if not
00461     Purpose:    Checks whether this print mark is similar to pOther. The current checks
00462                 for similarity are...
00463                 (1) the mark is of the same type
00464                 (2) the mark has the same menu text
00465 
00466 *****************************************************************************************/
00467 
00468 BOOL PrintMark::IsSimilarTo(const PrintMark* pOther) const
00469 {
00470     ERROR2IF(pOther==NULL, FALSE, "NULL PrintMark pointer passed to IsSimilar()");
00471 
00472     if (Type == pOther->GetType())
00473     {
00474         if (MenuText == pOther->GetMarkMenuText())
00475             return TRUE;
00476     }
00477     return FALSE;
00478 }
00479 
00480 
00481 
00482 /*****************************************************************************************
00483 
00484 >   PrintMarkItem::PrintMarkItem
00485 
00486     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00487     Created:    23/07/96
00488     Purpose:    Construct a new print mark item
00489 
00490 *****************************************************************************************/
00491 
00492 PrintMarkItem::PrintMarkItem()
00493 {
00494     pMarkGlyph  = NULL;
00495     Handle      = 0;
00496     Saveable    = TRUE;
00497     Renderable  = TRUE;
00498 }
00499 
00500 
00501 /*****************************************************************************************
00502 
00503 >   PrintMarkItem::~PrintMarkItem
00504 
00505     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00506     Created:    23/07/96
00507     Purpose:    destruct a print mark item
00508 
00509 *****************************************************************************************/
00510 
00511 PrintMarkItem::~PrintMarkItem()
00512 {
00513     RemoveMark();
00514 }
00515 
00516 
00517 
00518 
00519 /*****************************************************************************************
00520 
00521     BOOL PrintMarkItem::SetMarkGlyph(NodeGroup* pNewMark, BOOL MakeCopy=FALSE)
00522 
00523     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00524     Created:    23/07/96
00525     Inputs:     pNewMark = A pointer to a group node containing the mark. 
00526                            The node should still be in the tree.
00527                 MakeCopy = TRUE, the mark will be left where it is and an
00528                                  attribute complete copy will be made.
00529                            FALSE, the mark will be extracted from the document as is. 
00530     Purpose:    Cache a print mark in this print mark item. The mark pointer should be
00531                 a group held in the document tree. As we attempt to make attributes
00532                 complete on this group, it has to be in the tree. MakeCopy which defaults
00533                 to FALSE will, when TRUE, copy the entire group and used the copy, hence
00534                 it will leave the document unaffected. When FALSE the group will be
00535                 extracted from the tree. This is only acceptable in a few circumstances
00536                 when undo is not being generated.
00537 
00538 *****************************************************************************************/
00539 
00540 BOOL PrintMarkItem::SetMarkGlyph(NodeGroup* pNewMark, BOOL MakeCopy)
00541 {
00542     ERROR2IF(pNewMark==NULL,FALSE, "NULL mark pointer passed to SetMark");
00543 
00544     if (MakeCopy)
00545     {
00546         NodeGroup* pNewGroup = new NodeGroup;
00547         if (pNewGroup==NULL)
00548             return FALSE;
00549 
00550         NodeGroup* pNewGroup1 = new NodeGroup;
00551         if (pNewGroup1==NULL)
00552         {
00553             delete pNewGroup;
00554             return FALSE;
00555         }
00556         
00557         // attach this new group to the tree
00558         pNewGroup->AttachNode(pNewMark,NEXT);
00559         pNewGroup1->AttachNode(pNewGroup,FIRSTCHILD);
00560 
00561         // copy the children across to this new group
00562         if (!pNewMark->CopyChildrenTo(pNewGroup1))
00563         {
00564             // CascadeDelete unlinks the node from the tree so don't panic.
00565             pNewGroup->CascadeDelete();
00566             delete pNewGroup;
00567             return FALSE;
00568         }
00569 
00570         // make sure we have all the attributes we're gonna need
00571         if (!pNewGroup->MakeAttributeComplete(NULL,TRUE,NULL,TRUE))
00572         {
00573             pNewGroup->CascadeDelete();
00574             delete pNewGroup;
00575             return FALSE;
00576         }
00577 
00578         // dump the tree out
00579         //TRACEUSER( "Mike", _T("Dumping subtree contents\n\n"));
00580         //DebugTreeDlg::DumpSubTree(pNewGroup);
00581         
00582         // rip the node out of the tree and stick it in our cache.
00583         pNewGroup->UnlinkNodeFromTree();
00584                 
00585         // Make sure we get rid of any previously cached mark
00586         if (pMarkGlyph!=NULL)
00587             RemoveMark();
00588 
00589         pMarkGlyph = pNewGroup;
00590     }
00591     else
00592     {
00593         if (!pNewMark->MakeAttributeComplete(NULL,TRUE,NULL,TRUE))
00594             return FALSE;
00595 
00596         pNewMark->UnlinkNodeFromTree();
00597                 
00598         // Make sure we get rid of any previously cached mark
00599         if (pMarkGlyph!=NULL)
00600             RemoveMark();
00601 
00602         pMarkGlyph = pNewMark;
00603     }
00604 
00605     return TRUE;
00606 }
00607 
00608 
00609 /*****************************************************************************************
00610 
00611 >   void PrintMarkItem::RemoveMark()
00612 
00613     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00614     Created:    23/07/96
00615     Purpose:    Remove the cached mark from our list structure. This is generally
00616                 called when the mark item is destroyed.
00617 
00618 *****************************************************************************************/
00619 
00620 void PrintMarkItem::RemoveMark()
00621 {
00622     // check to see if we have a sub tree here
00623     if (pMarkGlyph!=NULL)
00624     {
00625         Node* pNode = pMarkGlyph->FindFirstChild();
00626         if (pNode!=NULL)
00627             pMarkGlyph->DeleteChildren(pNode);
00628     }
00629     delete pMarkGlyph;
00630     pMarkGlyph = NULL;
00631 }
00632 
00633 
00634 INT32 PrintMarkItem::GetWidth() const
00635 {
00636     if (pMarkGlyph!=NULL)
00637     {
00638         DocRect bounds = pMarkGlyph->GetBoundingRect();
00639         return bounds.Width();
00640     }
00641     return 0;
00642 }
00643 
00644 INT32 PrintMarkItem::GetHeight() const
00645 {
00646     if (pMarkGlyph!=NULL)
00647     {
00648         DocRect bounds = pMarkGlyph->GetBoundingRect();
00649         return bounds.Height();
00650     }
00651     return 0;
00652 }
00653 
00654 DocCoord PrintMarkItem::GetOrigin() const
00655 {
00656     if (pMarkGlyph!=NULL)
00657     {
00658         DocRect bounds = pMarkGlyph->GetBoundingRect();
00659         return bounds.lo;
00660     }
00661     return DocCoord(0,0);
00662 }
00663 
00664 
00665 MarkOrient PrintMarkItem::GetOrient() const
00666 {
00667     return Mark.GetOrientation();
00668 }
00669 
00670 
00671 BOOL PrintMarkItem::DefaultsToOn() const
00672 {
00673     return Mark.DefaultsToOn();
00674 }
00675 
00676 
00677 BOOL PrintMarkItem::NeedsSaving() const
00678 {
00679     return Saveable;
00680 }
00681 
00682 
00683 void PrintMarkItem::SetSaveable(BOOL savestate)
00684 {
00685     Saveable = savestate;
00686 }
00687 
00688 BOOL PrintMarkItem::NeedsToRender() const
00689 {
00690     return Renderable;
00691 }
00692 
00693 void PrintMarkItem::SetRenderable(BOOL renderstate)
00694 {
00695     Renderable = renderstate;
00696 }
00697 
00698 
00699 
00700 /*****************************************************************************************
00701 
00702 >   PrintMarksCache::PrintMarksCache()
00703 
00704     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00705     Created:    23/07/96
00706     Purpose:    Construct the PrintMarksCache object. This used to be part of the print
00707                 marks manager but I've now split it into its own class to prevent
00708                 confusion with the handling of cache marks and document marks. Various
00709                 functions do similar things so it could become confusing without a
00710                 scope resolution operator PMMCache::FindMark as opposed to Doc::FindMark
00711 
00712 *****************************************************************************************/
00713 
00714 PrintMarksCache::PrintMarksCache()
00715 {
00716     NextHandle=0;
00717     TextInfoHandle=0;
00718     CropMarkHandle=0;
00719 }
00720 
00721 
00722 /*****************************************************************************************
00723 
00724 >   PrintMarksCache::~PrintMarksCache()
00725 
00726     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00727     Created:    23/07/96
00728     Purpose:    Destroys the cached marks completely
00729 
00730 *****************************************************************************************/
00731 
00732 PrintMarksCache::~PrintMarksCache()
00733 {
00734     Invalidate();
00735 }
00736 
00737 
00738 /*****************************************************************************************
00739 
00740 >   PrintMarksCache::~PrintMarksCache()
00741 
00742     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00743     Created:    23/07/96
00744     Purpose:    Invalidate the cache list. If we do this, all the mark references
00745                 in existing document will reference nothing. As we create new marks
00746                 new handles will be built, so it might be necessary to delete references
00747                 made in all doc components.
00748                 Use with care.
00749 
00750 *****************************************************************************************/
00751 
00752 void PrintMarksCache::Invalidate()
00753 {
00754     // destroy all marks in the cache.
00755     PrintMarkItem* pItem;
00756     while ((pItem=(PrintMarkItem*)PrintMarkCache.RemoveTail())) // assignment
00757         delete pItem;
00758     // Make sure the crop and text info handles don't reference anything
00759     CropMarkHandle=0;
00760     TextInfoHandle=0;
00761 }
00762 
00763 
00764 /*****************************************************************************************
00765 
00766 >   UINT32 PrintMarksCache::GetUniqueHandle()
00767 
00768     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00769     Created:    23/07/96
00770     Inputs:     -
00771     Returns:    A handle used to reference a unique print mark
00772     Purpose:    Generate a unique print mark handle. All handles will be >=1 and hence
00773                 an illegal handle is given the value 0.
00774 
00775 *****************************************************************************************/
00776 
00777 UINT32 PrintMarksCache::GetUniqueHandle()
00778 {
00779     NextHandle++;
00780     return (NextHandle);
00781 }
00782 
00783 
00784 
00785 /*****************************************************************************************
00786 
00787 >   PrintMarkItem* PrintMarksCache::GetFirstMark() const
00788 
00789     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00790     Created:    23/07/96
00791     Inputs:     -
00792     Returns:    A pointer to the first cached mark
00793     Purpose:    Return a pointer to the first cached mark
00794 
00795 *****************************************************************************************/
00796 
00797 PrintMarkItem* PrintMarksCache::GetFirstMark() const
00798 {
00799     return ((PrintMarkItem*)PrintMarkCache.GetHead()); 
00800 }
00801 
00802 
00803 /*****************************************************************************************
00804 
00805 >   PrintMarkItem* PrintMarksCache::GetNextMark(PrintMarkItem* pCurrMark) const
00806 
00807     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00808     Created:    23/07/96
00809     Inputs:     A pointer to a print mark item
00810     Returns:    A pointer to the next print mark item after this
00811     Purpose:    Returns the next print mark item beyond pCurrMark
00812 
00813 *****************************************************************************************/
00814 
00815 PrintMarkItem* PrintMarksCache::GetNextMark(PrintMarkItem* pCurrMark) const
00816 {
00817     return ((PrintMarkItem*)PrintMarkCache.GetNext(pCurrMark));
00818 }
00819 
00820 
00821 /*****************************************************************************************
00822 
00823 >   BOOL PrintMarksCache::DoesMarkExist(PrintMark* pCheckMark) const
00824 
00825     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00826     Created:    23/07/96
00827     Inputs:     A pointer to a print mark
00828     Returns:    TRUE if this mark already exists in the cache
00829                 FALSE if not
00830     Purpose:    Try to find a print mark in the cache
00831 
00832 *****************************************************************************************/
00833 
00834 BOOL PrintMarksCache::DoesMarkExist(PrintMark* pCheckMark) const
00835 {
00836     PrintMarkItem* pItem = GetFirstMark();
00837     while (pItem)
00838     {
00839         PrintMark* pCurrMark = pItem->GetPrintMark();
00840         if (pCheckMark->IsSimilarTo(pCurrMark))
00841             return TRUE;
00842         pItem = GetNextMark(pItem);
00843     }
00844     return FALSE;
00845 }
00846 
00847 
00848 /*****************************************************************************************
00849 
00850 >   PrintMarkItem* PrintMarksCache::FindMark(UINT32 SearchHandle)
00851 
00852     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00853     Created:    23/07/96
00854     Inputs:     SearchHandle = the handle of the mark to search for
00855     Returns:    A pointer to the print mark described by this handle (NULL if none)
00856     Purpose:    Try to find a print mark in the cache, using its handle
00857 
00858 *****************************************************************************************/
00859 
00860 PrintMarkItem* PrintMarksCache::FindMark(UINT32 SearchHandle)
00861 {
00862     PrintMarkItem* pItem = GetFirstMark();
00863     while (pItem)
00864     {
00865         if (pItem->GetHandle() == SearchHandle)
00866             return pItem;
00867         pItem = GetNextMark(pItem);
00868     }
00869     return NULL;
00870 }
00871 
00872 
00873 
00874 
00875 /*****************************************************************************************
00876 
00877 >   BOOL PrintMarksCache::DecodeCachedLayers(Document* pDocument)
00878 
00879     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00880     Created:    23/07/96
00881     Inputs:     pDocument = a pointer to a document
00882     Returns:    TRUE if the document has been processed
00883                 
00884     Purpose:    Given a document, we scan each layer in the document. For each layer
00885                 we check the loaded layer name. If the layer name contains a % at the
00886                 begining (meaning its a format string) and the format is PRINTMARK, we
00887                 take the first group in the layer (+ all its contents) and assign a
00888                 new print mark item to this group. This group object will (if successfully)
00889                 loaded, become a new print mark.
00890     
00891 *****************************************************************************************/
00892 
00893 BOOL PrintMarksCache::DecodeCachedLayers(Document* pDocument)
00894 {
00895     ERROR2IF(pDocument==NULL,FALSE,"NULL Layer passed to DecodeCachedLayer");
00896     
00897     Spread* pSpread = pDocument->FindFirstSpread();
00898     Layer* pLayer;
00899     while (pSpread!=NULL)
00900     {
00901         pLayer = pSpread->FindFirstLayer();
00902         while (pLayer!=NULL)
00903         {
00904             DecodeCachedLayer(pLayer);
00905             pLayer = pLayer->FindNextLayer(); // Find next layer
00906         }
00907         pSpread = pSpread->FindNextSpread();
00908     }
00909     return TRUE;
00910 }
00911 
00912 
00913 /*****************************************************************************************
00914 
00915 >   BOOL PrintMarksMan::DecodeCachedLayer(Layer* pLayer)
00916 
00917     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00918     Created:    23/07/96
00919     Inputs:     pLayer = a pointer to a layer
00920     Returns:    TRUE if the layer has been processed
00921     Purpose:    Given a layer, if the layer contains a print mark, strip the print mark
00922                 out and try to add it to the PrintMarksMan cache.
00923     
00924 *****************************************************************************************/
00925 
00926 BOOL PrintMarksCache::DecodeCachedLayer(Layer* pLayer)
00927 {
00928     ERROR2IF(pLayer==NULL,FALSE,"NULL Layer passed to DecodeCachedLayer");
00929 
00930     // Read in the layer name
00931     String_256 Name;
00932     String_16 Token;
00933 
00934     Name = pLayer->GetLayerID();
00935     Name.Left(&Token, 10);
00936 
00937     BOOL IsValid = FALSE;
00938     BOOL IsCustomMark = FALSE;
00939     if (Token == String_16(_T("%PRINTMARK")))               // This text must not be internationalised
00940         IsValid = TRUE;
00941 
00942     if (!IsValid && Token == String_16(_T("%CUSTOMMAR")))   // This text must not be internationalised
00943     {
00944         IsValid = TRUE;
00945         IsCustomMark = TRUE;
00946     }
00947 
00948     if (!IsValid)
00949         return FALSE;
00950 
00951     // find the first renderable group in this layer.
00952     NodeGroup* pGroup = (NodeGroup*)pLayer->FindFirstChild(CC_RUNTIME_CLASS(NodeGroup));
00953     if (pGroup==NULL)
00954         return FALSE;
00955 
00956     // Create a new mark structure to put the decoded data into
00957     PrintMarkItem* pNewMark = new PrintMarkItem;
00958     if (!pNewMark)
00959         return FALSE;
00960 
00961     PrintMark* pMark = pNewMark->GetPrintMark();
00962     pMark->SetCustomOrDefault(IsCustomMark);        // Remember if it's a custom or default mark
00963     if (!DecodeMarkFormat(&Name, pMark))
00964     {
00965         delete pNewMark;
00966         return FALSE;
00967     }
00968 
00969     // Right we have a new print mark descriptor, 
00970     // we simply merge the mark into the
00971     // cache. It would be faster, before copying the subtree, to check whether we
00972     // dont already have this mark cached in the print mark manager.
00973 
00974     if (DoesMarkExist(pMark))
00975     {
00976         delete pNewMark;
00977         return TRUE;
00978     }
00979 
00980     // Add a handle to this mark
00981     pNewMark->SetHandle(GetUniqueHandle());
00982 
00983     // ok the mark does not exist, so now look for that first group
00984     if (!pNewMark->SetMarkGlyph(pGroup, TRUE))
00985     {
00986         delete pNewMark;
00987         return FALSE;
00988     }
00989 
00990     // Hey hey, we've finally done it! cool!
00991     PrintMarkCache.AddTail(pNewMark);
00992 
00993     return TRUE;
00994 }
00995 
00996 
00997 /*****************************************************************************************
00998 
00999 >   UINT32 PrintMarksCache::AddNewMark(PrintMarkItem* pNewMark, NodeGroup* pGroup)
01000 
01001     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01002     Created:    23/07/96
01003     Inputs:     pNewMark = a pointer to the new mark to add
01004                 pGroup = a pointer to the glyph to use. 
01005     Returns:    The handle of the newly added mark
01006     Purpose:    A simple way of adding a prebuilt mark to the list. The mark must be in
01007                 a renderable format, in that it should be a group with all needed attrs
01008                 as children, followed by a child group containing all the ink objects
01009     
01010 *****************************************************************************************/
01011 
01012 UINT32 PrintMarksCache::AddNewMark(PrintMarkItem* pNewMark, NodeGroup* pGroup)
01013 {
01014     // Add a handle to this mark
01015     UINT32 hndle = GetUniqueHandle();
01016     pNewMark->SetHandle(hndle);
01017     pNewMark->pMarkGlyph = pGroup;
01018     // Hey hey, we've finally done it! cool!
01019     PrintMarkCache.AddTail(pNewMark);
01020     return hndle;
01021 }
01022 
01023 
01024 /*****************************************************************************************
01025 
01026 >   void PrintMarksCache::UpdateMarkGlyph(PrintMarkItem *pMarkItem, NodeGroup *pGroup)
01027 
01028     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01029     Created:    23/07/96
01030     Inputs:     pMarkItem = a pointer to an existing cached mark
01031                 pGroup    = a pointer to a new glyph to use.
01032     Returns:    -
01033     Purpose:    Change the mark glyph to this new mark.
01034 
01035 *****************************************************************************************/
01036 
01037 void PrintMarksCache::UpdateMarkGlyph(PrintMarkItem *pMarkItem, NodeGroup *pGroup)
01038 {
01039     if (pMarkItem!=NULL)
01040     {
01041         // Make sure there's nothing in there at the mo.
01042         pMarkItem->RemoveMark();
01043         // now set the new mark glyph
01044         pMarkItem->pMarkGlyph = pGroup;
01045     }
01046 }
01047 
01048 
01049 
01050 /*****************************************************************************************
01051 
01052 >   BOOL PrintMarksCache::DecodeMarkFormat(const String_256 *pFormatString, PrintMark* pMark)
01053 
01054     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01055     Created:    23/07/96
01056     Inputs:     pFormatString
01057     Outputs:    pMark
01058     Returns:    TRUE if the format string was valid.
01059     Purpose:    Decode the string pointed to by pFormatString, placing each format
01060                 identifier into the output mark.
01061 
01062                 Special tag         Mark name           ID On/off Type      Position(s)
01063                 %PRINTMARK  = "Registration mark",      3,  1,  _R(ID_STAR), 3MCS + 7MC + 11MCS + 15MC
01064                 %CUSTOMMARK = "User registration mark", 0,  1,  _R(ID_STAR), 3MCS + 7MC + 11MCS + 15MC
01065 
01066 *****************************************************************************************/
01067 
01068 BOOL PrintMarksCache::DecodeMarkFormat(const String_256 *pFormatString, PrintMark* pMark)
01069 {
01070     ERROR2IF(pFormatString == NULL, FALSE, "NULL pointer passed to DecodeMarkFormat");
01071     ERROR2IF(pMark == NULL, FALSE, "NULL mark pointer passed to DecodeMarkFormat");
01072 
01073     String_256 Name(*pFormatString);
01074     String_256 MenuText;
01075     String_256 MenuID;
01076     MarkFormat NewFormat;
01077     MarkRegion NewRegion;
01078     MarkOrient NewOrient;
01079 
01080     const TCHAR COMMA   = TEXT(',');        // This text must not be internationalised
01081 //  const TCHAR EQUALS  = TEXT('=');
01082     const TCHAR QUOTES  = TEXT('"');
01083     const TCHAR PLUS    = TEXT('+');
01084     const TCHAR SPACE   = TEXT(' ');
01085 
01086     INT32 pos, pos1;
01087 
01088     // Everything is hunky dory at the moment! ER NOT!
01089     BOOL AllIsWell = FALSE;
01090 
01091     // Turn on the exceptions function in the string reading class
01092     StringBase::EnableExceptionHandler();
01093 
01094     //try 
01095     {
01096         // toast everything up to the first quote
01097         pos = Name.FindNextChar(QUOTES);
01098         Name.Remove(0,pos+1);
01099 
01100         // now find the last quote of the first string
01101         pos = Name.FindNextChar(QUOTES);
01102         Name.Left(&MenuText,pos);
01103         Name.Remove(0,pos+1);
01104 
01105         // skip over the first comma onto the ID field
01106         pos  = Name.SkipComma();
01107         Name.Remove(0,pos);
01108         pos = 0;
01109         INT32 ID = Name.ConvertToInteger(pos);
01110         Name.Remove(0,pos);
01111         if (ID < 0 || ID > 255)
01112             ID = 0;
01113         pMark->SetIDByte((BYTE)ID);
01114 
01115         // skip over the next comma onto the enable/disable state
01116         pos  = Name.SkipComma();
01117         Name.Remove(0,pos);
01118         BOOL Enabled = (Name[0] == TEXT('1'));
01119 
01120         // skip comma to next field
01121         pos  = Name.SkipComma();
01122         pos1 = Name.FindNextChar(COMMA, pos+1);
01123         Name.Mid(&MenuID, pos, (pos1-pos));
01124         Name.Remove(0,pos1+1);
01125 
01126         // turn the menu id into a type of mark if we recognise it
01127         MarkType actid = (MarkType)DecodeToMarkType(&MenuID);
01128 
01129         // skip the orientation field
01130         pos=Name.FindNextChar();
01131         NewOrient=MO_None;
01132         if (Name[pos] == TEXT('H'))
01133             NewOrient=MO_Horizontal;
01134         else if (Name[pos] == TEXT('V'))
01135             NewOrient=MO_Vertical;
01136 
01137         // remove the orientation bit
01138         pos = Name.SkipComma();
01139 
01140         // Add what we have so far
01141         pMark->SetMarkMenuText(&MenuText);
01142         pMark->SetOrientation(NewOrient);
01143         pMark->SetType(actid);
01144         pMark->SetDefaultState(Enabled);
01145 
01146         // The remainder of this string is a format list
01147 //      BOOL format=FALSE;
01148 //      BOOL eos=FALSE;
01149 
01150         // Turn our exception handler off but don't pop it.
01151         StringBase::DisableExceptionHandler(FALSE);
01152 
01153         INT32 region;
01154 
01155         while (pos>0)
01156         {
01157             // Try to create a new mark to add
01158             MarkPosition* pNewMark = new MarkPosition;
01159 
01160             if (pNewMark!=NULL)
01161             {
01162                 region = Name.ConvertToInteger(pos);
01163 
01164                 if (region<1 || region>MAXPAGEREGIONS)
01165                 {
01166                     // Ok, the region number is out of range so lets
01167                     // skip to the next one (if there is one!)
01168                     // we need to find the next +
01169                     delete pNewMark;
01170                     pos = Name.FindNextChar(PLUS, pos);
01171                 }
01172                 else
01173                 {
01174                     // store this type of region
01175                     NewRegion = (MarkRegion)(region-1);
01176                     pNewMark->SetRegion(NewRegion);
01177                                 
01178                     // if we haven't run off the end of the string
01179                     while ( Name.IsLegal(pos) && (Name[pos]!=PLUS) )
01180                     {
01181                         TCHAR c = Name[pos];
01182                         
01183                         switch (c)
01184                         {
01185                             case TEXT('T'): NewFormat.Top=TRUE;     break;
01186                             case TEXT('M'): NewFormat.Middle=TRUE;  break;
01187                             case TEXT('B'): NewFormat.Bottom=TRUE;  break;
01188                             case TEXT('L'): NewFormat.Left=TRUE;    break;
01189                             case TEXT('C'): NewFormat.Centre=TRUE;  break;
01190                             case TEXT('R'): NewFormat.Right=TRUE;   break;
01191                             default:
01192                                 // unknown token, just ignore it!
01193                                 if (c != SPACE)
01194                                     TRACEUSER( "Mike", _T("Unknown format character during PrintMarksMan::DecodeMarkFormat"));
01195                                 break;
01196                         }
01197                         
01198                         pos = Name.FindNextChar(pos+1);
01199                     }
01200 
01201                     // make sure the format is ok
01202                     if (!NewFormat.IsValid())
01203                         NewFormat.MakeValid();
01204                     
01205                     // and set it in the structure.
01206                     pNewMark->SetFormat(NewFormat);
01207 
01208                     // Add the new mark position to the list.
01209                     pMark->AddNewPosition(pNewMark);
01210 
01211                     AllIsWell=TRUE;
01212 
01213                     if (Name.IsLegal(pos))
01214                         pos = Name.FindNextChar(pos+1);
01215                 }
01216             }
01217             else
01218             {
01219                 pos = -1;
01220             }
01221         }
01222     }
01223 PORTNOTE("other", "Disabled random use of MFC CUserException in Kernel code")
01224 #ifndef EXCLUDE_FROM_XARALX
01225     catch (CUserException)
01226     {
01227         // An exception has been thrown which means
01228         // we failed to parse this string, so simply report failure
01229         AllIsWell = FALSE;
01230     }
01231 #endif
01232 
01233     // Switch off the exception state finally, (and of course pop it)!
01234     StringBase::DisableExceptionHandler();
01235 
01236     return AllIsWell;
01237 }
01238 
01239 
01240 
01241 /*****************************************************************************************
01242 
01243 >   UINT32 PrintMarksCache::DecodeToMarkType(String_256* Name) const
01244 
01245     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01246     Created:    23/07/96
01247     Inputs:     Name = a pointer to a string describing the mark type
01248     Returns:    A unsigned integer describing the mark type (see MarkType for instances)
01249     Purpose:    Have a look at the string passed in and check to see it matches any of
01250                 the known mark type names. If so return the proper mark type enum, otherwise
01251                 'Unkown' is returned.
01252     
01253 *****************************************************************************************/
01254 
01255 UINT32 PrintMarksCache::DecodeToMarkType(const String_256* Name) const
01256 {
01257     ERROR2IF(Name == NULL, MarkType_Unknown, "NULL pointer passed to DecodeToMarkType");
01258     
01259     if ((*Name)==String_16(_T("ID_NONE")))  return