fontcomp.cpp

Go to the documentation of this file.
00001 // $Id: fontcomp.cpp 1464 2006-07-18 12:32:26Z gerry $
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 >   fontcomp.cpp
00101 
00102     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00103     Created:    06/08/96
00104     Purpose:    Implementation of the document font component
00105 
00106 ********************************************************************************************/
00107 
00108 // Just a brief summary of the horrors of the way in which Camelot handles fonts.
00109 // 
00110 // There seem to be three independent systems handling fonts. The font
00111 // manager looks after installed fonts, specifically those used in
00112 // documents. The font gallery deals with both installed fonts and those
00113 // available (i.e. on the CD) and the text tool infobar deals with the
00114 // installed font families.
00115 // 
00116 // Each of these systems enumerates the fonts seperately, independently and
00117 // stores different information about the fonts. The biggedt gripe is with
00118 // the font gallery. When a font gets dragged form the font gallery to a
00119 // text story (to apply the font to the text story) the following steps are
00120 // done:
00121 // 
00122 // From the font gallery we know the LOGFONT structure for the font. We
00123 // remember the typeface name and whether its bold or italic (we store
00124 // these as booleans, even though the weight has at least 10 different
00125 // values). Then we ask the font manager for cache a font with the same
00126 // typeface name (doesn't care which font, just any font with the same
00127 // typeface name) and return a font handle. We then create a typeface
00128 // attribute with this font handle and the bold, italic booleans we
00129 // remembered.
00130 // 
00131 // The problem is that the font handle just points to any font with the
00132 // same typeface name, _not_ the font that was originally dragged from the
00133 // font manager. i.e. we could end up with the following situations.
00134 // 
00135 // Arial Bold Italic dragged from the font gallery
00136 // Typeface attribute:
00137 //  font handle -> Arial Regular
00138 //  bold        -> True
00139 //  italic      -> True
00140 // 
00141 // Arial Regular dragged from the font gallery
00142 // Typeface attribute:
00143 //  font handle -> Arial Bold Italic
00144 //  bold        -> False
00145 //  italic      -> False
00146 // 
00147 // (These do actually happen. The font found by the font manager when asked
00148 // for a font with a particular typeface is the first font installed with
00149 // that typeface. Try deinstalled the arial font family, install Arial Bold
00150 // Italic and then the other members of that family. Then see what happens
00151 // in the debug tree.)
00152 // 
00153 // Another point of evidence:
00154 // create four text stories, drag Arial to the first, Arial Bold to the
00155 // second, Arial Italic to the third and Arial Bold Italic to the fourth.
00156 // Then look at the debug tree - the text stories all have typeface
00157 // attributes, all with the same font handle but different bold and italic
00158 // flags.
00159 // 
00160 // Summary - after dragging a font from the font gallery to the document
00161 // there's absolutly no way to determine the name of the font originally
00162 // dragged. 
00163 // 
00164 // Shame really, since this information is required by the new file format.
00165 // The old .xar format gets around this by saving the typeface na,e and the
00166 // two flags and assuming that there are never more than 4 fonts with the
00167 // same typeface; one regular, one bold, one italic and one bold italic
00168 // (great - we'll assume the problem doesn't exist).
00169 // 
00170 // So, how can we correct this, since for the new file format we require
00171 // the full font name (we can't get this, remember?), the typeface name and
00172 // the PANOSE number for the original font (which we don't know, since we
00173 // don't know what the font originally dragged was).
00174 // 
00175 // Solution
00176 //  * ignore the full font name, just save out an empty string
00177 //  * save out the typeface name (at least we have something)
00178 //  * get the PANOSE number for the font we do have, alter the Weight
00179 //    and Letterform members to take into account the bold and italic
00180 //    flags.
00181 // 
00182 // On import we'll have to get a list of all the fonts with the typeface
00183 // and choose the closest using a metric on the PANOSE numbers - this may
00184 // work, but no guarentees. :(
00185 // 
00186 // In order to manage all this information and to provide a method of
00187 // retained font information should we load a file with contains font
00188 // definitions to fonts we don't have, I offer another method of handling
00189 // fonts the FontComponent document component.
00190 // 
00191 // When importing a new format file font defintions get matched immediatly
00192 // to one of the installed fonts using the font name, face name and PANOSE
00193 // number. All this information is then added to the font list maintained
00194 // by the FontComponent object attached to the document. Whe we reach a
00195 // font typeface attribute we can just retrieve the necessary information
00196 // and put it into the tree.
00197 // 
00198 // Whe exporting a new format file font definitions get requested by the
00199 // font typeface attribute code. We first search the list for a matching
00200 // item in the list, so we can immediatly get the relevant font information
00201 // (in case we're dealiing with a font not installed on this machine).
00202 // Otherwise we'll ask the font manager nicely for the typeface name and
00203 // PANOSE number (We can't get the font name because its all so screwed
00204 // up). Then we'll have to bodge the PANOSE nubmer using the IsBold and
00205 // IsItalic flags in the typeface attribute. Finally we'll put this
00206 // information into our list, write out a font definition record, store the
00207 // record number along side the rest of the information about this font and
00208 // return the record number.
00209 // 
00210 // Of course subsequent times we get asked for a font definition record we
00211 // can search the list and return the record number of the original font
00212 // definition record.
00213 // 
00214 // Before import and export we need to set all the record numbers to NULL
00215 // to show that they're not valid (i.e. to allow multiple imports and
00216 // exports to and from the same document).
00217 // 
00218 // Some of this information could be merged with the font manager (font
00219 // name, face name, PANOSE number), some of this is document specific
00220 // (record number).
00221 // 
00222 // There's bound to be some information I've missed out - so go and read
00223 // the code and work out for yourself how its all held together. 
00224 // 
00225 // Ach.
00226 
00227 #include "camtypes.h"
00228 
00229 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00230 #include "ccpanose.h"
00231 //#include "fontbase.h"
00232 #include "fontman.h"
00233 
00234 #include "cxftags.h"
00235 //#include "cxfrec.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00236 //#include "camfiltr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00237 //#include "filtrres.h" // _R(IDS_NATIVE_FONTWARNING)
00238 
00239 //#include "doccomp.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00240 #include "fontcomp.h"
00241 
00242 #include "ttfonts.h"
00243 //#include "atmfonts.h"
00244 
00245 CC_IMPLEMENT_DYNAMIC(FontComponentClass, DocComponentClass)
00246 CC_IMPLEMENT_DYNAMIC(FontComponentListItem, ListItem)
00247 CC_IMPLEMENT_DYNAMIC(FontComponentList, List)
00248 CC_IMPLEMENT_DYNAMIC(FontComponent, DocComponent)
00249 
00250 // Declare smart memory handling in Debug builds
00251 #define new CAM_DEBUG_NEW
00252 
00253 /********************************************************************************************
00254 
00255 >   BOOL FontComponentClass::Init()
00256 
00257     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00258     Created:    06/08/96
00259     Inputs:     -
00260     Returns:    TRUE if successful, FALSE otherwise
00261     Purpose:    Registers the font component with the main application
00262     See Also:   class DocComponentClass
00263 
00264 ********************************************************************************************/
00265 
00266 BOOL FontComponentClass::Init()
00267 {
00268     // Instantiate a component class to register with the application
00269     FontComponentClass *pClass = new FontComponentClass;
00270     if (pClass==NULL)
00271     {
00272         return FALSE;
00273     }
00274     else
00275     {
00276         GetApplication()->RegisterDocComponent(pClass);
00277         return TRUE;
00278     }
00279 }
00280 
00281 /********************************************************************************************
00282 
00283 >   BOOL FontComponentClass::AddComponent(BaseDocument *pDoc)
00284 
00285     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00286     Created:    06/08/96
00287     Inputs:     pDoc    - pointer to the document to which we add a component to
00288     Returns:    TRUE if successful, FALSE otherwise
00289     Purpose:    Adds a font component to the specified document
00290     See Also:   class FontComponent
00291 
00292 ********************************************************************************************/
00293 
00294 BOOL FontComponentClass::AddComponent(BaseDocument *pDoc)
00295 {
00296     // check to see if this document already has a font component, if so we leave it alone
00297     if (pDoc->GetDocComponent(CC_RUNTIME_CLASS(FontComponent)) != NULL)
00298     {
00299         return TRUE;
00300     }
00301     else
00302     {
00303         // no document component - try to create one for this document
00304         FontComponent *pFontComponent = new FontComponent;
00305 
00306         // now add this to the document
00307         pDoc->AddDocComponent(pFontComponent);
00308 
00309         // success!
00310         return TRUE;
00311     }
00312 }
00313 
00314 /********************************************************************************************
00315 
00316 >   FontComponentListItem::FontComponentListItem()
00317 
00318     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00319     Created:    09/08/96
00320     Inputs:     -
00321     Returns:    -
00322     Purpose:    Constructor
00323     See Also:   class FontComponentList, class FontComponent
00324 
00325 ********************************************************************************************/
00326 
00327 FontComponentListItem::FontComponentListItem()
00328 {
00329     mIsBold = FALSE;
00330     mIsItalic = FALSE;
00331     mRecentlyCreated = TRUE;        // set to FALSE before any imports or exports
00332     mFontHandle = ILLEGALFHANDLE;
00333     mRecordNumber = 0;
00334     mFullFontName = _T("");
00335     mTypeFaceName = _T("");
00336     mFontClass = FC_UNDEFINED;
00337     mPanoseNumber.SetAllToAny();
00338 }
00339 
00340 /********************************************************************************************
00341 
00342 >   FontComponentListItem::~FontComponentListItem()
00343 
00344     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00345     Created:    09/08/96
00346     Inputs:     -
00347     Returns:    -
00348     Purpose:    Destructor
00349     See Also:   class FontComponentList, class FontComponent
00350 
00351 ********************************************************************************************/
00352 
00353 FontComponentListItem::~FontComponentListItem()
00354 {
00355 }
00356 
00357 /********************************************************************************************
00358 
00359 >   FontComponentList::FontComponentList()
00360 
00361     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00362     Created:    09/08/96
00363     Inputs:     -
00364     Returns:    -
00365     Purpose:    Constructor
00366     See Also:   class FontComponent
00367 
00368 ********************************************************************************************/
00369 
00370 FontComponentList::FontComponentList()
00371 {
00372     ExportInitialised=FALSE;
00373     ImportInitialised=FALSE;
00374 }
00375 
00376 /********************************************************************************************
00377 
00378 >   FontComponentList::~FontComponentList()
00379 
00380     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00381     Created:    09/08/96
00382     Inputs:     -
00383     Returns:    -
00384     Purpose:    Destructor
00385     See Also:   class FontComponent
00386 
00387 ********************************************************************************************/
00388 
00389 FontComponentList::~FontComponentList()
00390 {
00391     ERROR3IF(ExportInitialised==TRUE, "Deconstructor called when ExportInitialised==TRUE");
00392     ERROR3IF(ImportInitialised==TRUE, "Deconstructor called when ImportInitialised==TRUE");
00393     
00394     DeleteAll();
00395 }
00396 
00397 /********************************************************************************************
00398 
00399 >   BOOL FontComponentList::ExportStart()
00400 
00401     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00402     Created:    09/08/96
00403     Inputs:     -
00404     Returns:    TRUE if successful, FALSE otherwise
00405     Purpose:    Gives objects of this type a chance to prepare for an export operation.
00406     See Also:   class FontComponent
00407 
00408 ********************************************************************************************/
00409 
00410 BOOL FontComponentList::ExportStart()
00411 {
00412     ERROR2IF(ExportInitialised!=FALSE, FALSE, "ExportStart called when ExportInitialised!=FALSE.");
00413 
00414     FontComponentListItem *pItem = (FontComponentListItem *) GetHead();
00415 
00416     // need to set the mRecentlyCreated and mRecordNumber member of all the elements in the list to NULL
00417     while (pItem!=NULL)
00418     {
00419         pItem->mRecentlyCreated = FALSE;
00420         pItem->mRecordNumber = 0;
00421         pItem = (FontComponentListItem *) GetNext(pItem);
00422     }
00423 
00424     ExportInitialised = TRUE;
00425 
00426     return TRUE;
00427 }
00428 
00429 /********************************************************************************************
00430 
00431 >   BOOL FontComponentList::ExportEnd(BOOL Success)
00432 
00433     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00434     Created:    09/08/96
00435     Inputs:     Success - succcess status of the export operation
00436     Returns:    TRUE if successful, FALSE otherwise
00437     Purpose:    Gives objects if this class a chance to recover from an export operation,
00438                 tidying up if neccessary.
00439     See Also:   class FontComponent
00440 
00441 ********************************************************************************************/
00442 
00443 BOOL FontComponentList::ExportEnd(BOOL Success)
00444 {
00445     //ERROR2IF(ExportInitialised==FALSE, FALSE, "ExportEnd called when ExportInitialised==FALSE.");
00446     // If we error about the ExportInitialised then we assume that the StartExport has been called.
00447     // This may not be the case if we are in clean up mode. So just handle it!
00448 
00449     if (Success==FALSE && ExportInitialised)
00450     {
00451         // export operation was unsuccessful, so need to delete all the entries in the list
00452         // made during the export. this is easy; since the mRecentlyCreated member of all the
00453         // elements in the list was set to FALSE before the export any element with an non-FALSE
00454         // mRecentlyCreated member.
00455 
00456         FontComponentListItem *pItem = (FontComponentListItem *) GetHead();
00457         FontComponentListItem *qItem;
00458 
00459         while (pItem!=NULL)
00460         {
00461             qItem = pItem;
00462             pItem = (FontComponentListItem *) GetNext(qItem);
00463 
00464             if (qItem->mRecentlyCreated==TRUE)
00465             {
00466                 RemoveItem(qItem);
00467                 delete qItem;
00468             }
00469         }
00470     }
00471     //else // Removed due to the change to the if statement above
00472     //{
00473     //  // oh well, the export operation was successful, so do nothing
00474     //}
00475 
00476     ExportInitialised=FALSE;
00477     return TRUE;
00478 }
00479 
00480 /********************************************************************************************
00481 
00482 >   FontComponentListItem *FontComponentList::ExportFind(WORD FontHandle, BOOL IsBold, BOOL IsItalic)
00483 
00484     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00485     Created:    09/08/96
00486     Inputs:     FontHandle  : font handle to search for
00487                 IsBold      : bold flag to search for
00488                 IsItalic    : italic flag to search for
00489     Returns:    Pointer to the matching FontComponentListItem if found, or NULL
00490     Purpose:    Searches the list of FontComponentListItem's for a match
00491     See Also:   class FontComponentListItem
00492 
00493 ********************************************************************************************/
00494 
00495 FontComponentListItem *FontComponentList::ExportFind(WORD FontHandle, BOOL IsBold, BOOL IsItalic)
00496 {
00497     ERROR2IF(ExportInitialised==FALSE, FALSE, "ExportFind called when ExportInitialised==FALSE.");
00498 
00499     // auxillary functions, searches using tail recursion. the msvc compiler should
00500     // optimise this quite well - at least, it should
00501     return ExportFindAux((FontComponentListItem *) GetHead(), FontHandle, IsBold, IsItalic);
00502 }
00503 
00504 /********************************************************************************************
00505 
00506 >   FontComponentListItem *FontComponentList::ExportFindAux(FontComponentListItem *pItem, WORD FontHandle, BOOL IsBold, BOOL IsItalic)
00507 
00508     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00509     Created:    09/08/96
00510     Inputs:     pItem       : current FontComponentListItem of interest
00511                 FontHandle  : font handle to search for
00512                 IsBold      : bold flag to search for
00513                 IsItalic    : italic flag to search for
00514     Returns:    Pointer to a matching FontComponentListItem, or null if not found
00515     Purpose:    Searches the list of FontComponentListItems for match
00516     See Also:   class FontComponentListItem, class FontComponent
00517 
00518 ********************************************************************************************/
00519 
00520 FontComponentListItem *FontComponentList::ExportFindAux(FontComponentListItem *pItem, WORD FontHandle, BOOL IsBold, BOOL IsItalic)
00521 {
00522     ERROR2IF(ExportInitialised==FALSE, FALSE, "ExportFindAux called when ExportInitialised==FALSE.");
00523     ERROR2IF(FontHandle==ILLEGALFHANDLE, FALSE, "ExportFindAux called with an illegal font handle.");
00524 
00525     if (pItem==NULL)
00526     {
00527         return NULL;
00528     }
00529     else if (pItem->mFontHandle==FontHandle && pItem->mIsBold==IsBold && pItem->mIsItalic==IsItalic)
00530     {
00531         return pItem;
00532     }
00533     else
00534     {
00535         // tail recursion ;)
00536         return ExportFindAux((FontComponentListItem *) GetNext(pItem), FontHandle, IsBold, IsItalic);
00537     }
00538 }
00539 
00540 /********************************************************************************************
00541 
00542 >   BOOL FontComponentList::ImportStart()
00543 
00544     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00545     Created:    09/08/96
00546     Inputs:     -
00547     Returns:    TRUE if successful, FALSE otherwise
00548     Purpose:    Allows objects of this class a chance to initialise before an import operation
00549     See Also:   class FontComponent
00550 
00551 ********************************************************************************************/
00552 
00553 BOOL FontComponentList::ImportStart()
00554 {
00555     ERROR2IF(ImportInitialised!=FALSE, FALSE, "ImportStart called when ImportInitialised!=FALSE");
00556 
00557     FontComponentListItem *pItem = (FontComponentListItem *) GetHead();
00558 
00559     // need to set the mRecentlyCreated and mRecordNumber members of all the elements in the list
00560     // to FALSE and NULL respectively.
00561     while (pItem!=NULL)
00562     {
00563         pItem->mRecentlyCreated=FALSE;
00564         pItem->mRecordNumber = 0;
00565         pItem = (FontComponentListItem *) GetNext(pItem);
00566     }
00567 
00568     ImportInitialised=TRUE;
00569 
00570     return TRUE;
00571 }
00572 
00573 /********************************************************************************************
00574 
00575 >   BOOL FontComponentList::ImportEnd(BOOL Success)
00576 
00577     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00578     Created:    09/08/96
00579     Inputs:     Success     - success status of the import operation
00580     Returns:    TRUE if successful, FALSE otherwise
00581     Purpose:    Allows objects of this class a chance to recover from an import operation
00582     See Also:   class FontComponent
00583 
00584 ********************************************************************************************/
00585 
00586 BOOL FontComponentList::ImportEnd(BOOL Success)
00587 {
00588     //ERROR2IF(ImportInitialised==FALSE, FALSE, "ImportEnd called when ImportInitialised==FALSE.");
00589     // If we error about the ImportInitialised then we assume that the StartExport has been called.
00590     // This may not be the case if we are in clean up mode. So just handle it!
00591 
00592     if (Success==FALSE && ImportInitialised)
00593     {
00594         // import operation was not successful, so we need to delete any elements in the list
00595         // created during the import. this is easy since all the elements in the list had
00596         // their mRecentlyCreated member set to FALSE before the import - any new elements will
00597         // have mRecentlyCreated==TRUE (thanks to the FontComponentListItem constructor).
00598 
00599         FontComponentListItem *pItem = (FontComponentListItem *) GetHead();
00600         FontComponentListItem *qItem = NULL;
00601 
00602         while (pItem!=NULL)
00603         {
00604             qItem = pItem;
00605             pItem = (FontComponentListItem *) GetNext(qItem);
00606 
00607             if (qItem->mRecentlyCreated==TRUE)
00608             {
00609                 RemoveItem(qItem);
00610                 delete qItem;
00611             }
00612         }
00613     }
00614     //else // Removed due to the change to the if statement above
00615     //{
00616     //  // import operation was successful, so just return.
00617     //}
00618 
00619     ImportInitialised=FALSE;
00620     return TRUE;
00621 }
00622 
00623 /********************************************************************************************
00624 
00625 >   FontComponentListItem *FontComponentList::ImportFind(INT32 RecordNumber)
00626 
00627     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00628     Created:    09/08/96
00629     Inputs:     RecordNumber    - record number to search for
00630     Returns:    pointer to the matching FontComponentListItem, or NULL if not found.
00631     Purpose:    Searches the list for a matching FontComponentListItem.
00632     See Also:   class FontComponentListItem, class FontComponent
00633 
00634 ********************************************************************************************/
00635 
00636 FontComponentListItem *FontComponentList::ImportFind(INT32 RecordNumber)
00637 {
00638     ERROR2IF(ImportInitialised==FALSE, FALSE, "ImportFind callled when ImportInitialied==FALSE.");
00639 
00640     return ImportFindAux((FontComponentListItem *) GetHead(), RecordNumber);
00641 }
00642 
00643 /********************************************************************************************
00644 
00645 >   FontComponentListItem *FontComponentList::ImportFindAux(FontComponentListItem *pItem, INT32 RecordNumber)
00646 
00647     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00648     Created:    09/08/96
00649     Inputs:     pItem           - current FontComponentListItem of interest
00650                 RecordNumber    - record number to search for
00651     Returns:    pointer to the matching FontComponentListItem or NULL if not found
00652     Purpose:    Searches the list for a matching FontComponentListItem
00653     See Also:   class FontComponentListItem, class FontComponent
00654 
00655 ********************************************************************************************/
00656 
00657 FontComponentListItem *FontComponentList::ImportFindAux(FontComponentListItem *pItem, INT32 RecordNumber)
00658 {
00659     ERROR2IF(ImportInitialised==FALSE, FALSE, "ImportFindAux called when ImportInitialised==FALSE.");
00660 
00661     if (pItem==NULL)
00662     {
00663         return NULL;
00664     }
00665     else if (pItem->mRecordNumber==RecordNumber)
00666     {
00667         return pItem;
00668     }
00669     else
00670     {
00671         // tail recursion ;)
00672         return ImportFindAux((FontComponentListItem *) GetNext(pItem), RecordNumber);
00673     }
00674 }
00675 
00676 /********************************************************************************************
00677 
00678 >   FontComponent::FontComponent()
00679 
00680     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00681     Created:    09/08/96
00682     Inputs:     -
00683     Returns:    -
00684     Purpose:    Constructor
00685     See Also:   class FontComponent
00686 
00687 ********************************************************************************************/
00688 
00689 FontComponent::FontComponent()
00690 {
00691     // constructor for this class, ho hum,
00692     ExportInitialised = FALSE;
00693     ImportInitialised = FALSE;
00694 
00695     pFontList = new FontComponentList;
00696     pFontManager = GetApplication()->GetFontManager();
00697 
00698     // Our link to the BaseCamelotFilter
00699     pCamFilter = NULL;
00700     // Set our variable so that we warn about a possible replacement only once
00701     WarnedBefore = FALSE;
00702 }
00703 
00704 /********************************************************************************************
00705 
00706 >   FontComponent::~FontComponent()
00707 
00708     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00709     Created:    09/08/96
00710     Inputs:     -
00711     Returns:    -
00712     Purpose:    Destructor
00713     See Also:   class FontComponent
00714 
00715 ********************************************************************************************/
00716 
00717 FontComponent::~FontComponent()
00718 {
00719     ERROR3IF(ImportInitialised!=FALSE, "Deconstructor called when ImportInitialised!=FALSE");
00720     ERROR3IF(ExportInitialised!=FALSE, "Deconstructor called when ExportInitialised!=FALSE");
00721 
00722     if (pFontList)
00723     {
00724         delete pFontList;
00725         pFontList = NULL;
00726     }
00727 }
00728 
00729 /********************************************************************************************
00730 
00731 >   BOOL FontComponent::StartExport(BaseCamelotFilter *pFilter)
00732 
00733     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00734     Created:    09/08/96
00735     Inputs:     -
00736     Returns:    TRUE if successful, FALSE otherwise
00737     Purpose:    Allows the font component a chance to prepare for an export operation
00738     See Also:   class FontComponent
00739 
00740 ********************************************************************************************/
00741 
00742 BOOL FontComponent::StartExport(BaseCamelotFilter *pFilter)
00743 {
00744     ERROR2IF(ExportInitialised!=FALSE, FALSE, "StartExport called when ExportInitialised!=FALSE");
00745     ERROR2IF(pFontList==NULL, FALSE, "StartExport called when pFontList==NULL.");
00746 
00747     BOOL ok = TRUE;
00748 
00749     if (ok) ok = pFontList->ExportStart();
00750     if (ok) ExportInitialised=TRUE;
00751 
00752     return ok;
00753 }
00754 
00755 /********************************************************************************************
00756 
00757 >   BOOL FontComponent::EndExport(BaseCamelotFilter *pFilter, BOOL Success)
00758 
00759     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00760     Created:    09/08/96
00761     Inputs:     -
00762     Returns:    TRUE if successful, FALSE otherwise
00763     Purpose:    Allows the font component a chance to recover from an export operation
00764     See Also:   class FontComponent
00765 
00766 ********************************************************************************************/
00767 
00768 BOOL FontComponent::EndExport(BaseCamelotFilter *pFilter, BOOL Success)
00769 {
00770     //ERROR2IF(ExportInitialised==FALSE, FALSE, "EndExport called when ExportInitialised==FALSE.");
00771     //ERROR2IF(pFontList==NULL, FALSE, "EndExport called when pFontList==NULL.");
00772     // If we error about the pFontList and ExportInitialised then we assume that the StartExport has been called.
00773     // This may not be the case if we are in clean up mode. So just handle it!
00774 
00775     BOOL ok = TRUE;
00776 
00777     if (ok && pFontList) ok = pFontList->ExportEnd(Success);
00778     if (ok) ExportInitialised=FALSE;
00779 
00780     return ok;
00781 }
00782 
00783 /********************************************************************************************
00784 
00785 >   INT32 FontComponent::WriteFontDefinition(BaseCamelotFilter *pFilter, WORD FontHandle, BOOL IsBold, BOOL IsItalic)
00786 
00787     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00788     Created:    09/08/96
00789     Inputs:     pFilter     - filter to write font defintion record to
00790                 FontHandle  - font handle of font definition to write
00791                 IsBold      - bold flag of font definition
00792                 IsItalic    - italic flag of font definition
00793     Returns:    RecordNumber of font definition, or NULL if unsuccessful
00794     Purpose:    Writes a font definition record to the filter, and returns with the record number
00795                 of this font definition record.
00796     See Also:   class FontComponent, class FontComponentList, class FontComponentListItem
00797 
00798 ********************************************************************************************/
00799 
00800 INT32 FontComponent::WriteFontDefinition(BaseCamelotFilter *pFilter, WORD FontHandle, BOOL IsBold, BOOL IsItalic)
00801 {
00802     ERROR2IF(ExportInitialised==FALSE, FALSE, "EndExport called when ExportInitialised==FALSE.");
00803     ERROR2IF(pFilter==NULL, FALSE, "Parameter pFilter==NULL.");
00804     ERROR2IF(FontHandle==ILLEGALFHANDLE, FALSE, "Parameter FontHandle==ILLEGALFHANDLE.");
00805     ERROR2IF(pFontList==NULL, FALSE, "member variable pFontList==NULL.");
00806 
00807     INT32 RecordNumber = 0;
00808     FontComponentListItem *pItem;
00809     
00810     // is this item already cached?
00811     pItem = pFontList->ExportFind(FontHandle, IsBold, IsItalic);
00812 
00813     if (pItem==NULL)
00814     {
00815         // first time we've come across this font, so cache some information about it.
00816         pItem = new FontComponentListItem;
00817         pItem->mFontHandle = FontHandle;
00818         pItem->mIsBold = IsBold;
00819         pItem->mIsItalic = IsItalic;
00820 
00821         (void) ExportCacheFont(pItem);      // cache the rest of the information about this font
00822 
00823         pFontList->AddTail(pItem);
00824     }
00825 
00826     // by now, pItem!=NULL, otherwise we've got serious problems
00827 
00828     if (pItem!=NULL)
00829     {
00830         // have we already written a font defintion record for this font? i.e. is
00831         // mRecordNumber!=NULL?
00832         if (pItem->mRecordNumber != 0)
00833         {
00834             RecordNumber = pItem->mRecordNumber;
00835         }
00836         else
00837         {
00838             RecordNumber = WriteFontRecord(pFilter, pItem);
00839             pItem->mRecordNumber=RecordNumber;
00840         }
00841     }
00842     else
00843     {
00844         ERROR3("pItem==NULL, and it shouldn't!");
00845         RecordNumber=0;
00846     }
00847 
00848     return RecordNumber;
00849 }
00850 
00851 /********************************************************************************************
00852 
00853 >   INT32 FontComponent::WriteFontRecord(BaseCamelotFilter *pFilter, FontComponentListItem *pItem)
00854     INT32 FontComponent::WriteTrueTypeRecord(BaseCamelotFilter *pFilter, FontComponentListItem *pItem)
00855     INT32 FontComponent::WriteATMRecord(BaseCamelotFilter *pFilter, FontComponentListItem *pItem)
00856     INT32 FontComponent::WriteUnknownRecord(BaseCamelotFilter *pFilter, FontComponentListItem *pItem)
00857 
00858     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00859     Created:    09/08/96
00860     Inputs:     pFilter     - filter to write
00861                 pItem       - fontto write a definition for
00862     Returns:    Record number of font definition record, or 0 if unsuccessful
00863     Purpose:    Writes a font definition record to the filter, and returns with the record number
00864     See Also:   class FontComponent, class FontComponentListItem
00865 
00866 ********************************************************************************************/
00867 
00868 INT32 FontComponent::WriteFontRecord(BaseCamelotFilter *pFilter, FontComponentListItem *pItem)
00869 {
00870     ERROR2IF(ExportInitialised==FALSE, FALSE, "EndExport called when ExportInitialised==FALSE.");
00871     ERROR2IF(pFilter==NULL, 0, "Parameter pFilter==NULL.");
00872     ERROR2IF(pItem==NULL, 0, "Parameter pItem==NULL.");
00873 
00874     INT32 RecordNumber;
00875     
00876     switch (pItem->mFontClass)
00877     {
00878         case FC_TRUETYPE        : RecordNumber = WriteTrueTypeRecord(pFilter, pItem); break;
00879         case FC_ATM             : RecordNumber = WriteATMRecord(pFilter, pItem); break;
00880         default                 : RecordNumber = WriteUnknownRecord(pFilter, pItem); break;
00881     }
00882 
00883     return RecordNumber;
00884 }
00885 
00886 INT32 FontComponent::WriteTrueTypeRecord(BaseCamelotFilter *pFilter, FontComponentListItem *pItem)
00887 {
00888     ERROR2IF(ExportInitialised==FALSE, FALSE, "EndExport called when ExportInitialised==FALSE.");
00889     ERROR2IF(pFilter==NULL, 0, "Parameter pFilter==NULL.");
00890     ERROR2IF(pItem==NULL, 0, "Parameter pItem==NULL.");
00891 
00892     BOOL ok = TRUE;
00893     INT32 RecordNumber = 0;
00894 
00895     CamelotFileRecord Rec(pFilter, TAG_FONT_DEF_TRUETYPE, TAG_FONT_DEF_TRUETYPE_SIZE);
00896 
00897     ok = Rec.Init();
00898 
00899     if (ok) ok = Rec.WriteUnicode((TCHAR*)pItem->mFullFontName);
00900     if (ok) ok = Rec.WriteUnicode((TCHAR*)pItem->mTypeFaceName);
00901     if (ok) ok = Rec.WriteCCPanose(pItem->mPanoseNumber);
00902 
00903     if (ok) ok = (0 != (RecordNumber = pFilter->WriteDefinitionRecord(&Rec)));
00904     
00905     // if ok==TRUE, then by the above line RecordNumber!=NULL. if ok==FALSE then
00906     // RecordNumber==NULL. so we don't need to check ok at this point.
00907     return RecordNumber;
00908 }
00909 
00910 INT32 FontComponent::WriteATMRecord(BaseCamelotFilter *pFilter, FontComponentListItem *pItem)
00911 {
00912     ERROR2IF(ExportInitialised==FALSE, FALSE, "EndExport called when ExportInitialised==FALSE.");
00913     ERROR2IF(pFilter==NULL, 0, "Parameter pFilter==NULL.");
00914     ERROR2IF(pItem==NULL, 0, "Parameter pItem==NULL.");
00915 
00916     BOOL ok = TRUE;
00917     INT32 RecordNumber = 0;
00918 
00919     CamelotFileRecord Rec(pFilter, TAG_FONT_DEF_ATM, TAG_FONT_DEF_ATM_SIZE);
00920 
00921     ok = Rec.Init();
00922 
00923     if (ok) ok = Rec.WriteUnicode((TCHAR*)pItem->mFullFontName);
00924     if (ok) ok = Rec.WriteUnicode((TCHAR*)pItem->mTypeFaceName);
00925     if (ok) ok = Rec.WriteCCPanose(pItem->mPanoseNumber);
00926 
00927     if (ok) ok = (0 != (RecordNumber = pFilter->WriteDefinitionRecord(&Rec)));
00928 
00929     // if ok==TRUE, then by the above line RecordNumber!=NULL. if ok==FALSE then
00930     // RecordNumber==NULL. so we don't need to check ok at this point.
00931     return RecordNumber;
00932 }
00933 
00934 INT32 FontComponent::WriteUnknownRecord(BaseCamelotFilter *pFilter, FontComponentListItem *pItem)
00935 {
00936     ERROR2IF(ExportInitialised==FALSE, FALSE, "EndExport called when ExportInitialised==FALSE.");
00937     ERROR2IF(pFilter==NULL, 0, "Parameter pFilter==NULL.");
00938     ERROR2IF(pItem==NULL, 0, "Parameter pItem==NULL.");
00939 
00940     ERROR3("Attempt to write an font definition for an unknown file type.");
00941     
00942     return 0;
00943 }
00944 
00945 /********************************************************************************************
00946 
00947 >   BOOL FontComponent::StartImport(BaseCamelotFilter *pFilter)
00948 
00949     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00950     Created:    12/08/96
00951     Inputs:     pFilter - filter to use
00952     Returns:    TRUE if successful, FALSE otherwise
00953     Purpose:    Gives objects of type class FontComponent a chance to prepare themselves for
00954                 an import operation
00955     See Also:   class FontComponent
00956 
00957 ********************************************************************************************/
00958 
00959 BOOL FontComponent::StartImport(BaseCamelotFilter *pFilter)
00960 {
00961     ERROR2IF(ImportInitialised!=FALSE, FALSE, "StartImport called when ImportInitialised!=FALSE.");
00962     ERROR2IF(pFontList==NULL, FALSE, "StartImport called when pFontList==NULL.");
00963 
00964     // Save this in our link to the BaseCamelotFilter
00965     pCamFilter = pFilter;
00966     // Set our variable so that we warn about a possible replacement only once
00967     WarnedBefore = FALSE;
00968 
00969     BOOL ok = TRUE;
00970 
00971     if (ok) ok = pFontList->ImportStart();
00972     if (ok) ImportInitialised=TRUE;
00973 
00974     return ok;
00975 }
00976 
00977 /********************************************************************************************
00978 
00979 >   BOOL FontComponent::EndImport(BaseCamelotFilter *pFilter, BOOL Success)
00980 
00981     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00982     Created:    12/08/96
00983     Inputs:     pFilter - filter to use
00984                 Success - TRUE if import operation was successful, FALSE otherwise
00985     Returns:    TRUE if successful, FALSE otherwise
00986     Purpose:    Gives this class a chance to recover from an import operation
00987     See Also:   class FontComponent
00988 
00989 ********************************************************************************************/
00990 
00991 BOOL FontComponent::EndImport(BaseCamelotFilter *pFilter, BOOL Success)
00992 {
00993     //ERROR2IF(ImportInitialised==FALSE, FALSE, "EndImport called when ImportInitialised==FALSE.");
00994     //ERROR2IF(pFontList==NULL, FALSE, "EndImport called when pFontList==NULL.");
00995     // If we error about the pFontList and ImportInitialised then we assume that the EndExport has been called.
00996     // This may not be the case if we are in clean up mode. So just handle it!
00997 
00998     BOOL ok = TRUE;
00999 
01000     if (ok && pFontList) ok = pFontList->ImportEnd(Success);
01001     if (ok) ImportInitialised=FALSE;
01002 
01003     // Null our link to the BaseCamelotFilter
01004     pCamFilter = NULL;
01005     // Set our variable so that we warn about a possible replacement only once
01006     WarnedBefore = FALSE;
01007 
01008     return ok;
01009 }
01010 
01011 /********************************************************************************************
01012 
01013 >   BOOL FontComponent::ReadFontDefinition(CXaraFileRecord *pRec)
01014     BOOL FontComponent::ReadFontTrueType(CXaraFileRecord *pRec)
01015     BOOL FontComponent::ReadFontATM(CXaraFileRecord *pRec)
01016     BOOL FontComponent::ReadFontDefault(CXaraFileRecord *pRec)
01017 
01018     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
01019     Created:    12/08/96
01020     Inputs:     pRec    : pointer to a CXaraFileRecord to read
01021     Returns:    TRUE if successful, FALSE otherwise
01022     Purpose:    Reads a font component record from the filter
01023     See Also:   class FontComponent, class TextObjRecordHandler
01024 
01025 ********************************************************************************************/
01026 
01027 BOOL FontComponent::ReadFontDefinition(CXaraFileRecord *pRec)
01028 {
01029     ERROR2IF(pRec==NULL, FALSE, "Parameter pRec==NULL.");
01030     ERROR2IF(ImportInitialised==FALSE, FALSE, "ReadFontDefinition called when ImportInitialised==FALSE.");
01031 
01032     BOOL ok;
01033 
01034     switch (pRec->GetTag())
01035     {
01036         case TAG_FONT_DEF_TRUETYPE  : ok = ReadFontTrueType(pRec); break;
01037         case TAG_FONT_DEF_ATM       : ok = ReadFontATM(pRec); break;
01038         default                     : ok = ReadFontUnknown(pRec); break;
01039     }
01040 
01041     return ok;
01042 }
01043 
01044 BOOL FontComponent::ReadFontTrueType(CXaraFileRecord *pRec)
01045 {
01046     ERROR2IF(ImportInitialised==FALSE, FALSE, "ReadFontTrueType called when ImportInitialised==FALSE.");
01047     ERROR2IF(pRec==NULL, FALSE, "Parameter pRec==NULL.");
01048     ERROR2IF(pFontList==NULL, FALSE, "ReadFontTrueType called when pFontList==NULL.");
01049 
01050     BOOL ok = TRUE;
01051 
01052     TCHAR Buffer[256];
01053     FontComponentListItem *pItem = new FontComponentListItem;
01054 
01055     pItem->mRecordNumber = pRec->GetRecordNumber();
01056 
01057     pItem->mFontClass = FC_TRUETYPE;
01058 
01059     if (ok) ok = pRec->ReadUnicode(Buffer, 256);
01060     pItem->mFullFontName = Buffer;
01061 
01062     if (ok) ok = pRec->ReadUnicode(Buffer, 256);
01063     pItem->mTypeFaceName = Buffer;
01064 
01065     if (ok) ok = pRec->ReadCCPanose( &(pItem->mPanoseNumber) );
01066 
01067     PORTNOTE("text","FontComponent::ReadFontTrueType - removed ImportCacheFont call");
01068 #ifndef DISABLE_TEXT_RENDERING
01069     if (ok) ok = ImportCacheFont(pItem);    // do all our clever matching
01070 
01071     if (ok) pFontList->AddTail(pItem);
01072 #endif
01073 
01074     return ok;
01075 }
01076 
01077 BOOL FontComponent::ReadFontATM(CXaraFileRecord *pRec)
01078 {
01079     ERROR2IF(ImportInitialised==FALSE, FALSE, "ReadFontATM called when ImportInitialised==FALSE.");
01080     ERROR2IF(pRec==NULL, FALSE, "Parameter pRec==NULL.");
01081     ERROR2IF(pFontList==NULL, FALSE, "ReadFontATM called when pFontList==NULL.");
01082 
01083     BOOL ok = TRUE;
01084 
01085     TCHAR Buffer[256];
01086     FontComponentListItem *pItem = new FontComponentListItem;
01087 
01088     pItem->mRecordNumber = pRec->GetRecordNumber();
01089 
01090     pItem->mFontClass = FC_ATM;
01091 
01092     if (ok) ok = pRec->ReadUnicode(Buffer, 256);
01093     pItem->mFullFontName = Buffer;
01094 
01095     if (ok) ok = pRec->ReadUnicode(Buffer, 256);
01096     pItem->mTypeFaceName = Buffer;
01097 
01098     if (ok) ok = pRec->ReadCCPanose( &(pItem->mPanoseNumber) );
01099 
01100     PORTNOTE("text","FontComponent::ReadFontATM - removed ImportCacheFont call");
01101 #ifndef DISABLE_TEXT_RENDERING
01102     if (ok) ok = ImportCacheFont(pItem);    // do all our clever matching
01103 
01104     if (ok) pFontList->AddTail(pItem);
01105 #endif
01106     return ok;
01107 }
01108 
01109 BOOL FontComponent::ReadFontUnknown(CXaraFileRecord *pRec)
01110 {
01111     ERROR2IF(ImportInitialised==FALSE, FALSE, "ReadFontTrueType called when ImportInitialised==FALSE.");
01112     ERROR2IF(pRec==NULL, FALSE, "Parameter pRec==NULL.");
01113     ERROR2IF(pFontList==NULL, FALSE, "ReadFontTrueType called when pFontList==NULL.");
01114 
01115     ERROR3("Attempt to read an unrecognised font definition record.");
01116 
01117     return FALSE;
01118 }
01119 
01120 /********************************************************************************************
01121 
01122 >   BOOL FontComponent::GetFontInformation(INT32 RecordNumber, WORD *pFontHandle, BOOL *pIsBold, BOOL *pIsItalic)
01123 
01124     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
01125     Created:    12/08/96
01126     Inputs:     RecordNumber    - Record number of font definition record
01127     Outputs:    pFontHandle     - pointer to a WORD to return the font maangers font handle in
01128                 pIsBold         - pointer to a BOOL to return the bold flag in
01129                 pIsItalic       - pointer to a BOOL to return the italic flag in
01130     Returns:    TRUE if successful, FALSE otherwise
01131     Purpose:    Retrives information from the font definition record with the corresponding record number
01132     See Also:   class FontComponent, class TextAttrRecordHandler
01133 
01134 ********************************************************************************************/
01135 
01136 BOOL FontComponent::GetFontInformation(INT32 RecordNumber, WORD *pFontHandle, BOOL *pIsBold, BOOL *pIsItalic)
01137 {
01138     ERROR2IF(ImportInitialised==FALSE, FALSE, "GetFontInformation called when ImportInitialised==FALSE.");
01139     ERROR2IF(pFontList==NULL, FALSE, "GetFontInformation called when pFontList==NULL.");
01140     ERROR2IF(pFontHandle==NULL, FALSE, "GetFontInformation called when pFontHandle==NULL.");
01141     ERROR2IF(pIsBold==NULL, FALSE, "GetFontInformation called when pIsBold==NULL.");
01142     ERROR2IF(pIsItalic==NULL, FALSE, "GetFontInformation called when pIsItalic==NULL.");
01143 
01144     BOOL ok;
01145 
01146     FontComponentListItem *pItem = pFontList->ImportFind(RecordNumber);
01147 
01148     if (pItem==NULL)
01149     {
01150         // oh dear, we can't find the font definition record - possibly an error in the file
01151         ok = TRUE;
01152