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 }