cxftfile.cpp

Go to the documentation of this file.
00001 // $Id: cxftfile.cpp 1679 2006-08-08 09:47:27Z gerry $
00002 // Implementation of the CXaraTemplateFile class
00003 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00004 ================================XARAHEADERSTART===========================
00005  
00006                Xara LX, a vector drawing and manipulation program.
00007                     Copyright (C) 1993-2006 Xara Group Ltd.
00008        Copyright on certain contributions may be held in joint with their
00009               respective authors. See AUTHORS file for details.
00010 
00011 LICENSE TO USE AND MODIFY SOFTWARE
00012 ----------------------------------
00013 
00014 This file is part of Xara LX.
00015 
00016 Xara LX is free software; you can redistribute it and/or modify it
00017 under the terms of the GNU General Public License version 2 as published
00018 by the Free Software Foundation.
00019 
00020 Xara LX and its component source files are distributed in the hope
00021 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00022 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00023 See the GNU General Public License for more details.
00024 
00025 You should have received a copy of the GNU General Public License along
00026 with Xara LX (see the file GPL in the root directory of the
00027 distribution); if not, write to the Free Software Foundation, Inc., 51
00028 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00029 
00030 
00031 ADDITIONAL RIGHTS
00032 -----------------
00033 
00034 Conditional upon your continuing compliance with the GNU General Public
00035 License described above, Xara Group Ltd grants to you certain additional
00036 rights. 
00037 
00038 The additional rights are to use, modify, and distribute the software
00039 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00040 library and any other such library that any version of Xara LX relased
00041 by Xara Group Ltd requires in order to compile and execute, including
00042 the static linking of that library to XaraLX. In the case of the
00043 "CDraw" library, you may satisfy obligation under the GNU General Public
00044 License to provide source code by providing a binary copy of the library
00045 concerned and a copy of the license accompanying it.
00046 
00047 Nothing in this section restricts any of the rights you have under
00048 the GNU General Public License.
00049 
00050 
00051 SCOPE OF LICENSE
00052 ----------------
00053 
00054 This license applies to this program (XaraLX) and its constituent source
00055 files only, and does not necessarily apply to other Xara products which may
00056 in part share the same code base, and are subject to their own licensing
00057 terms.
00058 
00059 This license does not apply to files in the wxXtra directory, which
00060 are built into a separate library, and are subject to the wxWindows
00061 license contained within that directory in the file "WXXTRA-LICENSE".
00062 
00063 This license does not apply to the binary libraries (if any) within
00064 the "libs" directory, which are subject to a separate license contained
00065 within that directory in the file "LIBS-LICENSE".
00066 
00067 
00068 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00069 ----------------------------------------------
00070 
00071 Subject to the terms of the GNU Public License (see above), you are
00072 free to do whatever you like with your modifications. However, you may
00073 (at your option) wish contribute them to Xara's source tree. You can
00074 find details of how to do this at:
00075   http://www.xaraxtreme.org/developers/
00076 
00077 Prior to contributing your modifications, you will need to complete our
00078 contributor agreement. This can be found at:
00079   http://www.xaraxtreme.org/developers/contribute/
00080 
00081 Please note that Xara will not accept modifications which modify any of
00082 the text between the start and end of this header (marked
00083 XARAHEADERSTART and XARAHEADEREND).
00084 
00085 
00086 MARKS
00087 -----
00088 
00089 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00090 designs are registered or unregistered trademarks, design-marks, and/or
00091 service marks of Xara Group Ltd. All rights in these marks are reserved.
00092 
00093 
00094       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00095                         http://www.xara.com/
00096 
00097 =================================XARAHEADEREND============================
00098  */
00099 
00100 #include "camtypes.h"
00101 
00102 #include "cxftfile.h"
00103 //#include "cxfrec.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00104 //#include "cxfrech.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00105 //#include "cxfdefs.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 #include "cxfmap.h"
00107 
00108 //#include "ccfile.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 //#include "progress.h"
00110 //#include "filtrres.h"
00111 
00112 #include "ccpanose.h"
00113 
00114 #include "bmpsrc.h"     // BitmapSource
00115 #include "ccbuffil.h"
00116 
00117 #include "cxftags.h"    // The tag definitions
00118 //#include "cxfdefs.h"  // The constants - in camtypes.h [AUTOMATICALLY REMOVED]
00119 #include "zutil.h"      // ZLIB_VERSIONNO
00120 
00121 //#include "camfiltr.h" // BaseCamelotFilter - in camtypes.h [AUTOMATICALLY REMOVED]
00122 
00123 #include "fttyplis.h"
00124 
00125 #include "fileutil.h"
00126 
00127 #include "ccbhfile.h"   // include the translating file proxy
00128 
00129 //#include "fthelper.h"
00130 
00131 //-----------------------------------------------
00132 
00133 CC_IMPLEMENT_DYNAMIC(CXaraTemplateFile, CXaraFile);
00134 
00135 // This will get Camelot to display the filename and linenumber of any memory allocations
00136 // that are not released at program exit
00137 // Declare smart memory handling in Debug builds
00138 #define new CAM_DEBUG_NEW
00139 
00140 /********************************************************************************************
00141 
00142 >   CXaraTemplateFile::CXaraTemplateFile()
00143 
00144     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00145     Created:    09/07/97
00146     Purpose:    Default constructor
00147     SeeAlso:    -
00148 
00149 ********************************************************************************************/
00150 
00151 CXaraTemplateFile::CXaraTemplateFile()
00152 {
00153     m_pTempFile = NULL;
00154     m_pBinHexFile = NULL;
00155     m_pOrigCCFile = NULL;
00156 }
00157 
00158 
00159 
00160 /********************************************************************************************
00161 
00162 >   BOOL CXaraTemplateFile::OpenToWrite(CCLexFile* pThisCCFile)
00163 
00164     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00165     Created:    20/5/96
00166     Inputs:     pThisCCFile = ptr to the file to write to
00167     Returns:    TRUE if the the system is ready to write to the file
00168                 FALSE otherwise
00169     Purpose:    Opens the CXaraFile object ready for writing.
00170                 It uses the given CCFile object as the file to write to.
00171 
00172                 NOTE:  It is assumed that the supplied CCFile has already been opened for writing.
00173 
00174     Errors:     -
00175     SeeAlso:    Close()
00176 
00177 ********************************************************************************************/
00178 
00179 BOOL CXaraTemplateFile::OpenToWrite(CCLexFile* pThisCCFile)
00180 {
00181     // Check entry params
00182     ERROR2IF(pThisCCFile == NULL,FALSE,"pThisCCFile is NULL");
00183 
00184     //  pCCFile should be NULL at this point
00185     ERROR3IF(pCCFile != NULL,"pThisCCFile is NULL");
00186 
00187     // Set our ptr the the CCFile to the one provided
00188     pCCFile = pThisCCFile;
00189 
00190     // Try to create a CCBinHexFile for later
00191 
00192     m_pBinHexFile = new CCBinHexFile(pCCFile, FALSE, FALSE);
00193 
00194     if (m_pBinHexFile == NULL)
00195         return(FALSE);
00196 
00197     // Reset the write vars
00198     RecordNumber    = 0;
00199     NumBytesWritten = 0;
00200 
00201     BOOL ok = TRUE;
00202 
00203     // The first 8 bytes should be our unique ID sequence
00204     if (ok) ok = pCCFile->write("FLARETEXT\r\n", 11).good();
00205 
00206     return ok;
00207 }
00208 
00209 
00210 
00211 /********************************************************************************************
00212 
00213 >   BOOL CXaraTemplateFile::OpenToRead(CCLexFile* pThisCCFile)
00214 
00215     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00216     Created:    20/07/97
00217     Inputs:     pThisCCFile = ptr to the file to read from
00218     Returns:    TRUE if the the system is ready to read from the file
00219                 FALSE otherwise
00220     Purpose:    Opens the CXaraFile object ready for reading.
00221                 It actually uses the given CCFile object as the file to read from.
00222 
00223                 NOTE:   It is assumed that the supplied CCFile has already been opened for reading
00224                         from the start of the file. This function will return FALSE if the initial
00225                         10 bytes do not contain the file header sequence.
00226     Errors:     -
00227     SeeAlso:    Close()
00228 
00229 ********************************************************************************************/
00230 
00231 BOOL CXaraTemplateFile::OpenToRead(CCLexFile* pThisCCFile)
00232 {
00233     PORTNOTETRACE("other","CXaraTemplateFile::OpenToRead - do nothing");
00234 #ifndef EXCLUDE_FROM_XARALX
00235     // Check entry params
00236     ERROR2IF(pThisCCFile == NULL,FALSE,"pThisCCFile is NULL");
00237 
00238     //  pCCFile should be NULL at this point
00239     ERROR3IF(pCCFile != NULL,"pThisCCFile is NULL");
00240 
00241     // Remember the original file
00242     m_pOrigCCFile = pThisCCFile;
00243     
00244     // Translate the file
00245     CCLexFile* pNewFile = FlareTemplateHelper::ConvertFile(pThisCCFile);
00246     
00247     if (pNewFile == NULL)
00248     {
00249         return(FALSE);
00250     }
00251 
00252     // And call the base class to do the rest
00253     return(CXaraFile::OpenToRead(pNewFile));
00254 #else
00255     return false;
00256 #endif
00257 }
00258 
00259 
00260 
00261 /********************************************************************************************
00262 
00263 >   BOOL CXaraTemplateFile::Close()
00264 
00265     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00266     Created:    14/7/97
00267     Inputs:     -
00268     Returns:    TRUE if the the system closed down correctly
00269                 FALSE otherwise
00270     Purpose:    This closes the CXaraFile object.
00271                 You should call this func at the very end of reading from or writing to the file
00272 
00273                 NOTE: The supplied pCCFile passed to OpenToWrite() and OpenToRead() is NOT
00274                 closed.  The calling code will have to handle the low level closing of the file.
00275 
00276     Errors:     -
00277     SeeAlso:    OpenToWrite(), OpenToRead()
00278 
00279 ********************************************************************************************/
00280 
00281 BOOL CXaraTemplateFile::Close()
00282 {
00283     // Reset all handlers that we set up via SetUpHandlers()
00284     ResetHandlers();
00285 
00286     if (m_pBinHexFile != NULL)
00287     {
00288         delete m_pBinHexFile;
00289         m_pBinHexFile = NULL;
00290     }
00291 
00292     // We must not delete this but we must delete the CCFile that we created
00293     if (m_pOrigCCFile != NULL)
00294     {
00295         if (pCCFile)
00296         {
00297             PathName TempPath = pCCFile->GetPathName();
00298             delete pCCFile;                             // delete the CCFile (closes it)
00299     PORTNOTETRACE("other","Removed FileUtil::DeleteFile usage");
00300 #ifndef EXCLUDE_FROM_XARALX
00301             FileUtil::DeleteFile(&TempPath);            // delete the actual file
00302 #endif
00303         }
00304         pCCFile = m_pOrigCCFile;
00305         m_pOrigCCFile = NULL;
00306     }
00307 
00308     return TRUE;
00309 }
00310 
00311 /********************************************************************************************
00312 
00313 >   virtual CCLexFile* CXaraTemplateFile::GetCCFile() const
00314 
00315     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00316     Created:    09/07/97
00317     Inputs:     -
00318     Returns:    The CCLexFile that is being used to export the data.
00319     Purpose:    Function to give public access to the underlying CCLexFile that is being used
00320                 to save out the data.
00321 
00322                 This either returns a special proxy CCFile which translates the data
00323                 or a temporary disk file (during streamed records)
00324 
00325 ********************************************************************************************/
00326 
00327 CCLexFile* CXaraTemplateFile::GetCCFile() const
00328 {
00329 //  TRACEUSER( "Gerry", _T("CXaraTemplateFile::GetCCFile()\n"));
00330 
00331     if (m_pOrigCCFile)
00332         return(pCCFile);
00333 
00334     if (m_pTempFile)
00335         return(m_pTempFile);
00336     else
00337         return(m_pBinHexFile);
00338 }
00339 
00340 
00341 
00342 /********************************************************************************************
00343 
00344 >   INT32 CXaraTemplateFile::StartRecord(UINT32 Tag,INT32 Size)
00345 
00346     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00347     Created:    14/7/97
00348     Inputs:     Tag = the tag for the record
00349                 Size = the size of the data section of the record in bytes, or CXF_UNKNOWN_SIZE
00350     Returns:    The record number of the record being written to the file.
00351                 If the function fails, 0 will be returned
00352     Purpose:    Prepares a record ready for writing to the file.
00353 
00354                 This function prepares a record that is buffered in memory before being
00355                 written out to file.  
00356                 
00357                 After this call all Write() functions write to the data section of the record.
00358                 The complete record (inc. the tag & size fields) is written out when EndRecord() is called.
00359 
00360                 If you know the exact size in bytes of the record you are writing, supply this
00361                 value via the Size parameter.  This allows the write functions to provide additional
00362                 error checking for you (e.g. if you try and write extra bytes)
00363                 
00364                 If you are not sure of the exact number of bytes that will be written to the data
00365                 section, set the Size param to CXF_UNKNOWN_SIZE.  EndRecord() will ensure that the
00366                 written record will have its size field set to the number of bytes that were written.
00367 
00368     Errors:     -
00369     SeeAlso:    EndRecord()
00370 
00371 ********************************************************************************************/
00372 
00373 INT32 CXaraTemplateFile::StartRecord(UINT32 Tag,INT32 Size)
00374 {
00375     if (EndRecord())
00376     {
00377         // Inc the record number
00378         RecordNumber++;
00379 
00380         // Create a new record, & initialise it
00381         pRecord = new CXaraFileRecord(Tag, Size);
00382 
00383         WriteToRecord = (pRecord != NULL && pRecord->Init());
00384 
00385         if (WriteToRecord)
00386         {
00387             pRecord->SetRecordNumber(RecordNumber);
00388             return RecordNumber;
00389         }
00390     }
00391 
00392     return 0;
00393 }
00394 
00395 
00396 INT32 CXaraTemplateFile::StartStreamedRecord(UINT32 Tag,INT32 Size)
00397 {
00398 //  TRACEUSER( "Gerry", _T("StartStreamed  %d, %d\n"), Tag, Size);
00399     
00400     ERROR2IF(WritingStreamedRecord,0,"Already writing a streamed record.  Forgot to call EndRecord()?");
00401 
00402     ERROR3IF(m_pTempFile != NULL, "TempFile is non-NULL!!!");
00403 
00404     WritingStreamedRecord = TRUE;
00405     WriteToRecord = FALSE;
00406 
00407     // Don't do any compression stuff
00408 //  CompOffDueToStreamedRecord = IsCompressionOn();
00409 //  BOOL ok = StopCompression();
00410     
00411     // And don't do any of this rampant poking of length values
00412 //  StartOfStreamedRecord = GetFilePos();
00413     
00414     // All streamed records have labels stuck on them (for now),
00415     // have length set to zero and consist of one BINH data item
00416     char Buf[64];
00417     INT32 Num = sprintf(Buf, "%%R%d%%{%d,%d,BINH(", (RecordNumber+1), Tag, 0);
00418     
00419     // make sure we write directly to the file
00420     BOOL ok = pCCFile->write(Buf, Num).good();
00421 
00422     if (!ok)
00423         return(0);
00424 
00425     // Now we create a temporary file which GetCCFile
00426     // will return until EndStreamedRecord is called
00427     PORTNOTETRACE("other","Removed FileUtil::GetTemporaryPathName usage");
00428 #ifndef EXCLUDE_FROM_XARALX
00429     m_TempPath = FileUtil::GetTemporaryPathName();
00430 #endif
00431     m_pTempFile = new CCDiskFile(m_TempPath, ios::out | ios::binary | ios::trunc);
00432 
00433     if (m_pTempFile == NULL || m_pTempFile->bad())
00434         return(0);
00435 
00436     RecordNumber++;
00437     return(RecordNumber);
00438 }
00439 
00440 
00441 /********************************************************************************************
00442 
00443 >   BOOL CXaraTemplateFile::EndRecord()
00444 
00445     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00446     Created:    14/7/97
00447     Inputs:     -
00448     Returns:    TRUE if the the system wrote out the record
00449                 FALSE otherwise
00450     Purpose:    Ends the current record.
00451 
00452                 If the record was started by StartRecord(), this call will write out the entire
00453                 buffered record (record header and data section) to the file.
00454 
00455     Errors:     -
00456     SeeAlso:    StartRecord()
00457 
00458 ********************************************************************************************/
00459 
00460 BOOL CXaraTemplateFile::EndRecord()
00461 {
00462     ERROR3IF(WriteToRecord && pRecord == NULL,"Writing to a NULL record!");
00463 
00464     BOOL ok = TRUE;
00465 
00466     if (WritingStreamedRecord)
00467     {
00468         // Not interested in the result, but we will pass through a variable anyway
00469         // Complete the process of writing out the streamed record
00470         UINT32 RecordSize = 0L;
00471         return EndStreamedRecord(&RecordSize);
00472     }
00473 
00474     if (WriteToRecord && pRecord != NULL)
00475     {
00476         WriteToRecord = FALSE;
00477 
00478         ERROR3IF(!pRecord->IsDataSectionFull(),"Data section of the record has not been filled");
00479 
00480 //      if (ok) ok = Write(pRecord->GetTag());
00481 //      if (ok) ok = Write(pRecord->GetSize());
00482 //      if (ok) ok = Write(pRecord->GetBuffer(),pRecord->GetSize());
00483 
00484         delete pRecord;
00485         pRecord = NULL;
00486     }
00487 
00488     return (ok);
00489 }
00490 
00491 /********************************************************************************************
00492 
00493 >   BOOL CXaraTemplateFile::EndStreamedRecord(UINT32 *RecordSize)
00494 
00495     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00496     Created:    14/7/97
00497     Inputs:     -
00498     Outputs:    RecordSize - the size of the record just written
00499     Returns:    TRUE if the the system wrote out the record
00500                 FALSE otherwise
00501     Purpose:    Ends the current streamed record.
00502 
00503                 If the record was started by StartStreamedRecord(), this call will do all
00504                 that is necessary to clean up the streamed record.
00505                 This mainly involves:-
00506                     Fixing the size in the record header to be correct.
00507                     Starting up compression, if required
00508 
00509     Errors:     -
00510     SeeAlso:    StartRecord()
00511 
00512 ********************************************************************************************/
00513 
00514 BOOL CXaraTemplateFile::EndStreamedRecord(UINT32 *RecordSize)
00515 {
00516     ERROR3IF(!WritingStreamedRecord,"Trying to end a non-streamed record!");
00517     if (!WritingStreamedRecord)
00518         return FALSE;
00519 
00520     BOOL ok = TRUE;
00521     // We must reset WritingStreamedRecord to FALSE immediately, to prevent stack overflow
00522     // due to recursion via the StartCompression() call below
00523     WritingStreamedRecord = FALSE;
00524 
00525     UINT32 SizeOfFile = 0;
00526 
00527     if (m_pTempFile == NULL)
00528         return(FALSE);
00529 
00530     m_pTempFile->close();
00531     delete m_pTempFile;
00532     m_pTempFile = NULL;
00533 
00534     m_pTempFile = new CCDiskFile(CCFILE_DEFAULTSIZE, FALSE, FALSE);
00535     if (m_pTempFile == NULL)
00536         return(FALSE);
00537     if(!m_pTempFile->open(m_TempPath, ios::in | ios::binary))
00538         return(FALSE);
00539 
00540     BYTE    Buffer[BinHexMaxLineLength * 10];       // Currently 1000
00541     size_t  left = m_pTempFile->Size();
00542     UINT32  len = BinHexMaxLineLength * 10;
00543 
00544     while (m_pTempFile->good() && m_pBinHexFile->good() && len > 0)
00545     {
00546         if (len > left)
00547             len = left;
00548         m_pTempFile->read( Buffer, len );
00549 
00550         if (m_pTempFile->fail())
00551             TRACEUSER( "Gerry", _T("read from temp file failed!!!\n"));
00552 
00553         m_pBinHexFile->write(Buffer, len);
00554 
00555         left -= len;
00556     }
00557 
00558     // Close and delete the temp file
00559     m_pTempFile->close();
00560     delete m_pTempFile;
00561     m_pTempFile = NULL;
00562     PORTNOTETRACE("other","Removed FileUtil::DeleteFile usage");
00563 #ifndef EXCLUDE_FROM_XARALX
00564     FileUtil::DeleteFile(&m_TempPath);
00565 #endif
00566 
00567     if (m_pBinHexFile->fail())
00568         return(FALSE);
00569 
00570     // Try to finish the record...
00571     if (pCCFile->write(")}\r\n", 4).fail())
00572         return(FALSE);
00573 
00574     // If we are passed a pointer then return the size to the caller
00575     if (RecordSize)
00576         *RecordSize = SizeOfFile;
00577 
00578     // Add this number to the number of bytes written
00579 //  TRACEUSER( "Gerry", _T("EndStreamedRecord update size by %d\n"), SizeOfFile);
00580     IncNumBytesWritten(SizeOfFile);
00581     
00582     // Reset the streamed record vars
00583     StartOfStreamedRecord = 0;
00584     CompOffDueToStreamedRecord = FALSE;
00585         
00586     return ok;
00587 }
00588 
00589 /********************************************************************************************
00590 
00591 >   virtual BOOL CXaraTemplateFile::FixStreamedRecordHeader(UINT32 *RecordSize)
00592 
00593     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00594     Created:    14/7/97
00595     Inputs:     -
00596     Outputs:    RecordSize - the size of the record just written
00597     Returns:    True if worked ok, False otherwise.
00598     Purpose:    Fixes up the previously saved record header for a streamed record.
00599                 The RecordSize is the size of the data section of the record and so does not
00600                 include the 8 bytes in the header.
00601     Errors:     -
00602     SeeAlso:    -
00603 
00604 ********************************************************************************************/
00605 
00606 BOOL CXaraTemplateFile::FixStreamedRecordHeader(UINT32 *RecordSize)
00607 {
00608     ERROR2IF(pCCFile == NULL,FALSE,"CXaraFile::FixStreamedRecordHeader NULL pCCFile");
00609     ERROR2IF(StartOfStreamedRecord == 0,FALSE,"CXaraFile::FixStreamedRecordHeader StartOfStreamedRecord == 0");
00610 
00611     // Dont do nuthin' 'ere 'cos we can't get the current file postion to determine the
00612     // length of the streamed record
00613     
00614     return(TRUE);
00615 }
00616 
00617 
00618 /********************************************************************************************
00619 
00620 >   UINT32 CXaraTemplateFile::WriteRecordHeader(UINT32 Tag, INT32 Size)
00621 
00622     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00623     Created:    14/7/97
00624     Inputs:     Tag     - the tag for this record
00625                 Size    - the size of the record
00626     Returns:    The record number of this record in the file.
00627                 If an error occurs, 0 is returned
00628     Purpose:    Writes out a record header directly to the file.
00629                 It expects the caller to handle other aspects of the record writing.
00630                 This should only be used by people who know what they are doing e.g. compression
00631                 It should not be required for template files but we'll see
00632     Errors:     -
00633     SeeAlso:    -
00634 
00635 ********************************************************************************************/
00636 
00637 UINT32 CXaraTemplateFile::WriteRecordHeader(UINT32 Tag, INT32 Size)
00638 {
00639 //  TRACEUSER( "Gerry", _T("WriteRecordHeader  %d, %d\n"), Tag, Size);
00640     
00641     BOOL ok = TRUE;
00642 
00643     char Buf[32];
00644     INT32 Num = sprintf(Buf, "{%d,%d", Tag, Size);
00645     
00646     // make sure we write directly to the file
00647     ok = pCCFile->write(Buf, Num).good();
00648 
00649     // Inc the record number
00650     RecordNumber++;
00651 
00652     if (ok)
00653         return RecordNumber;
00654     else
00655         return 0;
00656 }
00657 
00658 
00659 
00660 /********************************************************************************************
00661 
00662 >   virtual BOOL CXaraTemplateFile::Write(BYTE b)
00663 
00664     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00665     Created:    14/7/97
00666     Inputs:     pRecord = ptr to a record to write out to file
00667     Returns:    The record number of this record in the file.
00668                 If an error occurs, 0 is returned
00669     Purpose:    Writes out the record to the file.  Uses WriteAsText to do the work
00670     SeeAlso:    WriteAsText()
00671 
00672 ********************************************************************************************/
00673 
00674 BOOL CXaraTemplateFile::Write(BYTE b)
00675 {
00676     ERROR2IF(GetCCFile() == NULL,FALSE,"Can't write a BYTE with no pCCFile");
00677 
00678     BOOL ok = TRUE;
00679 
00680     // If we are writing to a record then let it handle the translation
00681     if (WriteToRecord && pRecord != NULL)
00682         ok = pRecord->WriteBYTE(b);
00683     else
00684     {
00685         // For streamed records we need to use our proxy CCFile
00686         GetCCFile()->write((void const*)&b);
00687         IncNumBytesWritten(1);
00688     }
00689 
00690     return ok;
00691 }
00692 
00693 
00694 
00695 /********************************************************************************************
00696 
00697 >   UINT32 CXaraTemplateFile::Write(CXaraFileRecord* pRecord)
00698 
00699     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00700     Created:    14/7/97
00701     Inputs:     pRecord = ptr to a record to write out to file
00702     Returns:    The record number of this record in the file.
00703                 If an error occurs, 0 is returned
00704     Purpose:    Writes out the record to the file.  Uses WriteAsText to do the work
00705     SeeAlso:    WriteAsText()
00706 
00707 ********************************************************************************************/
00708 
00709 UINT32 CXaraTemplateFile::Write(CXaraFileRecord* pRecord)
00710 {
00711     ERROR2IF(pRecord == NULL,FALSE,"pRecord param is NULL");
00712 
00713     BOOL ok = EndRecord();
00714 
00715     ERROR3IF(!pRecord->IsDataSectionFull(),"Data section of the record has not been filled");
00716 
00717     if (ok) ok = WriteAsText(pRecord);
00718     
00719     // Inc the record number
00720     RecordNumber++;
00721 
00722     if (ok)
00723         return RecordNumber;
00724     else
00725         return 0;
00726 }
00727 
00728 
00729 /********************************************************************************************
00730 
00731 >   UINT32 CXaraTemplateFile::WriteDefinitionRecord(CXaraFileRecord* pRecord)
00732 
00733     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00734     Created:    17/07/97
00735     Inputs:     pRecord = ptr to a record to write out to file
00736     Returns:    The record number of this record in the file.
00737                 If an error occurs, 0 is returned
00738     Purpose:    Writes out the record to the file
00739                 This version writes a label to the file
00740 
00741 ********************************************************************************************/
00742 
00743 UINT32 CXaraTemplateFile::WriteDefinitionRecord(CXaraFileRecord* pRecord)
00744 {
00745     ERROR2IF(pRecord == NULL,FALSE,"pRecord param is NULL");
00746 
00747     BOOL ok = EndRecord();
00748 
00749     ERROR3IF(!pRecord->IsDataSectionFull(),"Data section of the record has not been filled");
00750 
00751     if (ok) ok = WriteLabel();
00752     if (ok) ok = WriteAsText(pRecord);
00753     
00754     // Inc the record number
00755     RecordNumber++;
00756 
00757     if (ok)
00758         return RecordNumber;
00759     else
00760         return 0;
00761 }
00762 
00763 
00764 /********************************************************************************************
00765 
00766 >   BOOL CXaraTemplateFile::WriteLabel(void)
00767 
00768     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00769     Created:    17/07/97
00770     Inputs:     -
00771     Returns:    FALSE if fails
00772     Purpose:    Writes a label to the file of the form %R<RecordNumber>%
00773 
00774 ********************************************************************************************/
00775 
00776 BOOL CXaraTemplateFile::WriteLabel(void)
00777 {
00778     // TODOG: Well, not yet it doesn't...
00779 
00780     char Buffer[32];
00781 
00782     UINT32 Num = sprintf(Buffer, "%%R%d%%", (RecordNumber+1));
00783 
00784     return(pCCFile->write(Buffer, Num).good());
00785 }
00786 
00787 
00788 /********************************************************************************************
00789 
00790 >   BOOL CXaraTemplateFile::WriteAsText(CXaraFileRecord* pRecord)
00791 
00792     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00793     Created:    12/07/97
00794     Inputs:     pRec - pointer to record to write
00795     Purpose:    Writes the record in text format
00796 
00797     Notes:      This function is not particularly elegant (mainly due to time restrictions)
00798 
00799 ********************************************************************************************/
00800 
00801 BOOL CXaraTemplateFile::WriteAsText(CXaraFileRecord* pRecord)
00802 {
00803     ERROR3IF(pRecord == NULL, "NULL record in CXaraTemplateFile::WriteAsText");
00804 
00805     if (pRecord == NULL)
00806         return(FALSE);
00807 
00808     char Buffer[256];               // Allocate a buffer on the stack for now
00809     Buffer[0] = 0;                  // and make it empty
00810     INT32 Num;
00811 
00812     FTTypeList* pTypeList = pRecord->GetTypeList();
00813 
00814     // Write the "record header"
00815     Num = sprintf(Buffer, "{%d,%d", pRecord->GetTag(), pRecord->GetSize());
00816     BOOL ok = pCCFile->write(Buffer, Num).good();
00817 
00818     if (ok &&
00819         pTypeList != NULL &&
00820         pTypeList->GetCount() > 0)
00821     {
00822         BYTE* pBinPtr = pRecord->GetBuffer();
00823         BYTE* pPtr = pTypeList->GetBuffer();
00824         DWORD Count = pTypeList->GetCount();
00825         DWORD Index;
00826         for (Index = 0; ok && (Index < Count); Index++)
00827         {
00828 //          char* pType = NULL;
00829             Num = 0;                // Nothing to write
00830 
00831             // Now we fill the buffer and set Num to the number of bytes to write
00832             // or just write it ourselves and set Num to zero
00833             
00834             switch (pPtr[Index])
00835             {
00836                 case FTT_BYTE:
00837                     {
00838                         BYTE ByteVal = *pBinPtr;
00839                         TRACEUSER( "Gerry", _T("Byte : %d\n"), ByteVal);
00840                         Num = sprintf(Buffer, ",B(%u)", ByteVal);
00841                         pBinPtr+=1;
00842                         break;
00843                     }
00844 
00845                 case FTT_UINT32:
00846                     {
00847                         UINT32 ULongVal = *((UINT32*)pBinPtr);
00848                         TRACEUSER( "Gerry", _T("ULong : %u\n"), ULongVal);
00849                         Num = sprintf(Buffer, ",U(%u)", ULongVal);
00850                         pBinPtr+=4;
00851                         break;
00852                     }
00853                 
00854                 case FTT_INT32:
00855                     {
00856                         INT32 LongVal = *((INT32*)pBinPtr);
00857                         TRACEUSER( "Gerry", _T("Long : %d\n"), LongVal);
00858                         Num = sprintf(Buffer, ",L(%d)", LongVal);
00859                         pBinPtr+=4;
00860                         break;
00861                     }
00862                 
00863                 case FTT_UINT16:
00864                     {
00865                         WORD WordVal = *((WORD*)pBinPtr);
00866                         TRACEUSER( "Gerry", _T("UINT16 : %hu\n"), WordVal);
00867                         Num = sprintf(Buffer, ",W(%hu)", WordVal);
00868                         pBinPtr+=2;
00869                         break;
00870                     }
00871                 
00872                 case FTT_INT16:
00873                     {
00874                         INT16 ShortVal = *((INT16*)pBinPtr);
00875                         TRACEUSER( "Gerry", _T("INT16 : %hd\n"), ShortVal);
00876                         Num = sprintf(Buffer, ",I(%hd)", ShortVal);
00877                         pBinPtr+=2;
00878                         break;
00879                     }
00880 
00881                 case FTT_FLOAT:
00882                     {
00883                         double DoubleVal = *((FLOAT*)pBinPtr);
00884                         TRACEUSER( "Gerry", _T("Float : %g\n"), DoubleVal);
00885                         Num = sprintf(Buffer, ",F(%g)", DoubleVal);
00886                         pBinPtr+=4;
00887                         break;
00888                     }
00889                 
00890                 case FTT_DOUBLE:
00891                     {
00892                         double DoubleVal = *((double*)pBinPtr);
00893                         TRACEUSER( "Gerry", _T("Double : %g\n"), DoubleVal);
00894                         Num = sprintf(Buffer, ",D(%g)", DoubleVal);
00895                         pBinPtr+=8;
00896                         break;
00897                     }
00898                 
00899                 case FTT_REFERENCE:
00900                     {
00901                         INT32 LongVal = *((INT32*)pBinPtr);
00902                         TRACEUSER( "Gerry", _T("Long : %d\n"), LongVal);
00903                         if (LongVal <= 0)
00904                         {
00905                             // then write it as an INT32
00906                             Num = sprintf(Buffer, ",L(%d)", LongVal);
00907                         }
00908                         else
00909                         {
00910                             // Otherwise write a label reference
00911                             Num = sprintf(Buffer, ",R(R%d)", LongVal);
00912                         }
00913                         pBinPtr+=4;
00914                         break;
00915                     }
00916                 
00917                 case FTT_WCHAR:
00918                     {
00919                         TRACEUSER( "Gerry", _T("WCHAR : %d items\n"), Count - Index);
00920                         UINT32 NumChars = WriteMultipleWCHARs(&(pPtr[Index]), Count - Index, (UINT16*)pBinPtr);
00921                         if (NumChars == 0)
00922                             ok = FALSE;
00923                         pBinPtr += (NumChars * sizeof(WCHAR));  // Skip the pointerand 
00924                         Index += NumChars;                      // index on by NumChars
00925                         break;
00926                     }
00927                 
00928                 case FTT_COORD:
00929                     {
00930                         INT32* pLong = (INT32*)pBinPtr;
00931 //                      TRACEUSER( "Gerry", _T("Coord : %d, %d\n"), pLong[0], pLong[1]);
00932                         Num = sprintf(Buffer, ",C(%d,%d)", pLong[0], pLong[1]);
00933                         pBinPtr += 8;
00934                         break;
00935                     }
00936                 
00937                 case FTT_INTCOORD:
00938                     {
00939                         INT32 x = (pBinPtr[0] << 24);
00940                         INT32 y = (pBinPtr[1] << 24);
00941                         x += (pBinPtr[2] << 16);
00942                         y += (pBinPtr[3] << 16);
00943                         x += (pBinPtr[4] <<  8);
00944                         y += (pBinPtr[5] <<  8);
00945                         x += (pBinPtr[6] <<  0);
00946                         y += (pBinPtr[7] <<  0);
00947                         TRACEUSER( "Gerry", _T("IntCoord : %d, %d\n"), x, y);
00948                         Num = sprintf(Buffer, ",K(%d,%d)", x, y);
00949                         pBinPtr += 8;
00950                         break;
00951                     }
00952                 
00953                 case FTT_ASCII:
00954                     {
00955                         // Use ,ASC("String")
00956                         size_t len = strlen((char*)pBinPtr) + 1;
00957                         TRACEUSER("Gerry", _T("ASCII %d"), len);
00958                         ok = WriteSimpleASCII((char*)pBinPtr);
00959                         pBinPtr += len;
00960                         break;
00961                     }
00962 
00963                 case FTT_UNICODE:
00964                     {
00965                         UINT32 len = 1;
00966                         UINT16* pCh = (UINT16*)pBinPtr;
00967                         while (*pCh++ != 0)
00968                             len++;
00969                         TRACEUSER("Gerry", _T("Unicode %d"), len);
00970                         if (IsSimpleUnicode((UINT16*)pBinPtr))
00971                         {
00972                             ok = WriteSimpleUnicode((UINT16*)pBinPtr);
00973                         }
00974                         else
00975                         {
00976                             ok = WriteBinHex(pBinPtr, len);
00977                         }
00978                         pBinPtr += len;
00979                         break;
00980                     }
00981 
00982                 case FTT_BINHEX:
00983                     {
00984                         UINT32 len = *((DWORD*)(pPtr+Index+1)); // Get the length (BYTE pointer arithmetic)
00985                         TRACEUSER("Gerry", _T("BinHex %d"), len);
00986                         Index += 4;
00987                         ok = WriteBinHex(pBinPtr, len);
00988                         pBinPtr += len;
00989                         break;
00990                     }
00991                 default:
00992                     {
00993                         ok = FALSE;
00994                         break;
00995                     }
00996             }
00997 
00998             if (ok && Num > 0)
00999             {
01000 //              TRACEUSER( "Gerry", _T("Writing buffer  %d\n"), Num);
01001                 if (ok) ok = pCCFile->write(Buffer, Num).good();
01002             }
01003         }
01004     }
01005     
01006     if (ok) ok = pCCFile->write("}\r\n", 3).good();
01007 
01008     return(ok);
01009 }
01010 
01011 
01012 /********************************************************************************************
01013 
01014 >   BOOL CXaraTemplateFile::WriteBinHex(BYTE* pBuf, UINT32 BufSize)
01015 
01016     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01017     Created:    12/07/97
01018     Inputs:     pBuf - pointer to buffer to write
01019                 BufSize - number of bytes to write
01020     Purpose:    Writes the record in text format
01021 
01022     Notes:      This function is not particularly elegant (mainly due to time restrictions)
01023 
01024 ********************************************************************************************/
01025 
01026 BOOL CXaraTemplateFile::WriteBinHex(BYTE* pBuf, UINT32 BufSize)
01027 {
01028 //  TRACEUSER( "Gerry", _T("Writing BinHex  %d\n"), BufSize);
01029     
01030     // Write the type specifier
01031     BOOL ok = pCCFile->write(",BINH(", 6).good();
01032     // And get our special CCFile to translate it
01033     if (ok) ok = m_pBinHexFile->write(pBuf, BufSize).good();
01034     if (ok) ok = pCCFile->write(")", 1).good();
01035 
01036     return(ok);
01037 }
01038 
01039 
01040 
01041 /********************************************************************************************
01042 
01043 >   BOOL CXaraTemplateFile::IsSimpleUnicode(UINT16* pStr)
01044 
01045     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01046     Created:    12/07/97
01047     Inputs:     pStr - pointer to UNICODE string
01048     Purpose:    Determines if UNICODE is safe as ASCII
01049 
01050 ********************************************************************************************/
01051 
01052 BOOL CXaraTemplateFile::IsSimpleUnicode(UINT16* pStr)
01053 {
01054     if (pStr == NULL)
01055         return(FALSE);
01056     
01057     while (*pStr != 0)
01058     {
01059         if (((*pStr) > 126) ||
01060             ((*pStr) < 32))
01061         {
01062             return(FALSE);
01063         }
01064         pStr++;
01065     }
01066     
01067     return(TRUE);
01068 }
01069 
01070 
01071 /********************************************************************************************
01072 
01073 >   BOOL CXaraTemplateFile::WriteSimpleUnicode(WCHAR* pStr)
01074 
01075     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01076     Created:    12/07/97
01077     Inputs:     pBuf - pointer to buffer to write
01078                 BufSize - number of bytes to write
01079     Purpose:    Writes the record in text format
01080 
01081     Notes:      This function is not particularly elegant (mainly due to time restrictions)
01082 
01083 ********************************************************************************************/
01084 
01085 BOOL CXaraTemplateFile::WriteSimpleUnicode(UINT16* pStr)
01086 {
01087     if (pStr == NULL)
01088         return(FALSE);
01089     
01090     // Write the type specifier
01091     BOOL ok = pCCFile->write(",UNC(\"", 6).good();
01092 
01093     while (ok && *pStr != 0)
01094     {
01095         // Write a single byte
01096         ok = pCCFile->write(pStr).good();
01097 
01098         // If it's a quote then double it up
01099         if (ok && *pStr == '"')
01100             ok = pCCFile->write(pStr).good();
01101         
01102         // Advance to next UINT16
01103         pStr++;
01104     }
01105 
01106     if (ok) ok = pCCFile->write("\")", 2).good();
01107 
01108     return(ok);
01109 }
01110 
01111 
01112 
01113 /********************************************************************************************
01114 
01115 >   BOOL CXaraTemplateFile::WriteSimpleASCII(char* pStr)
01116 
01117     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01118     Created:    12/07/97
01119     Inputs:     pBuf - pointer to buffer to write
01120                 BufSize - number of bytes to write
01121     Purpose:    Writes the record in text format
01122 
01123     Notes:      This function is not particularly elegant (mainly due to time restrictions)
01124 
01125 ********************************************************************************************/
01126 
01127 BOOL CXaraTemplateFile::WriteSimpleASCII(char* pStr)
01128 {
01129     if (pStr == NULL)
01130         return(FALSE);
01131     
01132     // Write the type specifier
01133     BOOL ok = pCCFile->write(",ASC(\"", 6).good();
01134 
01135     while (ok && *pStr != 0)
01136     {
01137         // Write a single byte
01138         ok = pCCFile->write(pStr).good();
01139 
01140         // If it's a quote then double it up
01141         if (ok && *pStr == '"')
01142             ok = pCCFile->write(pStr).good();
01143         
01144         // Advance to next char
01145         pStr++;
01146     }
01147 
01148     if (ok) ok = pCCFile->write("\")", 2).good();
01149 
01150     return(ok);
01151 }
01152 
01153 
01154 
01155 /********************************************************************************************
01156 
01157 >   UINT32 CXaraTemplateFile::WriteMultipleWCHARs(BYTE* pTypes, DWORD Count, UINT16* pChars)
01158 
01159     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01160     Created:    12/07/97
01161     Inputs:     pTypes - pointer to array of types
01162                 Count - Size of type array
01163                 pChars - pointer to actual WCHARs
01164     Purpose:    Writes out one or more WCHARs using fancy concatenation to make the
01165                 output more readable
01166 
01167 ********************************************************************************************/
01168 
01169 UINT32 CXaraTemplateFile::WriteMultipleWCHARs(BYTE* pTypes, DWORD Count, UINT16* pChars)
01170 {
01171     TRACEUSER( "Gerry", _T("WriteMultipleWCHARs %d\n"), Count);
01172 
01173     ERROR3IF(pTypes == NULL, "NULL type array");
01174     ERROR3IF(pChars == NULL, "NULL chars array");
01175     ERROR3IF(pTypes[0] != FTT_WCHAR, "First type isn't a WCHAR");
01176     ERROR3IF(Count == 0, "No characters");
01177 
01178     if (Count == 0)
01179         return(0);
01180 
01181     WCHAR ch = pChars[0];
01182     if (Count == 1 || pTypes[1] != FTT_WCHAR)
01183         return(WriteSingleWCHAR(ch) ? 1 : 0);
01184 
01185     // Flag for type of current string
01186     BOOL bAscii = IsPrint(ch);
01187     BOOL ok = TRUE;
01188 
01189     // Indices where things change
01190     UINT32 ThisItem = 0;
01191     UINT32 NextItem = 1;
01192     UINT32 bContinue = TRUE;
01193     UINT32 NumWritten = 0;
01194 
01195     // While we should continue
01196     while (bContinue)
01197     {
01198         // While we have a next item, 
01199         while (ok &&
01200                 (NextItem < Count) &&
01201                 (pTypes[NextItem] == FTT_WCHAR) &&
01202                 (IsPrint(pChars[NextItem]) == bAscii))
01203         {
01204             NextItem++;
01205         }
01206 
01207         // Now the sense has changed or we are at the end...
01208         // So write out the data item
01209         if ((NextItem - ThisItem) == 1)
01210         {
01211             ok = WriteSingleWCHAR(pChars[ThisItem]);
01212         }
01213         else
01214         {
01215             if (bAscii)
01216             {
01217                 // Write the type specifier
01218                 ok = pCCFile->write(",WCS(\"", 6).good();
01219                 UINT32 i;
01220                 for (i = ThisItem; ok && (i < NextItem); i++)
01221                 {
01222                     // Write a single byte
01223                     ok = pCCFile->write(&(pChars[i])).good();
01224 
01225                     // If it's a quote then double it up
01226                     if (ok && pChars[i] == '"')
01227                         ok = pCCFile->write(&(pChars[i])).good();
01228                 }
01229 
01230                 if (ok) ok = pCCFile->write("\")", 2).good();
01231                 if (ok) NumWritten += NextItem - ThisItem;
01232             }
01233             else
01234             {
01235                 ok = WriteBinHex((BYTE*)&(pChars[ThisItem]), (NextItem - ThisItem) * sizeof(WCHAR));
01236                 if (ok) NumWritten += (NextItem - ThisItem);
01237             }
01238 
01239         }   // if ((NextItem - ThisItem) == 1)
01240 
01241 
01242         if (ok &&
01243             (NextItem < Count) &&
01244             (pTypes[NextItem] == FTT_WCHAR))
01245         {
01246 
01247             // Point at next item
01248             ThisItem = NextItem;
01249             // And then increment NextItem
01250             NextItem++;
01251             // Set correct sense for the next item
01252             bAscii = IsPrint(pChars[ThisItem]);
01253         }
01254         else
01255             bContinue = FALSE;      // Otherwise flag to stop
01256     }
01257 
01258     if (!ok)
01259         NumWritten = 0;
01260 
01261     return(NumWritten);
01262 }
01263 
01264 
01265 /********************************************************************************************
01266 
01267 >   BOOL CXaraTemplateFile::WriteSingleWCHAR(WCHAR ch)
01268 
01269     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01270     Created:    12/07/97
01271     Inputs:     ch - WCHAR to write
01272     Purpose:    Writes a single WCHAR as a complete data item
01273                 It uses WC() when the character is printable ascii otherwise it uses W()
01274                 output more readable
01275 
01276 ********************************************************************************************/
01277 
01278 BOOL CXaraTemplateFile::WriteSingleWCHAR(WCHAR ch)
01279 {
01280     BOOL ok = TRUE;
01281     char Buffer[16];
01282     UINT32 Num = 0;
01283     
01284     if (ch == '"')
01285     {
01286         // Special case the doubled up quotes
01287         memcpy(Buffer, ",WC(\"\"\"\")", 9);
01288     }
01289     else if (IsPrint(ch))
01290     {
01291         Num = sprintf(Buffer, ",WC(\"%c\")", (char)(ch & 0xFF));
01292     }
01293     else
01294     {
01295         Num = sprintf(Buffer, ",W(%hu)", (INT16)(ch & 0xFFFF));
01296     }
01297 
01298     ok = pCCFile->write(Buffer, Num).good();
01299 
01300     return(ok);
01301 }

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