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 *********************