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 ********************************************************************************************/
01344 
01345 void CCLexFile::AddToHTMLBuffer( char cToAdd )
01346 {
01347     //First, do we have an HTML buffer?
01348     if( NULL == m_pcHTMLBuffer )
01349     {
01350         //No. So create one now
01351         m_iLengthOfHTMLBuffer = TokenBufSize;
01352 
01353         m_pcHTMLBuffer = (char *)malloc( m_iLengthOfHTMLBuffer );
01354 
01355         m_iCharsInHTMLBuffer = 0;
01356     }
01357 
01358     //Now, is there enough room in our HTML buffer to store
01359     //our new character?
01360     if( m_iCharsInHTMLBuffer >= m_iLengthOfHTMLBuffer )
01361     {
01362         //No. So double the size of the buffer
01363         m_iLengthOfHTMLBuffer *= 2;
01364 
01365         m_pcHTMLBuffer = (char *)realloc( m_pcHTMLBuffer, m_iLengthOfHTMLBuffer );
01366     }
01367 
01368     ERROR3IF(m_pcHTMLBuffer==NULL, "AddToHTMLBUffer - realloc error");
01369     
01370     //And finally add our character
01371     m_pcHTMLBuffer[m_iCharsInHTMLBuffer] = cToAdd;
01372 
01373     //And increase the number of characters in the buffer
01374     m_iCharsInHTMLBuffer++;
01375 }
01376 
01377 
01378 /********************************************************************************************
01379 
01380 >   BOOL CCLexFile::GetHTMLToken(BOOL fIgnoreEOL=TRUE, BOOL fCorrectCase=TRUE)
01381 
01382     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
01383     Created:    14/5/97
01384     Inputs:     fIgnoreReturns  Whether all EOL characters should
01385                                 be removed from the text in the buffer. This
01386                                 is TRUE by default because HTML should
01387                                 normally ignore EOL characters
01388 
01389                 fCorrectCase    Whether the string should automatically
01390                                 be converted to upper case. This is TRUE
01391                                 by default because HTML should ignore case.
01392 
01393     Returns:    TRUE if all went well; 
01394                 FALSE otherwise.
01395     Purpose:    Get the next HTML token from the file.
01396 
01397                 This works as follows: if the first character read in the token
01398                 is a <, then the token will contain all the characters between
01399                 that < and the following >.
01400 
01401                 If the next character read is not a <, then the token will
01402                 contain all the characters until the next <.
01403 
01404                 So the token you get back from this function will
01405                 either be an HTML tag:
01406 
01407                 <IMG SRC="filename.gif" ALT="Alt text">
01408 
01409                 Or some text:
01410 
01411                 This is some text
01412 
01413                 Note that we read into a variable length buffer.
01414                 This is because HTML tokens could be any length at all. So,
01415                 as soon as you have called GetHTMLToken, you should call
01416                 GetHTMLTokenBuffer to get a pointer to the string that
01417                 has just been read.
01418 
01419     Errors:     -
01420 
01421     SeeAlso:    CCLexFile::GetToken; CCLexFile::GetHTMLTokenBuffer
01422 
01423   
01424 
01425 ********************************************************************************************/
01426 
01427 BOOL CCLexFile::GetHTMLToken(BOOL fIgnoreEOL, BOOL fCorrectCase)
01428 {
01429     //First delete our buffer
01430     DeleteHTMLBuffer();
01431                                        
01432     //Now, are we reading a tag or some text?
01433     //It depends on whether the first character we read is a <
01434     m_fIsTag=(PeekNextHTMLChar()=='<');
01435 
01436     //Create a two-character buffer to read characters into
01437     //(Why is it a buffer, not a single character? Because the
01438     //function _tcsupr needs to be passed a null-terminated
01439     //string rather than a single character)
01440     TCHAR               pcReadCharacter[2];
01441 
01442         
01443     //But when does the HTML token end? If the token is a tag, it ends after the 
01444     //next > is read. If the token is text, it ends just *before* the next <
01445     //is read. This condition is contained in the following while statement...
01446     while (!eof()
01447         && !(m_fIsTag && pcReadCharacter[0]=='>')
01448         && !(!m_fIsTag && PeekNextHTMLChar()=='<'))
01449     {
01450         //Read in a character
01451         pcReadCharacter[0]=ReadNextHTMLChar();
01452 
01453         //And null terminate the string
01454         pcReadCharacter[1]='\0';
01455 
01456         //Correct the string to uppercase if necessary
01457         if( fCorrectCase )
01458             CharUpper( pcReadCharacter );
01459 
01460         //If we just reached the end of the file, break
01461         if (eof())
01462             break;
01463 
01464         //Now, are we ignoring end of line characters?
01465         //And is the character we've read an end of line character?
01466         if (!(fIgnoreEOL && (pcReadCharacter[0]=='\r' || pcReadCharacter[0]=='\n')))
01467         {
01468             //No. So add the character to the buffer
01469             AddToHTMLBuffer(pcReadCharacter[0]);
01470         }
01471     }
01472 
01473     //If we reached the end of the file
01474     if (eof())
01475     {
01476         //Then set our member flag
01477         m_fEndOfHTMLFile=TRUE;
01478     }
01479 
01480     //And NULL terminate the buffer
01481     AddToHTMLBuffer('\0');
01482 
01483     //And return TRUE
01484     return TRUE;
01485 }
01486 
01487 /********************************************************************************************
01488 
01489 >   TCHAR CCLexFile::PeekNextHTMLChar()
01490 
01491     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
01492     Created:    14/5/97
01493     Returns:    The next character that will be read from the file
01494     Purpose:    In theory, this function finds out what the next character
01495                 that will be read from the file will be.
01496 
01497                 But of course to find out what the next character in the file is,
01498                 we have to read that character.
01499 
01500                 So this is what we do. We read the character, but we put it into
01501                 our member variable m_cWaitingCharacter. We also set our member flag
01502                 m_fIsCharacterWaiting to TRUE.
01503 
01504                 Then the function ReadNextHTMLCharacter will know there is a character waiting
01505                 to be 'read' in m_cWaitingCharacter, and will return that
01506                 character instead of actually reading one from the file.
01507 
01508                 Not perfect but it works.
01509 
01510     Errors:     -
01511 
01512     SeeAlso:    CCLexFile::GetHTMLToken; CCLexFile::ReadNextHTMLChar
01513                                      
01514 ********************************************************************************************/
01515 
01516 char CCLexFile::PeekNextHTMLChar()
01517 {
01518     //Is there a character waiting in m_cWaitingCharacter?
01519     if (!m_fIsCharacterWaiting)
01520     {
01521         //No. So read the next character into our "Waiting Character" buffer
01522         //We use "get" because "read" will throw an exception 
01523         //if you try to read past the end of the file.
01524         get(m_cWaitingCharacter);
01525 
01526         //And remember there's a character waiting
01527         m_fIsCharacterWaiting=TRUE;
01528     }
01529 
01530     //Now return the waiting character
01531     return m_cWaitingCharacter;
01532 
01533 }
01534 
01535 /********************************************************************************************
01536 
01537 >   TCHAR CCLexFile::ReadNextHTMLChar()
01538 
01539     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
01540     Created:    14/5/97
01541     Returns:    The next character in the file
01542     Purpose:    This function reads the next character from the file. Well, actually,
01543                 the way it works is slightly more complicated.
01544                 
01545                 That's because the function PeekNextHTMLChar may have given us
01546                 a character "waiting to be read" in m_cCharacterWaiting. If so, 
01547                 we should return that character first.
01548 
01549                 See PeekNextHTMLChar for a better explanation.
01550 
01551     Errors:     -
01552 
01553     SeeAlso:    CCLexFile::GetHTMLToken; CCLexFile::PeekNextHTMLChar
01554                                      
01555 ********************************************************************************************/
01556 
01557 char CCLexFile::ReadNextHTMLChar()
01558 {
01559     //Do we have a character waiting?
01560     if (m_fIsCharacterWaiting)
01561     {
01562         //Yes. So remember we no longer have a character waiting
01563         m_fIsCharacterWaiting=FALSE;
01564 
01565         //And return our waiting character
01566         return m_cWaitingCharacter;
01567                     
01568     }
01569     else
01570     {
01571         //No. So simply read a new character from the file
01572         //We use "get" because "read" will throw an exception 
01573         //if you try to read past the end of the file. 
01574         char            cToRead;
01575         get( cToRead );
01576 
01577         return cToRead;
01578     }
01579 }
01580 
01581 /********************************************************************************************
01582 
01583 >   String_256 CCLexFile::GetHTMLTagName()
01584 
01585     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
01586     Created:    14/5/97
01587     Returns:    The name of the tag which is currently in the buffer
01588     Purpose:    This function reads the name of the tag
01589                 in the buffer.
01590 
01591                 It does this by simply reading from the second character
01592                 in the buffer to the first whitespace character (where
01593                 whitespace is usually either a space or a tab).
01594 
01595                 Also, if the token in the buffer is not a tag, this function
01596                 returns FALSE.
01597 
01598     Errors:     -
01599 
01600     SeeAlso:    CCLexFile::GetHTMLToken
01601                                      
01602 ********************************************************************************************/
01603 
01604 String_256 CCLexFile::GetHTMLTagName()
01605 {
01606     //Create an empty string to return
01607     String_256 strToReturn = "";
01608 
01609     //If this isn't a tag, return that empty string
01610     if (!IsHTMLTag())
01611         return strToReturn;
01612 
01613     //And, if there's less than two characters in the buffer,
01614     //return now
01615     if (m_iCharsInHTMLBuffer<2)
01616         return strToReturn;
01617 
01618     //Otherwise, start copying from the buffer to the string
01619     //Start with the second character (remember that the second
01620     //character is m_pcHTMLBuffer[1]) and finish
01621     //when either we find a whitespace character or we go
01622     //past the end of the string
01623     INT32 i;
01624     for( i = 1; 
01625         ( i < 255 &&  
01626           i < ( m_iCharsInHTMLBuffer - 1 ) && 
01627           !IsWhitespace( m_pcHTMLBuffer[i] ) && 
01628           m_pcHTMLBuffer[i] != _T('>') ); 
01629         i++ )
01630     {
01631         strToReturn+=m_pcHTMLBuffer[i];
01632     }
01633 
01634     // test for overflow
01635     if (i == 255)
01636         return "";
01637 
01638     //Correct the string to upper case
01639     strToReturn.toUpper();
01640 
01641     //And return our string
01642     return strToReturn;
01643 
01644 }
01645 
01646 /********************************************************************************************
01647 
01648 >   String_256 CCLexFile::GetHTMLParameterValue(String_256 strParameterName, BOOL fCorrectCase=TRUE)
01649 
01650     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
01651     Created:    14/5/97
01652     Inputs:     strParameterName    The name of the parameter whose
01653                                     value we want to find. For example,
01654                                     in an image tag, we might want to find
01655                                     the value of 'SRC'.
01656 
01657                 fCorrectCase        TRUE if the value should be returned in uppercase
01658                                     FALSE if the value should be returned in its original case
01659     Returns:    If the parameter is specified within the buffer (e.g.
01660                 <IMG SRC="www.xara.com">, then the value of that parameter
01661                 will be returned without any enclosing quotes (e.g. www.xara.com
01662                 will be returned, not "www.xara.com").
01663 
01664                 If the parameter is not specified within the buffer, an
01665                 empty string will be returned.
01666                                                             
01667     Purpose:    Finds the value of the specified parameter.
01668 
01669                 For example, if we search for the value of "ALT" and 
01670                 the buffer contains the text
01671 
01672                 <IMG SRC="http://www.xara.com" ALT=Alt>
01673 
01674                 Then the string returned will be 
01675                 
01676                   Alt
01677 
01678                 This is done as follows: first we make up a composite string
01679                 consisting of the strParameterName with an equals sign on the end
01680                 (e.g. "ALT="). Then we search for that string.
01681 
01682                 If we find it:
01683 
01684                 Then if the character after that string is a ", we return everything
01685                 up until the next ".
01686 
01687                 Otherwise, if the character after that string is not a ", we
01688                 return everything up until the next > or whitespace character.
01689 
01690     Errors:     -
01691 
01692     SeeAlso:    CCLexFile::GetHTMLToken
01693                                      
01694 ********************************************************************************************/
01695 
01696 String_256 CCLexFile::GetHTMLParameterValue( const String_256 &strParameterName, BOOL fCorrectCase )
01697 {
01698     //Create an empty string to return
01699     String_256 strToReturn;
01700 
01701     //And, if there's less than two characters in the buffer,
01702     //return now
01703     if (m_iCharsInHTMLBuffer<2)
01704         return strToReturn;
01705 
01706     //So search for the string we have been told to search for  
01707     PCSTR               pcFound;
01708 #if 0 != wxUSE_UNICODE
01709     {
01710         size_t          cchParam = camWcstombs( NULL, (const TCHAR *)strParameterName, 0 ) + 1;
01711         PSTR            pszParam = PSTR( alloca( cchParam ) );
01712         camWcstombs( pszParam, (const TCHAR *)strParameterName, cchParam );
01713         pcFound = FindStringWithoutCase( m_pcHTMLBuffer, pszParam );
01714     }
01715 #else
01716     pcFound = FindStringWithoutCase( m_pcHTMLBuffer, (const TCHAR *)strParameterName );
01717 #endif
01718 
01719     //Have we found something?
01720     if (pcFound)
01721     {
01722         //Yes. So move our found pointer past the string we've found
01723 //      pcFound = camStrninc( pcFound, strParameterName.Length() );
01724         pcFound = pcFound + strParameterName.Length();
01725 
01726         //We're now pointing to the character after the parameter name
01727 
01728         //If we're pointing to a whitespace character, move forward
01729         //to the first character that's not whitespace                  
01730         while (*pcFound!='\0' && IsWhitespace(*pcFound))        
01731         {
01732 //          pcFound = camStrinc( pcFound );
01733             pcFound++;
01734         }
01735          
01736         //If that character is not an equals, return an empty string
01737         if (*pcFound!='=')
01738             return strToReturn;
01739 
01740         //And, again, move our found pointer to the next character that's not a space
01741         do
01742         {
01743 //          pcFound = camStrinc( pcFound );
01744             pcFound++;
01745         }
01746         while (*pcFound!='\0' && IsWhitespace(*pcFound));       
01747 
01748         //Note that there is no way that pcFound can
01749         //have been advanced past the end of the buffer.
01750         //It may, possibly, have been advanced to the NULL
01751         //character at the end of the buffer, and I'll handle that...
01752 
01753         //Now, this variable will tell us whether the parameter value
01754         //is in quotes. Set to FALSE by default.
01755         BOOL fInQuotes=FALSE;
01756 
01757         //And is the parameter value in quotes?
01758         if (*pcFound=='\"')
01759         {
01760             //Yes. So make a note of that
01761             fInQuotes=TRUE;
01762 
01763             //And move on to the character after the quotes
01764 //          pcFound=camStrinc(pcFound);
01765             pcFound++;
01766         }
01767 
01768         //Now, copy everything from the character we are pointing at
01769         //until...
01770         //IF the parameter value is in quotes, until the next "
01771         //OTHERWISE, until the next > or whitespace character
01772         while (*pcFound!='\0' &&
01773             ((fInQuotes && *pcFound!='\"')
01774             || (!fInQuotes && (!IsWhitespace(*pcFound) && *pcFound!='>'))))
01775         {
01776             strToReturn+=*pcFound;
01777 //          pcFound=camStrinc(pcFound);
01778             pcFound++;
01779         }
01780     }
01781 
01782     //And correct the case if necessary
01783     if (fCorrectCase)
01784         strToReturn.toUpper();
01785 
01786     //And return the string
01787     //Note that if nothing was found, this string will be empty
01788     return strToReturn;
01789 }
01790 
01791 /********************************************************************************************
01792 
01793 >   TCHAR* CCLexFile::FindStringWithoutCase(TCHAR* strToSearch, TCHAR* strToFind)
01794 
01795     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
01796     Created:    20/5/97
01797     Inputs:     strToSearch         The string in which to search
01798 
01799                 strToFind           The string to search for
01800     Returns:    A pointer to the first occurrence of strToFind within
01801                 strToSearch.
01802                                                             
01803     Purpose:    Finds strToFind within strToSearch.
01804 
01805                 The find operation is done without regard to case - so,
01806                 for example, the string "Map" would be found within the
01807                 string "<MAP NAME=MyMap>"
01808 
01809     Errors:     -
01810 
01811     SeeAlso:    CCLexFile::GetHTMLParameterValue
01812                                      
01813 ********************************************************************************************/
01814 
01815 PCSTR CCLexFile::FindStringWithoutCase( PCSTR strToSearch, PCSTR strToFind )
01816 {
01817     //We assume strToSearch and strToFind are valid
01818 
01819     //First set up a pointer to search strToSearch with
01820     PCSTR               pcThisChar = strToSearch;
01821 
01822     //Now, while pcThisChar is valid
01823     while( pcThisChar != NULL && *pcThisChar != '\0' )
01824     {
01825         //Is strToSearch from pcThisChar onwards the same
01826         //as strToFind, doing a case insensitive comparision?
01827         if( 0 == _strnicmp( pcThisChar, strToFind, strlen( strToFind ) ) )
01828         {
01829             //Yes. So return TRUE
01830             return pcThisChar;
01831         }
01832 
01833 //      pcThisChar = camStrinc(pcThisChar);
01834         pcThisChar++;
01835     }
01836 
01837     //Otherwise return NULL
01838     return NULL;
01839 }
01840 
01841 /********************************************************************************************
01842 
01843 >   BOOL CCLexFile::GetHexToken()
01844 
01845     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01846     Created:    05/04/94
01847     Returns:    TRUE if all went well; 
01848                 FALSE otherwise.
01849     Purpose:    Extract the next lexical token from the input stream of this file.
01850                 The token is expected to be a string of hexadecimal digits, and its length
01851                 should be an even number of characters. If whitespace or a delimiter is 
01852                 encountered then the token is returned ok.  If any other character is found
01853                 which is not a legal hex digit thenFALSE is returned.
01854 
01855     Errors:     A 'string' token exceeded 256 characters in length.
01856 
01857     SeeAlso:    CCLexFile::GetTokenType; CCLexFile::GetTokenBuf; CCLexFile::SetWhitespace;
01858                 CCLexFile::SetDelimiters; CCLexFile::SetCommentMarker;
01859                 CCLexFile::SetStringDelimiters; CCLexFile::InitLexer; CCLexFile
01860 
01861 ********************************************************************************************/
01862 
01863 BOOL CCLexFile::GetHexToken()
01864 {
01865     // Check to see if the client has put a token back onto the input stream
01866     if (TokenIsCached)
01867     {
01868         // Yes - just return success to the caller and they will use the current token
01869         // again.
01870         // But for hex token we must check that it is a legal hex token...
01871         INT32 i = 0;
01872         while (TokenBuf[i] != 0)
01873         {
01874             if (!camIsxdigit(TokenBuf[i]))
01875                 // Not valid hex data
01876                 return FALSE;
01877 
01878             // Try next character
01879             i++;
01880         }
01881 
01882         // Valid hex data - return success.
01883         TokenIsCached = FALSE;
01884         return TRUE;
01885     }
01886 
01887     DelimiterFound = FALSE;
01888 
01889     // Keep ignoring whitespace/comments etc
01890     for(;;)
01891     {
01892         // No effect if at EOF
01893         if (EOFFound)
01894         {
01895             // Did not find a hex token
01896             TokenType = TOKEN_EOF;
01897             TokenBuf[0] = 0;
01898             return FALSE;
01899         }
01900             
01901         // Ignore white space until we get something useful
01902         while (!EOFFound && IsWhitespace())
01903             GetCh();
01904         
01905         if (EOFFound)
01906         {
01907             // Did not find a hex token
01908             TokenType = TOKEN_EOF;
01909             TokenBuf[0] = 0;
01910             return FALSE;
01911         }
01912 
01913         if (Ch == 0)
01914         {
01915             // Skip line breaks
01916             GetCh();
01917         }
01918         else if (Ch == CommentMarker)
01919         {
01920             // It's a comment - ignore the rest of this line
01921             GetLine();
01922             GetCh();
01923         }
01924         else
01925         {
01926             // Ok - is it a hex digit?
01927             if (camIsxdigit(Ch))
01928                 // Yes - fall through to next bit of code to decode it
01929                 break;
01930             else
01931                 // No - so we can't find a hex string so return an error
01932                 return FALSE;
01933         }
01934     }
01935 
01936     // Read until not a hexadecimal digit, and analyse result.
01937     // NB. 0-terminator ends a token => tokens cannot be split over a line.
01938     INT32 i = 0;
01939 
01940     // This loop is hugely critical (e.g. importing large bitmaps), so we resort to direct 
01941     // buffer access and register variables. (sorry!)
01942     register TCHAR *pHexCh = Buf + Ofs - 1;
01943 
01944     while (camIsxdigit(*pHexCh))
01945     {
01946         TokenBuf[i++] = *pHexCh++;
01947     }
01948 
01949     // Update the offset variable and Ch variable so we maintain lookahead.
01950     Ofs += i;
01951     Ch = Buf[Ofs-1];
01952 
01953     // Set up token correctly.
01954     TokenBuf[i] = 0;
01955     TokenType = TOKEN_NORMAL;
01956 
01957     // End of hex data - is it a legal or illegal end?
01958     if ((i % 2) != 0)
01959     {
01960         // Not an even number of hex digits => illegal
01961         return FALSE;
01962     }
01963 
01964     // Inform caller if the hex data was terminated legally 
01965     // (i.e. delimiter, whitespace or line-end)
01966 
01967     return (IsDelim() || IsWhitespace() || (Ch == 0));
01968 }
01969 
01970 
01971 /********************************************************************************************
01972 
01973 >   void CCLexFile::UngetToken()
01974 
01975     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01976     Created:    03/08/94
01977     Purpose:    Put the current token back onto the input stream - i.e. the next time 
01978                 GetToken() is called it will return the token it returned last time.
01979                 This is not nestable - you can only put back one token at once.
01980     SeeAlso:    CCLexFile::GetToken(); CCLexFile
01981 
01982 ********************************************************************************************/
01983 
01984 void CCLexFile::UngetToken()
01985 {
01986     TokenIsCached = TRUE;
01987 }
01988 
01989 /********************************************************************************************
01990 
01991 >   BOOL CCLexFile::GetLineToken()
01992 
01993     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01994     Created:    09/08/94
01995     Returns:    TRUE if all went well; 
01996                 FALSE otherwise.
01997     Purpose:    Read in a token in a line-based manner.  If the current input position is 
01998                 in the middle of a line, the data up until the end of the line is read. 
01999                 If at the start of a line, the whole line is returned.
02000                 The token is still examined to work out what it is, but obviously it may not
02001                 match any proper construct, in which case the type of the token is set to 
02002                 TOKEN_LINE.
02003                 (NB this is the only time that TOKEN_LINE is used)
02004     SeeAlso:    CCLexFile::GetToken; CCLexFile::GetSimpleToken; CCLexFile::UngetToken
02005 
02006 ********************************************************************************************/
02007 
02008 BOOL CCLexFile::GetLineToken()
02009 {
02010     // Check to see if the client has put a token back onto the input stream
02011     if (TokenIsCached)
02012     {
02013         TokenIsCached = FALSE;
02014 
02015         if (Ofs == 1)
02016         {
02017             // We're at the start of the line, so the last token must have been the
02018             // wholeof the rest of the line, so just return it.
02019             return TRUE;
02020         }
02021 
02022         // Otherwise, we should append the rest of the current line to the token, 
02023         // and work out the token type again.
02024         camStrcpy( TokenBuf + camStrlen( TokenBuf ), Buf + Ofs - 1 );
02025 
02026         if (TokenBuf[0] == CommentMarker)
02027         {
02028             TokenType = TOKEN_COMMENT;
02029         }
02030         else
02031         {
02032             TokenType = TOKEN_LINE;
02033         }
02034 
02035         GetLine();
02036         GetCh();
02037 
02038         // We have a token
02039         return TRUE;
02040     }
02041 
02042     // No effect if at EOF
02043     if (EOFFound)
02044     {
02045         TokenType = TOKEN_EOF;
02046         TokenBuf[0] = 0;
02047         return TRUE;
02048     }
02049         
02050     // Ignore white space until we get something useful
02051     while (!EOFFound && IsWhitespace())
02052         GetCh();
02053     
02054     if (EOFFound)
02055     {
02056         TokenType = TOKEN_EOF;
02057         TokenBuf[0] = 0;
02058         return TRUE;
02059     }
02060 
02061     // Check for line breaks
02062     if (Ch == 0)
02063     {
02064         GetCh();
02065         TokenType = TOKEN_EOL;
02066         return TRUE;
02067     }
02068 
02069     // Otherwise, just get the rest of the line...
02070     camStrcpy( TokenBuf, Buf + Ofs - 1 );
02071 
02072     GetLine();
02073     GetCh();
02074 
02075     if (TokenBuf[0] == CommentMarker)
02076     {
02077         TokenType = TOKEN_COMMENT;
02078     }
02079     else
02080     {
02081         TokenType = TOKEN_LINE;
02082     }
02083 
02084     // Token extracted ok
02085     return TRUE;
02086 }
02087 
02088 /********************************************************************************************
02089 
02090 >   BOOL CCLexFile::GetStringToken()
02091 
02092     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02093     Created:    05/04/94
02094     Returns:    TRUE if all ok; FALSE if not.
02095     Purpose:    Extracts a string token from the input stream, as defined by the currently
02096                 installed string delimiters.
02097     Errors:     String too long.
02098     SeeAlso:    CCLexFile::InitLexer; CCLexFile; CCLexFile::SetStringDelimiters
02099 
02100 ********************************************************************************************/
02101 
02102 BOOL CCLexFile::GetStringToken()
02103 {
02104     INT32 i = 0;
02105 
02106     TokenType = TOKEN_STRING;
02107     
02108     // Extract the string.
02109     // The first time through the loop causes the 'open string' character character to be 
02110     // discarded.
02111     do
02112     {
02113         GetCh();
02114         TokenBuf[i++] = Ch;
02115         if (!IgnoreStringEscapeCodes)
02116         {
02117             // We are NOT ignoring '\' characters, so have we found one?
02118             if (Ch == '\\')
02119             {
02120                 // Backslash character - ignore it and insert the next character in its place.
02121                 GetCh();
02122                 if(Ch == 'r')
02123                 {
02124                     TokenBuf[i-1] = '\r';
02125                     Ch = 32;
02126                 }
02127                 else
02128                 {
02129                     TokenBuf[i-1] = Ch;
02130 
02131                     // Set Ch to 32, in case this is a string delimiter - it's been escaped (by
02132                     // a backslash) so we don't want it to terminate the loop.
02133                     // (Space (ASCII 32) is a 'safe' value - 0 is out as it causes GetCh() to
02134                     // read in the next line.
02135                     Ch = 32;
02136                 }
02137             }
02138         }
02139 
02140         // If string is too long to fit into our buffer, this is classed as an error
02141         ERRORIF(i >= TokenBufSize, _R(IDT_LEX_STRINGTOOLONG), FALSE);
02142 
02143     } while (!EOFFound && (Ch != StringDelimiters[1]));
02144     
02145     // Null terminate the token string
02146     TokenBuf[i-1] = 0;
02147 
02148     // Discard the 'close string' character
02149     GetCh();
02150 
02151     // String extracted ok
02152     return TRUE;
02153 }
02154 
02155 /********************************************************************************************
02156 
02157 >   void CCLexFile::GetLine()
02158 
02159     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02160     Created:    05/04/94
02161     Purpose:    Read in the next line from the file - used when extracted tokens with 
02162                 CCLexFile::GetToken().   Handles the current line count, number of chars
02163                 read count, etc.
02164     SeeAlso:    CCLexFile::GetCh
02165 
02166 ********************************************************************************************/
02167 
02168 void CCLexFile::GetLine()
02169 {
02170     // End of file?
02171     if (eof())
02172     {
02173         EOFFound = TRUE;
02174         return;
02175     }
02176     
02177     if(SeekingRequired)
02178     {
02179         // It would be much better to do it via variables rather than doing a tellin()
02180         //LastLinePos += CharsRead; //tellIn();
02181         //FilePos StartLastLinePos = LastLinePos;
02182 
02183         /*  static FilePos LastLinePosTmp = 0;
02184         static BOOL LastLinePosBool = FALSE;
02185                                            
02186         if(LastLinePosTmp == 0)
02187         {
02188             LastLinePosTmp = LastLinePos + Ofs - 1 + 2;
02189             LastLinePosBool = FALSE;
02190         }
02191         else
02192         {
02193             LastLinePosTmp += Ofs + 1 + 2;
02194             if(LastLinePosBool == FALSE)
02195             {
02196                 LastLinePosTmp -= 2;
02197                 LastLinePosBool = TRUE;
02198             }
02199         }
02200     
02201         LastLinePos = LastLinePosTmp;*/
02202 
02203         //LastLinePos += Ofs + 1;
02204 
02205         // Store position of start of line  
02206         LexerInitialised = FALSE;
02207         LastLinePos = tellIn();
02208         LexerInitialised = TRUE;
02209     }
02210     else
02211     {
02212         LastLinePos = 0;
02213     }
02214     
02215     // Get a new line from the file.
02216     read( LineBuf );
02217     Line++;
02218     Ofs = 0;
02219 }
02220 
02221 /********************************************************************************************
02222 
02223 >   void CCLexFile::GetCh()
02224 
02225     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02226     Created:    05/04/94
02227     Purpose:    Gets the next character from the input stream, reading in a new line if
02228                 necessary.
02229     SeeAlso:    CCLexFile::GetLine
02230 
02231 ********************************************************************************************/
02232 
02233 void CCLexFile::GetCh()
02234 {
02235     // Get a character from the stream.
02236     
02237     // If end of file, there is no effect
02238     if (EOFFound)
02239         return;
02240         
02241     // If at the end of a line, get a new line first
02242     if ((Ch == 0) && (Ofs != 0))
02243         GetLine();
02244     
02245     // Test again as GetLine() might encounter the end of the file...
02246     // NB the above comment inserted for the hard of thinking (e.g. Justin and Simon)
02247     if (EOFFound)
02248     {
02249         Ch = 0;
02250         return;
02251     }
02252         
02253     Ch = Buf[Ofs++];
02254 }
02255 
02256 /********************************************************************************************
02257 
02258 >   BOOL CCLexFile::IsDelim()
02259 
02260     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02261     Created:    05/04/94
02262     Returns:    TRUE if the current character is a delimiter; 
02263                 FALSE if not.
02264     Purpose:    Test the current character (as read in by CCLexFile::GetCh) to see if it
02265                 is a delimiter.
02266     SeeAlso:    CCLexFile::SetDelimiters
02267 
02268 ********************************************************************************************/
02269 
02270 BOOL CCLexFile::IsDelim()
02271 {
02272     if (DelimiterChars == NULL)
02273         return FALSE;
02274 
02275     return( strchr( DelimiterChars, Ch ) != NULL);
02276 }
02277 
02278 /********************************************************************************************
02279 
02280 >   BOOL CCLexFile::IsWhitespace()
02281 
02282     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02283     Created:    05/04/94
02284     Returns:    TRUE if the current character is white-space; 
02285                 FALSE if not.
02286     Purpose:    Test the current character (as read in by CCLexFile::GetCh) to see if it
02287                 is a white-space character.
02288     SeeAlso:    CCLexFile::SetWhitespace
02289 
02290 ********************************************************************************************/
02291 
02292 BOOL CCLexFile::IsWhitespace()
02293 {   
02294     // 0-terminators are not whitespace
02295     if (Ch == 0)
02296         return FALSE;
02297 
02298     return( strchr( WhitespaceChars, Ch ) != NULL );
02299 }
02300 
02301 /********************************************************************************************
02302 
02303 >   BOOL CCLexFile::IsWhitespace(TCHAR cToTest)
02304 
02305     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
02306     Created:    16/5/97
02307     Inputs:     cToTest Character to test
02308     Returns:    TRUE if the character is white-space; 
02309                 FALSE if not.
02310     Purpose:    Tests the character passed to see if it
02311                 is a white-space character.
02312     SeeAlso:    CCLexFile::GetWhitespace()
02313 
02314 ********************************************************************************************/
02315 
02316 BOOL CCLexFile::IsWhitespace( char cToTest )
02317 {   
02318     // 0-terminators are not whitespace
02319     if (cToTest == 0)
02320         return FALSE;
02321 
02322     return( strchr( WhitespaceChars, cToTest ) != NULL );
02323 }
02324 
02325 
02326 
02327 /********************************************************************************************
02328 
02329 >   BOOL CCLexFile::PutString(StringBase& str, UINT32 length=0, TCHAR* Sep=" ")
02330 
02331     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02332     Created:    6/4/94
02333     Inputs:     str    = string to write
02334                 length = num chars in str to write (0 means write to termination char)
02335                 Sep    = chars to use as a separator between this string and the next.
02336     Outputs:    -
02337     Returns:    TRUE = successful, FALSE = error
02338     Purpose:    Outputs the string to the file enclosed in the string delimiting chars.
02339                 (see CCLexFile::SetStringDelimiters for more details)
02340                 Writes out 'length' chars of str, then finishes off by writing 'Sep' out
02341                 as a bunch of Sep characters.
02342     Errors:     -
02343     SeeAlso:    -
02344 
02345 ********************************************************************************************/
02346 
02347 BOOL CCLexFile::PutString( const StringBase &str, UINT32 length, char* pszSep )
02348 {
02349     write( StringDelimiters[0] );
02350     write( str, length );
02351     write( StringDelimiters[1] );
02352     if( strlen( pszSep ) > 0 )
02353         write( pszSep, (UINT32)strlen( pszSep ) );
02354 
02355     return (good());
02356 }
02357 
02358 /********************************************************************************************
02359 
02360 >   BOOL CCLexFile::PutToken(StringBase& str, UINT32 length=0, TCHAR* Sep=" ")
02361 
02362     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02363     Created:    6/4/94
02364     Inputs:     str    = string to write
02365                 length = num chars in str to write (0 means write to termination char)
02366                 Sep    = chars to use as a separator between this string and the next.
02367     Outputs:    -
02368     Returns:    TRUE = successful, FALSE = error
02369     Purpose:    Outputs the string to the file.
02370                 Writes out 'length' chars of str, then finishes off by writing 'Sep' out
02371                 as a bunch of Sep characters.
02372     Errors:     -
02373     SeeAlso:    -
02374 
02375 ********************************************************************************************/
02376 
02377 BOOL CCLexFile::PutToken( const StringBase &str, UINT32 length, char *pszSep )
02378 {
02379     write( str, length );
02380     if( strlen( pszSep ) > 0 )
02381         write( pszSep, (UINT32)strlen( pszSep ) );
02382 
02383     return( good() );
02384 }
02385 
02386 /********************************************************************************************
02387 
02388 >   BOOL CCLexFile::PutToken(const TCHAR* buf, TCHAR* Sep=" ")
02389 
02390     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02391     Created:    6/4/94
02392     Inputs:     buf  = buffer of chars to write
02393                 Sep  = chars to use as a separator between this string and the next.
02394     Outputs:    -
02395     Returns:    TRUE = successful, FALSE = error
02396     Purpose:    Outputs the string to the file.
02397                 Writes out 'length' chars of str, then finishes off by writing 'Sep' out
02398                 as a bunch of Sep characters.
02399     Errors:     -
02400     SeeAlso:    -
02401 
02402 ********************************************************************************************/
02403 
02404 BOOL CCLexFile::PutToken( const TCHAR *buf, char *Sep )
02405 {
02406 #if 0 != wxUSE_UNICODE
02407     size_t              cch = camWcstombs( NULL, (const TCHAR *)buf, 0 ) + 1;
02408     PSTR                psz = PSTR( alloca( cch ) );
02409     camWcstombs( psz, (const TCHAR *)buf, cch );
02410     write( psz, cch );
02411 #else
02412     UINT32 length = camStrlen( buf );
02413     write( buf, length );
02414 #endif
02415     if( strlen( Sep ) > 0 )
02416         write( Sep, (UINT32)strlen( Sep ) );
02417 
02418     return (good());
02419 }
02420 
02421 /********************************************************************************************
02422 
02423 >   BOOL CCLexFile::PutToken(INT32 n, TCHAR* Sep=" ")
02424 
02425     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02426     Created:    6/4/94
02427     Inputs:     n    = a number to write
02428                 Sep  = chars to use as a separator between this string and the next.
02429     Outputs:    -
02430     Returns:    TRUE = successful, FALSE = error
02431     Purpose:    Outputs the number to the file.
02432                 Writes out 'n', then finishes off by writing 'Sep' out
02433                 as a bunch of Sep characters.
02434     Errors:     -
02435     SeeAlso:    -
02436 
02437 ********************************************************************************************/
02438 
02439 BOOL CCLexFile::PutToken( INT32 n, char *Sep )
02440 {
02441     char                buf[256];
02442     _snprintf( buf, 256, "%d", n );
02443 
02444     UINT32 length = strlen( buf );
02445     write( buf, length );
02446     if( strlen( Sep ) > 0 )
02447         write( Sep, (UINT32)strlen(Sep) );
02448 
02449     return( good() );
02450 }
02451 
02452 /********************************************************************************************
02453 
02454 >   BOOL CCLexFile::PutNewLine()
02455 
02456     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02457     Created:    6/4/94
02458     Inputs:     -
02459     Outputs:    -
02460     Returns:    TRUE = successful, FALSE = error
02461     Purpose:    Outputs a new line, followed by a number of spaces. The number of
02462                 spaces output can be changed using IncIndent() and DecIndent();
02463                 InitLexer resets the number of indent spaces to 0.
02464     Errors:     -
02465     SeeAlso:    -
02466 
02467 ********************************************************************************************/
02468 
02469 BOOL CCLexFile::PutNewLine()
02470 {
02471     write("\n");
02472     for (INT32 n=0; n < IndentSpaces;n++)
02473         write(" ");
02474 
02475     return (good());
02476 }
02477 
02478 /********************************************************************************************
02479 
02480 >   void CCLexFile::IncIndent()
02481 
02482     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02483     Created:    6/4/94
02484     Inputs:     -
02485     Outputs:    -
02486     Returns:    Increases IndentSpaces by IndentDelta.
02487     Purpose:    Increases the number of spaces written by PutNewLine() at the start
02488                 of the next line.  It is increased by IndentDelta, which can be altered
02489                 using SetIndentDelta()
02490     Errors:     -
02491     SeeAlso:    -
02492 
02493 ********************************************************************************************/
02494 
02495 void CCLexFile::IncIndent()
02496 {
02497     IndentSpaces += IndentDelta;
02498 }
02499 
02500 /********************************************************************************************
02501 
02502 >   void CCLexFile::DecIndent()
02503 
02504     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02505     Created:    6/4/94
02506     Inputs:     -
02507     Outputs:    -
02508     Returns:    Decreases IndentSpaces by IndentDelta.
02509     Purpose:    Decreases the number of spaces written by PutNewLine() at the start
02510                 of the next line.  It is decreased by IndentDelta, which can be altered
02511                 using SetIndentDelta()
02512     Errors:     -
02513     SeeAlso:    -
02514 
02515 ********************************************************************************************/
02516 
02517 void CCLexFile::DecIndent()
02518 {
02519     IndentSpaces -= IndentDelta;
02520     if (IndentSpaces < 0) IndentSpaces = 0;
02521 }
02522 
02523 
02524 
02532 
02533 
02534 
02535 /********************************************************************************************
02536 >   CCStreamFile::CCStreamFile(iostream* pStream,
02537                                UINT32 bufferSize = CCFILE_DEFAULTSIZE,
02538                                BOOL ErrorReporting = TRUE,
02539                                BOOL ExceptionThrowing = FALSE)
02540 
02541     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02542     Created:    1/9/93        
02543     Inputs:     pstream     - the iostream to use for inout and output
02544                 bufferSize  - Size of the fixed size buffer (default = 1024)
02545                             - if size > 0 then create a buffer of the specified size
02546                             - if size = 0 then create a file without a buffer
02547                 ReportErrors flag
02548                 ThrowException flag
02549     Purpose:    Default constructor.
02550     SeeAlso:    iostream::setbuf
02551 ********************************************************************************************/
02552 
02553 CCStreamFile::CCStreamFile(iostream* pStream, UINT32 bufferSize,
02554                            BOOL ErrorReporting, BOOL ExceptionThrowing)
02555   : CCLexFile(ErrorReporting, ExceptionThrowing),
02556     buffer(0),
02557     StreamFileInitialised(FALSE),
02558     IOFile(pStream),
02559     GZFile(NULL),
02560     GZStream(NULL),
02561     ModeOfFile(0)
02562 {
02563     // Nothing to do if there's no stream (and note that StreamFileInitialised
02564     // remains FALSE if no iostream is passed).
02565 //  TRACEUSER( "JustinF", _T("In CCStreamFile::CCStreamFile\n"));
02566     if (IOFile == NULL)
02567     {
02568         TRACE( _T("Null iostream* passed to CCStreamFile::CCStreamFile - is that OK?\n") );
02569         return;
02570     }
02571 
02572     // Possibly allocate a buffer.
02573 /*  if (bufferSize > 0)
02574     {
02575         // Deallocate any existing buffer.
02576         if (!IOFile->rdbuf()->setbuf(0, 0))
02577         {
02578             TRACEUSER( "JustinF", _T("\t- Can't deallocate iostream buffer\n"));
02579             String_256 ErrorMsg(_R(IDE_BUFFER_ERROR));
02580             GotError(_R(IDE_BUFFER_ERROR), ErrorMsg);   // handle the error
02581             return;
02582         }
02583 
02584         // Assign four extra bytes to workaround an MFC bug.
02585         buffer = new char[bufferSize +4];
02586         if (!buffer)
02587         {
02588             GotError(_R(IDE_NOMORE_MEMORY));
02589             return;
02590         }
02591 
02592         // Set the stream's buffer.
02593         if (!IOFile->rdbuf()->setbuf(buffer, bufferSize))
02594         {
02595             TRACEUSER( "JustinF", _T("\t- Can't allocate iostream buffer of %u bytes\n"),
02596                         (UINT32) bufferSize + 4);
02597             String_256 ErrorMsg(_R(IDE_BUFFER_ERROR));
02598             GotError(_R(IDE_BUFFER_ERROR), ErrorMsg);   // handle the error
02599             return;
02600         }
02601     }
02602 */
02603     // Everything is hunky-dory ...
02604     StreamFileInitialised = TRUE;
02605 }
02606 
02607 
02608 
02609 /********************************************************************************************
02610 
02611 >   CCStreamFile::~CCStreamFile()
02612 
02613     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02614     Created:    1/9/93        
02615     Purpose:    Default destructor. Closes file if it is still open.  Deallocates buffer.
02616 
02617 ********************************************************************************************/
02618 
02619 CCStreamFile::~CCStreamFile()
02620 {
02621     // If the compression flag is on then close down the compression system
02622 //  TRACEUSER( "JustinF", _T("In CCStreamFile::~CCStreamFile\n"));
02623     if (CompressData) StopCompression();
02624 
02625     // These are the special classes we might use to compress the file.
02626     // If present then delete them.
02627     if (GZStream)
02628     {
02629         delete GZStream;
02630         GZStream = NULL; 
02631     }
02632 
02633     if (GZFile)
02634     {
02635         delete GZFile;
02636         GZFile = NULL; 
02637     }
02638 
02639     // Finally, deallocate the stream object.  Derived classes should make sure they have set
02640     // the IOFile pointer to null if they pass CCStreamFile an iostream that wasn't allocated
02641     // on the heap.
02642     if (IOFile != NULL)
02643     {
02644         delete IOFile;
02645         IOFile = NULL;
02646     }
02647 
02648     // Finally, deallocate the buffer, as the iostream doesn't.
02649 /*  delete[] buffer;
02650     buffer = 0;             */
02651 }
02652 
02653 
02654 
02655 /********************************************************************************************
02656 
02657 >   BOOL CCStreamFile::IsInited()
02658 
02659     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02660     Created:    1/9/94
02661     Inputs:     None
02662     Returns:    TRUE if the contructor went without errors or FALSE otherwise.
02663     Purpose:    Allows errors to be returned from the constructor.
02664     SeeAlso:    CCStreamFile
02665 
02666 ********************************************************************************************/
02667 
02668 BOOL CCStreamFile::IsInited()
02669 {
02670     return StreamFileInitialised;
02671 }
02672 
02673 
02674 
02675 /********************************************************************************************
02676 >   virtual iostream* CCStreamFile::SetStream(iostream* pStream)
02677 
02678     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02679     Created:    16/8/96
02680     Inputs:     pStream     -       the new iostream to attach this CCStreamFile to
02681     Returns:    Pointer to the previous iostream.  You should deallocate this sometime
02682                 if you don't use it again in a different way.
02683     Purpose:    Changes the iostream that this CCStreamFile uses for I/O.  Don't call
02684                 this unless you know what you're doing - it probably won't work with
02685                 derived classes, such as CCDiskFile.
02686 ********************************************************************************************/
02687 
02688 iostream* CCStreamFile::SetStream(iostream* pStream)
02689 {
02690     iostream* pio = IOFile;
02691     IOFile = pStream;
02692     return pio;
02693 }
02694 
02695 
02696 
02697 /********************************************************************************************
02698 >   virtual BOOL CCStreamFile::isOpen() const
02699 
02700     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02701     Created:    16/8/96
02702     Returns:    TRUE if this CCFile is open.  CCStreamFiles are *always* open, provided they
02703                 were constructed successfully.
02704     Purpose:    Gives the status of this CCStreamFile.
02705 ********************************************************************************************/
02706 
02707 BOOL CCStreamFile::isOpen() const
02708 {
02709     // Stream files are always open, and cannot be closed.
02710     return StreamFileInitialised && IOFile != NULL;
02711 }
02712 
02713 
02714 
02715 /********************************************************************************************
02716 >   virtual void CCStreamFile::close()
02717 
02718     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02719     Created:    16/8/96
02720     Purpose:    Closes a CCStreamFile.  This is a no-op as CCStreamFiles are always open.
02721 ********************************************************************************************/
02722 
02723 void CCStreamFile::close()
02724 {
02725     TRACEUSER( "JustinF", _T("CCStreamFile::close called - I wonder why?\n") ); 
02726 }
02727 
02728 
02729 
02730 /********************************************************************************************
02731 >   CCFile& CCStreamFile::read(void* buf, UINT32 length)
02732 
02733     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02734     Created:    31/03/94
02735     Inputs:     buf - buffer to place the bytes in.
02736                 length - the number of bytes to read.
02737     Outputs:    buf - the data read from the file.
02738     Returns:    Reference to the CCFile object.
02739     Purpose:    Read a number of bytes from the file.
02740     Errors:     This function calls the error handling function (which could throw an
02741                 Exception if the ThrowExceptions flag is set) if the fail flag of the
02742                 file is set after the read.
02743 ********************************************************************************************/
02744 
02745 CCFile &CCStreamFile::read( void *buf, UINT32 length )
02746 {
02747 /* #ifdef _DEBUG
02748     if (length > 1)
02749     {
02750         TRACEUSER( "JustinF", _T("In CCStreamFile::read(void* 0x%p, %u)\n"),
02751                     (LPVOID) buf, (UINT32) length);
02752     }
02753 #endif */
02754     if (CompressData)
02755     {
02756         if (GZStream !=NULL && GZFile != NULL)
02757         {
02758             // returns the number of uncompressed bytes actually read
02759             // (0 for end of file, -1 for error)
02760             INT32 RetValue = GZFile->gzread( GZStream, (char *)buf, length );
02761                 
02762             if (RetValue < 0)
02763             {
02764                 TRACEUSER( "JustinF", _T("Read error = %d\n"), RetValue );
02765                 GZipErrorID = RetValue;
02766                 GotError(_R(IDE_ZFILE_READ_ERROR));
02767             }
02768     
02769             if (RetValue == 0)
02770             {
02771                 // found end of file so make sure we return an EOF as the data
02772                 TCHAR* b = (TCHAR*) buf;
02773                 *b = EOF;
02774                 IOFile->clear(ios::eofbit);
02775 
02776 
02777             }
02778 
02779             if (IOFile->fail())
02780             {
02781                 TRACEUSER( "JustinF", _T("Read fail error\n") );
02782                 GotError(_R(IDE_FILE_READ_ERROR));
02783             }
02784         }
02785         else
02786         {
02787             ERROR3("CCStreamFile::read bad GZFile/GZStream");
02788             GotError(_R(IDE_FILE_READ_ERROR));
02789         }
02790     }
02791     else
02792     {
02793         if (IOFile->read((char*) buf, length).fail()) GotError(_R(IDE_FILE_READ_ERROR));
02794     }
02795     
02796     // Update the CharsRead param
02797     CharsRead += length;
02798 
02799     // and return
02800     return *this;
02801 }
02802 
02803 
02804 
02805 /********************************************************************************************
02806 
02807 >   CCFile& CCStreamFile::read(StringBase* buf)
02808 
02809     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02810     Created:    31/03/94
02811     Inputs:     buf - the String object to place the characters in.
02812     Outputs:    buf - the characters read from the file.
02813     Returns:    Reference to the CCFile object.
02814     Purpose:    Read in a string from the file.  The read operation stops at the first
02815                 newline, or when the string is full.  The newline is removed from the input
02816                 stream.
02817 
02818 ********************************************************************************************/
02819 
02820 CCFile& CCStreamFile::read(StringBase* buf)
02821 {
02822     // Read characters in until we have MaxLength() of them, or we hit a new line
02823 //  TRACEUSER( "JustinF", _T("In CCStreamFile::read(String* 0x%p)\n"), (LPVOID) buf);
02824     INT32 Max = buf->MaxLength();
02825     INT32 Off = 0;
02826     TCHAR* Text = (TCHAR*) (*buf);
02827     char Ch;
02828 
02829     // chars to look for
02830     const TCHAR CR = TEXT('\n');
02831     const TCHAR LF = TEXT('\r');
02832 
02833     // We have to do this sneeky test for end of file because the iostream classes
02834     // are a load of old bollox!
02835     if (CompressData)
02836     {
02837         // First check if our zipping classes are present, if not then fail 
02838         if (GZStream ==NULL && GZFile == NULL)
02839         {
02840             ERROR3("CCStreamFile::read string bad GZFile/GZStream");
02841             GotError(_R(IDE_FILE_READ_ERROR));
02842         }
02843 
02844         // returns the number of uncompressed bytes actually read
02845         // (0 for end of file, -1 for error
02846         INT32 RetValue = GZFile->gzpeek( GZStream, &Ch );
02847             
02848         if (RetValue < 0)
02849         {
02850             TRACEUSER( "JustinF", _T("Peek error = %d\n"), RetValue );
02851             GZipErrorID = RetValue;
02852             GotError(_R(IDE_ZFILE_READ_ERROR));
02853         }
02854 
02855         if (RetValue == 0)
02856         {
02857             // found end of file so make sure we return an EOF as the data
02858             Ch = CHAR_EOF;
02859         }
02860 
02861         if (IOFile->fail())
02862         {
02863             TRACEUSER( "JustinF", _T("Peek char fail error\n") );
02864             GotError(_R(IDE_FILE_READ_ERROR));
02865         }
02866     }
02867     else
02868     {
02869         Ch = IOFile->peek();
02870     }
02871     
02872     // check if found the EOF
02873     if (Ch == CHAR_EOF)
02874     {
02875         // Mark the EOF has having been reached.
02876         IOFile->clear(ios::eofbit);
02877 
02878         // Its the end of the file all right
02879         Text[0] = TEXT('\0');
02880         return *this;
02881     }
02882     
02883 
02884     // Get the first char
02885     read(&Ch, 1);
02886 
02887     // loop around until we get to the end of the line or the end of the file
02888     if (CompressData)
02889     {
02890         // Must leave 1 character space in the buffer if we reach the maximum buffer size
02891         // so that we can fit the terminating zero in below.
02892         while ((Max>1) && (Ch!=CR) && (Ch!=LF) && (Ch!=CHAR_EOF))
02893         {
02894             // store the char we read
02895             Text[Off++] = Ch;
02896 
02897             // read another one and decrement the counter
02898             read(&Ch, 1);
02899 
02900             // Keep track of how much we have read
02901             Max--;
02902         }
02903 
02904         if (GZStream ==NULL && GZFile == NULL)
02905         {
02906             ERROR3("CCStreamFile::read string bad GZFile/GZStream");
02907             GotError(_R(IDE_FILE_READ_ERROR));
02908         }
02909 
02910         // returns the number of uncompressed bytes actually read
02911         // (0 for end of file, -1 for error
02912         INT32 RetValue = GZFile->gzpeek( GZStream, &Ch );
02913             
02914         if (RetValue < 0)
02915         {
02916             TRACEUSER( "JustinF", _T("Peek error = %d\n"), RetValue );
02917             GZipErrorID = RetValue;
02918             GotError(_R(IDE_ZFILE_READ_ERROR));
02919         }
02920 
02921         if (RetValue == 0)
02922         {
02923             // found end of file so make sure we return an EOF as the data
02924             Ch = CHAR_EOF;
02925         }
02926 
02927         if (IOFile->fail())
02928         {
02929             TRACEUSER( "JustinF", _T("Peek char fail error\n") );
02930             GotError(_R(IDE_FILE_READ_ERROR));
02931         }
02932         
02933         if ((Ch==LF) || (Ch==CR))
02934         {
02935             // eat the other part of the CR LF combo
02936             read(&Ch, 1);
02937         }
02938         
02939         // See if we have reached the end of the file
02940         if (Ch==CHAR_EOF)
02941         {
02942             // Mark the End Of File
02943             IOFile->clear(ios::eofbit);
02944         }
02945     }
02946     else
02947     {
02948         // Must leave 1 character space in the buffer if we reach the maximum buffer size
02949         // so that we can fit the terminating zero in below.
02950         while ((Max>1) && (Ch!=CR) && (Ch!=LF) && (IOFile->peek() != EOF))
02951         {
02952             // store the char we read
02953             Text[Off++] = Ch;
02954 
02955             // read another one and decrement the counter
02956             read(&Ch, 1);
02957 
02958             // Keep track of how much we have read
02959             Max--;
02960         }
02961 
02962         // if we ended at the end of a line, see if the next char is also part of a new line
02963         Ch = IOFile->peek();
02964         if ((Ch==LF) || (Ch==CR))
02965         {
02966             // eat the other part of the CR LF combo
02967             read(&Ch, 1);
02968         }
02969 
02970         // See if we have reached the end of the file
02971         if (Ch==CHAR_EOF)
02972         {
02973             // Mark the End Of File
02974             IOFile->clear(ios::eofbit);
02975         }
02976     }
02977 
02978     // Terminate the string
02979     Text[Off++] = 0;
02980 
02981     // return
02982     return *this;
02983 }
02984 
02985 
02986 
02987 /********************************************************************************************
02988 
02989 >   CCFile& CCStreamFile::read(TCHAR& buf)
02990 
02991     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02992     Created:    31/03/94
02993     Inputs:     Pointer to the TCHAR buffer.
02994     Outputs:    buf - the character read from the file.
02995     Returns:    Reference to the CCFile object.
02996     Purpose:    Read a character from the file.
02997 
02998 ********************************************************************************************/
02999 
03000 CCFile &CCStreamFile::read( char &buf )
03001 {
03002 //  TRACEUSER( "JustinF", _T("In CCStreamFile::read(TCHAR)\n"));
03003     if (CompressData)
03004     {
03005         if (GZStream !=NULL && GZFile != NULL)
03006         {
03007             // returns the number of uncompressed bytes actually read
03008             // (0 for end of file, -1 for error
03009             char        outbuf;
03010             INT32 RetValue = GZFile->gzread( GZStream, &outbuf, 1 );
03011                 
03012             if (RetValue < 0)
03013             {
03014                 TRACEUSER( "JustinF", _T("Read error = %d\n"), RetValue );
03015                 GZipErrorID = RetValue;
03016                 GotError(_R(IDE_ZFILE_READ_ERROR));
03017             }
03018     
03019             if (RetValue == 0)
03020             {
03021                 // found end of file so make sure we return an EOF as the data
03022                 Ch = CHAR_EOF;
03023             }
03024 
03025             if (IOFile->fail())
03026             {
03027                 TRACEUSER( "JustinF", _T("Read char fail error\n") );
03028                 GotError(_R(IDE_FILE_READ_ERROR));
03029             }
03030 
03031             buf = outbuf;
03032         }
03033         else
03034         {
03035             ERROR3("CCStreamFile::read char bad GZFile/GZStream");
03036             GotError(_R(IDE_FILE_READ_ERROR));
03037         }
03038     }
03039     else
03040     {
03041         if (IOFile->get(buf).fail()) GotError(_R(IDE_FILE_READ_ERROR));
03042     }
03043     
03044     return *this;
03045 }
03046                                     
03047 
03048 
03049 /********************************************************************************************
03050 
03051 >   CCFile& CCStreamFile::write(const StringBase& buf, UINT32 length = 0)
03052 
03053     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03054     Created:    1/9/93
03055     Inputs:     buf - String buffer.
03056                 length - number of characters to write.
03057                          (0 => write all of them up to the string terminator)
03058     Returns:    Reference to the CCFile object.
03059     Purpose:    Writes the number of charactors specified by length.
03060     SeeAlso:    fstream::write()
03061 
03062 ********************************************************************************************/
03063 
03064 CCFile &CCStreamFile::write( const StringBase &buf, UINT32 length )
03065 {
03066 //  TRACEUSER( "JustinF", _T("In CCStreamFile::write(String* 0x%p, %u)\n"), (LPVOID) &buf, (UINT32) length);
03067     ENSURE((INT32) length <= buf.Length(), "CCStreamFile::write(): Not enough characters in string!");
03068 
03069 #if 0 != wxUSE_UNICODE
03070     size_t              cch = camWcstombs( NULL, (const TCHAR *)buf, 0 ) + 1;
03071     PSTR                psz = PSTR( alloca( cch ) );
03072     camWcstombs( psz, (const TCHAR *)buf, cch );
03073 #else
03074     PCSTR               psz = PCSTR(buf);
03075 #endif
03076     
03077     if( 0 == length )
03078         length = (UINT32)strlen( psz );
03079 
03080     if (CompressData)
03081     {
03082         if (GZStream !=NULL && GZFile != NULL)
03083         {
03084             // returns the number of uncompressed bytes actually read
03085             // (0 for end of file, -1 for error
03086             INT32 RetValue = GZFile->gzwrite( GZStream, psz, DWORD(length) );
03087                 
03088             if (RetValue < 0)
03089             {
03090                 TRACEUSER( "JustinF", _T("Write error = %d\n"), RetValue );
03091                 GZipErrorID = RetValue;
03092                 GotError(_R(IDE_ZFILE_WRITE_ERROR));
03093             }
03094     
03095             if ((UINT32) RetValue != length)
03096             {
03097                 TRACEUSER( "JustinF", _T("Wrote wrong length = %d\n"), RetValue );
03098                 GotError(_R(IDE_FILE_WRITE_ERROR));
03099             }
03100 
03101             if (IOFile->bad())
03102             {
03103                 TRACEUSER( "JustinF", _T("Write bad error\n") );
03104                 GotError(_R(IDE_FILE_WRITE_ERROR));
03105             }
03106         }
03107         else
03108         {
03109             ERROR3("CCStreamFile::write bad GZFile/GZStream");
03110             GotError(_R(IDE_FILE_READ_ERROR));
03111         }
03112     }
03113     else
03114     {
03115         if( IOFile->write( psz, DWORD(length) ).bad() )
03116             GotError( _R(IDE_FILE_WRITE_ERROR) );
03117     }
03118     
03119     return *this;
03120 }
03121 
03122 
03123 
03124 /********************************************************************************************
03125 
03126 >   CCFile& CCStreamFile::write(const void *buf, UINT32 length)
03127 
03128     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03129     Created:    31/03/94
03130     Inputs:     buf - pointer to the bytes to write.
03131                 length - the number of bytes to write.
03132     Returns:    Reference to the CCFile object.
03133     Purpose:    Write a number of bytes to the file.
03134 
03135 ********************************************************************************************/
03136 
03137 CCFile& CCStreamFile::write(const void* buf, UINT32 length)
03138 {
03139 /* #ifdef _DEBUG
03140     if (length > 1)
03141     {
03142         TRACEUSER( "JustinF", _T("In CCStreamFile::write(void* 0x%p, %u)\n"),
03143                     (LPVOID) buf, (UINT32) length);
03144     }
03145 #endif */
03146 
03147     if (CompressData)
03148     {
03149         if (GZStream !=NULL && GZFile != NULL)
03150         {
03151             // returns the number of uncompressed bytes actually read
03152             // (0 for end of file, -1 for error
03153             INT32 RetValue = GZFile->gzwrite( GZStream, PSTR(buf), length );
03154                 
03155             if (RetValue < 0)
03156             {
03157                 TRACEUSER( "JustinF", _T("Write error = %d\n"), RetValue );
03158                 GZipErrorID = RetValue;
03159                 GotError(_R(IDE_ZFILE_WRITE_ERROR));
03160             }
03161     
03162             if ((UINT32) RetValue != length)
03163             {
03164                 TRACEUSER( "JustinF", _T("Wrote wrong length = %d\n") ,RetValue );
03165                 GotError(_R(IDE_FILE_WRITE_ERROR));
03166             }
03167 
03168             if (IOFile->bad())
03169             {
03170                 TRACEUSER( "JustinF", _T("Write bad error\n") );
03171                 GotError(_R(IDE_FILE_WRITE_ERROR));
03172             }
03173         }
03174         else
03175         {
03176             ERROR3("CCStreamFile::write bad GZFile/GZStream");
03177             GotError(_R(IDE_FILE_READ_ERROR));
03178         }
03179     }
03180     else
03181     {
03182         if( IOFile->write( PCSTR(buf), length).bad() )
03183             GotError( _R(IDE_FILE_WRITE_ERROR) );
03184     }
03185 
03186     return *this;
03187 }
03188 
03189 
03190 
03191 /********************************************************************************************
03192 
03193 >   CCFile& CCStreamFile::write(TCHAR& buf)
03194 
03195     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03196     Created:    31/03/94
03197     Inputs:     buf - the character to write out.
03198     Returns:    Reference to the CCFile object.
03199     Purpose:    Writes a character out to the file.
03200 
03201 ********************************************************************************************/
03202 
03203 CCFile &CCStreamFile::write( char &buf )
03204 {
03205 //  TRACEUSER( "JustinF", _T("In CCStreamFile::write(TCHAR %c)\n"), (TCHAR) buf);
03206     if (CompressData)
03207     {
03208         if (GZStream !=NULL && GZFile != NULL)
03209         {
03210             // returns the number of uncompressed bytes actually read
03211             // (0 for end of file, -1 for error
03212             INT32 RetValue = GZFile->gzwrite( GZStream, &buf, 1 );
03213                 
03214             if (RetValue <= 0 || IOFile->bad())
03215             {
03216                 TRACEUSER( "JustinF", _T("Write char error = %d\n"), RetValue );
03217                 GZipErrorID = RetValue;
03218                 GotError(_R(IDE_ZFILE_WRITE_ERROR));
03219             }
03220     
03221             if ((UINT32) RetValue != 1)
03222             {
03223                 TRACEUSER( "JustinF", _T("Wrote wrong length = %d\n"), RetValue );
03224                 GotError(_R(IDE_FILE_WRITE_ERROR));
03225             }
03226 
03227             if (IOFile->bad())
03228             {
03229                 TRACEUSER( "JustinF", _T("Write char bad error\n") );
03230                 GotError(_R(IDE_FILE_WRITE_ERROR));
03231             }
03232         }
03233         else
03234         {
03235             ERROR3("CCStreamFile::write char bad GZFile/GZStream");
03236             GotError(_R(IDE_FILE_READ_ERROR));
03237         }
03238     }
03239     else
03240     {
03241         if (IOFile->put(buf).bad())
03242             GotError(_R(IDE_FILE_WRITE_ERROR));
03243     }
03244     
03245     return *this;
03246 }
03247 
03248 
03249 
03250 /********************************************************************************************
03251 
03252 >   CCFile& CCStreamFile::seekIn(FilePos pos)
03253 
03254     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03255     Created:    1/9/93
03256     Inputs:     FilePos - a position in the file
03257     Returns:    Reference to the CCFile object.
03258     Purpose:    Sets the input pointer to the file position passed in.
03259     SeeAlso:    istream::seekg()
03260 
03261 ********************************************************************************************/
03262 
03263 CCFile& CCStreamFile::seekIn(FilePos pos)
03264 {
03265     if (CompressData)
03266     {
03267         // This is not implemented in compressed files so error
03268         ERROR3("seekIn called in Compressed mode");
03269         GotError(_R(IDE_FILE_READ_ERROR));
03270         return *this;
03271     }
03272     else
03273     {
03274         // Stuff to sort a seeking lexer out
03275         if (IsLexerInitialised() && SeekingRequired)
03276         {
03277             Ch = 0;
03278             Ofs = 0;
03279             LastLinePos = pos;
03280         }
03281 
03282         IOFile->seekg(pos);
03283         return *this;
03284     }
03285 }
03286 
03287 
03288 
03289 /********************************************************************************************
03290 
03291 >   CCFile& CCStreamFile::seekIn(INT32 Offset, ios::seek_dir Dir)
03292 
03293     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03294     Created:    1/9/93
03295     Inputs:     Offset - the file offset to seek to.
03296                 Dir - specifies where in the file the offset is relative to.
03297                       (can be ios::beg, ios::cur, or ios::end).
03298     Returns:    Reference to the CCFile object.
03299     Purpose:    Sets the input pointer to the offset passed in, relative to the specified
03300                 position in the file.
03301     SeeAlso:    istream::seekg()
03302 
03303 ********************************************************************************************/
03304 
03305 CCFile& CCStreamFile::seekIn(INT32 Offset, ios::seekdir Dir)
03306 {
03307     if (CompressData)
03308     {
03309         // This is not implemented in compressed files so error
03310         ERROR3("seekIn (Offset, dir) called in Compressed mode");
03311         GotError(_R(IDE_FILE_READ_ERROR));
03312     }
03313     else
03314     {
03315         IOFile->seekg( Offset, ios_base::seekdir(Dir) );
03316 
03317         // Stuff to sort the lexer out
03318         if (IsLexerInitialised() && SeekingRequired)
03319         {
03320             Ch = 0;
03321             Ofs = 0;
03322             LastLinePos = IOFile->tellg();
03323         }
03324     }
03325 
03326     return *this;
03327 }
03328 
03329 
03330 
03331 /********************************************************************************************
03332 
03333 >   FilePos CCStreamFile::tellIn()
03334 
03335     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03336     Created:    1/9/93
03337     Returns:    FilePos - a position in the file
03338     Purpose:    Gets the input pointer file position.
03339     SeeAlso:    istream::tellg()
03340 
03341 ********************************************************************************************/
03342 
03343 FilePos CCStreamFile::tellIn()
03344 {           
03345     if (CompressData)
03346     {
03347         // This is not implemented in compressed files so error
03348         //ERROR3("tellIn called in Compressed mode");
03349         //GotError(_R(IDE_FILE_READ_ERROR));
03350         return (FilePos) IOFile->tellg();
03351     }
03352     else
03353     {
03354         if (IsLexerInitialised())
03355         {
03356             ERROR3IF(!SeekingRequired,
03357                         "CCStreamFile::tellIn() will only work properly with seeking enabled");
03358 
03359             // -1 for the one character lookahead that's in operation
03360             return (FilePos) (Ofs + (INT32) LastLinePos - 1);
03361         }
03362 
03363         return (FilePos) IOFile->tellg();
03364     }
03365 }
03366 
03367 
03368              
03369 /********************************************************************************************
03370 
03371 >   CCFile& CCStreamFile::seek(FilePos pos)
03372 
03373     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03374     Created:    1/9/93
03375     Inputs:     FilePos - a position in the file
03376     Returns:    Reference to the CCFile object.
03377     Purpose:    Sets the output pointer to the file position passed in.
03378     SeeAlso:    ostream::seekp()
03379 
03380 ********************************************************************************************/
03381 
03382 CCFile& CCStreamFile::seek(FilePos pos)
03383 {                         
03384     if (CompressData)
03385     {
03386         // This is not implemented in compressed files so error
03387         ERROR3("seek called in Compressed mode");
03388         GotError(_R(IDE_FILE_READ_ERROR));
03389     }
03390     else
03391         IOFile->seekp(pos);
03392 
03393     return *this;
03394 }
03395 
03396 
03397 
03398 /********************************************************************************************
03399 
03400 >   FilePos CCStreamFile::tell()
03401 
03402     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03403     Created:    1/9/93
03404     Returns:    FilePos - a position in the file
03405     Purpose:    Gets the output pointer file position.
03406     SeeAlso:    ostream::tellp()
03407 
03408 ********************************************************************************************/
03409 
03410 FilePos CCStreamFile::tell()
03411 {           
03412     if (CompressData)
03413     {
03414         // This is not implemented in compressed files so error
03415         ERROR3("tell called in Compressed mode");
03416         GotError(_R(IDE_FILE_READ_ERROR));
03417     }
03418 
03419     return (FilePos) IOFile->tellp();
03420 }
03421 
03422 
03423              
03424 /********************************************************************************************
03425 
03426 >   CCFile& CCStreamFile::flush()
03427 
03428     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03429     Created:    1/9/93
03430     Returns:    Reference to the CCFile object.
03431     Purpose:    Clears the io buffer
03432     SeeAlso:    iostream::flush
03433 
03434 ********************************************************************************************/
03435 
03436 CCFile& CCStreamFile::flush()
03437 {
03438     if (CompressData)
03439     {
03440         if (GZStream !=NULL && GZFile != NULL)
03441         {
03442             // returns the number of uncompressed bytes actually read
03443             // (0 for end of file, -1 for error
03444             INT32 RetValue = GZFile->gzflush(GZStream, Z_FULL_FLUSH);
03445                 
03446             if (RetValue < 0)
03447             {
03448                 TRACEUSER( "JustinF", _T("flush error = %d\n"), RetValue );
03449                 GZipErrorID = RetValue;
03450                 GotError(_R(IDE_ZFILE_READ_ERROR));
03451             }
03452     
03453             if (IOFile->fail())
03454             {
03455                 TRACEUSER( "JustinF", _T("flush fail error\n") );
03456                 GotError(_R(IDE_FILE_READ_ERROR));
03457             }
03458         }
03459         else
03460         {
03461             ERROR3("CCStreamFile::flush has bad GZFile/GZStream");
03462             GotError(_R(IDE_FILE_READ_ERROR));
03463         }
03464 
03465         // now flush the main IOFIle itself 
03466         IOFile->flush();
03467     }
03468     else
03469         IOFile->flush();
03470 
03471     return *this;
03472 }
03473 
03474     
03475 
03476 /********************************************************************************************
03477 
03478 >   CCFile& CCStreamFile::get(TCHAR& buf)
03479 
03480     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03481     Created:    1/9/93
03482     Outputs:    Single charactor retrieved by get.
03483     Returns:    Reference to the CCFile object.
03484     Purpose:    Retrieves a single charactor from the file.
03485                 If the compression flag is on then it gets the compressed byte from the file
03486                 and decompresses it.
03487     SeeAlso:    fstream::operator<<()
03488 
03489 ********************************************************************************************/
03490 
03491 CCFile& CCStreamFile::get( char &buf )
03492 {
03493 //  TRACEUSER( "JustinF", _T("In CCStreamFile::get(TCHAR)\n"));
03494     if (CompressData)
03495     {
03496         if (GZStream !=NULL && GZFile != NULL)
03497         {
03498             // returns the number of uncompressed bytes actually read
03499             // (0 for end of file, -1 for error
03500             char        outbuf;
03501             INT32 RetValue = GZFile->gzread( GZStream, &outbuf, 1 );
03502                 
03503             if (RetValue < 0)
03504             {
03505                 TRACEUSER( "JustinF", _T("get error = %d\n"), RetValue );
03506                 GZipErrorID = RetValue;
03507                 GotError(_R(IDE_ZFILE_READ_ERROR));
03508             }
03509     
03510             if (RetValue == 0)
03511             {
03512                 // end of file reached so return the EOF character
03513                 buf = CHAR_EOF;
03514             }
03515             else
03516                 buf = outbuf;
03517         }
03518         else
03519         {
03520             ERROR3("CCStreamFile::get bad GZFile/GZStream");
03521             GotError(_R(IDE_FILE_READ_ERROR));
03522         }
03523     }
03524     else
03525         IOFile->get( buf );
03526     
03527     return *this;
03528 }
03529 
03530 
03531 
03532 /********************************************************************************************
03533 
03534 >   CCFile& CCStreamFile::put(const TCHAR& buf)
03535 
03536     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03537     Created:    1/9/93
03538     Inputs:     Single charactor to be inserted into file.
03539     Returns:    Reference to the CCFile object.
03540     Purpose:    Inserts a single charactor into the file.
03541                 If the compression flag is on then it sends it out compressed to file.
03542     SeeAlso:    fstream::operator<<()
03543 
03544 ********************************************************************************************/
03545 
03546 CCFile &CCStreamFile::put( const char &buf )
03547 {
03548 //  TRACEUSER( "JustinF", _T("In CCStreamFile::put(TCHAR %c)\n"), (TCHAR) buf);
03549     if (CompressData)
03550     {
03551         if (GZStream !=NULL && GZFile != NULL)
03552         {
03553             // returns the number of uncompressed bytes actually read
03554             // (0 for end of file, -1 for error
03555             char        outbuf = buf;       
03556             INT32 RetValue = GZFile->gzwrite( GZStream, &outbuf, 1 );
03557                 
03558             if (RetValue < 0)
03559             {
03560                 TRACEUSER( "JustinF", _T("put error = %d\n"), RetValue );
03561                 GZipErrorID = RetValue;
03562                 GotError(_R(IDE_ZFILE_WRITE_ERROR));
03563             }
03564     
03565             if ((UINT32) RetValue != 1)
03566             {
03567                 TRACEUSER( "JustinF", _T("put wrong length = %d\n"), RetValue );
03568                 GotError(_R(IDE_FILE_WRITE_ERROR));
03569             }
03570         }
03571         else
03572         {
03573             ERROR3("CCStreamFile::put bad GZFile/GZStream");
03574             GotError(_R(IDE_FILE_WRITE_ERROR));
03575         }
03576     }
03577     else
03578         IOFile->put(buf);
03579         
03580     return *this;
03581 }
03582 
03583 
03584 
03585 /********************************************************************************************
03586 
03587 >   BOOL CCStreamFile::good() const
03588 
03589     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03590     Created:    1/9/93
03591     Returns:    True if file status is healthy and FALSE otherwize.
03592     Purpose:    To identify if file is ok
03593     SeeAlso:    ios::good
03594 
03595 ********************************************************************************************/
03596 
03597 BOOL CCStreamFile::good() const
03598 {
03599     return IOFile->good();
03600 }
03601 
03602 
03603 
03604 /********************************************************************************************
03605 
03606 >   BOOL CCStreamFile::bad() const
03607 
03608     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03609     Created:    1/9/93
03610     Returns:    True if a serious I/O error occurs and FALSE otherwize.
03611     Purpose:    To identify an erroneous file status
03612     SeeAlso:    ios::bad
03613 
03614 ********************************************************************************************/
03615 
03616 BOOL CCStreamFile::bad() const
03617 {
03618     // If we are about to return True then make sure we call set error
03619     // as the caller may not have done this and hence a random error
03620     // may be displayed
03621     if (IOFile->bad()) Error::SetError( _R(IDE_IO_ERROR) );
03622     return IOFile->bad();
03623 }
03624 
03625 
03626 
03627 /********************************************************************************************
03628 
03629 >   BOOL CCStreamFile::fail() const
03630 
03631     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03632     Created:    1/9/93
03633     Returns:    True if a recoverable fail error occurs and FALSE otherwize.
03634     Purpose:    To identify recoverable file errors
03635     SeeAlso:    ios::fail
03636 
03637 ********************************************************************************************/
03638 
03639 BOOL CCStreamFile::fail() const
03640 {
03641     return IOFile->fail();
03642 }
03643 
03644 
03645 
03646 /********************************************************************************************
03647 
03648 >   BOOL CCStreamFile::eof() const
03649 
03650     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03651     Created:    1/9/93
03652     Returns:    True if end of file and FALSE otherwize.
03653     Purpose:    To identify end of file
03654     SeeAlso:    ios::eof
03655 
03656 ********************************************************************************************/
03657 
03658 BOOL CCStreamFile::eof() const
03659 {
03660     return IOFile->eof();
03661 }
03662 
03663 
03664 
03665 /********************************************************************************************
03666 
03667 >   BOOL CCStreamFile::SetBadState()
03668 
03669     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03670     Created:    31/08/94
03671     Returns:    None.
03672     Purpose:    It allows the forceable setting of the test that functions like bad() use
03673                 so the next check of the current file status to see if we should continue
03674                 using the file or not will fail. This will be called by the GotError function
03675                 so that any attempts to read/write after this should fail.
03676     SeeAlso:    CCFile::GotError
03677 
03678 ********************************************************************************************/
03679 
03680 void CCStreamFile::SetBadState()
03681 {
03682     // All the status functions should just return the state of eof()
03683     // Therefore, just make sure that eof() will fail. 
03684     IOFile->clear(IOFile->badbit);              // remember clear == set badbit
03685 }
03686 
03687 
03688 
03689 /********************************************************************************************
03690 
03691 >   BOOL CCStreamFile::SetGoodState()
03692 
03693     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03694     Created:    8/12/94
03695     Returns:    None.
03696     Purpose:    It allows the forceable setting of the test that functions like bad() use
03697                 so the next check of the current file status to see if we should continue
03698                 using the file or not will pass. It would seem that sometimes the eof() or
03699                 similar might need forcing by somebody using the class. 
03700     SeeAlso:    CCFile::GotError
03701 
03702 ********************************************************************************************/
03703 
03704 void CCStreamFile::SetGoodState()
03705 {
03706     // Nuke any existing error states that might exist e.g. a lying eof() bit
03707     IOFile->clear(IOFile->goodbit);
03708 }
03709 
03710 
03711 
03712 /********************************************************************************************
03713 >   virtual INT32 CCStreamFile::Size()
03714 
03715     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03716     Created:    13/8/96
03717     Returns:    The size of the attached stream, in bytes.
03718 ********************************************************************************************/
03719 
03720 size_t CCStreamFile::Size()
03721 {
03722     // We can't really do this for any stream, but we can have a bodgy bash.  We'll subtract
03723     // the start position from the end position of the file.
03724     streampos spOrigin = IOFile->tellg();
03725     size_t sz = IOFile->seekg(0, ios::end).tellg() - IOFile->seekg(0, ios::beg).tellg();
03726     IOFile->seekg(spOrigin);
03727     return sz;
03728 }
03729 
03730 
03731 
03732 /********************************************************************************************
03733 
03734 >   virtual BOOL CCStreamFile::InitCompression(BOOL Header = FALSE)
03735 
03736 
03737     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03738     Created:    1/6/95
03739     Purpose:    To initialise the compression system ready for use. This is to make sure
03740                 there is enough memory available for its buffers before writing out any
03741                 compression tokens into the output file.
03742                 Usually used for writing only. Reading, there should be no similar
03743                 requirement.
03744                 Graeme (15/11/99) - Added the Header parameter to the function to allow
03745                 compression to use the ZLib header. Previously, the CCFile functions were
03746                 hardwired to supress this, but Flash export needs it.
03747     SeeAlso:    StartCompression; StopCompression
03748 
03749 ********************************************************************************************/
03750 
03751 BOOL CCStreamFile::InitCompression(BOOL Header)
03752 {
03753 //  TRACEUSER( "JustinF", _T("CCStreamFile::InitCompression\n"));
03754 
03755     // We first need to create the classes that we will be using
03756     GZFile = new GZipFile;
03757     if (GZFile == NULL)
03758     {
03759         return FALSE;
03760     }
03761 
03762     // Can't seem to get to the read/write (in/out) flag states via IOFile.flags()
03763     // so use stored versions
03764     String_16           filemode;
03765 
03766     //return CCStreamFile::isOpen() && cs.is_open();
03767     
03768     if (ModeOfFile & ios::out)      filemode = _T("w");
03769     else if (ModeOfFile & ios::in)  filemode = _T("r");
03770     else ERROR3("filemode incorrect as neither in or out"); 
03771 
03772     // Add in the b if we are in binary mode
03773     if (ModeOfFile & ios::binary) filemode += _T("b");
03774 
03775     GZStream = GZFile->gz_init( IOFile, (TCHAR*) filemode, Header );        
03776     if (GZStream == NULL)
03777     {
03778         // Remove the class that we allocated
03779         delete GZFile;
03780         GZFile = NULL;
03781         return FALSE;
03782     }
03783     
03784     // Everything went ok
03785     return TRUE;    
03786 }
03787 
03788 
03789 
03790 /********************************************************************************************
03791 
03792 >   virtual BOOL CCStreamFile::StartCompression()
03793 
03794 
03795     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03796     Created:    25/5/95
03797     Purpose:    To start up the compression system.
03798                 If we are writing then should have called Init before so that we have
03799                 a chance to fail BEFORE the compression tokens are written
03800                 If we are reading then no need to do this.
03801     SeeAlso:    StopCompression
03802 
03803 ********************************************************************************************/
03804 
03805 BOOL CCStreamFile::StartCompression()
03806 {
03807 //  TRACEUSER( "JustinF", _T("CCStreamFile::StartCompression\n"));
03808 
03809     // We first need to create the classes that we will be using
03810     // Only create the GZFile class if not already present as in the writing case
03811     // we will have called Init and it will be present 
03812     if (GZFile == NULL) GZFile = new GZipFile;
03813     if (GZFile == NULL)
03814     {
03815         return FALSE;
03816     }
03817 
03818     // Can't seem to get to the read/write (in/out) flag states via IOFile.flags()
03819     // so use stored versions
03820     String_16           filemode;
03821     
03822     if( ModeOfFile & ios::out )
03823     {
03824         filemode = _T("w");
03825     }
03826     else
03827     if( ModeOfFile & ios::in )
03828     {
03829         filemode = _T("r");
03830     }
03831     else
03832     {
03833         ERROR3("filemode incorrect as neither in or out");  
03834     }
03835     
03836     // Add in the b if we are in binary mode
03837     if( ModeOfFile & ios::binary )
03838     {
03839         filemode += _T("b");
03840     }
03841     
03842     // Pass in the leafname of the file
03843     GZipErrorID = Z_OK;
03844 
03845     // If writing then should have called Init before so that we have a chance to 
03846     // fail BEFORE the compression tokens are written
03847     if (GZStream != NULL)
03848     {
03849         // In the write case Init has been called so just open the file
03850         INT32 RetValue = GZFile->gz_open(GZStream);
03851         if (RetValue < 0)
03852         {
03853             // Only set the error if it is not our special we have found uncompressed
03854             // data error
03855             if (RetValue == Z_UNCOMPRESSED_ERROR)
03856             {
03857                 // Found uncompressed data so stop compression
03858                 // Remove the class that we allocated
03859                 delete GZStream;
03860                 GZStream = NULL;
03861                 delete GZFile;
03862                 GZFile = NULL;
03863                 CompressData = FALSE;   
03864 
03865                 return TRUE;
03866             }
03867             else
03868             {
03869                 // Some other error has happened so remember this error
03870                 GZipErrorID = RetValue;
03871             }
03872         }
03873     }
03874     else
03875     {
03876         // In the read case Init will not have been called so we use the full
03877         // version of open.
03878         GZStream = GZFile->gz_open( IOFile, (TCHAR *)filemode, NULL );      // no paths please!
03879         if (GZStream == NULL)
03880         {
03881             // Remove the class that we allocated
03882             delete GZFile;
03883             GZFile = NULL;
03884 
03885             // Return False so that we error
03886             return FALSE;
03887         }
03888 
03889         // If it has given our special error then we have found uncompressed
03890         // data and should just stop the compression process
03891         if (GZStream->z_err == Z_UNCOMPRESSED_ERROR)
03892         {
03893             delete GZStream;
03894             GZStream = NULL;
03895 
03896             // Remove the class that we allocated
03897             delete GZFile;
03898             GZFile = NULL;
03899 
03900             // Make out that compression did start up ok otherwise it will error.
03901             // But ensure compression is off
03902             CompressData = FALSE;   
03903             return TRUE;
03904         }
03905     }
03906 
03907     if (GZStream->z_err != Z_OK) GZipErrorID = GZStream->z_err;
03908 
03909     // check if an error was detected in opening
03910     if (GZipErrorID != Z_OK)
03911     {
03912         // Work out if we are reading or writing and use the corresponding
03913         // correct error message
03914         UINT32 ErrorID = _R(IDE_ZFILE_READ_ERROR);
03915         if (ModeOfFile & ios::out)      ErrorID = _R(IDE_ZFILE_WRITE_ERROR);
03916         else if (ModeOfFile & ios::in)  ErrorID = _R(IDE_ZFILE_READ_ERROR);
03917         GotError(ErrorID);
03918     }
03919     
03920     return TRUE;    
03921 }   
03922 
03923 
03924 
03925 /********************************************************************************************
03926 
03927 >   virtual BOOL CCStreamFile::StopCompression()
03928 
03929 
03930     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03931     Created:    25/5/95
03932     Purpose:    To stop the compression system.
03933     SeeAlso:    StartCompression
03934 
03935 ********************************************************************************************/
03936 
03937 BOOL CCStreamFile::StopCompression()
03938 {
03939 //  TRACEUSER( "JustinF", _T("CCStreamFile::StopCompression\n"));
03940 
03941     BOOL Ok = TRUE;
03942 
03943     // Try and close down the system
03944     if (GZFile && GZStream)
03945     {
03946         INT32 RetValue = GZFile->gzclose(GZStream);
03947 
03948         // The close should have removed the GZStream.
03949         // Must set our pointer to NULL overwise there will be problems! 
03950         GZStream = NULL; 
03951 //      TRACEUSER( "JustinF", _T("CCStreamFile::StopCompression gzclose returned %d\n"),RetValue);
03952 
03953         if (RetValue < 0)
03954         {
03955             GZipErrorID = RetValue;
03956             // Work out if we are reading or writing and use the corresponding
03957             // correct error message
03958             UINT32 ErrorID = _R(IDE_ZFILE_READ_ERROR);
03959             if (ModeOfFile & ios::out)      ErrorID = _R(IDE_ZFILE_WRITE_ERROR);
03960             else if (ModeOfFile & ios::in)  ErrorID = _R(IDE_ZFILE_READ_ERROR);
03961             
03962             // Set up a friendly form of the error 
03963             SetZipFileErrorMessage(ErrorID);
03964 
03965             // return the fact to the caller
03966             Ok = FALSE; 
03967         }
03968 
03969         // Now try and clean up our special classes for compressing the file.
03970         if (GZFile)
03971         {
03972             delete GZFile;
03973             GZFile = NULL; 
03974         }
03975     }
03976 
03977     return Ok;
03978 }
03979 
03980 
03981 
03982 /********************************************************************************************
03983 
03984 >   virtual INT32 CCStreamFile::GetCharsRead()
03985 
03986 
03987     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03988     Created:    25/5/95
03989     Purpose:    To make sure the progress bar does not go over the end
03990     SeeAlso:    LexFile::GetCharsRead
03991 
03992 ********************************************************************************************/
03993 INT32 CCStreamFile::GetCharsRead()
03994 {
03995     // This is then used to update the progress bar on EPS import. 
03996     // A progress bar is started with the file size.
03997     // Hence, if we are compressing/decompressing we must not return the true value
03998 
03999     // If not compressing then just do what the lexfile does which is return the
04000     // number of characters read so far.
04001     if (!CompressData) return CharsRead;
04002 
04003     // Return the current position in the file. This must be the present
04004     if (GZFile && GZStream)
04005     {
04006         // Get the file stream class to tell us where it is currently in the compressed file
04007         // Must be the compressed file as the progress bar is started with the actual size of the
04008         // file i.e. compressed size. 
04009         return GZFile->GetCurrentFilePos(GZStream);
04010     }   
04011     else
04012         return (INT32) IOFile->tellg(); 
04013 }
04014 
04015 
04016 
04017 /********************************************************************************************
04018 >   virtual filedesc CCStreamFile::GetFileHandle() const
04019 
04020     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
04021     Created:    17/8/96
04022     Returns:    A "file-handle" for this CCStreamFile.  This is faked for plain iostreams.
04023     SeeAlso:    CCDiskFile::GetFileHandle
04024 ********************************************************************************************/
04025 
04026 filedesc CCStreamFile::GetFileHandle() const
04027 {
04028     return (filedesc) fake_filedesc(*IOFile);
04029 }
04030 
04031 
04032 PORTNOTE("other","Removed OLE stuff")
04033 #ifndef EXCLUDE_FROM_XARALX
04034 #ifndef RALPH
04035 
04043 
04044 
04045 /********************************************************************************************
04046 >   CCOleStream::CCOleStream(IStream* pIStream, UINT32 nBufSize, BOOL fReport, BOOL fThrow)
04047 
04048     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
04049     Created:    17/8/96
04050     Inputs:     pIStream    -   the IStream interface to attach to this CCOleStream.  This
04051                                 will be used for all I/O.
04052     Purpose:    Constructs a CCOleStream attached to the given IStream, or not.
04053 ********************************************************************************************/
04054 
04055 CCOleStream::CCOleStream(IStream* pIStream, UINT32 cbSize, BOOL fReport, BOOL fThrow)
04056   : CCStreamFile(new costream(pIStream), cbSize, fReport, fThrow)
04057 {
04058     // Work out the access mode, if any.
04059 //  TRACEUSER( "JustinF", _T("In CCOleStream::CCOleStream\n"));
04060 //  IOFile = NULL;
04061 
04062     if (isOpen()) GetCoStream().get_access_mode(&ModeOfFile, 0);
04063 }
04064 
04065 
04066 
04067 /********************************************************************************************
04068 >   costream& CCOleStream::GetCoStream()
04069 
04070     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
04071     Created:    9/11/77
04072     Inputs:     -
04073     Purpose:    I don't know why but things seem to be going awire!  Basically, camelot has
04074                 developed a severe BUG; and doing the following:  edit-copy, file-exit;
04075                 causes it to throw a wobobley!  The only thing that I managed to find that
04076                 was responsible for causing this was the inline function
04077                 CCOleStream::GetCoStream().  The original implementation of this function
04078                 should be fine (and had been fine for about four years); but (like most
04079                 things) it seems to have stopped working overnight - in the form of a nasty
04080                 access violation!  Anyway, I've made the function not-inline; and it seems
04081                 to have solved the bug (and the fellow line on 4021).  All I can hazard a
04082                 guess at is that the compiler was getting things wrong !!!!
04083 ********************************************************************************************/
04084 
04085 
04086 costream& CCOleStream::GetCoStream() const
04087 {
04088     return ((costream&) *IOFile);
04089 }
04090 
04091 
04092 
04093 /********************************************************************************************
04094 >   CCOleStream::CCOleStream(PathName path, INT32 fileMode,
04095                              INT32 fileAccess = filebuf::openprot,
04096                              UINT32 bufferSize = CCFILE_DEFAULTSIZE,
04097                              BOOL ErrorReporting = TRUE,
04098                              BOOL ExceptionThrowing = FALSE)
04099     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
04100     Created:    18/8/96
04101     Inputs:     path        -       the non-structured storage file to open.
04102                 fileMode    -       the opening mode, eg. ios::in
04103                 fileAccess  -       the sharing mode, eg. costream::sh_none
04104                   etc
04105     Purpose:    Opens the given "old" file in conversion mode, using the STGM_CONVERT
04106                 access mode.  See the OLE docs for an explanation of this.
04107     SeeAlso:    costream::open_file; STGM_CONVERT; StgCreateDocfile
04108 ********************************************************************************************/
04109 
04110 CCOleStream::CCOleStream(PathName path, INT32 nMode, INT32 nAccess, UINT32 cbSize,
04111                          BOOL fReport, BOOL fThrow)
04112   : CCStreamFile(new costream(path.GetPath(), nMode, nAccess), cbSize, fReport, fThrow)
04113 {
04114 //  TRACEUSER( "JustinF", _T("In CCOleStream::CCOleStream\n"));
04115     ModeOfFile = nMode;
04116 }
04117 
04118 
04119 
04120 /********************************************************************************************
04121 >   virtual BOOL CCOleStream::isOpen() const
04122 
04123     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
04124     Created:    17/8/96
04125     Returns:    TRUE if this CCOleStream is currently open, ie. attached to an IStream.
04126     Purpose:    Returns the status of this file object.
04127 ********************************************************************************************/
04128 
04129 BOOL CCOleStream::isOpen() const
04130 {
04131     // the inline function GetCoStream seems to have been fouling this up ....
04132     // so we are doing this for now ....
04133     
04134     const costream& cs = (const costream&) *IOFile;
04135     return CCStreamFile::isOpen() && cs.is_open();
04136 
04137     // instead of this ....
04138     
04139     //return CCStreamFile::isOpen() && GetCoStream().is_open();
04140 }
04141 
04142 
04143 
04144 /********************************************************************************************
04145 >   virtual BOOL CCOleStream::open_file(PathName path, INT32 fileMode,
04146                                         INT32 fileAccess = filebuf::openprot)
04147     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
04148     Created:    17/8/96
04149     Inputs:     path        -       the non-structured storage file to open.
04150                 fileMode    -       the opening mode, eg. ios::in
04151                 fileAccess  -       the sharing mode, eg. costream::sh_none
04152     Returns:    TRUE if successful, FALSE if something goes wrong.
04153     Purpose:    Opens the given "old" file in conversion mode, using the STGM_CONVERT
04154                 access mode.  See the OLE docs for an explanation of this.
04155     SeeAlso:    costream::open_file; STGM_CONVERT; StgCreateDocfile
04156 ********************************************************************************************/
04157 
04158 BOOL CCOleStream::open_file(PathName path, INT32 fileMode, INT32 fileAccess)
04159 {
04160     // Sanity check.
04161 //  TRACEUSER( "JustinF", _T("In CCOleStream::open_file(%s)\n"), (LPCTSTR) path.GetPath());
04162     ERROR2IF(!path.IsValid(), FALSE, "Invalid PathName in CCOleStream::open_file");
04163     ERROR2IF(!IsInited(), FALSE, "CCOleStream not initiallised in CCOleStream::open_file");
04164 
04165     // Nuke any existing open error states that might exist
04166     IOFile->clear(IOFile->goodbit);
04167 
04168     // If we are not opening this file for writing then set the ios::nocreate
04169     // flag due to a bug in the iostream classes (but not if the ios::out flag is specified
04170     // as well. If this is not set we can not open files on read-only mounts shared by windows 95.
04171     if ((fileMode & ios::in) && !(fileMode & ios::out)) fileMode |= ios::nocreate;
04172 
04173     // Set the sharing mode if the default was passed.
04174     if (fileAccess == filebuf::openprot) fileAccess = costream::sh_read | costream::sh_write;
04175 
04176     // Note the current opening mode.
04177     ModeOfFile = fileMode;
04178 
04179     // Try to open the stream.
04180     if (FAILED(GetCoStream().open_file(path.GetPath(), fileMode | ios::binary, fileAccess)))
04181     {
04182         // TO DO: fix this to be a more appropriate error message.
04183         GotError(_R(IDE_OPEN_ERROR));
04184         return FALSE;
04185     }
04186 
04187     // Success.
04188     return TRUE;
04189 }
04190 
04191 
04192 
04193 /********************************************************************************************
04194 >   virtual BOOL CCOleStream::attach(IStream* pIStream)
04195 
04196     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
04197     Created:    17/8/96
04198     Inputs:     pIStream    -   the IStream interface to connect to this CCOleStream.  This
04199                                 will be used for all subsequent I/O.
04200     Returns:    TRUE if successful, FALSE if not.
04201     Purpose:    Attaches this CCOleStream to the IStream.
04202 ********************************************************************************************/
04203 
04204 BOOL CCOleStream::attach(IStream* pIStream)
04205 {
04206 //  TRACEUSER( "JustinF", _T("In CCOleStream::attach\n"));
04207     return SUCCEEDED(GetCoStream().attach(pIStream));
04208 }
04209 
04210 
04211 
04212 /********************************************************************************************
04213 >   void CCOleStream::close()
04214 
04215     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
04216     Created:    17/8/96
04217     Purpose:    Closes this CCOleStream.  You must call attach with another IStream before
04218                 you perform I/O on it again.
04219     SeeAlso:    CCOleStream::attach
04220 ********************************************************************************************/
04221 
04222 void CCOleStream::close()
04223 {
04224 //  TRACEUSER( "JustinF", _T("In CCOleStream::close\n"));
04225     GetCoStream().close();
04226 }
04227 
04228 
04229 
04230 /********************************************************************************************
04231 >   virtual INT32 CCOleStream::Size()
04232 
04233     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
04234     Created:    17/8/96
04235     Returns:    The size of this IStream, in bytes.
04236 ********************************************************************************************/
04237 
04238 INT32 CCOleStream::Size()
04239 {
04240     // Size of what???
04241     if (!isOpen())
04242     {
04243         ERROR3("CCOleStream::Size called when stream is not open");
04244         return 0;
04245     }
04246     
04247     // Go direct to the IStream for this.
04248     STATSTG statstg;
04249     HRESULT hr = ((IStream*) GetCoStream())->Stat(&statstg, STATFLAG_NONAME);
04250     if (FAILED(hr))
04251     {
04252         ERROR3("CCOleStream::Size failed - why?");
04253         return 0;
04254     }
04255 
04256     // We can only return the lower 31 bits (doh!)
04257     return (INT32) statstg.cbSize.LowPart;
04258 }
04259 
04260 
04261 
04262 /********************************************************************************************
04263 >   virtual BOOL CCOleStream::setMode(INT32)
04264 
04265     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
04266     Created:    17/8/96
04267     Returns:    TRUE
04268     Purpose:    Set this CCOleStream's mode, either text or binary.  Does nothing, as
04269                 CCOleStreams only support binary mode.
04270 ********************************************************************************************/
04271 
04272 BOOL CCOleStream::setMode(INT32)
04273 {
04274     TRACEUSER( "JustinF", _T("CCOleStream::setMode called - is this OK?\n") );
04275     return TRUE;
04276 }
04277 
04278 // WEBSTER-Martin-29/12/96
04279 // no accusoft stuff
04280 #ifndef WEBSTER
04281 
04282 /********************************************************************************************
04283 >   CCOleAccusoftStream::CCOleAccusoftStream(IStream* pIStream = 0,
04284                                              UINT32 bufferSize = CCFILE_DEFAULTSIZE,
04285                                              BOOL ErrorReporting = TRUE,
04286                                              BOOL ExceptionThrowing = FALSE)
04287 
04288     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
04289     Created:    3/10/96
04290     Inputs:     See CCOleStream::CCOleStream.
04291     Purpose:    Like its base class, CCOleStream, but redirects the Accusoft libraries to
04292                 use a different stream as well.
04293     SeeAlso:    CCOleAccusoftStream::~CCOleAccusoftStream
04294 ********************************************************************************************/
04295 
04296 CCOleAccusoftStream::CCOleAccusoftStream(IStream* pIStream, UINT32 bufferSize,
04297                                          BOOL ErrorReporting, BOOL ExceptionThrowing)
04298   : CCOleStream(pIStream, bufferSize, ErrorReporting, ExceptionThrowing)
04299 {
04300 //  TRACEUSER( "JustinF", _T("CCOleAccusoftStream redirecting Accusoft ...\n"));
04301     AccusoftFilters::RedirectStream();
04302 }
04303 
04304 
04305 
04306 /********************************************************************************************
04307 >   CCOleAccusoftStream::CCOleAccusoftStream(PathName path, INT32 fileMode,
04308                                              INT32 fileAccess = filebuf::openprot,
04309                                              UINT32 bufferSize = CCFILE_DEFAULTSIZE,
04310                                              BOOL ErrorReporting = TRUE,
04311                                              BOOL ExceptionThrowing = FALSE)
04312 
04313     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
04314     Created:    3/10/96
04315     Inputs:     See CCOleStream::CCOleStream.
04316     Purpose:    Like its base class, CCOleStream, but redirects the Accusoft libraries to
04317                 use a different stream as well.
04318     SeeAlso:    CCOleAccusoftStream::~CCOleAccusoftStream
04319 ********************************************************************************************/
04320 
04321 CCOleAccusoftStream::CCOleAccusoftStream(PathName path, INT32 nMode, INT32 nAccess,
04322                                          UINT32 cbSize, BOOL fReport, BOOL fThrow)
04323   : CCOleStream(path, nMode, nAccess, cbSize, fReport, fThrow)
04324 {
04325 //  TRACEUSER( "JustinF", _T("CCOleAccusoftStream redirecting Accusoft ...\n"));
04326     AccusoftFilters::RedirectStream();
04327 }
04328 
04329 
04330 
04331 /********************************************************************************************
04332 >   virtual CCOleAccusoftStream::~CCOleAccusoftStream()
04333 
04334 
04335     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
04336     Created:    3/10/96
04337     Purpose:    
04338     SeeAlso:    CCOleAccusoftStream::CCOleAccusoftStream
04339 ********************************************************************************************/
04340 
04341 CCOleAccusoftStream::~CCOleAccusoftStream()
04342 {
04343     AccusoftFilters::UnredirectStream();
04344 //  TRACEUSER( "JustinF", _T("CCOleAccusoftStream un-redirecting Accusoft ...\n"));
04345 }
04346 
04347 #endif // WEBSTER
04348 
04349 #endif // RALPH
04350 
04351 #endif // !wx PORT
04352 
04353 
04354 //-----------------------
04355 /********************************************************************************************
04356 
04357                                         CCDiskFile
04358 
04359 ********************************************************************************************/
04360 //-----------------------
04361 
04362 
04363 
04364 /********************************************************************************************
04365 
04366 >   CCDiskFile::CCDiskFile(UINT32 bufferSize,
04367                            BOOL ErrorReporting = TRUE, BOOL ExceptionThrowing = FALSE)
04368 
04369     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com> (Altered by Neville 01/09/94)
04370     Created:    1/9/93        
04371     Inputs:     bufferSize  - Size of the fixed size buffer (default = 1024)
04372                             - if size > 0 then create a buffer of the specified size
04373                             - if size = 0 then create a file without a buffer
04374                 ReportErrors flag
04375                 ThrowException flag
04376     Purpose:    Default constructor.
04377     SeeAlso:    fstream::setbuf()
04378 
04379 ********************************************************************************************/
04380 
04381 CCDiskFile::CCDiskFile(UINT32 bufferSize,
04382                        BOOL ErrorReporting,
04383                        BOOL ExceptionThrowing)
04384   : CCStreamFile(new fstream, bufferSize, ErrorReporting, ExceptionThrowing)
04385 {
04386 //  TRACEUSER( "JustinF", _T("In CCDiskFile::CCDiskFile\n"));
04387 }
04388 
04389 
04390 /********************************************************************************************
04391 
04392 >   CCDiskFile::CCDiskFile(UINT32 bufferSize,
04393                            BOOL ErrorReporting = TRUE, BOOL ExceptionThrowing = FALSE)
04394 
04395     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com> (Altered by Neville 01/09/94)
04396     Created:    1/9/93        
04397     Inputs:     bufferSize  - Size of the fixed size buffer (default = 1024)
04398                             - if size > 0 then create a buffer of the specified size
04399                             - if size = 0 then create a file without a buffer
04400                 ReportErrors flag
04401                 ThrowException flag
04402     Purpose:    Default constructor.
04403     SeeAlso:    fstream::setbuf()
04404 
04405 ********************************************************************************************/
04406 
04407 CCDiskFile::CCDiskFile(fstream *pfstream,
04408                        UINT32 bufferSize,
04409                        BOOL ErrorReporting,
04410                        BOOL ExceptionThrowing)
04411   : CCStreamFile(pfstream, bufferSize, ErrorReporting, ExceptionThrowing)
04412 {                      
04413     // Empty.
04414 }
04415 
04416 /********************************************************************************************
04417 
04418 >   CCDiskFile(PathName fPath, INT32 fileMode, 
04419                INT32 fileAccess  = filebuf::openprot,
04420                UINT32 bufferSize = CCFILE_DEFAULTSIZE
04421                BOOL ErrorReporting = TRUE, BOOL ExceptionThrowing = FALSE);
04422 
04423     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>       (Altered by Neville 01/09/94)
04424     Created:    1/9/93
04425     Inputs:     fPath       - PathName for file to be opened
04426                 fileMode    - Mode in which file is to be opened - use ios flags  
04427                 fileAccess  - file access flag(s) as specified by the filebuf flags
04428                 bufferSize  - Size of the fixed size buffer (default = 1024)
04429                             - if size > 0 then create a buffer of the specified size
04430                             - if size = 0 then create a file without a buffer
04431                 ReportErrors flag
04432                 ThrowExceptions flag
04433     Purpose:    Constructs a CCDiskFile object and opens the file specified by the Path over it.
04434     SeeAlso:    fstream::setbuf()
04435     SeeAlso:    fstream::open()                  
04436     
04437 ********************************************************************************************/
04438 
04439 CCDiskFile::CCDiskFile(fstream *pfstream,
04440                        PathName fPath, 
04441                        INT32 fileMode, 
04442                        INT32,
04443                        UINT32 bufferSize,
04444                        BOOL ErrorReporting,
04445                        BOOL ExceptionThrowing)
04446   : CCStreamFile(pfstream, bufferSize, ErrorReporting, ExceptionThrowing)
04447 {
04448     // Set up Path name
04449     filePath = fPath;
04450     ModeOfFile = fileMode;  // note current state
04451 
04452     // Check if the base class setup OK.
04453     if (!IsInited()) return;
04454    
04455     // Open the file 
04456 #if 0 != wxUSE_UNICODE
04457     {
04458         size_t          cch = camWcstombs( NULL, (const TCHAR *)filePath.GetPath(), 0 ) + 1;
04459         PSTR            pszFileName = PSTR( alloca( cch ) );
04460         camWcstombs( pszFileName, (const TCHAR *)filePath.GetPath(), cch );
04461         GetFileStream().open( pszFileName, ios_base::openmode(fileMode) );
04462     }
04463 #else
04464     GetFileStream().open( filePath.GetPath(), ios_base::openmode(fileMode) );
04465 #endif
04466 
04467     // If file not opened properly report error
04468     if (IOFile->fail() || !GetFileStream().is_open())
04469     {
04470         String_256 ErrorMsg(_R(IDE_OPEN_ERROR));
04471         ErrorMsg += filePath.GetFileName(); 
04472         GotError(_R(IDE_OPEN_ERROR), ErrorMsg);
04473         StreamFileInitialised = FALSE;
04474     }
04475 }
04476 
04477 
04478 
04479 
04480 /********************************************************************************************
04481 
04482 >   CCDiskFile(PathName fPath, INT32 fileMode, 
04483                INT32 fileAccess  = filebuf::openprot,
04484                UINT32 bufferSize = CCFILE_DEFAULTSIZE
04485                BOOL ErrorReporting = TRUE, BOOL ExceptionThrowing = FALSE);
04486 
04487     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>       (Altered by Neville 01/09/94)
04488     Created:    1/9/93
04489     Inputs:     fPath       - PathName for file to be opened
04490                 fileMode    - Mode in which file is to be opened - use ios flags  
04491                 fileAccess  - file access flag(s) as specified by the filebuf flags
04492                 bufferSize  - Size of the fixed size buffer (default = 1024)
04493                             - if size > 0 then create a buffer of the specified size
04494                             - if size = 0 then create a file without a buffer
04495                 ReportErrors flag
04496                 ThrowExceptions flag
04497     Purpose:    Constructs a CCDiskFile object and opens the file specified by the Path over it.
04498     SeeAlso:    fstream::setbuf()
04499     SeeAlso:    fstream::open()                  
04500     
04501 ********************************************************************************************/
04502 
04503 CCDiskFile::CCDiskFile(PathName fPath, 
04504                        INT32 fileMode, 
04505                        INT32,
04506                        UINT32 bufferSize,
04507                        BOOL ErrorReporting,
04508                        BOOL ExceptionThrowing)
04509   : CCStreamFile(new fstream, bufferSize, ErrorReporting, ExceptionThrowing)
04510 {
04511     // Set up Path name
04512 //  TRACEUSER( "JustinF", _T("In CCDiskFile::CCDiskFile\n"));
04513     filePath = fPath;
04514     ModeOfFile = fileMode;  // note current state
04515 
04516     // Check if the base class setup OK.
04517     if (!IsInited()) return;
04518    
04519     // Open the file 
04520 #if 0 != wxUSE_UNICODE
04521     {
04522         size_t          cch = camWcstombs( NULL, (const TCHAR *)filePath.GetPath(), 0 ) + 1;
04523         PSTR            pszFileName = PSTR( alloca( cch ) );
04524         camWcstombs( pszFileName, (const TCHAR *)filePath.GetPath(), cch );
04525         GetFileStream().open( pszFileName, ios_base::openmode(fileMode) );
04526     }
04527 #else
04528     GetFileStream().open( filePath.GetPath(), ios_base::openmode(fileMode) );
04529 #endif
04530 
04531     // If file not opened properly report error
04532     if (IOFile->fail() || !GetFileStream().is_open())
04533     {
04534         GotError(_R(IDE_OPEN_ERROR));
04535         StreamFileInitialised = FALSE;
04536     }
04537 }
04538 
04539 
04540 
04541 /********************************************************************************************
04542 >   BOOL CCDiskFile::open(PathName fPath, INT32 fileMode, INT32 fileAccess = filebuf::openprot)
04543 
04544     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
04545     Created:    1/9/93
04546     Inputs:     fPath       - PathName for file to be opened
04547                 fileMode    - Mode in which file is to be opened - use ios flags  
04548                 fileAccess  - file access flag(s) as specified by the filebuf flags
04549     Returns:    TRUE if file is opened ok or FALSE otherwize
04550     Purpose:    opens file specified by the path.
04551     SeeAlso:    fstream::open()
04552 
04553     Note:       It would appear that calling this with ios::in | ios::out | ios::binary on
04554                 NT on an existing file truncates the file, whereas on Windows 95 it does
04555                 not truncate the file. Exporting bitmap and eps files was failing as the
04556                 data was appended to the end of the file on Windows 95.
04557                 OpMenuExport::DoWithParam fixed by adding a ios::trunc to the open call.
04558 
04559 ********************************************************************************************/
04560 
04561 BOOL CCDiskFile::open( PathName fPath, INT32 fileMode, INT32 )
04562 {
04563     // First check that the constructor went ok
04564     if (!StreamFileInitialised)
04565     {
04566         // Did not construct ok, error should have been reported, so just fail
04567         return FALSE;
04568     }
04569 
04570     // Nuke any existing open error states that might exist
04571     IOFile->clear(IOFile->goodbit);
04572 
04573     // If we are not opening this file for writing then set the ios::nocreate
04574     // flag due to a bug in the iostream classes (but not if the ios::out flag is specified
04575     // as well. If this is not set we can not open files on read-only mounts shared by windows 95.
04576 //  if ((fileMode & ios::in) && !(fileMode & ios::out)) fileMode |= ios::nocreate;
04577 
04578     // Set up file pathname
04579     filePath = fPath;
04580     ModeOfFile = fileMode;  // note current state
04581 
04582     // Open file
04583 #if 0 != wxUSE_UNICODE
04584     {
04585         size_t          cch = camWcstombs( NULL, (const TCHAR *)filePath.GetPath(), 0 ) + 1;
04586         PSTR            pszFileName = PSTR( alloca( cch ) );
04587         camWcstombs( pszFileName, (const TCHAR *)filePath.GetPath(), cch );
04588         GetFileStream().open( pszFileName, ios_base::openmode(fileMode) );
04589     }
04590 #else
04591     GetFileStream().open( filePath.GetPath(), ios_base::openmode(fileMode) );
04592 #endif
04593     
04594     // If error on opening file report it!
04595     if (IOFile->fail() || !GetFileStream().is_open())
04596     {
04597         GotError(_R(IDE_OPEN_ERROR));
04598         return FALSE;
04599     }
04600 
04601     return TRUE;
04602 }
04603 
04604 
04605 
04606 /********************************************************************************************
04607 
04608 >   void CCDiskFile::close()
04609 
04610 
04611     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
04612     Created:    1/9/93
04613     Purpose:    To close the file
04614     SeeAlso:    fstream::close()
04615 
04616 ********************************************************************************************/
04617 
04618 void CCDiskFile::close()
04619 {
04620     GetFileStream().close();
04621 }
04622 
04623 
04624 
04625 /********************************************************************************************
04626 
04627 >   BOOL CCDiskFile::setMode(INT32 fileMode)
04628 
04629     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
04630     Created:    1/9/93
04631     Inputs:     fileMode    - Text or Binary (default is text)  
04632     Returns:    TRUE if the mode has changed and FALSE otherwize.
04633     Purpose:    Changes the file's mode from text\binary.
04634     SeeAlso:    fstream::setmode()
04635 
04636 ********************************************************************************************/
04637 
04638 BOOL CCDiskFile::setMode(INT32 fileMode)
04639 {
04640     // This might cause problems in compressed mode so error if called in this mode
04641     ERROR3IF(CompressData, "DiskFile set mode called when compressed");
04642 
04643 PORTNOTE("other","ios::setmode not suppport anymore")
04644 #ifndef EXCLUDE_FROM_XARALX
04645     return GetFileStream().setmode(fileMode) >= 0;
04646 #else
04647     return true;
04648 #endif
04649 }
04650 
04651 
04652     
04653 /********************************************************************************************
04654 
04655 >   BOOL CCDiskFile::isOpen() const
04656 
04657     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
04658     Created:    2/9/93
04659     Returns:    TRUE if file is open and FALSE otherwize.
04660     Purpose:    Determines whether file is open
04661     SeeAlso:    fstream::is_open()
04662 
04663 ********************************************************************************************/
04664 
04665 BOOL CCDiskFile::isOpen() const
04666 {
04667     return CCStreamFile::isOpen() && const_cast<std::fstream &>(GetFileStream()).is_open();
04668 }
04669 
04670 
04671 
04672 /********************************************************************************************
04673 
04674 >   BOOL CCDiskFile::GetName( StringBase* name) const
04675 
04676     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04677     Created:    22/09/94
04678     Inputs:     Pointer to a CCFile name 
04679     Outputs:    None
04680     Returns:    True if a name has been set otherwise False. At present always returns False.
04681     Purpose:    Given a CCDiskFile*, you can ask for some sort of name which is associated with
04682                 that file. For filenames it might be a filename, or a pathname, for resource
04683                 files it might be "Default Bitmap" etc. These names could then be used for
04684                 making error messages have some extra useful information in.
04685     Errors:     None    
04686 
04687 ********************************************************************************************/
04688 
04689 BOOL CCDiskFile::GetName( StringBase* name) const
04690 {
04691     // Work out how much space we have
04692     INT32 MaxLen = name->MaxLength();
04693 
04694     filePath.GetPath();
04695 
04696     // Now fit our name into this space
04697     String_256 Pathname = filePath.GetPath();
04698     if (MaxLen < Pathname.Length())
04699     {
04700         // Use just the filename
04701         Pathname = filePath.GetFileName();
04702 
04703         // If it is still too long, turn it into the form "...ffff.ext", i.e. have an
04704         // ellipsis followed by as much of the filename as we can fit into the string.
04705         // (We use the last segment of the filename, i.e. we throw away characters from
04706         // the beginning).
04707         INT32 FilenameLen = Pathname.Length();
04708         if (MaxLen < FilenameLen)
04709         {
04710             // Shuffle pathname down to fit into buffer
04711             Pathname.Remove(0, FilenameLen - MaxLen);
04712 
04713             // Put the ellipsis at the front
04714             TCHAR *Buf = (TCHAR *) Pathname;
04715             Buf[0] = '.';
04716             Buf[1] = '.';
04717             Buf[2] = '.';
04718         }
04719     }
04720 
04721     // Copy into output parameter
04722     *name = Pathname;
04723 
04724     // Successful
04725     return TRUE;
04726 }
04727 
04728 
04729 
04730 /********************************************************************************************
04731 
04732 >   virtual PathName CCDiskFile::GetPathName() const
04733 
04734     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
04735     Created:    1/2/95
04736     Returns:    The pathname we have associated with the CCDiskFile
04737     Purpose:    To find out the name of the file
04738 
04739 ********************************************************************************************/
04740 
04741 PathName CCDiskFile::GetPathName() const
04742 {
04743     return filePath;
04744 }
04745 
04746 
04747 
04748 /********************************************************************************************
04749 
04750 >   filedesc CCDiskFile::GetFileHandle( ) 
04751 
04752     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04753     Created:    22/09/94
04754     Inputs:     None 
04755     Outputs:    None
04756     Returns:    The file handle (descriptor) for this file (really an INT32).
04757     Purpose:    Given an instance of a CCDiskFile, you can ask for the actual file handle
04758                 that describes the associated file. Required for the external filters. 
04759     Errors:     None    
04760 
04761 ********************************************************************************************/
04762 // defined in winoil\filehndl.cpp
04763 
04764 //filedesc CCDiskFile::GetFileHandle() const 
04765 //{ 
04766 //  // Need to convert this into a real file handle rather than the descriptor.
04767 //  // At present there seems to be no legal way of doing this.
04768 //  return _get_osfhandle(IOFile.fd());
04769 //}
04770 
04771 
04772 
04773 //-----------------------
04774 /********************************************************************************************
04775 
04776                                         CCMemFile
04777 
04778 ********************************************************************************************/
04779 //-----------------------
04780 
04781 
04782 /********************************************************************************************
04783 
04784 >   CCMemFile::CCMemFile(BOOL ErrorReporting = TRUE, BOOL ExceptionThrowing = FALSE)
04785 
04786     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04787     Inputs:     ReportErrors flag
04788                 ThrowExceptions flag
04789     Created:    1/9/94
04790     Purpose:    Constructs an instance of CCMemFile.
04791 
04792 ********************************************************************************************/
04793 
04794 CCMemFile::CCMemFile(BOOL ErrorReporting, BOOL ExceptionThrowing)
04795 {
04796     // Set our class variables from the passed in values
04797     ReportErrors = ErrorReporting;
04798     ThrowExceptions = ExceptionThrowing;
04799     WasError = FALSE;
04800     MemFileInitialised = TRUE;
04801 
04802     // Better set these up too or an unused object crashes on destuction
04803     MemHandle = BAD_MHANDLE;
04804     MemFile = NULL;
04805     FileSize = 0;
04806     CurrentPos = 0;
04807     IsOpen = FALSE;
04808     FileProt = CCMemRead;
04809 }
04810 
04811 
04812 /********************************************************************************************
04813 
04814 >   CCMemFile::CCMemFile(void *pFile, UINT32 size, FileAccess fProt,
04815                          BOOL ErrorReporting = TRUE, BOOL ExceptionThrowing = FALSE)
04816 
04817     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
04818     Inputs:     pFile - a pointer to the file
04819                 UINT32 - the size of the file
04820                 FileAccess - read or write access 
04821                 ReportErrors flag
04822                 ThrowExceptions flag
04823     Created:    6/9/93
04824     Purpose:    Constructs an instance of CCMemFile and Opens it
04825 
04826 ********************************************************************************************/
04827 
04828 CCMemFile::CCMemFile(void *pFile, UINT32 size, FileAccess fProt,
04829                      BOOL ErrorReporting, BOOL ExceptionThrowing)
04830 {
04831     // First, set up our initialised flag to False
04832     MemFileInitialised = FALSE;
04833     WasError = FALSE;
04834 
04835     // Set our class variables from the passed in values
04836     ReportErrors = ErrorReporting;
04837     ThrowExceptions = ExceptionThrowing;
04838 
04839     FileProt = fProt;
04840 
04841     IsOpen = FALSE;
04842 
04843     // If file is opened for reading
04844     if (FileProt == CCMemRead) 
04845     {
04846         // Is file pointer NULL?
04847         if (pFile == NULL)
04848         {
04849             // Yes; report error.
04850             IsOpen = FALSE;
04851             GotError(_R(IDE_NULL_FILE));
04852             return;
04853         }             
04854         
04855         MemHandle   = BAD_MHANDLE;
04856         MemFile     = (BYTE*) pFile;            // Set Memory file pointer
04857         CurrentPos  = 0;                        // Set Current file position        
04858         
04859         // Check that file size is greater than zero
04860         if (size > 0)
04861         {
04862             FileSize    = size;
04863             // Flag that everything has gone ok
04864             MemFileInitialised = TRUE;
04865         }
04866         else
04867         {
04868             IsOpen  = FALSE;
04869             GotError(_R(IDE_FILE_SIZE_ZERO));
04870             return;
04871         }
04872  
04873         IsOpen = TRUE;
04874     }
04875 
04876     // if file is open for writing  
04877     else if (FileProt == CCMemWrite)
04878     {                             
04879         // check file size 
04880         if (size > 0)
04881             FileSize = size;                    // if not zero use size passed in
04882         else
04883             FileSize = CCFILE_DEFAULTSIZE;              // else used default size
04884             
04885         //Allocate Memory 
04886         MemHandle = ClaimBlock(FileSize);
04887         
04888         // Check allocation worked ok
04889         if (MemHandle != BAD_MHANDLE)
04890         {
04891             IsOpen      = TRUE;
04892             CurrentPos  = 0;
04893             // Flag that everything has gone ok
04894             MemFileInitialised = TRUE;
04895         }
04896         else
04897         {
04898             IsOpen  = FALSE;
04899             GotError(_R(IDE_MEM_BLOCK_FAILURE));
04900             return;
04901         } 
04902     }
04903 }
04904 
04905 /********************************************************************************************
04906 
04907 >   CCMemFile::~CCMemFile()
04908 
04909     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
04910     Created:    6/9/93        
04911     Purpose:    Default destructor.
04912 
04913 ********************************************************************************************/
04914 
04915 CCMemFile::~CCMemFile()
04916 {                   
04917     if(isOpen())
04918     {
04919         // report error that file is not closed before destructor call
04920         GotError(_R(IDE_MEM_CLOSE_ERROR));
04921 
04922         // Release any memory block we might have
04923         if (MemHandle != BAD_MHANDLE)
04924         {
04925             ReleaseBlock(MemHandle);
04926             MemHandle = BAD_MHANDLE;
04927         }
04928     }
04929 }
04930 
04931 /********************************************************************************************
04932 
04933 >   BOOL CCMemFile::IsMemFileInited()
04934 
04935     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04936     Created:    1/9/94
04937     Inputs:     None
04938     Returns:    TRUE if the contructor went without errors or FALSE otherwise.
04939     Purpose:    Allows errors to be returned from the constructor.
04940     SeeAlso:    CCMemFile
04941 
04942 ********************************************************************************************/
04943 
04944 BOOL CCMemFile::IsMemFileInited()
04945 {
04946     return MemFileInitialised;
04947 }
04948 
04949 
04950 BOOL CCMemFile::GetBuffer(BYTE** ppBuffer, UINT32* pSize)
04951 {
04952     if (!MemFileInitialised)
04953         return(FALSE);
04954 
04955     BYTE* tempBuf = NULL;
04956     size_t tempSize = 0;
04957     
04958     // Get Pointer to the memory file
04959     if (!DescribeBlock(MemHandle, &tempBuf, &tempSize))
04960     {
04961         GotError(_R(IDE_MEM_BLOCK_FAILURE));
04962         return FALSE;
04963     } 
04964 
04965     *ppBuffer = tempBuf;
04966     *pSize = (UINT32)tempSize;
04967 
04968     return(TRUE);
04969 }
04970 
04971 
04972 /********************************************************************************************
04973 
04974 >   BOOL CCMemFile::open(void *pFile, UINT32 size, FileAccess fProt)
04975 
04976     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
04977     Created:    6/9/93
04978     Inputs:     pFile - a pointer to the file
04979                 UINT32 - the size of the file
04980                 fProt - defines the files protection - default = read only
04981     Returns:    TRUE if file is opened successfully or FALSE otherwize
04982     Purpose:    Opens an instance of a CCmemFile
04983 
04984 ********************************************************************************************/
04985 
04986 BOOL CCMemFile::open(void *pFile, UINT32 size, FileAccess fProt)
04987 {
04988     // First check that the constructor went ok
04989     if (!MemFileInitialised)
04990     {
04991         // Did not construct ok, error should have been reported, so just fail
04992             IsOpen  = FALSE;
04993             return FALSE;
04994     }
04995 
04996     FileProt    = fProt;
04997 
04998     // If file is opened for reading
04999     if (FileProt == CCMemRead) 
05000     {
05001         // Is file pointer NULL
05002         if (!pFile)
05003         {
05004             IsOpen  = FALSE;
05005             GotError(_R(IDE_NULL_FILE));
05006             return FALSE;
05007         }             
05008         
05009         MemFile     = (BYTE*) pFile;            // Set Memory file pointer
05010         CurrentPos  = 0;                        // Set Current file position        
05011         
05012         // Check that file size is greater than zero
05013         if (size > 0)
05014             FileSize    = size;
05015         else
05016         {
05017             IsOpen  = FALSE;
05018             GotError(_R(IDE_FILE_SIZE_ZERO));
05019             return FALSE;
05020         }
05021     }
05022     // if file is open for writing  
05023     else if (FileProt == CCMemWrite)
05024     {                             
05025         // check file size 
05026         if (size > 0)
05027             FileSize = size;                    // if not zero use size passed in
05028         else
05029             FileSize = CCFILE_DEFAULTSIZE;              // else used default size
05030             
05031         // Allocate Memory 
05032         MemHandle = ClaimBlock(FileSize);
05033         
05034         // Check allocation worked ok
05035         if (MemHandle != BAD_MHANDLE)
05036         {
05037             IsOpen      = TRUE;
05038             CurrentPos  = 0;
05039         }
05040         else
05041         {
05042             IsOpen  = FALSE;
05043             GotError(_R(IDE_MEM_BLOCK_FAILURE));
05044             return FALSE;
05045         } 
05046     }
05047         
05048     return IsOpen;
05049 }
05050 
05051 
05052 
05053 /********************************************************************************************
05054 
05055 >   BOOL CCMemFile::GrowMemFile()
05056 
05057     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
05058     Created:    13/9/93
05059     Return:     TRUE if size can be increased otherwize FALSE 
05060     Purpose:    
05061         Will increase the size of the memory file by allocating more space in blocks 1k.
05062         This function is called by all the write functions when the file size limit is 
05063         reached. 
05064     Scope:      Private 
05065 
05066 ********************************************************************************************/
05067 
05068 BOOL CCMemFile::GrowMemFile()
05069 {
05070     if (IncreaseBlock(MemHandle, CCFILE_DEFAULTSIZE))   //SplitBlock(MemHandle, CCFILE_DEFAULTSIZE, (FileSize  - 1)))
05071     {
05072         FileSize += CCFILE_DEFAULTSIZE;
05073         return TRUE;
05074     }
05075     else
05076     {               
05077         IsOpen  = FALSE;
05078         GotError(_R(IDE_MEM_BLOCK_FAILURE));
05079         return FALSE;
05080     }
05081 }
05082 
05083 /********************************************************************************************
05084 
05085 >   BOOL CCMemFile::setMode(INT32 fileMode)
05086 
05087     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
05088     Created:    31/03/94
05089     Purpose:    None- cannot change the mode on a memory file - either it's binary in
05090                 which case it's a CCMemFile, or it's text, in which case it's a 
05091                 CCMemTextFile.
05092     SeeAlso:    CCFile::setMode
05093 
05094 ********************************************************************************************/
05095 
05096 BOOL CCMemFile::setMode(INT32 fileMode)
05097 {
05098     ENSURE(FALSE, "Should use CCMemFile or CCMemTextFile to set the file mode!");
05099     return FALSE;
05100 }
05101 
05102 
05103 /********************************************************************************************
05104 
05105 >   BOOL CCMemFile::isOpen() const
05106 
05107     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
05108     Created:    6/9/93
05109     Return:     TRUE if file is open and FALSE otherwize
05110     Purpose:    Determines whether an instance of CCMemFile is open
05111 
05112 ********************************************************************************************/
05113 
05114 BOOL CCMemFile::isOpen() const
05115 {
05116     return IsOpen;
05117 }
05118 
05119 /********************************************************************************************
05120 
05121 >   CCFile& CCMemFile::read(void* buf, UINT32 length = 1)
05122 
05123     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
05124     Created:    6/9/93
05125     Outputs:    A pointer to a single byte
05126     Returns:    Reference to the CCFile object.
05127     Purpose:    Reads a single byte from the Memory file 
05128 
05129 ********************************************************************************************/
05130 
05131 CCFile& CCMemFile::read(void* buf, UINT32 length)
05132 {
05133     // Make sure the file is open before it is read!
05134     if (!isOpen())
05135     {
05136         GotError(_R(IDE_NOTOPEN_ERROR));
05137         return (CCFile&) *this;
05138     }
05139 
05140     // If not allowed to read, then exit.
05141     if (FileProt != CCMemRead)
05142     {
05143         GotError(_R(IDE_WRITE_ONLY));
05144         return (CCFile&) *this;
05145     }
05146     
05147     BYTE *TempBuf = (BYTE*) buf;
05148     
05149     while ((length > 0) && !eof())
05150     {
05151         *TempBuf++ = MemFile[CurrentPos++];
05152         length--;
05153     }
05154 
05155     if (length > 0)
05156     {
05157         // Could not read the required number of bytes.
05158         GotError(_R(IDE_EOF_ERROR));
05159     }
05160 
05161     return (CCFile&) *this;
05162 }
05163 
05164 CCFile& CCMemFile::read(StringBase *buf)
05165 {
05166     ENSURE(FALSE, "Use a CCMemTextFile for ASCII memory files!");
05167     return (CCFile&) *this;
05168 }
05169 
05170 CCFile &CCMemFile::read( char &buf )
05171 {
05172     // Make sure the file is open before it is read!
05173     if (!isOpen())
05174     {
05175         GotError(_R(IDE_NOTOPEN_ERROR));
05176         return *this;
05177     }
05178 
05179     // if file is write protected then exit
05180     if (FileProt != CCMemRead)
05181     {
05182         GotError(_R(IDE_WRITE_ONLY));
05183         return *this;
05184     }
05185     
05186     TCHAR* tempMemFile  = (TCHAR*) MemFile;         // Cast MemFile to a TCHAR pointer
05187 
05188     if (!eof())
05189     {
05190         buf = tempMemFile[CurrentPos++];
05191         CharsRead ++;
05192     }
05193     else
05194     {
05195         // Trying to read pasty EOF
05196         GotError(_R(IDE_EOF_ERROR));
05197     }
05198 
05199     return *this;
05200 }
05201 
05202 
05203 /********************************************************************************************
05204 
05205 >   CCFile& CCMemFile::write(const void* buf, UINT32 length = 1)
05206 
05207     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
05208     Created:    6/9/93
05209     Inputs:     A pointer to a single byte
05210                 Length denotes number of bytes to written 
05211     Returns:    Reference to the CCFile object.
05212     Purpose:    Writes a stream of bytes to the Memory file 
05213 
05214 ********************************************************************************************/
05215 
05216 CCFile& CCMemFile::write(const void* buf, UINT32 length)
05217 {                                      
05218     // Make sure the file is open before it is written!
05219     if (!isOpen())
05220     {
05221         GotError(_R(IDE_NOTOPEN_ERROR));
05222         return (CCFile&) *this;
05223     }
05224 
05225     // if file is read only then exit
05226     if (FileProt != CCMemWrite)
05227     {
05228         GotError(_R(IDE_READ_ONLY));
05229         return (CCFile&) *this;
05230     }
05231     
05232     BYTE* tempBuf = (BYTE*) buf;
05233     
05234     // Get Pointer to the memory file
05235     if (!DescribeBlock(MemHandle, &MemFile, &FileSize))
05236     {
05237         GotError(_R(IDE_MEM_BLOCK_FAILURE));
05238         return (CCFile&) *this;
05239     } 
05240 
05241     while (length > 0)
05242     {
05243         if (eof())
05244         {
05245             if (GrowMemFile())
05246             {
05247                 // Get Pointer to the memory file
05248                 if (!DescribeBlock(MemHandle, &MemFile, &FileSize))
05249                 {
05250                     GotError(_R(IDE_MEM_BLOCK_FAILURE));
05251                     return (CCFile&) *this;
05252                 }
05253             }
05254             else
05255                 // Can't increase memfile - error
05256                 break;
05257         }
05258 
05259         // Write input byte
05260         MemFile[CurrentPos++] = *tempBuf++;
05261         length--;
05262     }
05263     
05264     return (CCFile&) *this;
05265 }
05266 
05267 CCFile& CCMemFile::write(const StringBase& buf, UINT32 length)
05268 {
05269     ENSURE(FALSE, "Use a CCMemTextFile for ASCII memory files!");
05270     return (CCFile&) *this;
05271 }
05272 
05273 CCFile &CCMemFile::write( char &buf )
05274 {
05275     ENSURE(FALSE, "Use a CCMemTextFile for ASCII memory files!");
05276     return (CCFile&) *this;
05277 }
05278 
05279 /********************************************************************************************
05280 
05281 >   CCFile& CCMemFile::seek(FilePos pos)
05282 
05283     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
05284     Created:    6/9/93
05285     Returns:    Reference to the CCFile object.
05286     Purpose:
05287         Sets the file pointer to the file position passed in. (Position zero is the 
05288         beginning of the file)
05289 
05290 ********************************************************************************************/
05291 
05292 CCFile& CCMemFile::seek(FilePos pos)
05293 {
05294     if(!isOpen())
05295     {
05296         GotError(_R(IDE_NOTOPEN_ERROR));
05297         return (CCFile&) *this;
05298     }
05299     
05300     if (pos <= (FilePos)(FileSize))
05301     {
05302         CurrentPos = pos;
05303 
05304         // There were 1001 problems with memfile seeking / telling, the below sorts them out though
05305         if(IsLexerInitialised() && SeekingRequired)
05306         {
05307             Ch = 0;
05308             Ofs = 0;
05309             LastLinePos = pos;
05310             TokenBuf[0] = 0;
05311             Line = 0;
05312             CharsRead = 0;
05313             LastLinePos = pos;
05314             EOFFound = FALSE;
05315 
05316             // Fill up the buffers with the new chars           
05317             GetLine();
05318             //GetCh();
05319         }
05320     }
05321     else
05322     {
05323         GotError(_R(IDE_FILEPOS_ERROR));
05324         return (CCFile&) *this;
05325     }
05326 
05327     return (CCFile&) *this;
05328 }
05329 
05330 /********************************************************************************************
05331 
05332 >   FilePos CCMemFile::tell()
05333 
05334     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
05335     Created:    6/9/93
05336     Return:     current file pointer position
05337     Purpose:    Gets the file pointer  position of the file. 
05338 
05339 ********************************************************************************************/
05340 
05341 FilePos CCMemFile::tell()
05342 {
05343     return CurrentPos;
05344 }
05345 
05346 /********************************************************************************************
05347 
05348 >   CCFile& CCMemFile::seekIn(FilePos Pos)
05349 
05350     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
05351     Created:    31/03/94
05352     Inputs:     Pos - the desired file position.
05353     Returns:    Reference to the CCFile object.
05354     Purpose:    Alter position of the file input pointer.  NB. input and output
05355                 pointers are linked with CCMemFiles, so you will alter the output
05356                 pointer too.
05357 
05358 ********************************************************************************************/
05359 
05360 CCFile& CCMemFile::seekIn(FilePos Pos)
05361 {
05362     return seek(Pos);
05363 }
05364 
05365 
05366 
05367 /********************************************************************************************
05368 
05369 >   CCFile& CCMemFile::seekIn(INT32 Offset, ios::seek_dir Dir)
05370 
05371     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
05372     Created:    16/05/95
05373     Inputs:     Offset - the file offset required.
05374                 Dir - the offset mode to use.
05375     Outputs:    -
05376     Returns:    Reference to the CCFile object.
05377     Purpose:    Alter position of the file input pointer.  NB. input and output
05378                 pointers are linked with CCMemFiles, so you will alter the output
05379                 pointer too.
05380 
05381 ********************************************************************************************/
05382 
05383 CCFile& CCMemFile::seekIn(INT32 Offset, ios::seekdir Dir)
05384 {
05385     switch(Dir)
05386     {
05387         case ios::beg:
05388             return(seek(Offset));
05389 
05390         case ios::cur:
05391             return(seek(tell() + Offset));
05392 
05393         case ios::end:
05394             {
05395                 FilePos NewPos = (FilePos)(FileSize - Offset);
05396                 if (NewPos < 0)
05397                 {
05398                     ERROR3("Attempt to seek before beginning of file using seekIn with ios::end");
05399                     NewPos = 0;
05400                 }
05401                 return(seek(NewPos));
05402             }
05403         default:
05404             break; // fall through
05405     }
05406 
05407     ERROR3("Illegal seekIn seek_dir value (CCMemFile::seekIn)");
05408     return (CCFile&) *this;
05409 }
05410 
05411 
05412 
05413 /********************************************************************************************
05414 
05415 >   FilePos CCMemFile::tellIn()
05416 
05417     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
05418     Created:    31/03/94
05419     Returns:    File position.
05420     Purpose:    Return the position of the file input pointer.
05421 
05422 ********************************************************************************************/
05423 
05424 FilePos CCMemFile::tellIn()
05425 {
05426     if(IsLexerInitialised())
05427     {
05428         if(!SeekingRequired)
05429             ERROR3("CCMemFile::tellIn() will only work properly with seeking enabled");
05430 
05431         // -1 for the character lookahead in operation
05432         return (FilePos)(Ofs + (INT32) LastLinePos - 1);
05433     }
05434 
05435     return tell();
05436 }
05437 
05438 
05439 /********************************************************************************************
05440 
05441 >   virtual INT32 CCMemFile::Size()
05442 
05443     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
05444     Created:    31/03/94
05445     Returns:    Size in bytes of the file.
05446     Purpose:    Find the size of the file.
05447 
05448 ********************************************************************************************/
05449 
05450 size_t CCMemFile::Size()
05451 {
05452     return FileSize;
05453 }
05454 
05455 
05456 /********************************************************************************************
05457 
05458 >   BOOL CCMemFile::eof()
05459 
05460     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com> (fixed by Andy)
05461     Created:    6/9/93
05462     Return:     TRUE if end of file and FALSE otherwize
05463     Purpose:    Determines whether an instance of CCMemFile is open
05464 
05465 ********************************************************************************************/
05466 
05467 BOOL CCMemFile::eof() const
05468 {
05469     return (CurrentPos >= FileSize);
05470 }
05471 
05472 BOOL CCMemFile::good() const
05473 {
05474     return !WasError;
05475 }
05476 
05477 BOOL CCMemFile::bad() const
05478 {
05479     return WasError;
05480 }
05481 
05482 BOOL CCMemFile::fail() const
05483 {
05484     return WasError;
05485 }
05486 
05487 /********************************************************************************************
05488 
05489 >   BOOL CCMemFile::SetBadState()
05490 
05491     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
05492     Created:    31/08/94
05493     Returns:    None.
05494     Purpose:    It allows the forceable setting of the test that functions like bad() use
05495                 so the next check of the current file status to see if we should continue
05496                 using the file or not will fail. This will be called by the GotError function
05497                 so that any attempts to read/write after this should fail.
05498     SeeAlso:    CCFile::GotError
05499 
05500 ********************************************************************************************/
05501 
05502 void CCMemFile::SetBadState()
05503 {
05504     WasError = TRUE;
05505 }
05506 
05507 /********************************************************************************************
05508 
05509 >   BOOL CCMemFile::SetGoodState()
05510 
05511     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
05512     Created:    8/12/94
05513     Returns:    None.
05514     Purpose:    It allows the forceable setting of the test that functions like bad() use
05515                 so the next check of the current file status to see if we should continue
05516                 using the file or not will pass.
05517     SeeAlso:    CCFile::GotError
05518 
05519 ********************************************************************************************/
05520 
05521 void CCMemFile::SetGoodState()
05522 {
05523     // Nuke any existing error states that might exist e.g. a lying eof() bit
05524     WasError = FALSE;
05525 }
05526 
05527 /********************************************************************************************
05528 
05529 >   BOOL CCMemFile::GetName( StringBase* name) const
05530 
05531     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
05532     Created:    22/09/94
05533     Inputs:     Pointer to a CCMemFile name 
05534     Outputs:    None
05535     Returns:    True if a name has been set otherwise False. At present always returns False.
05536     Purpose:    Given a CCMemFile*, you can ask for some sort of name which is associated with
05537                 that file. For filenames it might be a filename, or a pathname, for resource
05538                 files it might be "Default Bitmap" etc. These names could then be used for
05539                 making error messages have some extra useful information in.
05540     Errors:     None    
05541 
05542 ********************************************************************************************/
05543 BOOL CCMemFile::GetName( StringBase* name) const
05544 {
05545     return FALSE;
05546 }
05547 
05548 
05549 /********************************************************************************************
05550 
05551 >   filedesc CCMemFile::GetFileHandle( ) 
05552 
05553     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
05554     Created:    22/09/94
05555     Inputs:     None 
05556     Outputs:    None
05557     Returns:    The file handle (descriptor) for this file (really an INT32).
05558     Purpose:    Given an instance of a CCMemFile, you can ask for the actual file handle
05559                 that describes the associated file. Required for the external filters.
05560     Errors:     Not appropriate for memory files hence error at present
05561     SeeAlso:    CCDiskFile::GetFileHandle(); CCFile::GetFileHandle()    
05562 
05563 ********************************************************************************************/
05564 filedesc CCMemFile::GetFileHandle() const 
05565 {
05566     ERROR3("CCMemFile::GetFileHandle() called");
05567     return -1;
05568 }
05569 
05570 /********************************************************************************************
05571 
05572 >   void CCMemFile::close()
05573 
05574     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
05575     Created:    6/9/93
05576     Purpose:    Closes an instance of a CCMemFile
05577 
05578 ********************************************************************************************/
05579 
05580 void CCMemFile::close()
05581 {
05582     IsOpen = FALSE;
05583 
05584     // Release any memory block we might have
05585     if (MemHandle != BAD_MHANDLE)
05586     {
05587         ReleaseBlock(MemHandle);
05588         MemHandle = BAD_MHANDLE;
05589     }
05590 }
05591 
05592 
05593 /********************************************************************************************
05594 
05595 >   virtual BOOL CCMemFile::InitCompression(BOOL Header = FALSE)
05596 
05597 
05598     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
05599     Created:    1/6/95
05600     Purpose:    To initialise the compression system ready for use. This is to make sure
05601                 there is enough memory available for its buffers before writing out any
05602                 compression tokens into the output file.
05603                 MemFiles not supported at present so always returns FALSE.
05604                 Graeme (15/11/99): Added the Header parameter.
05605     SeeAlso:    StartCompression; StopCompression
05606 
05607 ********************************************************************************************/
05608 
05609 BOOL CCMemFile::InitCompression(BOOL Header)
05610 {
05611     ERROR3("CCMemFile::InitCompression Cannot compress memory files yet");
05612     return FALSE;   
05613 }
05614 
05615 /********************************************************************************************
05616 
05617 >   virtual BOOL CCMemFile::StartCompression()
05618 
05619 
05620     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
05621     Created:    25/5/95
05622     Purpose:    To start up the compression system.
05623                 MemFiles not supported at present so always returns FALSE.
05624     SeeAlso:    StopCompression
05625 
05626 ********************************************************************************************/
05627 
05628 BOOL CCMemFile::StartCompression()
05629 {
05630     ERROR3("CCMemFile::StartCompression Cannot compress memory files yet");
05631     return FALSE;   
05632 }   
05633 
05634 /********************************************************************************************
05635 
05636 >   virtual BOOL CCMemFile::StopCompression()
05637 
05638 
05639     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
05640     Created:    25/5/95
05641     Purpose:    To stop the compression system.
05642                 MemFiles not supported at present so always returns FALSE.
05643     SeeAlso:    StartCompression
05644 
05645 ********************************************************************************************/
05646 
05647 BOOL CCMemFile::StopCompression()
05648 {
05649     ERROR3("CCMemFile::StartCompression Cannot compress memory files yet");
05650     return FALSE;
05651 }
05652 
05653 /********************************************************************************************
05654                                         CCMemTextFile
05655 ********************************************************************************************/
05656 
05657 
05658 
05659 
05660 /********************************************************************************************
05661 
05662 >   CCMemFile::CCMemFile(TCHAR *pFile, UINT32 size, FileAccess fProt)
05663 
05664     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
05665     Inputs:     pFile - a pointer to the file
05666                 UINT32 - the size of the file
05667                 fProt - file protection - default = Read Only
05668     Created:    6/9/93
05669     Purpose:    Constructs an instance of CCMemTextFile and Opens it
05670 
05671 ********************************************************************************************/
05672 
05673 CCMemTextFile::CCMemTextFile( char *pFile, UINT32 size, FileAccess fProt,
05674                               BOOL ErrorReporting, BOOL ExceptionThrowing )
05675  : CCMemFile( pFile, size, fProt, ErrorReporting, ExceptionThrowing )
05676 {
05677 }
05678 
05679 /********************************************************************************************
05680 
05681 >   CCMemTextFile::~CCMemTextFile()
05682 
05683     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
05684     Created:    6/9/93        
05685     Purpose:    Default destructor.
05686 
05687 ********************************************************************************************/
05688 
05689 CCMemTextFile::~CCMemTextFile()
05690 {                   
05691 }
05692 
05693 /********************************************************************************************
05694 
05695 >   BOOL CCMemTextFile::open(TCHAR *pFile, UINT32 size, FileAccess fProt)
05696 
05697     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
05698     Created:    6/9/93
05699     Inputs:     pFile - a pointer to the file
05700                 UINT32 - the size of the file  
05701                 fProt - file protection - default = Read Only
05702     Returns:    TRUE if file is opened successfully or FALSE otherwize
05703     Purpose:    Opens an instance of a CCMemTextFile
05704 
05705 ********************************************************************************************/
05706 
05707 BOOL CCMemTextFile::open( char *pFile, UINT32 size, FileAccess fProt )
05708 {
05709     return CCMemFile::open(pFile, size, fProt);
05710 }
05711 
05712 /********************************************************************************************
05713 
05714 >   CCFile& CCMemTextFile::read(TCHAR& buf)
05715 
05716     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
05717     Created:    6/9/93
05718     Outputs;    character read in
05719     Returns:    Reference to the CCFile object.
05720     Purpose:    Reads a single character from the Memory file 
05721 
05722 ********************************************************************************************/
05723 
05724 CCFile &CCMemTextFile::read( char &buf )
05725 {
05726     // Make sure the file is open before it is read!
05727     if (!isOpen())
05728     {
05729         GotError(_R(IDE_NOTOPEN_ERROR));
05730         return *this;
05731     }
05732 
05733     // if file is write protected then exit
05734     if (FileProt != CCMemRead)
05735     {
05736         GotError(_R(IDE_WRITE_ONLY));
05737         return *this;
05738     }
05739     
05740     char* tempMemFile   = (char*) MemFile;          // Cast MemFile to a TCHAR pointer
05741 
05742     if (!eof())
05743     {
05744         buf = tempMemFile[CurrentPos++];
05745         CharsRead ++;
05746     }
05747     else
05748     {
05749         // Trying to read pasty EOF
05750         GotError(_R(IDE_EOF_ERROR));
05751     }
05752 
05753     return *this;
05754 }
05755 
05756 /********************************************************************************************
05757 
05758 >   CCFile& CCMemTextFile::read(StringBase* buf)
05759 
05760     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com> (Fixed by Richard)
05761     Created:    6/9/93 (14/4/95)
05762     Inputs:     - 
05763     Output:     Buf is the string buffer to return the string in
05764     Returns:    Reference to the CCFile object.
05765     Purpose:    Reads a stream of characters from the Memory file .
05766                 We now stop the string if it won't fit in the buffer, or has hit an EOL.
05767 
05768 ********************************************************************************************/
05769 
05770 CCFile& CCMemTextFile::read( StringBase *pBuf )
05771 {
05772     // Make sure the file is open before it is read!
05773     if (!isOpen())
05774     {
05775         GotError(_R(IDE_NOTOPEN_ERROR));
05776         return (CCFile&) *this;
05777     }
05778 
05779     // if file is write protected then exit
05780     if (FileProt != CCMemRead)
05781     {
05782         GotError(_R(IDE_WRITE_ONLY));
05783         return (CCFile&) *this;
05784     }
05785     
05786     // Read characters in until we have MaxLength() of them, or we hit a new line
05787     PSTR                tempMemFile = PSTR(MemFile);    // Cast MemFile to a char pointer
05788     char                Ch;
05789     INT32               Max = pBuf->MaxLength();
05790     INT32               Off = 0;
05791     
05792     PTSTR               Text = *pBuf;
05793 
05794     // chars to look for
05795     const char          CR = '\n';
05796     const char          LF = '\r';
05797 
05798     // We have to do this sneeky test for end of file because the io stream classes
05799     // are a load of old bollox!
05800     if (eof())
05801     {
05802         // Its the end of the file all right
05803         Text[0] = 0;
05804         return (CCFile&) *this;
05805     }
05806 
05807     // Get the first char
05808     read(Ch);
05809 
05810     // Loop around until we get to the end of the line or the end of the file
05811     // Must leave 1 character space in the buffer if we reach the maximum buffer size
05812     // so that we can fit the terminating zero in below.
05813     while ((Max>1) && (Ch!=CR) && (Ch!=LF) && (!eof()))
05814     {
05815         // store the char we read
05816 #if FALSE != wxUSE_UNICODE
05817         Text[Off]=_T('?'); // in case it doesn't convert, we don't want unititalized memory
05818         mbtowc( Text + Off, &Ch, 1 );
05819         ++Off;
05820 #else
05821         Text[Off++] = Ch;
05822 #endif
05823         
05824         // read another one and decrement the counter
05825         read(Ch);
05826 
05827         // Keep track of how much we have read
05828         Max--;
05829     }
05830     
05831     // if we ended at the end of a line, see if the next char is also part of a new line
05832     Ch = tempMemFile[CurrentPos];
05833     if ((Ch==LF) || (Ch==CR))
05834     {
05835         // eat the other part of the CR LF combo
05836         read(Ch);
05837     }
05838 
05839     // Terminate the string
05840     Text[Off++] = 0;
05841 
05842     // return
05843     return (CCFile&) *this;
05844 
05845 #if 0
05846     // ******* This is the old Mario code
05847 
05848     // Make sure the file is open before it is read!
05849     if (!isOpen())
05850     {
05851         GotError(_R(IDE_NOTOPEN_ERROR));
05852         return (CCFile&) *this;
05853     }
05854 
05855     // if file is write protected then exit
05856     if (FileProt != CCMemRead)
05857     {
05858         GotError(_R(IDE_WRITE_ONLY));
05859         return (CCFile&) *this;
05860     }
05861     
05862     TCHAR* tempMemFile  = (TCHAR*) MemFile;         // Cast MemFile to a TCHAR pointer
05863     TCHAR* pString      = *buf;                     // Cast input string to a TCHAR pointer
05864     UINT32 i = 0;
05865     
05866     // While String Length > String Max size
05867     //  and not end of file
05868     while ((i <= DEF_STRING_SIZE) && (!eof())) 
05869     {
05870         *pString = tempMemFile[CurrentPos++];       // output buffer = char read
05871         pString++;                                  // increment output buffer ptr
05872         i++;                                        // increment counter
05873     }
05874     
05875     return (CCFile&) *this;
05876 #endif
05877 }
05878 
05879 /********************************************************************************************
05880 
05881 >   CCFile& CCMemTextFile::write(const char& buf)
05882 
05883     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
05884     Created:    6/9/93
05885     Inputs:     A pointer to a single byte
05886     Returns:    Reference to the CCFile object.
05887     Purpose:    Writes a single byte to the Memory file 
05888 
05889 ********************************************************************************************/
05890 
05891 CCFile &CCMemTextFile::write( const char &buf )
05892 {
05893     // Make sure the file is open before it is written!
05894     if (!isOpen())
05895     {
05896         GotError(_R(IDE_NOTOPEN_ERROR));
05897         return (CCFile&) *this;
05898     }
05899 
05900     // if file is read only then exit
05901     if (FileProt != CCMemWrite)
05902     {
05903         GotError(_R(IDE_READ_ONLY));
05904         return (CCFile&) *this;
05905     }
05906     
05907     TCHAR* tempMemFile;
05908     
05909     // Get Pointer to the memory file
05910     if (!DescribeBlock(MemHandle, &MemFile, &FileSize))
05911     {
05912         GotError(_R(IDE_MEM_BLOCK_FAILURE));
05913         return (CCFile&) *this;
05914     } 
05915     
05916     // Cast pointer to memory file to TCHAR
05917     tempMemFile = (TCHAR*) MemFile;
05918     
05919     // if the file size limit is reached then increase memory file by default amount
05920     if (CurrentPos != (FileSize - 1)) 
05921         tempMemFile[CurrentPos++] = buf;
05922     else
05923     {
05924         if (GrowMemFile())
05925         {
05926             // Get Pointer to the memory file
05927             if (!DescribeBlock(MemHandle, &MemFile, &FileSize))
05928             {
05929                 GotError(_R(IDE_MEM_BLOCK_FAILURE));
05930                 return (CCFile&) *this;
05931             } 
05932             // Cast pointer to memory file to TCHAR
05933             tempMemFile = (TCHAR*) MemFile;
05934             // write input byte
05935             tempMemFile[CurrentPos++] = buf;
05936         }
05937     }
05938                 
05939     return (CCFile&) *this;
05940 }
05941 
05942 /********************************************************************************************
05943 
05944 >   CCFile& CCMemTextFile::write(const StringBase& buf, UINT32 length = 0)
05945 
05946     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
05947     Created:    6/9/93
05948     Inputs:     constant unicode string
05949                 Length denotes number of bytes to written 
05950     Returns:    Reference to the CCFile object.
05951     Purpose:    Writes a stream of bytes to the Memory file 
05952 
05953 ********************************************************************************************/
05954 
05955 CCFile& CCMemTextFile::write(const StringBase& buf, UINT32 length)
05956 {                                      
05957     // Make sure the file is open before it is written!
05958     if (!isOpen())
05959     {
05960         GotError(_R(IDE_NOTOPEN_ERROR));
05961         return (CCFile&) *this;
05962     }
05963 
05964     // if file is read only then exit
05965     if (FileProt != CCMemWrite)
05966     {
05967         GotError(_R(IDE_READ_ONLY));
05968         return (CCFile&) *this;
05969     }
05970     
05971     // Ensure that the length of the string to be written is not longer
05972     // than the string's size.
05973     if (length == 0)
05974         length = buf.Length();
05975     else if ((INT32) length > buf.Length())
05976     {
05977         GotError(_R(IDE_STRING_SIZE_ERROR));
05978         return (CCFile&) *this;
05979     }
05980 
05981     const TCHAR* tempBuf = (const TCHAR *) buf;
05982     TCHAR* tempMemFile;
05983     
05984     // Get Pointer to the memory file
05985     if (!DescribeBlock(MemHandle, &MemFile, &FileSize))
05986     {
05987         GotError(_R(IDE_MEM_BLOCK_FAILURE));
05988         return (CCFile&) *this;
05989     } 
05990     
05991     // Cast pointer to memory file to TCHAR
05992     tempMemFile = (TCHAR*) MemFile;
05993 
05994     for (UINT32 i = 0; (i <= length); i++)
05995     {
05996         // if the file size limit is reached then increase memory file by default amount
05997         if (CurrentPos != (FileSize - 1))
05998             tempMemFile[CurrentPos++] = *tempBuf++;
05999         else
06000         if (GrowMemFile())
06001         {
06002             // Get Pointer to the memory file
06003             if (!DescribeBlock(MemHandle, &MemFile, &FileSize))
06004             {
06005                 GotError(_R(IDE_MEM_BLOCK_FAILURE));
06006                 return (CCFile&) *this;
06007             } 
06008             // Cast pointer to memory file to TCHAR
06009             tempMemFile = (TCHAR*) MemFile;
06010 
06011             // write input byte
06012             tempMemFile[CurrentPos++] = *tempBuf++;
06013         }
06014     }
06015     
06016     return (CCFile&) *this;
06017 }
06018 
06019 
06020 /********************************************************************************************
06021 
06022 >   BOOL CCMemTextFile::eof()
06023 
06024     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
06025     Created:    8/9/93
06026     Return:     TRUE if end of file and FALSE otherwise.
06027     Purpose:    Determines whether an instance of CCMemTextFile has reached its EOF or not.
06028 
06029 ********************************************************************************************/
06030 
06031 BOOL CCMemTextFile::eof() const
06032 {
06033     // Cast pointer to memory file to TCHAR
06034     char* tempMemFile = (char*) MemFile;
06035 
06036     if ((CurrentPos == (FileSize - 1)) || (tempMemFile[CurrentPos] == END_OF_FILE))
06037         return TRUE;
06038     else
06039         return FALSE;
06040 }
06041 
06042 
06043 
06044 
06046 
06047 
06048 
06049 /********************************************************************************************
06050 >   INT32 fake_filedesc(iostream& io)
06051 
06052     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
06053     Created:    11/8/96
06054     Inputs:     io      -       a reference to an iostream object (not constant).
06055     Returns:    An integer 'file-descriptor'.  This can be passed to the stream_* functions
06056                 to identify the stream they should work on.
06057     Purpose:    Creates a fake 'file-descriptor' that can be passed to C libraries, such
06058                 as the Accusoft filter library, that allow the caller to redirect I/O.
06059     SeeAlso:    unfake_filedesc; stream_read; stream_write; stream_seek; _read; _write;
06060                 _lseek; fstream::fd
06061 ********************************************************************************************/
06062 
06063 UINT_PTR fake_filedesc(iostream& io)
06064 {
06065     // Make sure this dirty trick is possible.
06066     ERROR3IF(sizeof(INT32) < sizeof(void*),
06067              "type 'INT32' too small for type 'istream*' in fake_filedesc");
06068 
06069     // Return a "magic number" file-descriptor which is really a pointer to an iostream.
06070     return ~UINT32( (UINT_PTR)(&io) );
06071 }
06072 
06073 
06074 
06075 /********************************************************************************************
06076 >   iostream* unfake_filedesc(INT32 nFileDesc)
06077 
06078     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
06079     Created:    12/8/96
06080     Inputs:     nFileDesc       -   the integer fake 'file-descriptor' previously obtained
06081                                     by a call to fake_filedesc.
06082     Returns:    A pointer to the iostream object the 'file-descriptor' refers to.
06083     Purpose:    Complementary function to fake_filedesc.
06084     SeeAlso:    fake_filedesc; stream_read; stream_write; stream_seek; _read; _write;
06085                 _lseek; fstream::fd
06086 ********************************************************************************************/
06087 
06088 iostream* unfake_filedesc( UINT_PTR nFileDesc )
06089 {
06090     // Make sure this dirty trick is possible.
06091     ERROR3IF(sizeof(INT32) < sizeof(void*),
06092              "type 'INT32' too small for type 'istream*' in unfake_filedesc");
06093 
06094     // Convert this magic number back into a pointer to an iostream.
06095     iostream* ps = (iostream*) (void*) ~nFileDesc;
06096     ERROR3IF(ps == 0, "Null 'file-descriptor' in unfake_filedesc");
06097     return ps;
06098 }
06099 
06100 
06101 
06102 /********************************************************************************************
06103 >   extern "C" INT32 ACCUAPI_IO stream_read(INT32 nFileDesc, char* pchBuffer, unsigned nBufSize)
06104 
06105     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
06106     Created:    5/8/96
06107     Inputs:     nFileDesc       -   the "file-descriptor" of the "file" to read from.  This
06108                                     is really an iostream* cast to an INT32.
06109                 pchBuffer       -   where to put the data that is read.
06110                 nBufSize        -   the size of the input buffer pointed to by pchBuffer
06111     Returns:    The number of bytes read by the call, or zero if at the end of the file, or
06112                 -1 if there is an error.
06113     Purpose:    Adapts functions that call C-style I/O routines so that they can use
06114                 C++ streams instead.  This function substitutes for the standard C
06115                 read() function.  Instead of nFileDesc being a file-descriptor, it
06116                 is expected to be an INT32 returned by fake_filedesc.  Using this function we
06117                 can persuade old code, such as the Accusoft library, to read and write
06118                 from structured storage.
06119     Errors:     ERROR3 if the given buffer is larger than that allowed by istream.
06120     SeeAlso:    stream_write; stream_seek; fake_filedesc; unfake_filedesc; iostream;
06121                 istream::read; ios::eof; ios::bad; costream; fstream; _read
06122 ********************************************************************************************/
06123 
06124 INT32 ACCUAPI_IO stream_read(INT32 nFileDesc, char* pchBuffer, unsigned nBufSize)
06125 {
06126     // Extract the input stream object associated with this request.
06127     iostream* ps = unfake_filedesc(nFileDesc);
06128     if (ps == 0 || ps->bad()) return -1;
06129 
06130     // Make sure the buffer isn't too big for a signed integer.
06131     if (nBufSize > INT_MAX)
06132     {
06133         ERROR3("Buffer too large for type 'signed INT32' in stream_read");
06134         nBufSize = INT_MAX;
06135     }
06136 
06137     // If we're already at the end of the file then indicate this.
06138     if (ps->eof()) return 0;
06139 
06140     // Try to read the data into the given buffer.
06141     if (!ps->read(pchBuffer, (INT32) nBufSize) && !ps->eof()) return -1;
06142 
06143     // Return the number of bytes actually read.
06144     return ps->gcount();
06145 }
06146 
06147 
06148 
06149 /********************************************************************************************
06150 >   extern "C" INT32 ACCUAPI_IO stream_write(INT32 nFileDesc, char* pchBuffer, unsigned nBufSize)
06151 
06152     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
06153     Created:    5/8/96
06154     Inputs:     nFileDesc       -   the "file-descriptor" of the "file" to write to.  This
06155                                     is really an iostream* cast to an INT32.
06156                 pchBuffer       -   where to get the data that is to be written.
06157                 nBufSize        -   the size of the output buffer pointed to by pchBuffer
06158     Returns:    The number of bytes written by the call, or -1 if there is an error.
06159     Purpose:    Adapts functions that call C-style I/O routines so that they can use
06160                 C++ streams instead.  This function substitutes for the standard C
06161                 write() function.  Instead of nFileDesc being a file-descriptor, it
06162                 is expected to be an INT32 returned by fake_filedesc.  Using this function we
06163                 can persuade old code, such as the Accusoft library, to read and write
06164                 from structured storage.
06165     Errors:     ERROR3 if the given buffer is larger than that allowed by ostream.
06166     SeeAlso:    stream_read; stream_seek; fake_filedesc; iostream; ostream::write; costream;
06167                 fstream; _write
06168 ********************************************************************************************/
06169 
06170 INT32 ACCUAPI_IO stream_write(INT32 nFileDesc, char* pchBuffer, unsigned nBufSize)
06171 {
06172     // Extract the output stream object associated with this request.
06173     iostream* ps = unfake_filedesc(nFileDesc);
06174     if (ps == 0 || ps->bad()) return -1;
06175 
06176     // Make sure the buffer isn't too big for a signed integer.
06177     if (nBufSize > INT_MAX)
06178     {
06179         ERROR3("Buffer too large for type 'signed INT32' in stream_write");
06180         nBufSize = INT_MAX;
06181     }
06182 
06183     // Try to write the data from the given buffer.
06184     if (!ps->write(pchBuffer, (INT32) nBufSize)) return -1;
06185 
06186     // Return the number of bytes actually written, which is always all or none.
06187     return (INT32) nBufSize;
06188 }
06189 
06190 
06191 
06192 /********************************************************************************************
06193 >   extern "C" INT32 ACCUAPI_IO stream_seek(INT32 nFileDesc, INT32 nOffset, unsigned fSeekType)
06194 
06195     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
06196     Created:    5/8/96
06197     Inputs:     nFileDesc       -   the "file-descriptor" of the "file" to write to.  This
06198                                     is really an iostream* cast to an INT32.
06199                 nOffset         -   the amount to seek by or the position to seek to.
06200                 fSeekType       -   the direction of the seek (see the run-time docs for
06201                                     the _lseek function to get these flags).
06202     Returns:    The new seek position, or -1 if there was an error.
06203     Purpose:    Adapts functions that call C-style I/O routines so that they can use
06204                 C++ streams instead.  This function substitutes for the standard C
06205                 seek() function.  Instead of nFileDesc being a file-descriptor, it
06206                 is expected to be an INT32 returned by fake_filedesc.  Using this function we
06207                 can persuade old code, such as the Accusoft library, to read and write
06208                 from structured storage.  Note that the function assumes that the stream
06209                 has only one combined seek pointer, just like fstream and costream.  If
06210                 moving the input seek pointer doesn't also move the output seek pointer,
06211                 as may be the case for some exotic iostream derivatives, then the function
06212                 won't work properly.
06213     Errors:     ERROR3 if the seek type is invalid or if the put and get seek positions
06214                 aren't tied, as the semantics of the stream require.
06215     SeeAlso:    stream_read; stream_write; fake_filedesc; iostream; iostream::seekg;
06216                 fstream; costream; _lseek
06217 ********************************************************************************************/
06218 
06219 INT32 ACCUAPI_IO stream_seek(INT32 nFileDesc, INT32 nOffset, unsigned fSeekType)
06220 {
06221     // Extract the stream object associated with this request.  Note that in disk-based
06222     // streams (including the costream), the get and put seek positions are tied, so
06223     // moving one moves the other.  Hence we can use a plain istream here.
06224     iostream* ps = unfake_filedesc(nFileDesc);
06225     if (ps == 0 || ps->bad()) return -1;
06226 
06227     // Convert the standard C flags for fSeekType into the iostream equivalents.
06228     // NB. make sure the flags as passed by Accusoft are the same as those used by
06229     // the Microsoft run-time library!
06230     ios::seekdir dir;
06231     switch (fSeekType)
06232     {
06233     case SEEK_SET:  dir = ios::beg; break;
06234     case SEEK_CUR:  dir = ios::cur; break;
06235     case SEEK_END:  dir = ios::end; break;
06236     default:        ERROR3("Bad seek direction in stream_seek"); return -1;
06237     }
06238 
06239     // Try to seek to the new position.
06240     if( !ps->seekg( (streampos)nOffset, ios_base::seekdir(dir) ) )
06241         return -1;
06242 
06243     // Check if the iostream has similar semantics to fstream.
06244     ERROR3IF(ps->tellp() != ps->tellg(),
06245              "Put and get seek pointers aren't tied in stream_seek");
06246 
06247     // Return the new seek position.
06248     return (INT32) ps->tellg();
06249 }

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