ccfile.cpp

Go to the documentation of this file.
00001 // $Id: ccfile.cpp 1607 2006-07-29 20:24:58Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 
00099 /********************************************************************************************
00100     
00101     CCFile.cpp  - Contains the function declarations of the Kernel CCFile derived classes.
00102     These include: CCDiskFile, CCMemFile and CCMemTextFile. 
00103 
00104 ********************************************************************************************/
00105 
00106 
00107 #include "camtypes.h"
00108 
00109 //#include "costream.h"
00110 //#include "ccfile.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 #include "zstream.h"
00112 // WEBSTER-Martin-29/12/96 no accusoft stuff
00113 #ifndef WEBSTER
00114 //#include "extfilts.h"
00115 #endif //WEBSTER
00116 
00117 #include <errno.h>
00118 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00119 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00120 
00121 //#include "mario.h"
00122 //#include "nev.h"
00123 //#include "tim.h"
00124 
00125 DECLARE_SOURCE("$Revision: 1607 $");
00126 
00127 CC_IMPLEMENT_DYNAMIC(CCFile, CCObject);
00128 CC_IMPLEMENT_DYNAMIC(CCLexFile, CCFile);
00129 CC_IMPLEMENT_DYNAMIC(CCStreamFile, CCLexFile);
00130 CC_IMPLEMENT_DYNAMIC(CCDiskFile, CCStreamFile);
00131 CC_IMPLEMENT_DYNAMIC(CCMemFile, CCLexFile);
00132 CC_IMPLEMENT_DYNAMIC(CCMemTextFile, CCMemFile);
00133 
00134 // Declare smart memory handling in Debug builds
00135 #define new CAM_DEBUG_NEW
00136 
00137 #define CHAR_EOF ((char)EOF)
00138 
00139 /********************************************************************************************
00140 
00141 >   CCFile::CCFile(BOOL ReportErrors, BOOL ThrowExceptions)
00142 
00143     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00144     Created:    29/08/94
00145     Inputs:     Flags to specify whether reporting errors or throwing exceptions.
00146                 Defaults specified to backward compatible. Set to report errors but not to
00147                 throw exceptions.
00148     Outputs:    None
00149     Returns:    None
00150     Purpose:    Default CCFile class constructor. Does nothing but set the reporting flags.
00151     Errors:     None    
00152 
00153 ********************************************************************************************/
00154 
00155 CCFile::CCFile(BOOL ErrorReporting, BOOL ExceptionThrowing)
00156 {
00157     // Set our class variables from the passed in values
00158     ReportErrors = ErrorReporting;
00159     ThrowExceptions = ExceptionThrowing;
00160 
00161     // Default to no compression
00162     CompressData = FALSE;
00163     // Default to no GZipErrorID
00164     GZipErrorID = 0;
00165 }
00166 
00167 /********************************************************************************************
00168 
00169 >   BOOL CCFile::IsCompressionSet( )
00170 
00171     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00172     Created:    29/08/94
00173     Inputs:     None
00174     Outputs:    None
00175     Returns:    The state of the compression flag, TRUE if compression is on.
00176     Purpose:    Allow the reading of the compression flag to see if all output data is
00177                 compressed or not.
00178 
00179 ********************************************************************************************/
00180 
00181 BOOL CCFile::IsCompressionSet( )
00182 {
00183     return CompressData;
00184 }   
00185 
00186 /********************************************************************************************
00187 
00188 >   BOOL CCFile::SetCompression( BOOL NewState)
00189 
00190     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00191     Created:    29/08/94
00192     Inputs:     TRUE if want compression, false otherhwise.
00193     Outputs:    None
00194     Returns:    True, if it was successful, False otherwise.
00195     Purpose:    Allow the setting of the compression flag so that all output data is
00196                 compressed.
00197 
00198 ********************************************************************************************/
00199 
00200 BOOL CCFile::SetCompression( BOOL NewState)
00201 {
00202 //  BOOL OldState = CompressData;
00203 
00204     CompressData = NewState;
00205 
00206     BOOL ok = TRUE;
00207     
00208     // If turning compression On then start the compression up
00209     // else turn it off.
00210     if (NewState)
00211     {
00212         // Get the class itself to start the compression process up
00213         ok = StartCompression();
00214         if (!ok)
00215         {
00216             CompressData = FALSE;   
00217         }
00218     }
00219     else
00220     {
00221         // Get the class itself to start the compression process up
00222         ok = StopCompression();
00223     }
00224 
00225     return ok;  
00226 }
00227 
00228 /********************************************************************************************
00229 
00230 >   CCFile::GotError( UNIT errorID )
00231 >   CCFile::GotError( UNIT errorID , const TCHAR*)
00232 
00233     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00234     Created:    29/08/94
00235     Inputs:     Unsigned interger which is the error id and possible error message string
00236     Outputs:    None
00237     Returns:    None
00238     Purpose:    Error handler for the CCFile class. It uses flags set in the constructor
00239                 to determine if the user requires errors to be reported or exceptions
00240                 thrown. 
00241     Errors:     None
00242     SeeAlso:    SetReportErrors; SetThrowExceptions
00243 
00244 ********************************************************************************************/
00245 
00246 void CCFile::GotError( UINT32 errorID , const TCHAR* errorString)
00247 {
00248     ERROR3IF(errorString == 0, "errorString is null. Oh dear.");
00249 
00250     Error::SetError(errorID, errorString, 0);
00251 
00252     // Flag that no more reads/writes should happen by forcing bad() to return True/.
00253     // So that if the user continues to access the file then they should get an error.
00254     SetBadState();
00255     
00256 #if !defined(EXCLUDE_FROM_XARLIB)
00257     // If the ReportErrors flag is set then report the error now.
00258     if (ReportErrors)
00259         InformError();
00260 #endif
00261 
00262     // If the ThrowExceptions flag is set then throw an exception.
00263     // Use the CFileException with a generic or unknown error and make the ioserror
00264     // our error number.
00265     if (ThrowExceptions)
00266     {   
00267         TRACE( _T("CCFile GotError call to throw exception\n") );
00268     
00269         throw( CFileException( errorID ) );
00270 //      AfxThrowFileException(CFileException::generic, errorID);
00271     }
00272 }
00273 
00274 void CCFile::GotError( UINT32 errorID )
00275 {
00276     // Expand certain types of error messages to make them more informative
00277     if ((errorID == _R(IDE_OPEN_ERROR)) ||
00278         (errorID == _R(IDE_FILE_READ_ERROR)) ||
00279         (errorID == _R(IDE_FILE_WRITE_ERROR)) )
00280         // Make the error message contain handy information.
00281         SetFileErrorMessage(errorID);
00282     else if ((errorID == _R(IDE_ZOPEN_ERROR) ) ||
00283         (errorID == _R(IDE_ZFILE_READ_ERROR)) ||
00284         (errorID == _R(IDE_ZFILE_WRITE_ERROR)) )
00285         // Make the error message contain handy information.
00286         SetZipFileErrorMessage(errorID);
00287     else
00288         Error::SetError(errorID, 0);
00289 
00290     // Flag that no more reads/writes should happen by forcing bad() to return True.
00291     // So that if the user continues to access the file then they should get an error.
00292     SetBadState();
00293     
00294 #if !defined(EXCLUDE_FROM_XARLIB)
00295     // If the ReportErrors flag is set then report the error now.
00296     if (ReportErrors)
00297         InformError();
00298 #endif
00299     
00300     // If the ThrowExceptions flag is set then throw an exception.
00301     // Use the CFileException with a generic or unknown error and make the ioserror
00302     // our error number.
00303     if (ThrowExceptions)
00304     {   
00305         TRACE( _T("CCFile GotError call to throw exception\n") );
00306         //TRACEUSER( "Chris", _T("EXCEPTION!!!!!"));
00307         //AfxDebugBreak();
00308         throw( CFileException( errorID ) );
00309     }
00310 }
00311 
00312 
00313 
00314 /********************************************************************************************
00315 
00316 >   BOOL CCFile::SetFileErrorMessage(UINT32 ErrorID)
00317 
00318     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00319     Created:    02/11/94
00320     Inputs:     ErrorID - the ID of the string resource to use as the error message.
00321     Returns:    TRUE if the error message was constructed ok;
00322                 FALSE if not (e.g. string resource did not load).
00323     Purpose:    Looks at the 'errno' variable to determine what kind of error occured, and
00324                 uses the specified error resource string to make a helpful error message
00325                 out of it.
00326                 NB. The string must have two string fields, to be replaced as follows:
00327                     #1%s  =  description of error
00328                     #2%s  =  name of the file that went wrong.
00329 
00330                 An example is _R(IDE_FILE_READ_ERROR):
00331 
00332                     "A read error occured (#1%s) with the file: #2%s"
00333 
00334     SeeAlso:    CCFile::GotError
00335 
00336 ********************************************************************************************/
00337 
00338 BOOL CCFile::SetFileErrorMessage(UINT32 ErrorID)
00339 {
00340     UINT32 FileErrorID;
00341 
00342     // Work out which error description string to use...
00343     switch (errno)
00344     {
00345         case EACCES:
00346             // Permission denied
00347             FileErrorID = _R(IDE_FILE_PERM_DENIED);
00348             break;
00349 
00350         case EBADF:
00351             // Bad file number
00352             FileErrorID = _R(IDE_FILE_BAD_FILE);
00353             break;
00354 
00355         case EEXIST:
00356             // File already exists
00357             FileErrorID = _R(IDE_FILE_EXISTS);
00358             break;
00359 
00360         case EMFILE:
00361             // Too many open files
00362             FileErrorID = _R(IDE_FILE_TOO_MANY_OPEN);
00363             break;
00364 
00365         case ENOENT:
00366             // No such file or directory
00367             FileErrorID = _R(IDE_FILE_NO_EXIST);
00368             break;
00369 
00370         case ENOSPC:
00371             // No space left on device
00372             FileErrorID = _R(IDE_FILE_NO_SPACE);
00373             break;
00374 
00375         default:
00376             // Unknown error
00377             FileErrorID = _R(IDE_FILE_UNKNOWN);
00378     }
00379 
00380     // Load in this resource
00381     String_64 FileError;
00382 
00383     if (!FileError.Load(FileErrorID))
00384     {
00385         // Error occured - just use the error number
00386         if( FileError._MakeMsg( _T("#1%d"), errno ) == 0 )
00387             // Couldn't do this (we must be severely shafted by now!) - return error
00388             return FALSE;
00389     }
00390 
00391     // Get a shortened name for the file
00392     String_64 Filename;
00393 
00394     if (!GetName(&Filename))
00395     {
00396         // Unable to get a name - substitute with "unknown"
00397         if (!Filename.Load(_R(IDE_FILE_UNKNOWN)))
00398         {
00399             // Error occured - just use the hard-coded literal "unknown"
00400             // (This was sanctioned by Phil)
00401             Filename = TEXT("unknown");
00402         }
00403     }
00404 
00405     // Use this information to build an error string and pass it to the SetError() function.
00406     String_256 ErrorMsg;
00407 
00408     if (ErrorMsg.MakeMsg(ErrorID, (LPCTSTR) FileError, (LPCTSTR) Filename) == 0)
00409         // Error occured - maybe resource would not load...not much we can do now.
00410         return FALSE;
00411 
00412     Error::SetError(ErrorID, (TCHAR *) ErrorMsg, 0);
00413 
00414     // Error string was constructed ok
00415     return TRUE;
00416 }
00417 
00418 /********************************************************************************************
00419 
00420 >   BOOL CCFile::SetZipFileErrorMessage(UINT32 ErrorID)
00421 
00422     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00423     Created:    1/6/94
00424     Inputs:     ErrorID - the ID of the string resource to use as the error message.
00425     Returns:    TRUE if the error message was constructed ok;
00426                 FALSE if not (e.g. string resource did not load).
00427     Purpose:    Looks at the 'GZipErrorID' variable to determine what kind of error occured, and
00428                 uses the specified error resource string to make a helpful error message
00429                 out of it.
00430                 NB. The string must have two string fields, to be replaced as follows:
00431                     #1%s  =  description of error
00432                     #2%s  =  name of the file that went wrong.
00433 
00434                 An example is _R(IDE_FILE_READ_ERROR):
00435 
00436                     "A read error occured (#1%s) with the file: #2%s"
00437 
00438                 Exactly the same as above but is designed for zip file errors.
00439 
00440     SeeAlso:    SetFileErrorMessage; CCFile::GotError
00441 
00442 ********************************************************************************************/
00443 
00444 BOOL CCFile::SetZipFileErrorMessage(UINT32 ErrorID)
00445 {
00446     UINT32 ZipFileErrorID;
00447 
00448     // Work out which error description string to use...
00449     switch (GZipErrorID)
00450     {
00451         case Z_ERRNO:
00452             // Bad file number
00453             ZipFileErrorID = _R(IDE_ZFILE_ERRORNO);
00454             break;
00455 
00456         case Z_STREAM_ERROR:
00457             // Permission denied
00458             ZipFileErrorID = _R(IDE_ZFILE_STREAMERROR);
00459             break;
00460 
00461         case Z_DATA_ERROR:
00462             // Bad file number
00463             ZipFileErrorID = _R(IDE_ZFILE_DATAERROR);
00464             break;
00465 
00466         case Z_MEM_ERROR:
00467             // Bad file number
00468             ZipFileErrorID = _R(IDE_ZFILE_MEMORYERROR);
00469             break;
00470 
00471         case Z_BUF_ERROR:
00472             // Bad file number
00473             ZipFileErrorID = _R(IDE_ZFILE_BUFFERERROR);
00474             break;
00475 
00476         default:
00477             // Unknown error
00478             ZipFileErrorID = _R(IDE_ZFILE_BASEEERROR);
00479     }
00480 
00481     // Load in this resource
00482     String_64 FileError;
00483 
00484     if (!FileError.Load(ZipFileErrorID))
00485     {
00486         // Error occured - just use the error number
00487         if( FileError._MakeMsg( _T("#1%d"), errno ) == 0 )
00488             // Couldn't do this (we must be severely shafted by now!) - return error
00489             return FALSE;
00490     }
00491 
00492     // Get a shortened name for the file
00493     String_32 Filename;
00494 
00495     if (!GetName(&Filename))
00496     {
00497         // Unable to get a name - substitute with "unknown"
00498         if (!Filename.Load(_R(IDE_FILE_UNKNOWN)))
00499         {
00500             // Error occured - just use the hard-coded literal "unknown"
00501             // (This was sanctioned by Phil)
00502             Filename = TEXT("unknown");
00503         }
00504     }
00505 
00506     // Use this information to build an error string and pass it to the SetError() function.
00507     String_256 ErrorMsg;
00508 
00509     if (ErrorMsg.MakeMsg(ErrorID, (LPCTSTR) FileError, (LPCTSTR) Filename) == 0)
00510         // Error occured - maybe resource would not load...not much we can do now.
00511         return FALSE;
00512 
00513     Error::SetError(ErrorID, (TCHAR *) ErrorMsg, 0);
00514 
00515     // Error string was constructed ok
00516     return TRUE;
00517 }
00518 
00519 /********************************************************************************************
00520 
00521 >   BOOL CCFile::SetReportErrors( BOOL )
00522 
00523     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00524     Created:    29/08/94
00525     Inputs:     BOOL which is the TRUE/FALSE state required.
00526     Outputs:    None
00527     Returns:    Old state of the flag
00528     Purpose:    Public way of setting the internal error handling flag to say whether
00529                 errors are going to be reported or not.
00530     Errors:     None
00531     SeeAlso:    GotError; IsReportingSet; IsThrowingSet     
00532 
00533 ********************************************************************************************/
00534 BOOL CCFile::SetReportErrors( BOOL newState )
00535 {
00536     BOOL OldState = ReportErrors;
00537 
00538     ReportErrors = newState;
00539 
00540     return OldState;
00541 }
00542 
00543 /********************************************************************************************
00544 
00545 >   BOOL CCFile::SetThrowExceptions( BOOL )
00546 
00547     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00548     Created:    29/08/94
00549     Inputs:     BOOL which is the TRUE/FALSE state required.
00550     Outputs:    None
00551     Returns:    Old state of the flag
00552     Purpose:    Public way of setting the internal error handling flag to say whether
00553                 errors are going to throw an exception or not.
00554     Errors:     None    
00555     SeeAlso:    GotError; IsReportingSet; IsThrowingSet 
00556 
00557 ********************************************************************************************/
00558 BOOL CCFile::SetThrowExceptions( BOOL newState )
00559 {
00560     BOOL OldState = ThrowExceptions;
00561 
00562     ThrowExceptions = newState;
00563 
00564     return OldState;
00565 }
00566 
00567 /********************************************************************************************
00568 
00569 >   BOOL CCFile::IsReportingSet()
00570 
00571     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00572     Created:    22/09/94
00573     Inputs:     None.
00574     Outputs:    None
00575     Returns:    True if error reporting flag is set.
00576     Purpose:    Public way of checking the internal error reporting flag to say whether
00577                 InformError is going to be called or not.
00578     Errors:     None    
00579     SeeAlso:    GotError; SetReportErrors; SetThrowExceptions   
00580 
00581 ********************************************************************************************/
00582 BOOL CCFile::IsReportingSet()
00583 {
00584     return ReportErrors;
00585 }
00586 
00587 /********************************************************************************************
00588 
00589 >   BOOL CCFile::IsThrowingSet()
00590 
00591     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00592     Created:    22/09/94
00593     Inputs:     None.
00594     Outputs:    None
00595     Returns:    True if exception throwing flag is set.
00596     Purpose:    Public way of checking the internal error throwing flag to say whether
00597                 errors are going to throw an exception or not.
00598     Errors:     None    
00599     SeeAlso:    GotError; SetReportErrors; SetThrowExceptions   
00600 
00601 ********************************************************************************************/
00602 BOOL CCFile::IsThrowingSet()
00603 {
00604     return ThrowExceptions;
00605 }
00606 
00607 /********************************************************************************************
00608 
00609 >   BOOL CCFile::GetName( StringBase* name) const
00610 
00611     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00612     Created:    22/09/94
00613     Inputs:     Pointer to a CCFile name 
00614     Outputs:    None
00615     Returns:    True if a name has been set otherwise False. At present always returns False.
00616     Purpose:    Given a CCFile*, you can ask for some sort of name which is associated with
00617                 that file. For filenames it might be a filename, or a pathname, for resource
00618                 files it might be "Default Bitmap" etc. These names could then be used for
00619                 making error messages have some extra useful information in.
00620     Errors:     None    
00621 
00622 ********************************************************************************************/
00623 
00624 BOOL CCFile::GetName( StringBase* name) const
00625 {
00626     return FALSE;
00627 }
00628 
00629 
00630 
00631 /********************************************************************************************
00632 >   virtual PathName CCFile::GetPathName() const
00633 
00634     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00635     Created:    15/8/96
00636     Returns:    The path-name of this file.  If the file doesn't support the notion of a
00637                 file-path (as, for instance, CCMemFiles and CCStreamFiles), then returns
00638                 an empty string.
00639 ********************************************************************************************/
00640 
00641 PathName CCFile::GetPathName() const
00642 {
00643     PathName pn;
00644     return pn;
00645 }
00646 
00647 
00648 
00649 /********************************************************************************************
00650 
00651 >   CCFile& CCFile::operator>>(StringBase* buf)
00652 
00653     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
00654     Created:    1/9/93
00655     Inputs:     String buffer.
00656     Returns:    Reference to the CCFile object.
00657     Purpose:    Reads file until string buffer is full or end of line or end of file is met.
00658     SeeAlso:    CCFile::read
00659 
00660 ********************************************************************************************/
00661 
00662 CCFile& CCFile::operator>>(StringBase* buf)
00663 {
00664     return read(buf);
00665 }
00666 
00667 /********************************************************************************************
00668 
00669 >   CCFile& CCFile::operator<<(const StringBase& buf)
00670 
00671     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
00672     Created:    1/9/93
00673     Inputs:     buf - the string to write out to the file.
00674     Returns:    Reference to the CCFile object.
00675     Purpose:    Writes the charactors found in the String buffer.
00676     SeeAlso:    CCFile::write
00677 
00678 ********************************************************************************************/
00679 
00680 CCFile& CCFile::operator<<(const StringBase& buf)
00681 {
00682     return write(buf);
00683 }
00684 
00685 // These should be deleted soon..?
00686 CCFile &CCFile::get( char &buf )
00687 {
00688     return read(buf);
00689 }
00690 
00691 CCFile &CCFile::put( const char &buf )
00692 {
00693     return write((void *) &buf);
00694 }
00695 
00696 /********************************************************************************************
00697 
00698 >   virtual CCFile& CCFile::flush()
00699 
00700     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00701     Created:    31/03/94
00702     Returns:    Reference to the CCFile object.
00703     Purpose:    Flushes a file's buffers.  By default it does nothing - override it if you  
00704                 want it to do anything.  (The CCDiskFile class overrides this function.)
00705     SeeAlso:    CCDiskFile::flush
00706 
00707 ********************************************************************************************/
00708 
00709 CCFile& CCFile::flush()
00710 {
00711     return (CCFile&) *this;
00712 }
00713 
00714 /********************************************************************************************
00715 
00716 >   BOOL CCFile::good()
00717 
00718     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00719     Created:    31/03/94
00720     Returns:    TRUE  => file stream is ok.
00721                 FALSE => an error has occured.
00722     Purpose:    Simple base implentation of this function - just examines EOF status.
00723                 It allows checking of the current file status to see if we should continue
00724                 using the file or not.
00725                 Override this function to provide more sophisticated error checking
00726                 (the CCDiskFile class overrides this function).
00727 
00728 ********************************************************************************************/
00729 
00730 BOOL CCFile::good() const
00731 {
00732     return !eof();
00733 }
00734 
00735 /********************************************************************************************
00736 
00737 >   BOOL CCFile::bad()
00738 
00739     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00740     Created:    31/03/94
00741     Returns:    TRUE  => An error has occured.
00742                 FALSE => The file stream is ok.
00743     Purpose:    Simple base implementation of this function - just examines EOF status.
00744                 It allows checking of the current file status to see if we should continue
00745                 using the file or not.
00746                 Override this function to provide more sophisticated error checking
00747                 (the CCDiskFile class overrides this function).
00748 
00749 ********************************************************************************************/
00750 
00751 BOOL CCFile::bad() const
00752 {
00753     return eof();
00754 }
00755 
00756 /********************************************************************************************
00757 
00758 >   BOOL CCFile::fail()
00759 
00760     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00761     Created:    31/03/94
00762     Returns:    TRUE  => An error has occured.
00763                 FALSE => The file stream is ok.
00764     Purpose:    Simple base implementation of this function - just examines EOF status.
00765                 It allows checking of the current file status to see if we should continue
00766                 using the file or not.
00767                 Override this function to provide more sophisticated error checking
00768                 (the CCDiskFile class overrides this function).
00769 
00770 ********************************************************************************************/
00771 
00772 BOOL CCFile::fail() const
00773 {
00774     return eof();
00775 }
00776 
00777 
00778 
00779 
00780 
00781 //-----------------------
00782 /********************************************************************************************
00783 
00784                                         CCLexFile
00785 
00786 ********************************************************************************************/
00787 //-----------------------
00788 
00789 
00790 
00791 
00792 /********************************************************************************************
00793 
00794 >   CCLexFile::CCLexFile(BOOL ErrorReporting = TRUE, BOOL ExceptionThrowing = FALSE)
00795 
00796     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>               (Altered by Neville 01/08/94) 
00797     Created:    05/04/94
00798     Purpose:    Initialise a CCLexFile object.
00799 
00800 ********************************************************************************************/
00801 
00802 CCLexFile::CCLexFile(BOOL ErrorReporting, BOOL ExceptionThrowing)
00803   : CCFile(ErrorReporting, ExceptionThrowing),
00804     CharsRead(0)
00805 {
00806     // Ensure that the buffers are NULL so that DeinitLexer() can be called
00807     // safely even if called after a failed InitLexer() call.
00808     LineBuf  = NULL;
00809     Buf      = NULL;
00810     TokenBuf = NULL;
00811 
00812     LexerInitialised = FALSE;
00813     TokenIsCached    = FALSE;
00814 
00815     SeekingRequired  = FALSE;
00816     IgnoreStringEscapeCodes = FALSE;
00817 
00818     DontFail = FALSE;
00819 
00820     //Graham's HTML parsing variables
00821     m_pcHTMLBuffer=NULL;
00822 }
00823 
00824 /********************************************************************************************
00825 
00826 >   CCLexFile::~CCLexFile()
00827 
00828     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00829     Created:    05/04/94
00830     Purpose:    Deinitialises a CCLexFile object (calls DeinitLexer() for you).
00831 
00832 ********************************************************************************************/
00833 
00834 CCLexFile::~CCLexFile()
00835 {
00836     DeinitLexer();
00837 }
00838 
00839 // The size of the token buffer used for lexical analysis in the CCLexFile class.
00840 const INT32 TokenBufSize = 256;
00841 
00842 /********************************************************************************************
00843 
00844 >   BOOL CCLexFile::InitLexer(BOOL IsSeekingRequired = FALSE, BOOL DoIgnoreStringEscapeCodes = FALSE)
00845 
00846     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00847     Created:    05/04/94
00848     Inputs:     IsSeekingRequired - Set to TRUE and seekin and tellin will work, but
00849                                     all the lexfile stuff is slowed down a bit
00850                 DoIgnoreStringEscapeCodes - Set to TRUE to force '\' chars in strings to be ignored
00851                                             (see below)
00852     Returns:    TRUE if successful; FALSE otherwise.
00853     Purpose:    Prepare the file object for performing lexical analysis on the input
00854                 stream.  This allocates the buffers and sets the various character sets
00855                 to the default values:
00856                     Whitespace: spaces and tabs
00857                     Delimiters: none
00858                     Comment:    #
00859                     String:     Delimited by " and " (i.e. like C)
00860                 Also resets the newline indent output used by PutNewLine() to 0;
00861 
00862                 DoIgnoreStringEscapeCodes = Should escape codes in strings be ignored?
00863                 e.g. Should "hello\r" turn into "hello" + CR, or should we ignore the \r code and hence leave
00864                 the string unaltered?
00865                 I.e. if DoIgnoreStringEscapeCodes is TRUE, then the '\' character in strings is left alone.
00866 
00867     Errors:     Out of memory.
00868     SeeAlso:    CCLexFile::SetWhitespace; CCLexFile::SetDelimiters; 
00869                 CCLexFile::SetCommentMarker; CCLexFile::SetStringDelimiters
00870 
00871 ********************************************************************************************/
00872 
00873 BOOL CCLexFile::InitLexer(BOOL IsSeekingRequired, BOOL DoIgnoreStringEscapeCodes)
00874 {
00875     // If we've already been here before, get out of town.
00876     if (LexerInitialised) return TRUE;
00877 
00878     // Allocate buffer for reading in each line
00879     LineBuf = new String_256;
00880     if (LineBuf == NULL)
00881         return FALSE;
00882 
00883     // Allocate space for storing tokens while decoding a line
00884     TokenBuf = new TCHAR[TokenBufSize];
00885     if (TokenBuf == NULL)
00886     {
00887         delete LineBuf; 
00888         LineBuf = NULL; 
00889         return FALSE;
00890     }
00891 
00892     // Get ready to parse tokens.
00893     TokenBuf[0] = 0;
00894     Ofs = 0;
00895     Ch = 0;
00896     Line = 0;
00897     
00898     // Make buffer pointer point to line buffer.
00899     Buf = (TCHAR *) (*LineBuf);
00900 
00901     CharsRead = 0;
00902     LastLinePos = (FilePos) 0;
00903     EOFFound = FALSE;
00904 
00905     // Set character classes to reasonable defaults.
00906     WhitespaceChars = " \t";
00907     DelimiterChars = NULL;
00908     CommentMarker = '#';
00909     StringDelimiters = "\"\"";
00910 
00911     // reset the current indent count and delta value
00912     IndentSpaces = 0;
00913     IndentDelta  = 4;
00914 
00915     // If true then seeking and tellin lex files will work - slows things down a bit
00916     SeekingRequired = IsSeekingRequired;
00917 
00918     // Ignore '\' characters in string tokens?
00919     IgnoreStringEscapeCodes = DoIgnoreStringEscapeCodes;
00920 
00921     InitHTMLLexer();
00922                         
00923     LexerInitialised = TRUE;
00924 
00925     return TRUE;
00926 }
00927 
00928 
00929 /********************************************************************************************
00930 
00931 >   void CCLexFile::DeinitLexer()
00932 
00933     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00934     Created:    05/04/94
00935     Purpose:    Frees up the dynamic objects allocated by CCLexFile::InitLexer.
00936                 Can be called at any point, and should be called before the next call
00937                 to InitLexer(), even if the last InitLexer() call has failed.
00938     SeeAlso:    CCLexFile::InitLexer
00939 
00940 ********************************************************************************************/
00941 
00942 void CCLexFile::DeinitLexer()
00943 {
00944     // Deallocate our buffers
00945     if (LineBuf  != NULL) delete LineBuf;
00946     if (TokenBuf != NULL) delete [] TokenBuf;
00947 
00948     LineBuf  = NULL;
00949     TokenBuf = NULL;
00950     Buf      = NULL;
00951 
00952     DeleteHTMLBuffer();
00953 
00954     LexerInitialised = FALSE;
00955 }
00956 
00957 /********************************************************************************************
00958 
00959 >   void CCLexFile::SetWhitespace(char *Str)
00960 
00961     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00962     Created:    05/04/94
00963     Inputs:     Str - the set of characters to treat as whitespace.
00964     Purpose:    This function changes the set of characters that the lexical analyser
00965                 treats as white space.  Note that it defaults to tabs and spaces, but you
00966                 can specify any set of characters you want - for example you could even
00967                 pass in " tf" and it would treat spaces, lower case t's and lower case f's
00968                 as whitespace characters.  Tokens extracted by CCLexFile::GetToken never
00969                 contain any whitespace characters.
00970     SeeAlso:    CCLexFile::InitLexer; CCLexFile::GetToken
00971 
00972 ********************************************************************************************/
00973 
00974 void CCLexFile::SetWhitespace(char *Str)
00975 {
00976     WhitespaceChars = Str;
00977 }
00978 
00979 /********************************************************************************************
00980 
00981 >   void CCLexFile::SetDelimiters(char *Str)
00982 
00983     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00984     Created:    05/04/94
00985     Inputs:     Str - the set of characters to be interpreted as token delimiters.
00986     Purpose:    Change the set of characters that are treated as 'delimiters'. A delimiter
00987                 character indicates that a token has finished. A delimiter character *will*
00988                 be extracted by CCLexFile::GetToken, and returned on its own.  For example, 
00989                 for the line "hello; there ();", processed with the set of delimiters
00990                 ";()", you would get the following tokens out of CCLexFile::GetToken:
00991                 MonoOn
00992                     "hello"
00993                     ";"
00994                     "there"
00995                     "("
00996                     ")"
00997                     ";"
00998                 MonoOff
00999 
01000                 By default, the set of delimiter characters is empty.
01001 
01002     SeeAlso:    CCLexFile::InitLexer; CCLexFile::GetToken
01003 
01004 ********************************************************************************************/
01005 
01006 void CCLexFile::SetDelimiters(char *Str)
01007 {
01008     DelimiterChars = Str;
01009 }
01010 
01011 /********************************************************************************************
01012 
01013 >   void CCLexFile::SetCommentMarker(char ch)
01014 
01015     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01016     Created:    05/04/94
01017     Inputs:     ch - the character to use as the comment marker.
01018     Purpose:    Change the character used to denote a comment token.
01019                 Comments start from the comment character until the end of the line.
01020                 So, for example, to set the lexer up for PostScript style comments, pass
01021                 in '%' as the comment marker; for assembler style comments, pass in ';'.
01022                 Multi-line comments are not supported.
01023     SeeAlso:    CCLexFile::InitLexer; CCLexFile::GetToken
01024 
01025 ********************************************************************************************/
01026 
01027 void CCLexFile::SetCommentMarker(char ch)
01028 {
01029     CommentMarker = ch;
01030 }
01031 
01032 /********************************************************************************************
01033 
01034 >   void CCLexFile::SetStringDelimiters(char *Str)
01035 
01036     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01037     Created:    05/04/94
01038     Inputs:     Str - the two-character string to indicate what characters to use to
01039                       start and end strings.
01040     Purpose:    Change the characters used to delimit a string.  The lexer will handle
01041                 strings as a special token type (see CCLexFile::GetToken).
01042                 You can specify which characters delimit the strings - you pass in a 
01043                 two-character string; the first character is used to start the string,and
01044                 the second is used to terminate it.  The two characters can be the same.
01045                 So, for example, for PostScript strings, use "()", or for C-style strings,
01046                 use "\"\"".
01047     SeeAlso:    CCLexFile::InitLexer; CCLexFile::GetToken
01048 
01049 ********************************************************************************************/
01050 
01051 void CCLexFile::SetStringDelimiters(char *Str)
01052 {
01053     StringDelimiters = Str;
01054 }
01055 
01056 /********************************************************************************************
01057 
01058 >   BOOL CCLexFile::GetSimpleToken()
01059 
01060     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01061     Created:    07/04/94
01062     Inputs:     -
01063     Purpose:    A simplified interface onto GetToken().
01064                 The caller is not informed of token types TOKEN_COMMENT and TOKEN_EOL.
01065                 The function returns TRUE if a TOKEN_NORMAL or TOKEN_STRING is read.
01066                 FALSE is returned if TOKEN_EOF is read, or if FALSE is returned by 
01067                 GetToken().
01068 
01069     SeeAlso:    CCLexFile::GetToken
01070 
01071 ********************************************************************************************/
01072 
01073 BOOL CCLexFile::GetSimpleToken()
01074 {
01075     BOOL ok;
01076     LexTokenType TokenType;
01077 
01078     do
01079     {
01080         do
01081         {
01082             ok = GetToken();
01083         } while (DelimiterFound);
01084 
01085         TokenType = GetTokenType();
01086     } while (ok &&  (TokenType != TOKEN_NORMAL) && 
01087                     (TokenType != TOKEN_STRING) && 
01088                     (TokenType != TOKEN_EOF));
01089 
01090     return (ok && (TokenType != TOKEN_EOF));
01091 }
01092         
01093 
01094 
01095 
01096 
01097 /********************************************************************************************
01098 
01099 >   BOOL CCLexFile::GetToken()
01100 
01101     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01102     Created:    05/04/94
01103     Returns:    TRUE if all went well; 
01104                 FALSE otherwise.
01105     Purpose:    Extract the next lexical token from the input stream of this file.
01106                 Tokens are separated by whitespace, delimiters, line-breaks, or any 
01107                 combination of the three.  Delimiters and line-breaks are returned as
01108                 tokens (and may be ignored if desired); whitespace is never returned.
01109                 Call CCLexFile::GetTokenType() to find out what kind of token was extracted.
01110                 You can examine the token directly by looking at the buffer returned by
01111                 CCLexFile::GetTokenBuf() (this is a const buffer so you may examine it, but
01112                 not alter it).  This buffer address will not change unless 
01113                 CCLexFile::InitLexer is called again, so it is safe to cache the return
01114                 value of CCLexFile::GetTokenBuf.
01115 
01116     Errors:     A 'string' token exceeded 256 characters in length.
01117 
01118     SeeAlso:    CCLexFile::GetTokenType; CCLexFile::GetTokenBuf; CCLexFile::SetWhitespace;
01119                 CCLexFile::SetDelimiters; CCLexFile::SetCommentMarker;
01120                 CCLexFile::SetStringDelimiters; CCLexFile::InitLexer; CCLexFile
01121 
01122 ********************************************************************************************/
01123 
01124 BOOL CCLexFile::GetToken()
01125 {
01126     // Check to see if the client has put a token back onto the input stream
01127     if (TokenIsCached)
01128     {
01129         // Yes - just return success to the caller and they will use the current token
01130         // again.
01131         TokenIsCached = FALSE;
01132         return TRUE;
01133     }
01134 
01135     DelimiterFound = FALSE;
01136 
01137     // No effect if at EOF
01138     if (EOFFound)
01139     {
01140         TokenType = TOKEN_EOF;
01141         TokenBuf[0] = 0;
01142         return TRUE;
01143     }
01144         
01145     // Ignore white space until we get something useful
01146     while (!EOFFound && IsWhitespace())
01147         GetCh();
01148     
01149     if (EOFFound)
01150     {
01151         TokenType = TOKEN_EOF;
01152         TokenBuf[0] = 0;
01153         return TRUE;
01154     }
01155 
01156     // Check for line breaks
01157     if (Ch == 0)
01158     {
01159         GetCh();
01160         TokenType = TOKEN_EOL;
01161         return TRUE;
01162     }
01163     else if (Ch == StringDelimiters[0])
01164     {
01165         // It's a string
01166         return GetStringToken();
01167     }
01168     else if (Ch == CommentMarker)
01169     {
01170         // It's a comment - ignore the rest of this line
01171         camStrcpy( TokenBuf, Buf + Ofs - 1 );
01172         TokenType = TOKEN_COMMENT;
01173         
01174         GetLine();
01175         GetCh();
01176     }
01177     // Extract the next token
01178     else
01179     {
01180         // Read until delimiter or white-space, and analyse result.
01181         // NB. 0-terminator ends a token => tokens cannot be split over a line.
01182         INT32 i = 0;
01183 
01184         if (IsDelim())
01185         {
01186             // Found a delimiter token - just return it
01187             TokenBuf[i++] = Ch;
01188             GetCh();
01189             DelimiterFound = TRUE;
01190         }
01191         else
01192         {
01193             do
01194             {
01195                 TokenBuf[i++] = Ch;
01196                 GetCh();
01197             } while (!EOFFound && !IsDelim() && !IsWhitespace() && (Ch != 0));
01198         }
01199 
01200         // Terminate the token
01201         TokenBuf[i] = 0;
01202         TokenType = TOKEN_NORMAL;
01203     } 
01204 
01205     // Token extracted ok
01206     return TRUE;
01207 }
01208 
01209 /********************************************************************
01210 
01211   Graham 15/5/97
01212 
01213   CCLexFile: HTML parsing code
01214 
01215   The lexer above isn't suited to parsing HTML code. For example, it insists
01216   on breaking tokens at the end of lines, but HTML should be able to run
01217   over lines ignoring line break characters. And HTML tokens should be able
01218   to be any length...not just 256 characters. And so on.
01219 
01220   So it makes sense to do HTML parsing completely separately.
01221   
01222     This HTML lexer returns two sorts of tokens:
01223 
01224   TAGS  Which start with < and end with >
01225 
01226   TEXT  Which is anything in between tags.
01227 
01228   So for example, a file containing the characters <B>Bold</B> would produce
01229   three tokens:
01230 
01231   TAG   <B>
01232   TEXT  Bold
01233   TAG   </B>
01234 
01235   Here's an example of how to use the lexer. This code reads
01236   all the HTML from a file pMyFile and prints out only the tags. (I haven't
01237   tested this code, of course, there might be the odd mistake).
01238 
01239   //First initialise the lexer. This function will call InitHTMLLexer().
01240   InitLexer();
01241 
01242   //And read HTML tokens from the file until we reach the end of the file
01243   while (!pMyFile->IsEndOfHTMLFile())
01244   {
01245         //Tell the HTML lexer to get an HTML token into its buffer
01246         pMyFile->GetHTMLToken();
01247 
01248         //Get the text buffer
01249         TCHAR* pcBuffer=pMyFile->GetHTMLTokenBuffer();
01250 
01251         //Now, does the buffer contain a tag?
01252         if (pMyFile->IsHTMLTag())
01253         {
01254             //Yes. So print it out.
01255             //Remember that pcBuffer may be NULL if it had nothing in it
01256             if (pcBuffer)
01257                 TRACE(pcBuffer);
01258         }
01259     }
01260 
01261   //And deinitialise the lexer
01262   DeInitLexer();
01263 
01264 
01265   Also see the function ImagemapFilter::WriteExistingDataHelper.
01266 
01267   ************************************************************************/
01268 
01269 /********************************************************************************************
01270 
01271 >   void CCLexFile::InitHTMLLexer()
01272 
01273     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
01274     Created:    15/5/97
01275     Inputs:     -
01276     Returns:    -
01277     Purpose:    Initialises all the variables used in the HTML parsing code
01278 
01279     Errors:     -
01280     SeeAlso:    CCLexFile::InitLexer
01281 
01282 ********************************************************************************************/
01283 
01284 void CCLexFile::InitHTMLLexer()
01285 {
01286     //Initialise the "character waiting" variables
01287     m_cWaitingCharacter=0;
01288     m_fIsCharacterWaiting=FALSE;
01289 
01290     //And delete the buffer
01291     DeleteHTMLBuffer();
01292 
01293     //And say that we haven't reached the end of the file   
01294     m_fEndOfHTMLFile=FALSE;
01295 
01296     //And say that the current token is not a tag
01297     m_fIsTag=FALSE;
01298     
01299 }
01300 
01301 /********************************************************************************************
01302 
01303 >   void CCLexFile::DeleteHTMLBuffer()
01304 
01305     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
01306     Created:    15/5/97
01307     Inputs:     -
01308     Returns:    -
01309     Purpose:    Deletes the HTML buffer and sets all the member variables
01310                 that refer to it to appropriate defaults
01311 
01312     Errors:     -
01313     SeeAlso:    CCLexFile::InitHTMLLexer
01314 
01315 ********************************************************************************************/
01316 
01317 void CCLexFile::DeleteHTMLBuffer()
01318 {
01319     if (m_pcHTMLBuffer)
01320         free( m_pcHTMLBuffer );
01321 
01322     m_pcHTMLBuffer=NULL;
01323 
01324     m_iCharsInHTMLBuffer=0;
01325     m_iLengthOfHTMLBuffer=0;
01326 
01327 }
01328 
01329 /********************************************************************************************
01330 
01331 >   void CCLexFile::AddToHTMLBuffer(TCHAR &cToAdd)
01332 
01333     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
01334     Created:    15/5/97
01335     Inputs:     cToAdd - the character to add to the buffer
01336     Returns:    -
01337     Purpose:    Adds cToAdd to the buffer, extending the buffer if
01338                 necessary.
01339 
01340     Errors:     -
01341     SeeAlso:    CCLexFile::GetHTMLToken
01342 
01343 *********************