textfltr.cpp

Go to the documentation of this file.
00001 // $Id: textfltr.cpp 1282 2006-06-09 09:46:49Z 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 // An input filter for importing text files.
00099 
00100 
00101 #include "camtypes.h"
00102 #include "textfltr.h"
00103 
00104 #if BUILD_TEXT_FILTERS
00105 
00106 //#include "filtrres.h"
00107 
00108 // code headers
00109 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 #include "clipmap.h"
00111 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00114 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00115 #include "fontman.h"
00116 #include "nodetxts.h"
00117 #include "nodetext.h"
00118 #include "nodetxtl.h"
00119 //#include "oilfltrs.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00120 #include "page.h"
00121 //#include "pathname.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00122 #include "progress.h"
00123 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00124 #include "textfuns.h"
00125 
00126 // resource headers
00127 //#include "mario.h"
00128 //#include "peter.h"
00129 //#include "tim.h"
00130 
00131 
00132 DECLARE_SOURCE("$Revision: 1282 $");
00133 
00134 
00135 CC_IMPLEMENT_DYNAMIC(BaseTextFilter, TextFilter)
00136 
00137 
00138 #if BUILD_OTHER_TEXT_FILTER
00139 
00140 CC_IMPLEMENT_DYNAMIC(ANSITextFilter, BaseTextFilter)
00141 CC_IMPLEMENT_DYNAMIC(UnicodeTextFilter, ANSITextFilter)
00142 CC_IMPLEMENT_DYNAMIC(RTFTextFilter, BaseTextFilter)
00143 
00144 // RTF implementation classes
00145 CC_IMPLEMENT_DYNAMIC(StateStore, ListItem)
00146 
00147 CC_IMPLEMENT_DYNAMIC(RTFColourTable, List);
00148 CC_IMPLEMENT_DYNAMIC(RTFColourTableEntry, ListItem);
00149 CC_IMPLEMENT_DYNAMIC(RTFFontTable, List);
00150 CC_IMPLEMENT_DYNAMIC(RTFFontTableEntry, ListItem);
00151 
00152 CC_IMPLEMENT_MEMDUMP(RTFControlAction, CC_CLASS_MEMDUMP)
00153 CC_IMPLEMENT_MEMDUMP(RTFEnterSkipDest, RTFControlAction)
00154 CC_IMPLEMENT_MEMDUMP(RTFNewParaAction, RTFControlAction)
00155 CC_IMPLEMENT_MEMDUMP(RTFColourTableAction, RTFControlAction)
00156 CC_IMPLEMENT_MEMDUMP(RTFFontTableAction, RTFControlAction)
00157 
00158 CC_IMPLEMENT_MEMDUMP(RTFPaperWidth, RTFControlAction)
00159 CC_IMPLEMENT_MEMDUMP(RTFPaperHeight, RTFControlAction)
00160 CC_IMPLEMENT_MEMDUMP(RTFLeftMargin, RTFControlAction)
00161 CC_IMPLEMENT_MEMDUMP(RTFRightMargin, RTFControlAction)
00162 CC_IMPLEMENT_MEMDUMP(RTFTopMargin, RTFControlAction)
00163 CC_IMPLEMENT_MEMDUMP(RTFBottomMargin, RTFControlAction)
00164 CC_IMPLEMENT_MEMDUMP(RTFResetCharAttrs, RTFControlAction)
00165 CC_IMPLEMENT_MEMDUMP(RTFResetParaAttrs, RTFControlAction)
00166 CC_IMPLEMENT_MEMDUMP(RTFTableCellAction, RTFControlAction)
00167 CC_IMPLEMENT_MEMDUMP(RTFTableRowAction, RTFControlAction)
00168 CC_IMPLEMENT_MEMDUMP(RTFTabAction, RTFControlAction)
00169 CC_IMPLEMENT_MEMDUMP(RTFSingleCharAction, RTFControlAction)
00170 
00171 CC_IMPLEMENT_MEMDUMP(RTFAttributeAction, RTFControlAction)
00172 CC_IMPLEMENT_MEMDUMP(RTFBoldAttribute, RTFAttributeAction)
00173 CC_IMPLEMENT_MEMDUMP(RTFTextSizeAttribute, RTFAttributeAction)
00174 CC_IMPLEMENT_MEMDUMP(RTFTextColourAttribute, RTFAttributeAction)
00175 CC_IMPLEMENT_MEMDUMP(RTFTextFontAttribute, RTFAttributeAction)
00176 CC_IMPLEMENT_MEMDUMP(RTFItalicAttribute, RTFAttributeAction)
00177 CC_IMPLEMENT_MEMDUMP(RTFNoscriptAttribute, RTFAttributeAction)
00178 CC_IMPLEMENT_MEMDUMP(RTFSubscriptAttribute, RTFAttributeAction)
00179 CC_IMPLEMENT_MEMDUMP(RTFSuperscriptAttribute, RTFAttributeAction)
00180 CC_IMPLEMENT_MEMDUMP(RTFTWIPTrackingAttribute, RTFAttributeAction)
00181 CC_IMPLEMENT_MEMDUMP(RTFQPTrackingAttribute, RTFAttributeAction)
00182 
00183 CC_IMPLEMENT_MEMDUMP(RTFHexCharAction, RTFSingleCharAction)
00184 CC_IMPLEMENT_MEMDUMP(RTFEmDashAction, RTFSingleCharAction)
00185 CC_IMPLEMENT_MEMDUMP(RTFEnDashAction, RTFSingleCharAction)
00186 CC_IMPLEMENT_MEMDUMP(RTFEmSpaceAction, RTFSingleCharAction)
00187 CC_IMPLEMENT_MEMDUMP(RTFEnSpaceAction, RTFSingleCharAction)
00188 CC_IMPLEMENT_MEMDUMP(RTFBulletAction, RTFSingleCharAction)
00189 CC_IMPLEMENT_MEMDUMP(RTFSingleLeftQuoteAction, RTFSingleCharAction)
00190 CC_IMPLEMENT_MEMDUMP(RTFSingleRightQuoteAction, RTFSingleCharAction)
00191 CC_IMPLEMENT_MEMDUMP(RTFDoubleLeftQuoteAction, RTFSingleCharAction)
00192 CC_IMPLEMENT_MEMDUMP(RTFDoubleRightQuoteAction, RTFSingleCharAction)
00193 CC_IMPLEMENT_MEMDUMP(RTFNonBreakSpaceAction, RTFSingleCharAction)
00194 
00195 #endif  //#if BUILD_OTHER_TEXT_FILTER
00196 
00197 #define new CAM_DEBUG_NEW
00198 
00199 
00200 
00201 /********************************************************************************************
00202 >   BaseTextFilter::BaseTextFilter()
00203 
00204     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00205     Created:    24/11/95
00206     Purpose:    Constructor.  Initialises member variables
00207 ********************************************************************************************/
00208 BaseTextFilter::BaseTextFilter()
00209 {
00210 }
00211 
00212 
00213 
00214 /********************************************************************************************
00215 >   BaseTextFilter::~BaseTextFilter()
00216 
00217     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00218     Created:    24/11/95
00219     Purpose:    Destructor.  Frees memory and cleans up.
00220 ********************************************************************************************/
00221 BaseTextFilter::~BaseTextFilter()
00222 {
00223 
00224 }
00225 
00226 
00227 
00228 /********************************************************************************************
00229 >   TextStory* BaseTextFilter::CreateImportStory(DocCoord Pos);
00230 
00231     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00232     Created:    24/11/95
00233     Inputs:     Pos - the position of the top left of the text story
00234     Outputs:    -
00235     Returns:    Pointer to a created TextStory object.  NULL on error
00236     Purpose:    Creates an empty text story for importing characters into
00237     SeeAlso:    BaseTextFilter::AddCharToStory
00238 ********************************************************************************************/
00239 TextStory* BaseTextFilter::CreateImportStory(DocCoord Pos)
00240 {
00241     return TextStory::CreateTextObject(Pos);
00242 }
00243 
00244 
00245 
00246 /********************************************************************************************
00247 >   VisibleTextNode* BaseTextFilter::AddCharToStory(TextStory* pStory, WCHAR NewChar);
00248 
00249     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00250     Created:    24/11/95
00251     Inputs:     pStory - pointer to the story to add character to
00252                 NewChar - the character (Unicode value)
00253     Outputs:    -
00254     Returns:    Pointer to the new character, NULL for error
00255     Purpose:    Adds the given character to the story.  It is added as the last character on
00256                 the last line.  The filters current attributes are applied to the new
00257                 character.
00258     SeeAlso:    BaseTextFilter::AddNewLineToStory
00259 ********************************************************************************************/
00260 VisibleTextNode* BaseTextFilter::AddCharToStory(TextStory* pStory, WCHAR NewChar)
00261 {
00262     ERROR2IF(pStory == NULL, NULL, "NULL Story pointer");
00263     
00264     // Find the EOLNode on the last line
00265     VisibleTextNode* pLastNode = pStory->FindLastVTN();
00266     ERROR2IF(pLastNode == NULL, NULL, "Story was (very) empty");
00267 
00268     // Create a new character, inserting into the story at the same time
00269     VisibleTextNode* pNew = new TextChar(pLastNode, PREV, NewChar);
00270 
00271     if (pNew != NULL)
00272     {
00273         if (!AttributeManager::ApplyBasedOnDefaults(pNew, CurrentAttrs))
00274         {
00275             delete pNew;
00276             pNew = NULL;
00277         }
00278     }
00279 
00280     return pNew;
00281 }
00282 
00283 
00284 
00285 /********************************************************************************************
00286 >   BOOL BaseTextFilter::AddNewLineToStory(TextStory* pStory)
00287 
00288     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00289     Created:    24/11/95
00290     Inputs:     pStory - pointer to the story to add the line to
00291     Outputs:    -
00292     Returns:    TRUE/FALSE for success/failure
00293     Purpose:    Adds a new (empty) line to the end of the story
00294     SeeAlso:    BaseTextFilter::AddCharToStory
00295 ********************************************************************************************/
00296 BOOL BaseTextFilter::AddNewLineToStory(TextStory* pStory)
00297 {
00298     ERROR2IF(pStory == NULL, NULL, "NULL Story pointer");
00299 
00300     // Create the new line as the last child of the story
00301     TextLine* pNewLine = new TextLine(pStory, LASTCHILD);
00302 
00303     // Create an EOL node for the new line
00304     EOLNode* pEOL = NULL;
00305     if (pNewLine != NULL)
00306     {
00307         pEOL = new EOLNode(pNewLine, LASTCHILD);
00308         if ( (pEOL == NULL) || (!AttributeManager::ApplyBasedOnDefaults(pEOL, CurrentAttrs)) )
00309         {
00310             pNewLine->CascadeDelete();
00311             delete pNewLine;
00312             pNewLine = NULL;
00313         }
00314     }
00315     
00316     return ((pNewLine != NULL) && (pEOL != NULL));
00317 }
00318 
00319 
00320 
00321 /********************************************************************************************
00322 >   BOOL BaseTextFilter::AddTabToStory(TextStory* pStory, MILLIPOINT TabLength = 50000)
00323 
00324     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00325     Created:    25/11/95
00326     Inputs:     pStory - pointer to the story to add the tab to
00327                 TabLength - the length of the tab
00328     Outputs:    -
00329     Returns:    TRUE/FALSE for success/failure
00330     Purpose:    Adds a TAB character to the story.  As stories currently don't have tabs a
00331                 kern character of the appropiate size is added instead
00332     SeeAlso:    BaseTextFilter::AddCharToStory
00333 ********************************************************************************************/
00334 BOOL BaseTextFilter::AddTabToStory(TextStory* pStory, MILLIPOINT TabLength)
00335 {
00336     ERROR2IF(pStory == NULL, FALSE, "NULL Story pointer");
00337 
00338     // Find the EOLNode on the last line
00339     VisibleTextNode* pLastNode = pStory->FindLastVTN();
00340     ERROR2IF(pLastNode == NULL, FALSE, "Story was (very) empty");
00341 
00342     // Create a new kern, inserting into the story at the same time
00343     KernCode* pNewKern = new KernCode(pLastNode, PREV, DocCoord(TabLength, 0));
00344 
00345     if (pNewKern != NULL)
00346         return AttributeManager::ApplyBasedOnDefaults(pNewKern, CurrentAttrs);
00347     else
00348         return FALSE;
00349 }
00350 
00351 
00352 
00353 
00354 #if BUILD_OTHER_TEXT_FILTER
00355 
00356 /********************************************************************************************
00357 >   ANSITextFilter::ANSITextFilter()
00358 
00359     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00360     Created:    24/11/95
00361     Purpose:    Filter constructor - this initialises the default attributes and the
00362                 input buffer.
00363 ********************************************************************************************/
00364 ANSITextFilter::ANSITextFilter()
00365 {
00366     Flags.CanImport = TRUE;
00367     Flags.CanExport = FALSE;
00368 
00369     // Set up filter descriptions.
00370     FilterName.Load(_R(IDT_TEXT_FILTERNAME));
00371     FilterInfo.Load(_R(IDT_TEXT_FILTERINFO));
00372     FilterID = FILTERID_TEXT_ASCII;
00373 
00374     BytesReadSoFar = 0;
00375     EscapeWasPressed = FALSE;
00376 };
00377 
00378 
00379 
00380 /********************************************************************************************
00381 >   ANSITextFilter::~ANSITextFilter()
00382 
00383     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00384     Created:    24/11/95
00385     Purpose:    Destructor for the filter
00386 ********************************************************************************************/
00387 ANSITextFilter::~ANSITextFilter()
00388 {
00389 }
00390 
00391 
00392 
00393 /********************************************************************************************
00394 >   BOOL ANSITextFilter::Init()
00395 
00396     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00397     Created:    24/11/95
00398     Returns:    TRUE for successful initialisation, FALSE if error occured
00399     Purpose:    Initialise the filter (attaches a TextOILFilter object).
00400     SeeAlso:    TextOILFilter
00401 ********************************************************************************************/
00402 BOOL ANSITextFilter::Init()
00403 {
00404     // Get the OILFilter object
00405     pOILFilter = new ANSITextOILFilter(this);
00406     if (pOILFilter == NULL)
00407         return FALSE;
00408 
00409     // All ok
00410     return TRUE;
00411 }
00412 
00413 
00414 
00415 /********************************************************************************************
00416 >   virtual BOOL ANSITextFilter::IsDefaultDocRequired(const TCHAR* pcszPathName)
00417 
00418     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00419     Created:    24/11/95
00420     Inputs:     pcszPathName - pointer to the pathname to check
00421     Returns:    TRUE if the filter requires a default document, FALSE if not.
00422     Purpose:    Works out if opening a file of this type requires a default document to be
00423                 loaded.  This filter always returns TRUE as ANSI text files have no page
00424                 information
00425     SeeAlso:    Filter::IsDefaultDocRequired
00426 ********************************************************************************************/
00427 BOOL ANSITextFilter::IsDefaultDocRequired(const TCHAR* pcszPathName)
00428 {
00429     return TRUE;
00430 }   
00431 
00432 
00433 
00434 /********************************************************************************************
00435 >   INT32 ANSITextFilter::HowCompatible(PathName& Filename, ADDR HeaderStart, UINT32 HeaderSize, UINT32 FileSize)
00436 
00437     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00438     Created:    24/11/95
00439     Inputs:     Filename - name of the file.
00440                 HeaderStart - Address of the first few bytes of the file.
00441                 HeaderSize - the number of bytes in the header pointed to by FileStart.
00442                 FileSize - the size of the whole file, in bytes.
00443     Returns:    Compatibility: 0 => Not an ANSI text file; 10 => It is an ANSI text file
00444     Purpose:    Analyse a file to see if it contains ANSI text.
00445     SeeAlso:    TextOILFilter::HowCompatible
00446 ********************************************************************************************/
00447 INT32 ANSITextFilter::HowCompatible(PathName& Filename, ADDR HeaderStart, UINT32 HeaderSize, UINT32 FileSize)
00448 {
00449 PORTNOTE("byteorder", "TODO: Check byte ordering")
00450     if (pOILFilter == NULL)
00451     {
00452         ERROR3("No oil filter!");
00453         return 0;
00454     }
00455     
00456     // check the file type against the type for text files.  If it matches only return 9 so the 
00457     // more specialised text files (eg Unicode) can claim it by returning 10.
00458     if (pOILFilter->DoesExtensionOfPathNameMatch(&Filename))
00459         return 9;
00460 
00461     // We can have a stab at loading any file as text as a last resort
00462     return 1;
00463 }
00464 
00465 
00466 
00467 /********************************************************************************************
00468 >   BOOL ANSITextFilter::PrepareToImport()
00469 
00470     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00471     Created:    24/11/95
00472     Returns:    TRUE if it succeeds, FALSE if not.
00473     Purpose:    Sets up the filter so it can attempt to read in a file.
00474     SeeAlso:    ANSITextFilter::CleanUpAfterImport
00475 ********************************************************************************************/
00476 BOOL ANSITextFilter::PrepareToImport()
00477 {
00478     // Get a default set of attributes for ink objects.
00479     if (!SetUpCurrentAttrs())
00480         return FALSE;
00481 
00482     BytesReadSoFar = 0;
00483     EscapeWasPressed = FALSE;
00484 
00485     return TRUE;
00486 }
00487 
00488 
00489 
00490 /********************************************************************************************
00491 >   void ANSITextFilter::CleanUpAfterImport()
00492 
00493     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00494     Created:    24/11/95
00495     Purpose:    Delete dynamic objects used in the import process.
00496     SeeAlso:    ANSITextFilter::PrepareToImport; ANSITextFilter::DoImport
00497 ********************************************************************************************/
00498 void ANSITextFilter::CleanUpAfterImport()
00499 {
00500     DeleteCurrentAttrs();
00501 }
00502 
00503 
00504 
00505 /********************************************************************************************
00506 >   BOOL ANSITextFilter::DoImport(SelOperation *Op, CCLexFile* pFile, 
00507                                    Document *DestDoc, BOOL AutoChosen, ImportPosition *Pos)
00508 
00509     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00510     Created:    24/11/93
00511     Inputs:     Op - pointer to the operation that this read process is associated with.
00512                 pFile - The file that we are trying to import
00513                 DestDoc - pointer to the document to insert the file data into.
00514                 AutoChosen -
00515                 Pos - pointer to the position to insert the text file at
00516     Returns:    TRUE if the read was successful, FALSE if not.
00517     Purpose:    Import the named text file into the specified document.
00518                 If the read is successful, the End() function of the 'Op' operation is
00519                 called, otherwise it is not called.
00520     Errors:     Unable to open file, corrupted document tree found.
00521 ********************************************************************************************/
00522 BOOL ANSITextFilter::DoImport(SelOperation *Op, CCLexFile* pFile, 
00523                                Document *DestDoc, BOOL AutoChosen, ImportPosition *Pos)
00524 {
00525     ERROR2IF((Op == NULL) || (pFile == NULL) || (DestDoc == NULL), FALSE, "NULL Parameter");
00526 
00527     // Let's get ready
00528     if (!PrepareToImport()) return FALSE;
00529 
00530     // Get spread and import position
00531     Spread *pSpread = NULL;
00532     DocCoord ImportPos(0,0);
00533     if (Pos == NULL)
00534     {
00535         pSpread = GetFirstSpread(DestDoc);
00536         ERROR2IF(pSpread == NULL, FALSE, "No spread in document");
00537         Page* pPage = pSpread->FindFirstPageInSpread();
00538         ERROR2IF(pPage == NULL, FALSE, "No page in spread");
00539         ImportPos = DocCoord(pPage->GetPageRect().lox, pPage->GetPageRect().hiy);
00540     }
00541     else
00542     {
00543         pSpread = Pos->pSpread;
00544         ImportPos = Pos->Position;
00545     }
00546 
00547     // Create a text story object to add the characters into.
00548     TextStory* pStory = CreateImportStory(ImportPos);
00549     if (pStory == NULL)
00550         return FALSE;
00551     
00552     //FlagChangedByOp() modified to mModifiedByOp()
00553     pStory->mModifiedByOp();
00554     if (!DestDoc->GetAttributeMgr().ApplyCurrentAttribsToNode(pStory))
00555     {
00556         pStory->CascadeDelete();
00557         delete pStory;
00558         return FALSE;
00559     }
00560     
00561     // Initialise our handling of the file
00562     pFile->SetReportErrors(FALSE);
00563     pFile->SetThrowExceptions(FALSE);
00564 
00565     // Call the virtual import function
00566     BOOL Success = DoInternalImport(pStory, pFile);
00567     
00568     // Clean up after importing
00569     EndSlowJob();
00570     CleanUpAfterImport();
00571 
00572     // Insert the new sub-tree into the document
00573     if (!EscapeWasPressed)
00574     {
00575         if (Success)
00576             Success = pStory->FormatAndChildren();
00577         if (Success)
00578             Success = Op->DoInsertNewNode(pStory, pSpread, TRUE);
00579     }
00580     
00581     // If the load failed for any reason, delete the subtree we have created
00582     if (!Success || EscapeWasPressed)
00583     {
00584         pStory->CascadeDelete();
00585         delete pStory;
00586     }
00587 
00588     return Success;
00589 }
00590 
00591 
00592 
00593 /********************************************************************************************
00594 >   BOOL ANSITextFilter::DoExport(Operation*, CCLexFile*, PathName*, Document*)
00595 
00596     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00597     Created:    24/11/95
00598     Inputs:     As base class version.
00599     Returns:    TRUE/FALSE for success/failure
00600     Purpose:    Exports the document as an ANSI text file.
00601     SeeAlso:    Filter::DoExport
00602 ********************************************************************************************/
00603 BOOL ANSITextFilter::DoExport(Operation*, CCLexFile*, PathName* pPath, Document*)
00604 {
00605     ERROR3("ANSITextFilter::DoExport is not implemented");
00606     return FALSE;
00607 }
00608 
00609 
00610 
00611 /********************************************************************************************
00612 >   virtual BOOL ANSITextFilter::DoInternalImport(TextStory* pImportStory, CCLexFile* pFile)
00613 
00614     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00615     Created:    25/11/95
00616     Inputs:     pImportStory - the TextStory to import into
00617                 pFile - the file to read the characters from
00618     Returns:    TRUE/FALSE for success/failure
00619     Purpose:    Imports ANSI and multi-byte characters from the file into the text story.
00620     SeeAlso:    ANSITextFilter::DoImport
00621 ********************************************************************************************/
00622 BOOL ANSITextFilter::DoInternalImport(TextStory* pImportStory, CCLexFile* pFile)
00623 {
00624     ERROR2IF((pImportStory == NULL) || (pFile == NULL), FALSE, "NULL entry parameter");
00625     UINT32 FileSize = pFile->Size();
00626         
00627     // Set the progress indicator for a nice percentage display
00628     String_64 ImportMessage(_R(IDT_IMPORTMSG_TEXT));
00629     ImportMessage = GetImportProgressString(pFile, _R(IDT_IMPORTMSG_TEXT));
00630     BeginSlowJob(FileSize, TRUE, &ImportMessage);
00631 
00632     // Skip over any header that may be on the file
00633     if (!SkipHeader(pFile))
00634         return FALSE;
00635 
00636     // Process the file character by character, adding it to the story each time
00637     WCHAR PrevChar = ' ';
00638     WCHAR NewChar = ' ' ;
00639     BOOL ok = TRUE;
00640     do 
00641     {
00642         // Read and process each character
00643         PrevChar = NewChar;
00644         NewChar = GetNextCharacter(pFile);
00645 
00646         if (NewChar < ' ')
00647         {
00648             switch (NewChar)
00649             {
00650                 case 0x00:  // Error in reading
00651                     ok = FALSE;
00652                     break;
00653                 case 0x09:  // Tab
00654                     ok = AddTabToStory(pImportStory);
00655                     break;
00656                 case 0x0A:  // NewLine
00657                     if (PrevChar != 0x0D)
00658                         ok = AddNewLineToStory(pImportStory);
00659                     break;
00660                 case 0x0D:  // CR
00661                     if (PrevChar != 0x0A)
00662                         ok = AddNewLineToStory(pImportStory);
00663                     break;
00664                 default:
00665                     ;       // Ignore the character
00666             }
00667         }
00668         else
00669             ok = (AddCharToStory(pImportStory, NewChar) != NULL);
00670 
00671         if (!ContinueSlowJob(BytesReadSoFar))
00672         {
00673             EscapeWasPressed = TRUE;
00674             return TRUE;
00675         }
00676     }
00677     while ((BytesReadSoFar < FileSize) && ok && pFile->good());
00678 
00679     return pFile->good() && ok;
00680 }
00681 
00682 
00683 
00684 /********************************************************************************************
00685 >   WCHAR ANSITextFilter::GetNextCharacter(CCLexFile* pFile)
00686 
00687     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00688     Created:    25/11/95
00689     Inputs:     pImportStory - the TextStory to import into
00690                 pFile - the file to read the characters from
00691     Returns:    Next character from file.  0 if error
00692     Purpose:    Gets the next character from the import file
00693     SeeAlso:    ANSITextFilter::DoInternalImport
00694 ********************************************************************************************/
00695 WCHAR ANSITextFilter::GetNextCharacter(CCLexFile* pFile)
00696 {
00697     ERROR2IF((pOILFilter == NULL), 0, "No Text OIL filter");
00698 
00699     UINT32 BytesRead = 0;
00700     WCHAR ReadChar = ((ANSITextOILFilter*)pOILFilter)->ReadMultiByteChar(pFile, &BytesRead);
00701     
00702     BytesReadSoFar += BytesRead;
00703 
00704     return ReadChar;
00705 }
00706 
00707 
00708 
00709 /********************************************************************************************
00710 >   virtual BOOL ANSITextFilter::SkipHeader(CCLexFile* pFile)
00711 
00712     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00713     Created:    25/11/95
00714     Inputs:     pFile - the file to read the characters from
00715     Returns:    TRUE/FALSE for success/failure
00716     Purpose:    Does nothing as ANSI text files have no header
00717 ********************************************************************************************/
00718 BOOL ANSITextFilter::SkipHeader(CCLexFile* pFile)
00719 {
00720     return TRUE;
00721 }
00722 
00723 
00724 
00725 
00726 
00727 
00728 
00729 
00730 /********************************************************************************************
00731 >   UnicodeTextFilter::UnicodeTextFilter()
00732 
00733     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00734     Created:    24/11/95
00735     Purpose:    Filter constructor - this initialises the default attributes and the
00736                 input buffer.
00737 ********************************************************************************************/
00738 UnicodeTextFilter::UnicodeTextFilter()
00739 {
00740     Flags.CanImport = TRUE;
00741     Flags.CanExport = FALSE;
00742 
00743     // Set up filter descriptions.
00744     FilterName.Load(_R(IDT_TEXT_FILTERNAME));
00745     FilterInfo.Load(_R(IDT_TEXT_FILTERINFO));
00746     FilterID = FILTERID_TEXT_UNICODE;
00747 };
00748 
00749 
00750 
00751 /********************************************************************************************
00752 >   UnicodeTextFilter::~UnicodeTextFilter()
00753 
00754     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00755     Created:    24/11/95
00756     Purpose:    Destructor for the filter - this deallocates the input buffer.
00757 ********************************************************************************************/
00758 
00759 UnicodeTextFilter::~UnicodeTextFilter()
00760 {
00761 }
00762 
00763 
00764 
00765 /********************************************************************************************
00766 >   BOOL UnicodeTextFilter::Init()
00767 
00768     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00769     Created:    24/11/95
00770     Returns:    TRUE for successful initialisation, FALSE if error occured
00771     Purpose:    Initialise the filter (attaches an OILFilter object).
00772     SeeAlso:    UnicodeTextOILFilter
00773 ********************************************************************************************/
00774 BOOL UnicodeTextFilter::Init()
00775 {
00776     // Get the OILFilter object
00777     pOILFilter = new UnicodeTextOILFilter(this);
00778     if (pOILFilter == NULL)
00779         return FALSE;
00780 
00781     // All ok
00782     return TRUE;
00783 }
00784 
00785 
00786 
00787 /********************************************************************************************
00788 >   INT32 UnicodeTextFilter::HowCompatible(PathName& Filename, ADDR HeaderStart, UINT32 HeaderSize, UINT32 FileSize)
00789 
00790     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00791     Created:    24/11/95
00792     Inputs:     Filename - name of the file.
00793                 HeaderStart - Address of the first few bytes of the file.
00794                 HeaderSize - the number of bytes in the header pointed to by FileStart.
00795                 FileSize - the size of the whole file, in bytes.
00796     Returns:    Compatibility: 0 => Not a Unicode text file; 10 => It is a Unicode text file
00797     Purpose:    Analyse a file to see if it contains Unicode text.
00798     SeeAlso:    ANSITextFilter::HowCompatible
00799 ********************************************************************************************/
00800 INT32 UnicodeTextFilter::HowCompatible(PathName& Filename, ADDR HeaderStart, UINT32 HeaderSize, UINT32 FileSize)
00801 {
00802 PORTNOTE("byteorder", "TODO: Check byte ordering")
00803     if (pOILFilter == NULL)
00804     {
00805         ERROR3("No oil filter!");
00806         return 0;
00807     }
00808     
00809     // To load Unicode text the extension must match
00810     if (pOILFilter->DoesExtensionOfPathNameMatch(&Filename))
00811     {
00812         // The first two bytes must be 0xFFFE too
00813         if ( (*HeaderStart == 0xFF) && (*(HeaderStart+1) == 0xFE) )
00814             return 10;
00815     }
00816 
00817     return 0;
00818 }
00819 
00820 
00821 
00822 /********************************************************************************************
00823 >   WCHAR UnicodeTextFilter::GetNextCharacter(CCLexFile* pFile)
00824 
00825     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00826     Created:    25/11/95
00827     Inputs:     pImportStory - the TextStory to import into
00828                 pFile - the file to read the characters from
00829     Returns:    Next character from file.  0 if error
00830     Purpose:    Gets the next character from the import file
00831     SeeAlso:    UnicodeTextFilter::DoInternalImport
00832 ********************************************************************************************/
00833 WCHAR UnicodeTextFilter::GetNextCharacter(CCLexFile* pFile)
00834 {
00835     ERROR2IF((pOILFilter == NULL), 0, "No Text OIL filter");
00836 
00837     BytesReadSoFar += 2;
00838     return ((UnicodeTextOILFilter*)pOILFilter)->ReadUnicodeChar(pFile);
00839 }
00840 
00841 
00842 
00843 /********************************************************************************************
00844 >   virtual BOOL UnicodeTextFilter::SkipHeader(CCLexFile* pFile)
00845 
00846     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00847     Created:    25/11/95
00848     Inputs:     pFile - the file to read the characters from
00849     Returns:    TRUE/FALSE for success/failure
00850     Purpose:    Skips over the header on Unicode files
00851 ********************************************************************************************/
00852 BOOL UnicodeTextFilter::SkipHeader(CCLexFile* pFile)
00853 {
00854     BYTE Dummy[2];
00855 
00856     pFile->read(Dummy, 2);
00857     BytesReadSoFar += 2;
00858 
00859     return pFile->good();
00860 }
00861 
00862 
00863 
00864 /********************************************************************************************
00865 >   StateStore::StateStore()
00866 
00867     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00868     Created:    15/12/95
00869     Purpose:    Constructor - initialises member variables
00870 ********************************************************************************************/
00871 StateStore::StateStore()
00872 {
00873     DestinationState = rdsNorm;
00874     InternalState = risNorm;
00875     InterCharGap = 0;
00876 }
00877 
00878 StateStore::~StateStore() {}
00879     
00880 StateStore& StateStore::operator=(const StateStore& rhs)
00881 {
00882     this->DestinationState = rhs.DestinationState;
00883     this->InternalState = rhs.InternalState;
00884     this->InterCharGap = rhs.InterCharGap;
00885 
00886     return *this;
00887 }
00888 
00889 
00890 
00891 /********************************************************************************************
00892 >   RTFTextFilter::RTFTextFilter()
00893 
00894     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00895     Created:    25/11/95
00896     Purpose:    Filter constructor
00897 ********************************************************************************************/
00898 RTFTextFilter::RTFTextFilter()
00899 {
00900     Flags.CanImport = TRUE;
00901     Flags.CanExport = FALSE;
00902 
00903     // Set up filter descriptions.
00904     FilterName.Load(_R(IDT_RTF_FILTERNAME));
00905     FilterInfo.Load(_R(IDT_RTF_FILTERINFO));
00906     FilterID = FILTERID_TEXT_RTF;
00907 
00908     // Init member vars to safe values
00909     EscapeWasPressed = FALSE;
00910     pImportStory = NULL;
00911     BytesReadSoFar = 0;
00912     ImportHasFinished = FALSE;
00913 };
00914 
00915 
00916 
00917 /********************************************************************************************
00918 >   RTFTextFilter::~RTFTextFilter()
00919 
00920     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00921     Created:    25/11/95
00922     Purpose:    Destructor for the filter
00923 ********************************************************************************************/
00924 RTFTextFilter::~RTFTextFilter()
00925 {
00926 }
00927 
00928 
00929 
00930 /********************************************************************************************
00931 >   BOOL RTFTextFilter::Init()
00932 
00933     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00934     Created:    25/11/95
00935     Returns:    TRUE for successful initialisation, FALSE if error occured
00936     Purpose:    Initialise the filter (attaches a TextOILFilter object).
00937     SeeAlso:    RTFTextOILFilter
00938 ********************************************************************************************/
00939 BOOL RTFTextFilter::Init()
00940 {
00941     // Get the OILFilter object
00942     pOILFilter = new RTFTextOILFilter(this);
00943     if (pOILFilter == NULL)
00944         return FALSE;
00945 
00946     return ((RTFTextOILFilter*)pOILFilter)->RegisterWithClipboard(this);
00947 }
00948 
00949 
00950 
00951 /********************************************************************************************
00952 >   virtual BOOL RTFTextFilter::IsDefaultDocRequired(const TCHAR* pcszPathName)
00953 
00954     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00955     Created:    25/11/95
00956     Inputs:     pcszPathName    pointer to the pathname to check
00957     Returns:    TRUE if the filter requires a default document, FALSE if not.
00958     Purpose:    Works out if opening a file of this type requires a default document to be
00959                 loaded.  This filter always returns TRUE as RTF files have no page
00960                 information
00961     SeeAlso:    Filter::IsDefaultDocRequired
00962 ********************************************************************************************/
00963 BOOL RTFTextFilter::IsDefaultDocRequired(const TCHAR* pcszPathName)
00964 {
00965     return TRUE;
00966 }   
00967 
00968 
00969 
00970 /********************************************************************************************
00971 >   INT32 RTFTextFilter::HowCompatible(PathName& Filename, ADDR HeaderStart, UINT32 HeaderSize, UINT32 FileSize)
00972 
00973     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00974     Created:    24/11/95
00975     Inputs:     Filename - name of the file.
00976                 HeaderStart - Address of the first few bytes of the file.
00977                 HeaderSize - the number of bytes in the header pointed to by FileStart.
00978                 FileSize - the size of the whole file, in bytes.
00979     Returns:    Compatibility: 0 => Not a RTF file; 10 => It is a RTF file
00980     Purpose:    Analyse a file to see if it contains RTF information
00981 ********************************************************************************************/
00982 INT32 RTFTextFilter::HowCompatible(PathName& Filename, ADDR HeaderStart, UINT32 HeaderSize, UINT32 FileSize)
00983 {
00984 PORTNOTE("byteorder", "TODO: Check byte ordering")
00985     if (pOILFilter == NULL)
00986     {
00987         ERROR3("No oil filter!");
00988         return 0;
00989     }
00990 
00991     // File extension must be RTF
00992     if (pOILFilter->DoesExtensionOfPathNameMatch(&Filename))
00993     {
00994         // File must start "{\rtf"
00995         if ((*HeaderStart == '{') && (*(HeaderStart+1) == '\\') && (*(HeaderStart+2) == 'r')
00996                     && (*(HeaderStart+3) == 't') && (*(HeaderStart+4) == 'f') )
00997             return 10;
00998     }
00999 
01000     return 0;
01001 }
01002 
01003 
01004 
01005 /********************************************************************************************
01006 >   BOOL RTFTextFilter::PrepareToImport()
01007 
01008     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01009     Created:    25/11/95
01010     Returns:    TRUE if it succeeds, FALSE if not.
01011     Purpose:    Sets up the filter so it can attempt to read in a file.
01012     SeeAlso:    RTFTextFilter::CleanUpAfterImport
01013 ********************************************************************************************/
01014 BOOL RTFTextFilter::PrepareToImport()
01015 {
01016     // Get a default set of attributes for ink objects.
01017     if (!SetUpCurrentAttrs())
01018         return FALSE;
01019 
01020     // Set the fill colour to black and the outline to none
01021     SetFillColour(DocColour(COLOUR_BLACK));
01022     SetLineColour(DocColour(COLOUR_TRANS));
01023 
01024     BytesReadSoFar = 0;
01025     pImportStory = NULL;
01026     EscapeWasPressed = FALSE;
01027     ImportHasFinished = FALSE;
01028 
01029     // Ensure the various stacks and tables are empty
01030     if (!StateStack.IsEmpty())
01031     {
01032         ERROR3("State stack was not empty when import started");
01033         StateStack.DeleteAll();
01034     }
01035     if (!PreviousAttributes.GetList()->IsEmpty())
01036     {
01037         ERROR3("Attribute stack was not empty when import started");
01038         PreviousAttributes.GetList()->DeleteAll();
01039     }
01040     if (!ColourTable.IsEmpty())
01041     {
01042         ERROR3("Colour table not empty when import started");
01043         ColourTable.DeleteAll();
01044     }
01045     
01046     InitialiseInfo();
01047     cbBin = 0;
01048     fSkipDestIfUnk = FALSE;
01049 
01050     return TRUE;
01051 }
01052 
01053 
01054 
01055 /********************************************************************************************
01056 >   void RTFTextFilter::CleanUpAfterImport()
01057 
01058     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01059     Created:    25/11/95
01060     Purpose:    Delete dynamic objects used in the import process.
01061     SeeAlso:    RTFTextFilter::PrepareToImport; RTFTextFilter::DoImport
01062 ********************************************************************************************/
01063 void RTFTextFilter::CleanUpAfterImport()
01064 {
01065     DeleteCurrentAttrs();
01066 
01067     // Ensure the various stacks and tables are empty and memory freed
01068     StateStack.DeleteAll();
01069     PreviousAttributes.GetList()->DeleteAll();
01070     ColourTable.DeleteAll();
01071     FontTable.DeleteAll();
01072 }
01073 
01074 
01075 
01076 /********************************************************************************************
01077 >   BOOL RTFTextFilter::DoImport(SelOperation *Op, CCLexFile* pFile, 
01078                                  Document *DestDoc, BOOL AutoChosen, ImportPosition *Pos)
01079 
01080     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01081     Created:    24/11/93
01082     Inputs:     Op - pointer to the operation that this read process is associated with.
01083                 pFile - The file that we are trying to import
01084                 DestDoc - pointer to the document to insert the file data into.
01085                 AutoChosen -
01086                 Pos - pointer to the position to insert the text file at
01087     Returns:    TRUE if the read was successful, FALSE if not.
01088     Purpose:    Import the named text file into the specified document.
01089                 If the read is successful, the End() function of the 'Op' operation is
01090                 called, otherwise it is not called.
01091     Errors:     Unable to open file, corrupted document tree found.
01092 ********************************************************************************************/
01093 BOOL RTFTextFilter::DoImport(SelOperation *Op, CCLexFile* pFile, 
01094                              Document* DestDoc, BOOL AutoChosen, ImportPosition* Pos)
01095 {
01096     ERROR2IF((Op == NULL) || (pFile == NULL) || (DestDoc == NULL), FALSE, "NULL Parameter");
01097 
01098     if (!PrepareToImport())
01099         return FALSE;
01100 
01101     // Get spread and import position
01102     Spread *pSpread = NULL;
01103     DocCoord ImportPos(0,0);
01104     if (Pos == NULL)
01105     {
01106         pSpread = GetFirstSpread(DestDoc);
01107         ERROR2IF(pSpread == NULL, FALSE, "No spread in document");
01108         Page* pPage = pSpread->FindFirstPageInSpread();
01109         ERROR2IF(pPage == NULL, FALSE, "No page in spread");
01110         ImportPos = DocCoord(pPage->GetPageRect().lox, pPage->GetPageRect().hiy);
01111     }
01112     else
01113     {
01114         pSpread = Pos->pSpread;
01115         ImportPos = Pos->Position;
01116     }
01117 
01118     // Create a text story object to add the characters into.
01119     pImportStory = CreateImportStory(ImportPos);
01120     if (pImportStory == NULL)
01121         return FALSE;
01122     
01123     // Initialise our handling of the file
01124     pFile->SetReportErrors(FALSE);
01125     pFile->SetThrowExceptions(FALSE);
01126     pImportFile = pFile;
01127 
01128     // Call the virtual import function
01129     BOOL Success = DoInternalImport();
01130     
01131     // Clean up after importing
01132     EndSlowJob();
01133     CleanUpAfterImport();
01134 
01135     // Insert new sub-tree into the document
01136     if (!EscapeWasPressed && Success)
01137     {
01138         if (Success)
01139             Success = pImportStory->OptimiseAttributes();       // Optimise up to story level
01140         if (Success)
01141             Success = pImportStory->FormatAndChildren();        // Initial format to setup char bounds
01142         pImportStory->SetImportFormatWidth(PaperWidth - LeftMargin - RightMargin);
01143         if (Success)
01144             Success = pImportStory->FormatToWidth();            // split paras to story width
01145         if (Success)
01146             Success = pImportStory->FormatAndChildren();        // Format again for new lines
01147         if (Success)
01148             Success = Op->DoInsertNewNode(pImportStory, pSpread, TRUE);
01149     }
01150 
01151     // If the load failed for any reason, delete the subtree we have created
01152     if (!Success || EscapeWasPressed)
01153     {
01154         pImportStory->CascadeDelete();
01155         delete pImportStory;
01156     }
01157 
01158     return Success;
01159 }
01160 
01161 
01162 
01163 /********************************************************************************************
01164 >   BOOL RTFTextFilter::DoExport(Operation*, CCLexFile*, PathName*, Document*)
01165 
01166     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01167     Created:    24/11/95
01168     Inputs:     As base class version.
01169     Returns:    TRUE/FALSE for success/failure
01170     Purpose:    Exports the document as an ANSI text file.
01171     SeeAlso:    Filter::DoExport
01172 ********************************************************************************************/
01173 BOOL RTFTextFilter::DoExport(Operation*, CCLexFile*, PathName*, Document*)
01174 {
01175     ERROR3("RTFTextFilter::DoExport is not implemented");
01176     return FALSE;
01177 }
01178 
01179 
01180 
01181 /********************************************************************************************
01182 >   virtual BOOL RTFTextFilter::DoInternalImport()
01183 
01184     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01185     Created:    25/11/95
01186     Inputs:     -
01187     Returns:    TRUE/FALSE for success/failure
01188     Purpose:    Parses the RTF file for the text and the control parts
01189     SeeAlso:    RTFTextFilter::DoImport
01190 ********************************************************************************************/
01191 BOOL RTFTextFilter::DoInternalImport()
01192 {
01193     ERROR2IF((pImportStory == NULL) || (pImportFile == NULL), FALSE, "NULL entry parameter");
01194     UINT32 FileSize = pImportFile->Size();
01195         
01196     // Set the progress indicator for a nice percentage display
01197     String_64 ImportMessage(_R(IDT_IMPORTMSG_TEXT));
01198     ImportMessage = GetImportProgressString(pImportFile, _R(IDT_IMPORTMSG_TEXT));
01199     BeginSlowJob(FileSize, TRUE, &ImportMessage);
01200     BOOL ok = TRUE;
01201 
01202     CurrentState.InternalState = StateStore::risNorm;
01203     CurrentState.DestinationState = StateStore::rdsNorm;
01204 
01205     TCHAR ReadChar;
01206     while (pImportFile->good() && (BytesReadSoFar <= FileSize-1) && !ImportHasFinished)
01207     {
01208         // Update the percentage, allows users to press escape
01209         if (!ContinueSlowJob(BytesReadSoFar))
01210         {
01211             EscapeWasPressed = TRUE;
01212             return TRUE;
01213         }
01214         
01215         if (!ReadCharFromFile(&ReadChar))
01216             return FALSE;
01217 
01218         if (CurrentState.InternalState == StateStore::risBin)   // if we're parsing binary data, handle it directly
01219         {
01220             ERROR3("BinaryData not yet handled");
01221             if (!ParseChar(ReadChar))
01222                return FALSE;
01223         }
01224         else
01225         {
01226             switch (ReadChar)
01227             {
01228                 case '{':
01229                     if (!PushRTFState())
01230                         return FALSE;
01231                     break;
01232                 case '}':
01233                     if (!PopRTFState())
01234                         return FALSE;
01235                     break;
01236                 case '\\':
01237                     if (!ParseRTFKeyword())
01238                         return FALSE;
01239                     break;
01240                 default:
01241                     ERROR2IF(CurrentState.InternalState != StateStore::risNorm, FALSE, "In unknown parsing state");
01242                     if (!ParseChar(ReadChar))
01243                         return FALSE;
01244                     break;
01245             }       // switch
01246         }           // else (ris != risBin)
01247     }               // while
01248 
01249     if (!StateStack.IsEmpty())
01250         ERROR1(FALSE, _R(IDE_RTF_DUFFFILE));
01251 
01252     // Delete any empty lines at the end of the story
01253     if (ok)
01254     {
01255         VisibleTextNode* pLastNode = pImportStory->FindLastVisibleTextNode();
01256         BOOL LastLineEmpty = FALSE;
01257         if (pLastNode != NULL)
01258             LastLineEmpty = (pLastNode->FindPrevious() == NULL);
01259 
01260         while (LastLineEmpty)
01261         {
01262             Node* pParent = pLastNode->FindParent();
01263             if (pParent != NULL)
01264             {
01265                 pParent->CascadeDelete();
01266                 delete pParent;
01267 
01268                 pLastNode = pImportStory->FindLastVisibleTextNode();
01269                 if (pLastNode != NULL)
01270                     LastLineEmpty = (pLastNode->FindPrevious() == NULL);
01271             }
01272             else
01273                 LastLineEmpty = FALSE;
01274         }
01275     }
01276 
01277     return pImportFile->good() && ok;
01278 }
01279 
01280 
01281 
01282 /********************************************************************************************
01283 >   BOOL RTFTextFilter::PushRTFState(void)
01284 
01285     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01286     Created:    27/11/95
01287     Inputs:     -
01288     Returns:    TRUE/FALSE for success/failure
01289     Purpose:    Pushes the current state RTF state onto the state stack
01290     SeeAlso:    RTFTextFilter::PopRTFState
01291 ********************************************************************************************/
01292 BOOL RTFTextFilter::PushRTFState(void)
01293 {
01294     // Create a new object to store the state in
01295     StateStore* pState = new StateStore;
01296     if (pState == NULL)
01297         return FALSE;
01298     *pState = CurrentState;
01299     StateStack.Push(pState);
01300 
01301     // Store the current attribute state
01302     if (!PreviousAttributes.SaveContext(CurrentAttrs))
01303         return FALSE;
01304 
01305     // Reset the current state
01306     CurrentState.InternalState = StateStore::risNorm;
01307 
01308     return TRUE;
01309 }
01310 
01311 
01312 
01313 /********************************************************************************************
01314 >   BOOL RTFTextFilter::PopRTFState(void)
01315 
01316     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01317     Created:    27/11/95
01318     Inputs:     -
01319     Returns:    TRUE/FALSE for success/failure
01320     Purpose:    Pops the state off the top of the RTF stack and set the current state to it.
01321     SeeAlso:    RTFTextFilter::PushRTFState
01322 ********************************************************************************************/
01323 BOOL RTFTextFilter::PopRTFState(void)
01324 {
01325     StateStore* pState = (StateStore*)StateStack.Pop();
01326     ERROR2IF(pState == NULL, FALSE, "State stack was empty");
01327 
01328     // Are we going to change destination on this state change?
01329     if (CurrentState.DestinationState != pState->DestinationState)
01330     {
01331         if (!EndGroupAction(CurrentState.DestinationState))
01332             return FALSE;
01333     }
01334 
01335     CurrentState = *pState;
01336 
01337     delete pState;
01338 
01339     // Set current state to stored state
01340     if (!PreviousAttributes.RestoreContext(CurrentAttrs))
01341         return FALSE;
01342 
01343     if (StateStack.IsEmpty())
01344         ImportHasFinished = TRUE;
01345 
01346     return TRUE;
01347 }
01348 
01349 
01350 
01351 /********************************************************************************************
01352 >   BOOL RTFTextFilter::ParseRTFKeyword()
01353 
01354     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01355     Created:    27/11/95
01356     Inputs:     -
01357     Returns:    TRUE/FALSE for success/failure
01358     Purpose:    Reads and proccesses a RTF control word and its parameter
01359     SeeAlso:    RTFTextFilter::TranslateKeyword
01360 ********************************************************************************************/
01361 BOOL RTFTextFilter::ParseRTFKeyword()
01362 {
01363     String_256 Keyword = "";
01364     INT32 Parameter = 0;
01365     BOOL ParameterUsed = FALSE;
01366 
01367     if (RTFTextFilter::ReadKeyword(&Keyword, &Parameter, &ParameterUsed))
01368         return TranslateKeyword(&Keyword, Parameter, ParameterUsed);
01369     else
01370         return FALSE;
01371 }
01372 
01373 
01374 
01375 /********************************************************************************************
01376 >   BOOL RTFTextFilter::ParseChar(WCHAR ch)
01377 
01378     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01379     Created:    27/11/95
01380     Inputs:     ch - character
01381     Returns:    TRUE/FALSE for success/failure
01382     Purpose:    Process a single character from the RTF stream
01383     SeeAlso:    RTFTextFilter::ParseRTFKeyword, RTFTextFilter::PrintChar
01384 ********************************************************************************************/
01385 BOOL RTFTextFilter::ParseChar(WCHAR ch)
01386 {
01387     // Have we reached the end of the binary skip?
01388     if (CurrentState.InternalState == StateStore::risBin && --cbBin <= 0)
01389         CurrentState.InternalState = StateStore::risNorm;
01390 
01391     switch (CurrentState.DestinationState)
01392     {
01393         case StateStore::rdsSkip:
01394             // Toss this character (away 8-).
01395             return TRUE;
01396         case StateStore::rdsNorm:
01397             // Insert a character into the story
01398             if (ch >= 32)
01399             {
01400 //              PATRACE( _T("Adding char %c\n"), ch);
01401                 
01402                 // Before we insert the char we need to setup some attributes that depend on other
01403                 // attributes, eg tracking.
01404 
01405                 // Get the current size of an Em
01406                 if (CurrentState.InterCharGap != 0)
01407                 {
01408                     MILLIPOINT Em = 0;
01409                     if (!((RTFTextOILFilter*)pOILFilter)->GetCurrentEmSize(this, &Em))
01410                         return FALSE;
01411                     else
01412                         SetTextTracking((INT32)((CurrentState.InterCharGap/(double)Em)*1000));
01413                 }
01414                 else
01415                     SetTextTracking(0);
01416 
01417                 return (AddCharToStory(pImportStory, ch) != NULL);
01418             }
01419         default:
01420             // handle other destinations....
01421             return TRUE;
01422     }
01423 }
01424 
01425 
01426 
01427 /********************************************************************************************
01428 >   BOOL RTFTextFilter::TranslateKeyword(StringBase* pKeyword, INT32 param, BOOL fParam)
01429 
01430     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01431     Created:    27/11/95
01432     Inputs:     pKeyword - the keyword read from the file
01433                 param - the keywords parameter (0 if no parameter)
01434                 fParam - TRUE if the keyword uses the parameter, FALSE if unused
01435     Returns:    TRUE/FALSE for success/failure
01436     Purpose:    Called to translate a keyword read from the file into an internal object
01437                 that can be acted upon
01438     SeeAlso:    RTFTextFilter::ParseRTFKeyword
01439 ********************************************************************************************/
01440 BOOL RTFTextFilter::TranslateKeyword(StringBase* pKeyword, INT32 param, BOOL fParam)
01441 {
01442     // Test the keyword against all the known control handlers
01443     BOOL Success = TRUE;
01444     // Bold
01445     if (RTFBoldAttribute::IsThisAction(pKeyword))
01446         Success = RTFBoldAttribute::CreateAndExecute(param, fParam, this);
01447     // Italic
01448     else if(RTFItalicAttribute::IsThisAction(pKeyword))
01449         Success = RTFItalicAttribute::CreateAndExecute(param, fParam, this);
01450     // Size
01451     else if(RTFTextSizeAttribute::IsThisAction(pKeyword))
01452         Success = RTFTextSizeAttribute::CreateAndExecute(param, fParam, this);
01453     // Super/Sub script off
01454     else if(RTFNoscriptAttribute::IsThisAction(pKeyword))
01455         Success = RTFNoscriptAttribute::CreateAndExecute(this);
01456     // Superscript
01457     else if(RTFSuperscriptAttribute::IsThisAction(pKeyword))
01458         Success = RTFSuperscriptAttribute::CreateAndExecute(this);
01459     // Subscript
01460     else if(RTFSubscriptAttribute::IsThisAction(pKeyword))
01461         Success = RTFSubscriptAttribute::CreateAndExecute(this);
01462     // Colour
01463     else if(RTFTextColourAttribute::IsThisAction(pKeyword))
01464         Success = RTFTextColourAttribute::CreateAndExecute(param, fParam, this);
01465     // Font
01466     else if(RTFTextFontAttribute::IsThisAction(pKeyword))
01467         Success = RTFTextFontAttribute::CreateAndExecute(param, fParam, this);
01468     // Tracking in twips
01469     else if(RTFTWIPTrackingAttribute::IsThisAction(pKeyword))
01470         Success = RTFTWIPTrackingAttribute::CreateAndExecute(param, fParam, this);
01471     // Tracking in quarter points
01472     else if(RTFQPTrackingAttribute::IsThisAction(pKeyword))
01473         Success = RTFQPTrackingAttribute::CreateAndExecute(param, fParam, this);
01474     
01475     // New line
01476     else if(RTFNewParaAction::IsThisAction(pKeyword))
01477         Success = RTFNewParaAction::CreateAndExecute(this);
01478     // Tab
01479     else if(RTFTabAction::IsThisAction(pKeyword))
01480         Success = RTFTabAction::CreateAndExecute(this);
01481     // Start skipping text
01482     else if(RTFEnterSkipDest::IsThisAction(pKeyword))
01483         Success = RTFEnterSkipDest::CreateAndExecute(this);
01484 
01485     // Single character definied as two hex digits
01486     else if(RTFHexCharAction::IsThisAction(pKeyword))
01487         Success = RTFHexCharAction::CreateAndExecute(this);
01488     // An Em dash
01489     else if(RTFEmDashAction::IsThisAction(pKeyword))
01490         Success = RTFEmDashAction::CreateAndExecute(this);
01491     // An en dash
01492     else if(RTFEnDashAction::IsThisAction(pKeyword))
01493         Success = RTFEnDashAction::CreateAndExecute(this);
01494     // An em space
01495     else if(RTFEmSpaceAction::IsThisAction(pKeyword))
01496         Success = RTFEmSpaceAction::CreateAndExecute(this);
01497     // An en space
01498     else if(RTFEnSpaceAction::IsThisAction(pKeyword))
01499         Success = RTFEnSpaceAction::CreateAndExecute(this);
01500     // A bullet symbol
01501     else if(RTFBulletAction::IsThisAction(pKeyword))
01502         Success = RTFBulletAction::CreateAndExecute(this);
01503     // Single left sexed quote
01504     else if(RTFSingleLeftQuoteAction::IsThisAction(pKeyword))
01505         Success = RTFSingleLeftQuoteAction::CreateAndExecute(this);
01506     // Single right sexed quote
01507     else if(RTFSingleRightQuoteAction::IsThisAction(pKeyword))
01508         Success = RTFSingleRightQuoteAction::CreateAndExecute(this);
01509     // Double left sexed quote
01510     else if(RTFDoubleLeftQuoteAction::IsThisAction(pKeyword))
01511         Success = RTFDoubleLeftQuoteAction::CreateAndExecute(this);
01512     // Double right sexed quote
01513     else if(RTFDoubleRightQuoteAction::IsThisAction(pKeyword))
01514         Success = RTFDoubleRightQuoteAction::CreateAndExecute(this);
01515     // Non-breaking space
01516     else if(RTFNonBreakSpaceAction::IsThisAction(pKeyword))
01517         Success = RTFNonBreakSpaceAction::CreateAndExecute(this);
01518 
01519     // New cell in table
01520     else if(RTFTableCellAction::IsThisAction(pKeyword))
01521         Success = RTFTableCellAction::CreateAndExecute(this);
01522     // New row in table
01523     else if(RTFTableRowAction::IsThisAction(pKeyword))
01524         Success = RTFTableRowAction::CreateAndExecute(this);
01525     // Reset character attributes
01526     else if(RTFResetCharAttrs::IsThisAction(pKeyword))
01527         Success = RTFResetCharAttrs::CreateAndExecute(this);
01528     // Reset paragraph attributes
01529     else if(RTFResetParaAttrs::IsThisAction(pKeyword))
01530         Success = RTFResetParaAttrs::CreateAndExecute(this);
01531     // Colour table
01532     else if(RTFColourTableAction::IsThisAction(pKeyword))
01533         Success = RTFColourTableAction::CreateAndExecute(this);
01534     // Font table
01535     else if(RTFFontTableAction::IsThisAction(pKeyword))
01536         Success = RTFFontTableAction::CreateAndExecute(this);
01537 
01538     // Paper width
01539     else if(RTFPaperWidth::IsThisAction(pKeyword))
01540     {
01541         ERROR1IF(!fParam, FALSE, _R(IDE_RTF_DUFFFILE));
01542         Success = RTFPaperWidth::CreateAndExecute(this, param);
01543     }
01544     // Paper height
01545     else if(RTFPaperHeight::IsThisAction(pKeyword))
01546     {
01547         ERROR1IF(!fParam, FALSE, _R(IDE_RTF_DUFFFILE));
01548         Success = RTFPaperHeight::CreateAndExecute(this, param);
01549     }
01550     // Left margin
01551     else if(RTFLeftMargin::IsThisAction(pKeyword))
01552     {
01553         ERROR1IF(!fParam, FALSE, _R(IDE_RTF_DUFFFILE));
01554         Success = RTFLeftMargin::CreateAndExecute(this, param);
01555     }
01556     // Right margin
01557     else if(RTFRightMargin::IsThisAction(pKeyword))
01558     {
01559         ERROR1IF(!fParam, FALSE, _R(IDE_RTF_DUFFFILE));
01560         Success = RTFRightMargin::CreateAndExecute(this, param);
01561     }
01562     // Top margin
01563     else if(RTFTopMargin::IsThisAction(pKeyword))
01564     {
01565         ERROR1IF(!fParam, FALSE, _R(IDE_RTF_DUFFFILE));
01566         Success = RTFTopMargin::CreateAndExecute(this, param);
01567     }
01568     // Bottom margin
01569     else if(RTFBottomMargin::IsThisAction(pKeyword))
01570     {
01571         ERROR1IF(!fParam, FALSE, _R(IDE_RTF_DUFFFILE));
01572         Success = RTFBottomMargin::CreateAndExecute(this, param);
01573     }
01574     else
01575     {
01576         // if this is a new destination skip the destination, else just discard it
01577         if (fSkipDestIfUnk)             
01578             CurrentState.DestinationState = StateStore::rdsSkip;    
01579         fSkipDestIfUnk = FALSE;
01580     }
01581 
01582     return Success;
01583 }
01584 
01585 
01586 
01587 /********************************************************************************************
01588 >   BOOL RTFTextFilter::EndGroupAction(StateStore::DestinationStateTypes rds)
01589 
01590     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01591     Created:    27/11/95
01592     Inputs:     rds - the current destination
01593     Returns:    TRUE/FALSE for success/failure
01594     Purpose:    Called at the end of a group to allow cleanup
01595     SeeAlso:    -
01596 ********************************************************************************************/
01597 BOOL RTFTextFilter::EndGroupAction(StateStore::DestinationStateTypes rds)
01598 {
01599     return TRUE;
01600 }
01601 
01602 
01603 
01604 /********************************************************************************************
01605 >   BOOL RTFTextFilter::SetSuperscript()
01606 
01607     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01608     Created:    6/12/95
01609     Inputs:     -
01610     Returns:    TRUE/FALSE for success/failure
01611     Purpose:    Set the filters current attributes to have superscript on
01612     SeeAlso:    RTFTextFilter::SetSubscript()
01613 ********************************************************************************************/
01614 BOOL RTFTextFilter::SetSuperscript()
01615 {
01616     return SetTextScript((INT32)(Text_SuperScriptOffset*GetTextSize()), (INT32)(Text_SuperScriptSize*GetTextSize()));
01617 }
01618 
01619 
01620 /********************************************************************************************
01621 >   BOOL RTFTextFilter::SetSubscript()
01622 
01623     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01624     Created:    6/12/95
01625     Inputs:     -
01626     Returns:    TRUE/FALSE for success/failure
01627     Purpose:    Set the filters current attributes to have subscript on
01628     SeeAlso:    RTFTextFilter::SetSuperscript()
01629 ********************************************************************************************/
01630 BOOL RTFTextFilter::SetSubscript()
01631 {
01632     return SetTextScript((INT32)(Text_SubScriptOffset*GetTextSize()), (INT32)(Text_SubScriptSize*GetTextSize()));
01633 }
01634 
01635 
01636 
01637 /********************************************************************************************
01638 >   BOOL RTFTextFilter::ReadKeyword(StringBase* pKeyword, INT32* pParam, BOOL* pParamUsed)
01639 
01640     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01641     Created:    6/12/95
01642     Inputs:     pKeyword - return pointer for the keyword string
01643                 pParam - return pointer for the parameter
01644                 pParamUsed - return pointer for the flag saying wether the parameter is used.
01645     Returns:    TRUE/FALSE for success/failure
01646     Purpose:    Reads an RTF keyword and its optional parameter
01647     SeeAlso:    -
01648 ********************************************************************************************/
01649 BOOL RTFTextFilter::ReadKeyword(StringBase* pKeyword, INT32* pParam, BOOL* pParamUsed)
01650 {
01651     TCHAR ch = 0;
01652     BOOL fNegative = FALSE;
01653     *pParam = 0;
01654     *pParamUsed = FALSE;
01655     *pKeyword = "";
01656     String_256 Parameter = "";
01657 
01658     // Read the first character of the control word
01659     if (!ReadCharFromFile(&ch))
01660         return FALSE;
01661 
01662     // If it's a control symbol there is no delimiter, its just one character
01663     if (!camIsalpha(ch))
01664     {
01665         *pKeyword = ch;
01666 //      PATRACE( _T("Control symbol \\%s\n"), (TCHAR*)(*pKeyword));
01667         return TRUE;
01668     }
01669 
01670     // Read in the rest of the control word
01671     while (camIsalpha(ch))
01672     {
01673         *pKeyword += ch;
01674         if (!ReadCharFromFile(&ch))
01675             return FALSE;
01676     }
01677 //  PATRACE( _T("Control word \\%s\n"), (TCHAR*)(*pKeyword));
01678 
01679     // If the delimeter was '-' then the following parameter is negative
01680     if (ch == '-')
01681     {
01682         fNegative = TRUE;
01683         if (!ReadCharFromFile(&ch))
01684             return FALSE;
01685     }
01686 
01687     // Read the numeric parameter (if there is one)
01688     if (camIsdigit(ch))
01689     {
01690         *pParamUsed = TRUE;
01691         while (camIsdigit(ch))
01692         {
01693             Parameter += ch;
01694             if (!ReadCharFromFile(&ch))
01695                 return FALSE;
01696         }
01697 
01698         TCHAR* pChar = (TCHAR*)Parameter;
01699         *pParam = camStrtol(pChar);     // BODGE - use string class conversions
01700         if (fNegative)
01701             *pParam = -*pParam;
01702 //      PATRACE( _T("Parameter %d\n"), *pParam);
01703     }
01704 
01705     // If the delimeter was non-space then this character is part of the following text!
01706     if (ch != ' ')
01707         return SkipBackChar();
01708     else
01709         return TRUE;
01710 }
01711 
01712 
01713 
01714 /********************************************************************************************
01715 >   BOOL RTFTextFilter::ReadColourTable()
01716 
01717     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01718     Created:    6/12/95
01719     Inputs:     -
01720     Returns:    TRUE/FALSE for success/failure
01721     Purpose:    Reads the RTF colour table, storing it within the filter for future use
01722     SeeAlso:    -
01723 ********************************************************************************************/
01724 BOOL RTFTextFilter::ReadColourTable()
01725 {
01726     // Ensure the colour table is empty before we start
01727     if (!ColourTable.IsEmpty())
01728     {
01729         ERROR3("Color table was not empty");
01730         ColourTable.DeleteAll();
01731     }
01732 
01733     TCHAR CurrentChar=0;    //TCHAR CurrentChar = 0;- adapted for DBCS
01734     if (!ReadCharFromFile(&CurrentChar))
01735         return FALSE;
01736 
01737     String_256 Keyword = "";
01738     INT32 Parameter = 0;
01739     BOOL ParamUsed = FALSE;
01740     while (CurrentChar != '}')
01741     {
01742         // Create a new entry for the colour table
01743         RTFColourTableEntry* pNew = new RTFColourTableEntry;
01744         if (pNew == NULL)
01745             return FALSE;
01746 
01747         if (CurrentChar == _T(';')) //if (CurrentChar == ';')-adapted for DBCS
01748         {
01749             // Default colour required              
01750             pNew->Colour = DocColour(COLOUR_BLACK);
01751         }
01752         else
01753         {
01754             BOOL TableError = FALSE;
01755             if (CurrentChar == _T('\\'))    //if (CurrentChar ==';')-adapted for DBCS
01756             {
01757                 // read colour definition
01758                 INT32 Red = 0;
01759                 INT32 Blue = 0;
01760                 INT32 Green = 0;
01761 
01762                 // read Red, Green and Blue values (will be in that order).
01763                 if (!ReadKeyword(&Keyword, &Parameter, &ParamUsed))
01764                     return FALSE;
01765                 if ((Keyword == String_8("red")) && ParamUsed)
01766                     Red = Parameter;
01767                 else
01768                     TableError = TRUE;
01769                 // Read slash at start of next keyword
01770                 if (!ReadCharFromFile(&CurrentChar) || (CurrentChar != _T('\\')))
01771                     TableError = TRUE;
01772 
01773                 if (!TableError)
01774                 {
01775                     if (!ReadKeyword(&Keyword, &Parameter, &ParamUsed))
01776                         return FALSE;
01777                     if ((Keyword == String_8("green")) && ParamUsed)
01778                         Green = Parameter;
01779                     else
01780                         TableError = TRUE;
01781                     if (!ReadCharFromFile(&CurrentChar) || (CurrentChar != _T('\\')))
01782                         TableError = TRUE;
01783                 }
01784 
01785                 if (!TableError)
01786                 {
01787                     if (!ReadKeyword(&Keyword, &Parameter, &ParamUsed))
01788                         return FALSE;
01789                     if ((Keyword == String_8("blue")) && ParamUsed)
01790                         Blue = Parameter;
01791                     else
01792                         TableError = TRUE;
01793                     if (!ReadCharFromFile(&CurrentChar) || (CurrentChar != _T(';')))
01794                         TableError = TRUE;
01795                 }
01796 
01797                 pNew->Colour = DocColour(Red, Green, Blue);
01798             }
01799             else
01800                 TableError = TRUE;
01801 
01802             ERROR3IF(TableError, "Error in colour table");
01803             ERROR1IF(TableError, FALSE, _R(IDE_RTF_DUFFFILE));
01804         }
01805 
01806         // Add the colour to the table
01807         ColourTable.AddTail(pNew);
01808 
01809         // Read in the next char
01810         if (!ReadCharFromFile(&CurrentChar))
01811             return FALSE;
01812     }
01813 
01814     // Put the '}' back into the input stream
01815     return SkipBackChar();
01816 }
01817 
01818 
01819 
01820 /*********************************************************************************************
01821 >   BOOL RTFTextFilter::ReadCharFromFile(TCHAR* pCh, BOOL SkipCR = TRUE)
01822 
01823     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01824     Created:    28/11/95
01825     Inputs:     pCh - return pointer
01826                 SkipCR - TRUE if CRs and LFs should be skipped over
01827     Outputs:    pCh contains the read character
01828     Returns:    TRUE id character read ok, FALSE if file error occured
01829     Purpose:    Reads a character from the input file and increments the bytes read counter.
01830 **********************************************************************************************/  
01831 BOOL RTFTextFilter::ReadCharFromFile(TCHAR* pCh, BOOL SkipCR)
01832 {
01833     do
01834     {
01835         pImportFile->read(pCh);
01836         BytesReadSoFar++;
01837 
01838         if (pImportFile->bad())
01839         {
01840             Error::SetError(_R(IDE_FILE_READ_ERROR));
01841             return FALSE;
01842         }
01843     } while (SkipCR && ((*pCh==13) || (*pCh==10)) );
01844 
01845     return TRUE;
01846 }
01847 
01848 
01849 
01850 /*********************************************************************************************
01851 >   BOOL RTFTextFilter::SkipBackChar(INT32 Count = 1)
01852 
01853     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01854     Created:    28/11/95
01855     Inputs:     Count - number of bytes to skip back
01856     Outputs:    -
01857     Returns:    TRUE/FALSE for success/failure
01858     Purpose:    Skips the import files position back a number of characters
01859 **********************************************************************************************/  
01860 BOOL RTFTextFilter::SkipBackChar(INT32 Count)
01861 {
01862     FilePos NewPos = pImportFile->tellIn() - Count;
01863     pImportFile->seekIn(NewPos);
01864     BytesReadSoFar -= Count;
01865 
01866     return pImportFile->good();
01867 }
01868 
01869 
01870 
01871 /********************************************************************************************
01872 >   BOOL RTFTextFilter::ReadFontTable()
01873 
01874     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01875     Created:    7/12/95
01876     Inputs:     -
01877     Returns:    TRUE/FALSE for success/failure
01878     Purpose:    Reads the RTF font table, storing it within the filter for future use
01879     SeeAlso:    RTFFilter::ReadOneFontFromTable
01880 ********************************************************************************************/
01881 BOOL RTFTextFilter::ReadFontTable()
01882 {
01883     // Ensure the font table is empty before we start
01884     if (!FontTable.IsEmpty())
01885     {
01886         ERROR3("Font table was not empty");
01887         FontTable.DeleteAll();
01888     }
01889 
01890     TCHAR CurrentChar = 0;
01891     if (!ReadCharFromFile(&CurrentChar))
01892         return FALSE;
01893 
01894     if (CurrentChar == _T('\\'))
01895     {
01896         // one entry in the font table
01897         // BODGE - (just to get your attention - Test one item font tables!)
01898         if (!ReadOneFontFromTable())
01899             return FALSE;
01900     }
01901     else
01902     {
01903         if (CurrentChar != _T('{'))
01904         {
01905             ERROR3("Error in font table");
01906             ERROR1(FALSE, _R(IDE_RTF_DUFFFILE));
01907         }
01908 
01909         // multiple entries in font table
01910         while (CurrentChar != _T('}'))
01911         {
01912             if (CurrentChar == _T('{'))
01913             {
01914                 if (!ReadCharFromFile(&CurrentChar))
01915                     return FALSE;
01916             }
01917             
01918             if (!ReadOneFontFromTable())
01919                 return FALSE;
01920 
01921             // now eat whitespace until we hit either '}' (end of font group) or '{' (another font item)
01922             do {
01923                 if (!ReadCharFromFile(&CurrentChar))
01924                     return FALSE;
01925             } while ( (CurrentChar != _T('}')) && (CurrentChar != _T('{')) );
01926         }
01927     }
01928 
01929     // Put the close group symbol back into the input stream
01930     return SkipBackChar();
01931 }
01932 
01933 
01934 
01935 /********************************************************************************************
01936 >   BOOL RTFTextFilter::ReadOneFontFromTable()
01937 
01938     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01939     Created:    7/12/95
01940     Inputs:     -
01941     Returns:    TRUE/FALSE for success/failure
01942     Purpose:    Reads one font item from the font table in the RTF font table.  When called
01943                 the file must be at the f of the 'f' (fontnum) keyword
01944     SeeAlso:    RTFFilter::ReadFontTable
01945 ********************************************************************************************/
01946 BOOL RTFTextFilter::ReadOneFontFromTable()
01947 {
01948     // Optional data that may not be present in the file
01949     INT32 CharacterSet = -1;
01950     INT32 CodePage = -1;
01951 
01952     String_256 Keyword = "";
01953     TCHAR ReadChar;
01954     INT32 Parameter = 0;
01955     BOOL ParamUsed = FALSE;
01956 
01957     // Read the font index (must be specified)
01958     if (!ReadKeyword(&Keyword, &Parameter, &ParamUsed))
01959         return FALSE;
01960     if ((Keyword != String_8("f")) || !ParamUsed)
01961         ERROR1(FALSE, _R(IDE_RTF_DUFFFILE));
01962     INT32 FontIndex = Parameter;
01963 
01964     // Read the font family (must be specified)
01965     RTFFontTableEntry::FontFamilyType FontFamily = RTFFontTableEntry::FamNil;
01966     if (!ReadCharFromFile(&ReadChar))
01967         return FALSE;
01968     if (ReadChar != _T('\\'))
01969         ERROR1(FALSE, _R(IDE_RTF_DUFFFILE));
01970     if (!ReadKeyword(&Keyword, &Parameter, &ParamUsed))
01971         return FALSE;
01972     if (Keyword == String_8("fnil"))
01973         FontFamily = RTFFontTableEntry::FamNil;
01974     else if (Keyword == String_16("froman"))
01975         FontFamily = RTFFontTableEntry::FamRoman;
01976     else if (Keyword == String_16("fswiss"))
01977         FontFamily = RTFFontTableEntry::FamSwiss;
01978     else if (Keyword == String_16("fmodern"))
01979         FontFamily = RTFFontTableEntry::FamModern;
01980     else if (Keyword == String_16("fscript"))
01981         FontFamily = RTFFontTableEntry::FamScript;
01982     else if (Keyword == String_16("fdecor"))
01983         FontFamily = RTFFontTableEntry::FamDecor;
01984     else if (Keyword == String_16("ftech"))
01985         FontFamily = RTFFontTableEntry::FamTech;
01986     else if (Keyword == String_16("fbidi"))
01987         FontFamily = RTFFontTableEntry::FamBiDi;
01988     else
01989     {
01990         ERROR3("Unknown font family type");
01991         FontFamily = RTFFontTableEntry::FamNil;
01992     }
01993 
01994     // Now (possibly) comes some optional keyword before the fontname
01995     if (!ReadCharFromFile(&ReadChar))
01996         return FALSE;
01997     while (ReadChar == _T('\\'))
01998     {
01999         if (!ReadKeyword(&Keyword, &Parameter, &ParamUsed))
02000             return FALSE;
02001 
02002         if (Keyword == String_16("fcharset"))
02003         {
02004             if (ParamUsed)
02005                 CharacterSet = Parameter;
02006             else
02007                 ERROR1(FALSE, _R(IDE_RTF_DUFFFILE));
02008         }
02009         else if (Keyword == String_16("cpg"))
02010         {
02011             if (ParamUsed)
02012                 CodePage = Parameter;
02013             else
02014                 ERROR1(FALSE, _R(IDE_RTF_DUFFFILE));
02015         }
02016 
02017         if (!ReadCharFromFile(&ReadChar))
02018             return FALSE;
02019     }
02020 
02021     // Now comes the font name, terminated by either a close brace or a slash or a semi-colon
02022     String_64 FontName = "";
02023     while ( (ReadChar != _T('}')) && (ReadChar != _T('\\')) && (ReadChar != _T(';')) )
02024     {
02025         FontName += ReadChar;
02026         if (!ReadCharFromFile(&ReadChar))
02027             return FALSE;
02028     }
02029 
02030     // Munch the remaining control words down to the close brace
02031     while (ReadChar != '}')
02032     {
02033         if (!ReadCharFromFile(&ReadChar))
02034             return FALSE;
02035     }
02036 
02037     // Create the font entry and put it into the font table
02038     RTFFontTableEntry* pNewFont = new RTFFontTableEntry;
02039     if (pNewFont == NULL)
02040         return FALSE;
02041 
02042     pNewFont->RealFontName = FontName;
02043     pNewFont->ApplyFontName = FontName;
02044     pNewFont->FontFamily = FontFamily;
02045     pNewFont->FontIndex = FontIndex; 
02046     if (CharacterSet != -1)
02047         pNewFont->CharacterSet = CharacterSet;
02048     if (CodePage != -1)
02049         pNewFont->CodePage = CodePage;
02050 
02051     FontTable.AddTail(pNewFont);
02052 
02053     return TRUE;
02054 }
02055 
02056 
02057 
02058 /********************************************************************************************
02059 >   BOOL RTFTextFilter::InitialiseInfo()
02060 
02061     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02062     Created:    14/12/95
02063     Inputs:     -
02064     Returns:    TRUE/FALSE for success/failure
02065     Purpose:    Initialises the RTF document values to their defaults
02066     SeeAlso:    -
02067 ********************************************************************************************/
02068 BOOL RTFTextFilter::InitialiseInfo()
02069 {
02070     PaperWidth = 12240*50;
02071     PaperHeight = 15840*50;
02072     LeftMargin = 1800*50;
02073     RightMargin = 1800*50;
02074     TopMargin = 1440*50;
02075     BottomMargin =1440*50;
02076 
02077     CurrentState.InterCharGap = 0;
02078 
02079     return TRUE;
02080 }
02081 
02082 
02083 
02084 /********************************************************************************************
02085 >   BOOL RTFTextFilter::ResetCharacterAttributes()
02086 
02087     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02088     Created:    18/12/95
02089     Inputs:     -
02090     Returns:    TRUE/FALSE for success/failure
02091     Purpose:    Resets all the character attributes back to their defaults
02092     SeeAlso:    -
02093 ********************************************************************************************/
02094 BOOL RTFTextFilter::ResetCharacterAttributes()
02095 {
02096     BOOL ok = TRUE;
02097     
02098     if (ok)
02099         ok = SetTextBold(FALSE);
02100     if (ok)
02101         ok = SetTextItalic(FALSE);
02102     if (ok)
02103         ok = SetTextSize(12000);
02104     if (ok)
02105         ok = SetTextColour(DocColour(COLOUR_BLACK));
02106     if (ok)
02107         ok = SetFont(&DefaultAttrs.FontName);
02108 
02109     return ok;
02110 }
02111 
02112 
02113 
02114 /********************************************************************************************
02115 >   BOOL RTFTextFilter::ResetParagraphAttributes()
02116 
02117     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02118     Created:    18/12/95
02119     Inputs:     -
02120     Returns:    TRUE/FALSE for success/failure
02121     Purpose:    Resets all the paragraph attributes back to their defaults
02122     SeeAlso:    -
02123 ********************************************************************************************/
02124 BOOL RTFTextFilter::ResetParagraphAttributes()
02125 {
02126     return TRUE;
02127 }
02128 
02129 
02130 
02131 
02132 
02133 
02134 /*********************************************************************************************
02135 >   DocColour RTFColourTable::GetColourAt(INT32 TableIndex)
02136 
02137     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02138     Created:    28/11/95
02139     Inputs:     TableIndex - the index into the RTF filter's colour table
02140     Outputs:    -
02141     Returns:    A DocColour describing the colour at that position in the colour table
02142     Purpose:    Gets a colour from the colour table.  If the index into the table is not valid
02143                 then the colour black is returned.  (It's not an error)
02144 **********************************************************************************************/  
02145 DocColour RTFColourTable::GetColourAt(INT32 TableIndex)
02146 {
02147     RTFColourTableEntry* pItem = (RTFColourTableEntry*)FindItem(TableIndex);
02148 
02149     if (pItem == NULL)
02150         return DocColour(COLOUR_BLACK);
02151     else
02152         return pItem->Colour;
02153 }
02154 
02155 
02156 
02157 /*********************************************************************************************
02158 >   BOOL RTFFontTable::GetIndexedFont(INT32 TableIndex, String_64* pFontName)
02159 
02160     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02161     Created:    7/12/95
02162     Inputs:     TableIndex - the index into the RTF filter's font table
02163                 pFontName - return pointer for the name of the font at that index.
02164     Outputs:    -
02165     Returns:    TRUE/FALSE for success/failure
02166     Purpose:    Gets a font from the font table.  If the index into the table is not valid
02167                 then a default font is returned
02168 **********************************************************************************************/  
02169 BOOL RTFFontTable::GetIndexedFont(INT32 TableIndex, String_64* pFontName)
02170 {
02171     ERROR2IF(pFontName == NULL, FALSE, "Null entry param");
02172 
02173     // We have to look through all the items in the table to find one with a matching index
02174     RTFFontTableEntry* pItem = (RTFFontTableEntry*)GetHead();
02175 
02176     while (pItem != NULL)
02177     {
02178         if (pItem->FontIndex == TableIndex)
02179         {
02180             *pFontName = pItem->ApplyFontName;
02181             return TRUE;
02182         }
02183 
02184         pItem = (RTFFontTableEntry*)GetNext(pItem);
02185     }
02186 
02187     return TRUE;
02188 }
02189 
02190 
02191 
02192 /*********************************************************************************************
02193 >   RTFFontTableEntry::RTFFontTableEntry()
02194 
02195     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02196     Created:    7/12/95
02197     Purpose:    Constructor - initialises member variables to sensible values
02198 **********************************************************************************************/  
02199 RTFFontTableEntry::RTFFontTableEntry()
02200 {
02201     RealFontName = "Times New Roman";       // BODGE - get default from font manager
02202     ApplyFontName = RealFontName;
02203     FontFamily = FamNil;
02204     CharacterSet = 0;
02205     CodePage = 819;
02206     FontIndex = 0;
02207 }
02208 
02209 
02210 /*********************************************************************************************
02211 >   RTFFontTableEntry::~RTFFontTableEntry()
02212 
02213     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02214     Created:    7/12/95
02215     Purpose:    Destructor
02216 **********************************************************************************************/  
02217 RTFFontTableEntry::~RTFFontTableEntry()
02218 {
02219 }
02220 
02221 
02222 
02223 
02224 
02225 
02226 /*********************************************************************************************
02227 >   RTFControlAction::RTFControlAction(INT32 Param, RTFTextFilter* pFilt)
02228 
02229     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02230     Created:    6/12/95
02231     Purpose:    Base constructor of all RTF control handlers
02232 **********************************************************************************************/  
02233 RTFControlAction::RTFControlAction(RTFTextFilter* pFilt, INT32 Param)
02234 {
02235     Parameter = Param;
02236     pFilter = pFilt;
02237 }
02238 
02239 
02240 
02241 /*********************************************************************************************
02242 >   BOOL RTFControlAction::ExecuteControlCarefully(RTFControlAction* pAction)
02243 
02244     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02245     Created:    6/12/95
02246     Inputs:     pAction - pointer to the created action (may be NULL)
02247     Returns:    TRUE/FALSE for success/failure
02248     Purpose:    Common code for executing a newly created control handler.
02249 **********************************************************************************************/  
02250 BOOL RTFControlAction::ExecuteControlCarefully(RTFControlAction* pAction)
02251 {
02252     if (pAction != NULL)
02253     {
02254         BOOL Success = pAction->ExecuteControl();
02255         delete pAction;
02256         return Success;
02257     }
02258     else
02259         return FALSE;       // Error will have already been set!
02260 }
02261 
02262 
02263 /*********************************************************************************************
02264 >   RTFAttributeAction::RTFAttributeAction(RTFTextFilter* pFilt, INT32 Param) : RTFControlAction(pFilt, Param)
02265 
02266     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02267     Created:    6/12/95
02268     Purpose:    Base constructor of all RTF attribute control handlers
02269 **********************************************************************************************/  
02270 RTFAttributeAction::RTFAttributeAction(RTFTextFilter* pFilt, INT32 Param) : RTFControlAction(pFilt, Param)
02271 {
02272 }
02273 
02274 
02275 
02276 
02277 /*********************************************************************************************
02278 >   RTFBoldAttribute
02279 
02280     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02281     Created:    6/12/95
02282     Purpose:    Deals with the bold character property in importing RTF
02283                 Parameter is 0 to turn bold off, otherwise turn it on
02284 **********************************************************************************************/  
02285 RTFBoldAttribute::RTFBoldAttribute(RTFTextFilter* pFilt, INT32 Param) : RTFAttributeAction(pFilt, Param)
02286 {
02287 }
02288 
02289 BOOL RTFBoldAttribute::IsThisAction(StringBase* pControl)
02290 {
02291     return (*pControl == String_8("b"));
02292 }
02293 
02294 BOOL RTFBoldAttribute::ExecuteControl()
02295 {
02296     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02297     return pFilter->SetBold(Parameter);
02298 }
02299 
02300 BOOL RTFBoldAttribute::CreateAndExecute(INT32 Param, BOOL UseParam, RTFTextFilter* pFilter)
02301 {
02302     RTFBoldAttribute* pNew = NULL;
02303     
02304     if (UseParam)
02305         pNew = new RTFBoldAttribute(pFilter, Param);
02306     else
02307         pNew = new RTFBoldAttribute(pFilter);
02308 
02309     return ExecuteControlCarefully(pNew);
02310 }
02311 
02312 
02313 
02314 /*********************************************************************************************
02315 >   RTFItalicAttribute
02316 
02317     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02318     Created:    6/12/95
02319     Purpose:    Deals with the italic character property in importing RTF
02320                 Parameter is 0 to turn italic off, otherwise turn it on
02321 **********************************************************************************************/  
02322 RTFItalicAttribute::RTFItalicAttribute(RTFTextFilter* pFilt, INT32 Param) : RTFAttributeAction(pFilt, Param)
02323 {
02324 }
02325 
02326 BOOL RTFItalicAttribute::IsThisAction(StringBase* pControl)
02327 {
02328     return (*pControl == String_8("i"));
02329 }
02330 
02331 BOOL RTFItalicAttribute::ExecuteControl()
02332 {
02333     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02334     return pFilter->SetItalic(Parameter);
02335 }
02336 
02337 BOOL RTFItalicAttribute::CreateAndExecute(INT32 Param, BOOL UseParam, RTFTextFilter* pFilter)
02338 {
02339     RTFItalicAttribute* pNew = NULL;
02340     
02341     if (UseParam)
02342         pNew = new RTFItalicAttribute(pFilter, Param);
02343     else
02344         pNew = new RTFItalicAttribute(pFilter);
02345 
02346     return ExecuteControlCarefully(pNew);
02347 }
02348 
02349 
02350 
02351 /*********************************************************************************************
02352 >   RTFTextSizeAttribute
02353 
02354     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02355     Created:    6/12/95
02356     Purpose:    Deals with the text size character property in importing RTF.
02357                 Parameter if the new text size (defined in half-point units)
02358 **********************************************************************************************/  
02359 RTFTextSizeAttribute::RTFTextSizeAttribute(RTFTextFilter* pFilt, INT32 Param) : RTFAttributeAction(pFilt, Param)
02360 {
02361 }
02362 
02363 BOOL RTFTextSizeAttribute::IsThisAction(StringBase* pControl)
02364 {
02365     return (*pControl == String_8("fs"));
02366 }
02367 
02368 BOOL RTFTextSizeAttribute::ExecuteControl()
02369 {
02370     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02371 
02372     return pFilter->SetSize(Parameter);
02373 }
02374 
02375 BOOL RTFTextSizeAttribute::CreateAndExecute(TWIP Param, BOOL UseParam, RTFTextFilter* pFilter)
02376 {
02377     RTFTextSizeAttribute* pNew = NULL;
02378     
02379     if (UseParam)
02380         pNew = new RTFTextSizeAttribute(pFilter, Param*500);
02381     else
02382         pNew = new RTFTextSizeAttribute(pFilter, 24*500);       // 12 point default
02383 
02384     return ExecuteControlCarefully(pNew);
02385 }
02386 
02387 
02388 
02389 /*********************************************************************************************
02390 >   RTFSubscriptAttribute
02391 
02392     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02393     Created:    6/12/95
02394     Purpose:    Deals with the subscript character property in importing RTF.
02395                 No parameter
02396 **********************************************************************************************/  
02397 RTFSubscriptAttribute::RTFSubscriptAttribute(RTFTextFilter* pFilt) : RTFAttributeAction(pFilt, 0)
02398 {
02399 }
02400 
02401 BOOL RTFSubscriptAttribute::IsThisAction(StringBase* pControl)
02402 {
02403     return (*pControl == String_8("sub"));
02404 }
02405 
02406 BOOL RTFSubscriptAttribute::ExecuteControl()
02407 {
02408     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02409     return pFilter->SetSubscript();
02410 }
02411 
02412 BOOL RTFSubscriptAttribute::CreateAndExecute(RTFTextFilter* pFilter)
02413 {
02414     RTFSubscriptAttribute* pNew = NULL;
02415 
02416     pNew = new RTFSubscriptAttribute(pFilter);
02417 
02418     return ExecuteControlCarefully(pNew);
02419 }
02420 
02421 
02422 
02423 /*********************************************************************************************
02424 >   RTFSuperscriptAttribute
02425 
02426     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02427     Created:    6/12/95
02428     Purpose:    Deals with the superscript character property in importing RTF.
02429                 No parameter
02430 **********************************************************************************************/  
02431 RTFSuperscriptAttribute::RTFSuperscriptAttribute(RTFTextFilter* pFilt) : RTFAttributeAction(pFilt, 0)
02432 {
02433 }
02434 
02435 BOOL RTFSuperscriptAttribute::IsThisAction(StringBase* pControl)
02436 {
02437     return (*pControl == String_8("super"));
02438 }
02439 
02440 BOOL RTFSuperscriptAttribute::ExecuteControl()
02441 {
02442     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02443     return pFilter->SetSuperscript();
02444 }
02445 
02446 BOOL RTFSuperscriptAttribute::CreateAndExecute(RTFTextFilter* pFilter)
02447 {
02448     RTFSuperscriptAttribute* pNew = NULL;
02449     
02450     pNew = new RTFSuperscriptAttribute(pFilter);
02451 
02452     return ExecuteControlCarefully(pNew);
02453 }
02454 
02455 
02456 
02457 /*********************************************************************************************
02458 >   RTFSuperscriptAttribute
02459 
02460     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02461     Created:    6/12/95
02462     Purpose:    Deals with the no superscript/subscript character property in importing RTF.
02463                 No parameter
02464 **********************************************************************************************/  
02465 RTFNoscriptAttribute::RTFNoscriptAttribute(RTFTextFilter* pFilt) : RTFAttributeAction(pFilt, 0)
02466 {
02467 }
02468 
02469 BOOL RTFNoscriptAttribute::IsThisAction(StringBase* pControl)
02470 {
02471     return (*pControl == String_16("Nosupersub"));
02472 }
02473 
02474 BOOL RTFNoscriptAttribute::ExecuteControl()
02475 {
02476     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02477     return pFilter->SetNoscript();
02478 }
02479 
02480 BOOL RTFNoscriptAttribute::CreateAndExecute(RTFTextFilter* pFilter)
02481 {
02482     RTFNoscriptAttribute* pNew = NULL;
02483     
02484     pNew = new RTFNoscriptAttribute(pFilter);
02485 
02486     return ExecuteControlCarefully(pNew);
02487 }
02488 
02489 
02490 
02491 /*********************************************************************************************
02492 >   RTFTextColourAttribute
02493 
02494     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02495     Created:    6/12/95
02496     Purpose:    Deals with the foreground colour character property in importing RTF.
02497                 Parameter is the index into the colour tale of the new text colour
02498 **********************************************************************************************/  
02499 RTFTextColourAttribute::RTFTextColourAttribute(RTFTextFilter* pFilt, INT32 Param) : RTFAttributeAction(pFilt, Param)
02500 {
02501 }
02502 
02503 BOOL RTFTextColourAttribute::IsThisAction(StringBase* pControl)
02504 {
02505     return (*pControl == String_8("cf"));
02506 }
02507 
02508 BOOL RTFTextColourAttribute::ExecuteControl()
02509 {
02510     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02511 
02512     DocColour TableColour = pFilter->GetColourTable()->GetColourAt(Parameter);
02513     return pFilter->SetTextColour(TableColour);
02514 }
02515 
02516 BOOL RTFTextColourAttribute::CreateAndExecute(INT32 Param, BOOL UseParam, RTFTextFilter* pFilter)
02517 {
02518     RTFTextColourAttribute* pNew = NULL;
02519     
02520     if (UseParam)
02521         pNew = new RTFTextColourAttribute(pFilter, Param);
02522     else
02523         pNew = new RTFTextColourAttribute(pFilter);
02524 
02525     return ExecuteControlCarefully(pNew);
02526 }
02527 
02528 
02529 
02530 /*********************************************************************************************
02531 >   RTFTextFontAttribute
02532 
02533     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02534     Created:    7/12/95
02535     Purpose:    Deals with the font character property in importing RTF.
02536                 Parameter is the index into the font tale of the new font
02537 **********************************************************************************************/  
02538 RTFTextFontAttribute::RTFTextFontAttribute(RTFTextFilter* pFilt, INT32 Param) : RTFAttributeAction(pFilt, Param)
02539 {
02540 }
02541 
02542 BOOL RTFTextFontAttribute::IsThisAction(StringBase* pControl)
02543 {
02544     return (*pControl == String_8("f"));
02545 }
02546 
02547 BOOL RTFTextFontAttribute::ExecuteControl()
02548 {
02549     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02550 
02551     String_64 FontName;
02552     if (!pFilter->GetFontTable()->GetIndexedFont(Parameter, &FontName))
02553         return FALSE;
02554     else
02555     {
02556         if ((FONTMANAGER->CacheNamedFont(&FontName, FC_TRUETYPE) != ILLEGALFHANDLE))
02557             return pFilter->SetFont(&FontName);
02558         else
02559             return FALSE;
02560     }
02561 }
02562 
02563 BOOL RTFTextFontAttribute::CreateAndExecute(INT32 Param, BOOL UseParam, RTFTextFilter* pFilter)
02564 {
02565     RTFTextFontAttribute* pNew = NULL;
02566     
02567     if (UseParam)
02568         pNew = new RTFTextFontAttribute(pFilter, Param);
02569     else
02570         pNew = new RTFTextFontAttribute(pFilter);
02571 
02572     return ExecuteControlCarefully(pNew);
02573 }
02574 
02575 
02576 
02577 /*********************************************************************************************
02578 >   RTFQPTrackingAttribute
02579 
02580     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02581     Created:    6/12/95
02582     Purpose:    Deals with the old-style tracking character property in importing RTF.
02583                 Parameter is tracking size in quarter-point units
02584 **********************************************************************************************/  
02585 RTFQPTrackingAttribute::RTFQPTrackingAttribute(RTFTextFilter* pFilt, INT32 Param) : RTFAttributeAction(pFilt, Param)
02586 {
02587 }
02588 
02589 BOOL RTFQPTrackingAttribute::IsThisAction(StringBase* pControl)
02590 {
02591     return (*pControl == String_8("expnd"));
02592 }
02593 
02594 BOOL RTFQPTrackingAttribute::ExecuteControl()
02595 {
02596     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02597     pFilter->SetInterCharGap(Parameter);
02598     return TRUE;
02599 }
02600 
02601 BOOL RTFQPTrackingAttribute::CreateAndExecute(MILLIPOINT Param, BOOL UseParam, RTFTextFilter* pFilter)
02602 {
02603     RTFQPTrackingAttribute* pNew = NULL;
02604     
02605     if (UseParam)
02606         pNew = new RTFQPTrackingAttribute(pFilter, Param*250);      // Convert 1/4 point to millipoint
02607     else
02608         pNew = new RTFQPTrackingAttribute(pFilter);
02609 
02610     return ExecuteControlCarefully(pNew);
02611 }
02612 
02613 
02614 
02615 /*********************************************************************************************
02616 >   RTFTWIPTrackingAttribute
02617 
02618     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02619     Created:    6/12/95
02620     Purpose:    Deals with the new-style tracking character property in importing RTF.
02621                 Parameter is tracking size in twips
02622 **********************************************************************************************/  
02623 RTFTWIPTrackingAttribute::RTFTWIPTrackingAttribute(RTFTextFilter* pFilt, INT32 Param) : RTFAttributeAction(pFilt, Param)
02624 {
02625 }
02626 
02627 BOOL RTFTWIPTrackingAttribute::IsThisAction(StringBase* pControl)
02628 {
02629     return (*pControl == String_8("expndtw"));
02630 }
02631 
02632 BOOL RTFTWIPTrackingAttribute::ExecuteControl()
02633 {
02634     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02635     pFilter->SetInterCharGap(Parameter);
02636     return TRUE;
02637 }
02638 
02639 BOOL RTFTWIPTrackingAttribute::CreateAndExecute(TWIP Param, BOOL UseParam, RTFTextFilter* pFilter)
02640 {
02641     RTFTWIPTrackingAttribute* pNew = NULL;
02642     
02643     if (UseParam)
02644         pNew = new RTFTWIPTrackingAttribute(pFilter, Param*TwipToMillpoint);
02645     else
02646         pNew = new RTFTWIPTrackingAttribute(pFilter);
02647 
02648     return ExecuteControlCarefully(pNew);
02649 }
02650 
02651 
02652 
02653 
02654 
02655 
02656 /*********************************************************************************************
02657 >   RTFEnterSkipDest
02658 
02659     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02660     Created:    6/12/95
02661     Purpose:    Deals skipping text following unknown control words
02662                 No parameter
02663 **********************************************************************************************/  
02664 RTFEnterSkipDest::RTFEnterSkipDest(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0)
02665 {
02666 }
02667 
02668 BOOL RTFEnterSkipDest::IsThisAction(StringBase* pControl)
02669 {
02670     return ((*pControl == String_16("author"))      ||
02671             (*pControl == String_16("buptim"))      ||
02672             (*pControl == String_16("comment"))     ||
02673             (*pControl == String_16("creatim"))     ||
02674             (*pControl == String_16("doccomm"))     ||
02675             (*pControl == String_16("footer"))      ||
02676             (*pControl == String_16("footerf"))     ||
02677             (*pControl == String_16("footerl"))     ||
02678             (*pControl == String_16("footerr"))     ||
02679             (*pControl == String_16("footnote"))    ||
02680             (*pControl == String_16("ftncn"))       ||
02681             (*pControl == String_16("ftnsep"))      ||
02682             (*pControl == String_16("ftnsepc"))     ||
02683             (*pControl == String_16("header"))      ||
02684             (*pControl == String_16("headerf"))     ||
02685             (*pControl == String_16("headerl"))     ||
02686             (*pControl == String_16("headerr"))     ||
02687             (*pControl == String_16("info"))        ||
02688             (*pControl == String_16("keywords"))    ||
02689             (*pControl == String_16("operator"))    ||
02690             (*pControl == String_16("pict"))        ||
02691             (*pControl == String_16("printim"))     ||
02692             (*pControl == String_16("private1"))    ||
02693             (*pControl == String_16("revtim"))      ||
02694             (*pControl == String_16("rxe"))         ||
02695             (*pControl == String_16("stylesheet"))  ||
02696             (*pControl == String_16("subject"))     ||
02697             (*pControl == String_16("tc"))          ||
02698             (*pControl == String_16("title"))       ||
02699             (*pControl == String_16("txe"))         ||
02700             (*pControl == String_16("*"))           ||
02701             (*pControl == String_16("xe")) );
02702 }
02703 
02704 BOOL RTFEnterSkipDest::ExecuteControl()
02705 {
02706     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02707     pFilter->SetSkipping();
02708     return TRUE;
02709 }
02710 
02711 BOOL RTFEnterSkipDest::CreateAndExecute(RTFTextFilter* pFilter)
02712 {
02713     RTFEnterSkipDest* pNew = new RTFEnterSkipDest(pFilter);
02714 
02715     return ExecuteControlCarefully(pNew);
02716 }
02717 
02718 
02719 
02720 /*********************************************************************************************
02721 >   RTFNewParaAction
02722 
02723     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02724     Created:    6/12/95
02725     Purpose:    Deals with the text in the RTF file starting a new paragraph
02726                 No parameter
02727 **********************************************************************************************/  
02728 RTFNewParaAction ::RTFNewParaAction(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0)
02729 {
02730 }
02731 
02732 BOOL RTFNewParaAction::IsThisAction(StringBase* pControl)
02733 {
02734     return (*pControl == String_8("par")) || (*pControl == String_8("sect"));
02735 }
02736 
02737 BOOL RTFNewParaAction::ExecuteControl()
02738 {
02739     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02740     return pFilter->StartNewLine();
02741 }
02742 
02743 BOOL RTFNewParaAction::CreateAndExecute(RTFTextFilter* pFilter)
02744 {
02745     RTFNewParaAction* pNew = new RTFNewParaAction(pFilter);
02746 
02747     return ExecuteControlCarefully(pNew);
02748 }
02749 
02750 
02751 
02752 /*********************************************************************************************
02753 >   RTFColourTableAction
02754 
02755     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02756     Created:    6/12/95
02757     Purpose:    Deals with reading the colour table from a RTF file
02758                 No parameter
02759 **********************************************************************************************/  
02760 RTFColourTableAction::RTFColourTableAction(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0)
02761 {
02762 }
02763 
02764 BOOL RTFColourTableAction::IsThisAction(StringBase* pControl)
02765 {
02766     return *pControl == String_16("colortbl");
02767 }
02768 
02769 BOOL RTFColourTableAction::ExecuteControl()
02770 {
02771     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02772     return pFilter->ReadColourTable();
02773 }
02774 
02775 BOOL RTFColourTableAction::CreateAndExecute(RTFTextFilter* pFilter)
02776 {
02777     RTFColourTableAction* pNew = new RTFColourTableAction(pFilter);
02778 
02779     return ExecuteControlCarefully(pNew);
02780 }
02781 
02782 
02783 /*********************************************************************************************
02784 >   RTFFontTableAction
02785 
02786     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02787     Created:    6/12/95
02788     Purpose:    Deals with reading the font table from a RTF file
02789                 No parameter
02790 **********************************************************************************************/  
02791 RTFFontTableAction::RTFFontTableAction(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0)
02792 {
02793 }
02794 
02795 BOOL RTFFontTableAction::IsThisAction(StringBase* pControl)
02796 {
02797     return *pControl == String_16("fonttbl");
02798 }
02799 
02800 BOOL RTFFontTableAction::ExecuteControl()
02801 {
02802     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02803     return pFilter->ReadFontTable();
02804 }
02805 
02806 BOOL RTFFontTableAction::CreateAndExecute(RTFTextFilter* pFilter)
02807 {
02808     RTFFontTableAction* pNew = new RTFFontTableAction(pFilter);
02809 
02810     return ExecuteControlCarefully(pNew);
02811 }
02812 
02813 
02814 
02815 /********************************************************************************************
02816 >   class RTFPaperWidth : public RTFControlAction
02817 
02818     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02819     Created:    14/12/95
02820     Purpose:    Reads RTF document's paper width.  Parameter is width of paper in twips
02821 ********************************************************************************************/
02822 RTFPaperWidth::RTFPaperWidth(RTFTextFilter* pFilt, MILLIPOINT Width) : RTFControlAction(pFilt, Width)
02823 {
02824 }
02825 
02826 BOOL RTFPaperWidth::IsThisAction(StringBase* pControl)
02827 {
02828     return *pControl == String_16("paperw");
02829 }
02830 
02831 BOOL RTFPaperWidth::ExecuteControl()
02832 {
02833     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02834     pFilter->SetPaperWidth(Parameter);
02835     return TRUE;
02836 }
02837 
02838 BOOL RTFPaperWidth::CreateAndExecute(RTFTextFilter* pFilter, TWIP Width)
02839 {
02840     RTFPaperWidth* pNew = new RTFPaperWidth(pFilter, Width*TwipToMillpoint);
02841 
02842     return ExecuteControlCarefully(pNew);
02843 }
02844 
02845 
02846 
02847 /********************************************************************************************
02848 >   class RTFPaperHeight : public RTFControlAction
02849 
02850     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02851     Created:    14/12/95
02852     Purpose:    Read RTF document's paper height
02853 ********************************************************************************************/
02854 RTFPaperHeight::RTFPaperHeight(RTFTextFilter* pFilt, MILLIPOINT Height) : RTFControlAction(pFilt, Height)
02855 {
02856 }
02857 
02858 BOOL RTFPaperHeight::IsThisAction(StringBase* pControl)
02859 {
02860     return *pControl == String_16("paperh");
02861 }
02862 
02863 BOOL RTFPaperHeight::ExecuteControl()
02864 {
02865     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02866     pFilter->SetPaperHeight(Parameter);
02867     return TRUE;
02868 }
02869 
02870 BOOL RTFPaperHeight::CreateAndExecute(RTFTextFilter* pFilter, TWIP Height)
02871 {
02872     RTFPaperHeight* pNew = new RTFPaperHeight(pFilter, Height*TwipToMillpoint);
02873 
02874     return ExecuteControlCarefully(pNew);
02875 }
02876 
02877 
02878 
02879 /********************************************************************************************
02880 >   class RTFLeftMargin : public RTFControlAction
02881 
02882     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02883     Created:    14/12/95
02884     Purpose:    Sets the width of the left-hand page margin
02885 ********************************************************************************************/
02886 RTFLeftMargin::RTFLeftMargin(RTFTextFilter* pFilt, MILLIPOINT Width) : RTFControlAction(pFilt, Width)
02887 {
02888 }
02889 
02890 BOOL RTFLeftMargin::IsThisAction(StringBase* pControl)
02891 {
02892     return *pControl == String_16("margl");
02893 }
02894 
02895 BOOL RTFLeftMargin::ExecuteControl()
02896 {
02897     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02898     pFilter->SetLeftMargin(Parameter);
02899     return TRUE;
02900 }
02901 
02902 BOOL RTFLeftMargin::CreateAndExecute(RTFTextFilter* pFilter, TWIP Width)
02903 {
02904     RTFLeftMargin* pNew = new RTFLeftMargin(pFilter, Width*TwipToMillpoint);
02905 
02906     return ExecuteControlCarefully(pNew);
02907 }
02908 
02909 
02910 
02911 /********************************************************************************************
02912 >   class RTFRightMargin : public RTFControlAction
02913 
02914     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02915     Created:    14/12/95
02916     Purpose:    Sets the width of the right-hand page margin
02917 ********************************************************************************************/
02918 RTFRightMargin::RTFRightMargin(RTFTextFilter* pFilt, MILLIPOINT Width) : RTFControlAction(pFilt, Width)
02919 {
02920 }
02921 
02922 BOOL RTFRightMargin::IsThisAction(StringBase* pControl)
02923 {
02924     return *pControl == String_16("margr");
02925 }
02926 
02927 BOOL RTFRightMargin::ExecuteControl()
02928 {
02929     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02930     pFilter->SetRightMargin(Parameter);
02931     return TRUE;
02932 }
02933 
02934 BOOL RTFRightMargin::CreateAndExecute(RTFTextFilter* pFilter, TWIP Width)
02935 {
02936     RTFRightMargin* pNew = new RTFRightMargin(pFilter, Width*TwipToMillpoint);
02937 
02938     return ExecuteControlCarefully(pNew);
02939 }
02940 
02941 
02942 
02943 /********************************************************************************************
02944 >   class RTFTopMargin : public RTFControlAction
02945 
02946     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02947     Created:    14/12/95
02948     Purpose:    Sets the height of the margin at the top of the page
02949 ********************************************************************************************/
02950 RTFTopMargin::RTFTopMargin(RTFTextFilter* pFilt, MILLIPOINT Height) : RTFControlAction(pFilt, Height)
02951 {
02952 }
02953 
02954 BOOL RTFTopMargin::IsThisAction(StringBase* pControl)
02955 {
02956     return *pControl == String_16("margt");
02957 }
02958 
02959 BOOL RTFTopMargin::ExecuteControl()
02960 {
02961     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02962     pFilter->SetTopMargin(Parameter);
02963     return TRUE;
02964 }
02965 
02966 BOOL RTFTopMargin::CreateAndExecute(RTFTextFilter* pFilter, TWIP Height)
02967 {
02968     RTFTopMargin* pNew = new RTFTopMargin(pFilter, Height*TwipToMillpoint);
02969 
02970     return ExecuteControlCarefully(pNew);
02971 }
02972 
02973 
02974 
02975 /********************************************************************************************
02976 >   class RTFBottomMargin : public RTFControlAction
02977 
02978     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02979     Created:    14/12/95
02980     Purpose:    Sets the height of the margin at the bottom of the page
02981 ********************************************************************************************/
02982 RTFBottomMargin::RTFBottomMargin(RTFTextFilter* pFilt, MILLIPOINT Height) : RTFControlAction(pFilt, Height)
02983 {
02984 }
02985 
02986 BOOL RTFBottomMargin::IsThisAction(StringBase* pControl)
02987 {
02988     return *pControl == String_16("margb");
02989 }
02990 
02991 BOOL RTFBottomMargin::ExecuteControl()
02992 {
02993     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
02994     pFilter->SetBottomMargin(Parameter);
02995     return TRUE;
02996 }
02997 
02998 BOOL RTFBottomMargin::CreateAndExecute(RTFTextFilter* pFilter, TWIP Height)
02999 {
03000     RTFBottomMargin* pNew = new RTFBottomMargin(pFilter, Height*TwipToMillpoint);
03001 
03002     return ExecuteControlCarefully(pNew);
03003 }
03004 
03005 
03006 
03007 /********************************************************************************************
03008 >   class RTFResetCharAttrs : public RTFControlAction
03009 
03010     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03011     Created:    18/12/95
03012     Purpose:    Dispatches the reset character attributes command.
03013                 No parameter.
03014 ********************************************************************************************/
03015 RTFResetCharAttrs::RTFResetCharAttrs(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0)
03016 {
03017 }
03018 
03019 BOOL RTFResetCharAttrs::IsThisAction(StringBase* pControl)
03020 {
03021     return *pControl == String_16("plain");
03022 }
03023 
03024 BOOL RTFResetCharAttrs::ExecuteControl()
03025 {
03026     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
03027     pFilter->ResetCharacterAttributes();
03028     return TRUE;
03029 }
03030 
03031 BOOL RTFResetCharAttrs::CreateAndExecute(RTFTextFilter* pFilter)
03032 {
03033     RTFResetCharAttrs* pNew = new RTFResetCharAttrs(pFilter);
03034 
03035     return ExecuteControlCarefully(pNew);
03036 }
03037 
03038 
03039 
03040 /********************************************************************************************
03041 >   class RTFResetParaAttrs : public RTFControlAction
03042 
03043     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03044     Created:    18/12/95
03045     Purpose:    Dispatches the reset paragraph attributes command.
03046                 No parameter.
03047 ********************************************************************************************/
03048 RTFResetParaAttrs::RTFResetParaAttrs(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0)
03049 {
03050 }
03051 
03052 BOOL RTFResetParaAttrs::IsThisAction(StringBase* pControl)
03053 {
03054     return *pControl == String_16("pard");
03055 }
03056 
03057 BOOL RTFResetParaAttrs::ExecuteControl()
03058 {
03059     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
03060     pFilter->ResetParagraphAttributes();
03061     return TRUE;
03062 }
03063 
03064 BOOL RTFResetParaAttrs::CreateAndExecute(RTFTextFilter* pFilter)
03065 {
03066     RTFResetParaAttrs* pNew = new RTFResetParaAttrs(pFilter);
03067 
03068     return ExecuteControlCarefully(pNew);
03069 }
03070 
03071 
03072 
03073 /********************************************************************************************
03074 >   class RTFTableCellAction : public RTFControlAction
03075 
03076     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03077     Created:    19/12/95
03078     Purpose:    Dispatches a 'cell' command in a table
03079                 No parameter.
03080 ********************************************************************************************/
03081 RTFTableCellAction::RTFTableCellAction(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0)
03082 {
03083 }
03084 
03085 BOOL RTFTableCellAction::IsThisAction(StringBase* pControl)
03086 {
03087     return *pControl == String_16("cell");
03088 }
03089 
03090 BOOL RTFTableCellAction::ExecuteControl()
03091 {
03092     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
03093     return pFilter->InsertTab();
03094 }
03095 
03096 BOOL RTFTableCellAction::CreateAndExecute(RTFTextFilter* pFilter)
03097 {
03098     RTFTableCellAction* pNew = new RTFTableCellAction(pFilter);
03099 
03100     return ExecuteControlCarefully(pNew);
03101 }
03102 
03103 
03104 
03105 /********************************************************************************************
03106 >   class RTFTableRowAction : public RTFControlAction
03107 
03108     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03109     Created:    19/12/95
03110     Purpose:    Dispatches a 'row' command in a table
03111                 No parameter.
03112 ********************************************************************************************/
03113 RTFTableRowAction::RTFTableRowAction(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0)
03114 {
03115 }
03116 
03117 BOOL RTFTableRowAction::IsThisAction(StringBase* pControl)
03118 {
03119     return *pControl == String_16("row");
03120 }
03121 
03122 BOOL RTFTableRowAction::ExecuteControl()
03123 {
03124     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
03125     return pFilter->StartNewLine();
03126 }
03127 
03128 BOOL RTFTableRowAction::CreateAndExecute(RTFTextFilter* pFilter)
03129 {
03130     RTFTableRowAction* pNew = new RTFTableRowAction(pFilter);
03131 
03132     return ExecuteControlCarefully(pNew);
03133 }
03134 
03135 
03136 
03137 /********************************************************************************************
03138 >   class RTFTabAction : public RTFControlAction
03139 
03140     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03141     Created:    19/12/95
03142     Purpose:    Processes a tab character
03143 ********************************************************************************************/
03144 RTFTabAction::RTFTabAction(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0)
03145 {
03146 }
03147 
03148 BOOL RTFTabAction::IsThisAction(StringBase* pControl)
03149 {
03150     return *pControl == String_16("tab");
03151 }
03152 
03153 BOOL RTFTabAction::ExecuteControl()
03154 {
03155     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
03156     return pFilter->InsertTab();
03157 }
03158 
03159 BOOL RTFTabAction::CreateAndExecute(RTFTextFilter* pFilter)
03160 {
03161     RTFTabAction* pNew = new RTFTabAction(pFilter);
03162     return ExecuteControlCarefully(pNew);
03163 }
03164 
03165 
03166 
03167 /********************************************************************************************
03168 >   class RTFSingleCharAction : public RTFControlAction
03169 
03170     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03171     Created:    2/1/96
03172     Purpose:    Inserts a single 'special' character into the import story
03173                 This class cannot be created and executed; only classes derived from it
03174 ********************************************************************************************/
03175 RTFSingleCharAction::RTFSingleCharAction(RTFTextFilter* pFilt, WCHAR Character) : RTFControlAction(pFilt, Character)
03176 {
03177 }
03178 
03179 BOOL RTFSingleCharAction::ExecuteControl()
03180 {
03181     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
03182     return pFilter->InsertChar((WCHAR)Parameter);
03183 }
03184 
03185 
03186 
03187 /********************************************************************************************
03188 >   class RTFHexCharAction : public RTFSingleCharAction
03189 
03190     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03191     Created:    2/1/96
03192     Purpose:    Processes a character defined by two hex chars
03193 ********************************************************************************************/
03194 RTFHexCharAction::RTFHexCharAction(RTFTextFilter* pFilt, WCHAR Character) : RTFSingleCharAction(pFilt, Character)
03195 {
03196 }
03197 
03198 BOOL RTFHexCharAction::IsThisAction(StringBase* pControl)
03199 {
03200     return *pControl == String_16("'");
03201 }
03202 
03203 BOOL RTFHexCharAction::CreateAndExecute(RTFTextFilter* pFilter)
03204 {
03205     ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
03206 
03207     // read the two hex digits defining this character
03208     BYTE Digits = 0;
03209     for (INT32 loop = 1; loop<=2; loop++)
03210     {
03211         Digits = Digits << 4;
03212         INT32 Base = 0;
03213         TCHAR ReadChar = 0;
03214         if (!pFilter->ReadCharFromFile(&ReadChar))
03215             return FALSE;
03216 
03217         if (ReadChar >= '0' && ReadChar <= '9')
03218             Base = '0';
03219         else
03220         {
03221             if (ReadChar >= 'a' && ReadChar <= 'f')
03222                 Base =  'a' - 10;
03223             else
03224             {
03225                 if (ReadChar >= 'A' && ReadChar <= 'F')
03226                     Base =  'A' - 10;
03227                 else
03228                 {
03229                     Error::SetError(_R(IDE_RTF_DUFFFILE));
03230                     return FALSE;
03231                 }
03232             }
03233         }
03234 
03235         Digits += ReadChar - Base;
03236     }
03237 
03238     WCHAR Character = TextManager::MultiByteToUnicode(Digits);
03239 
03240     RTFHexCharAction* pNew = new RTFHexCharAction(pFilter, Character);
03241 
03242     return ExecuteControlCarefully(pNew);
03243 }
03244 
03245 
03246 
03247 /********************************************************************************************
03248 >   class RTFEmDashAction : public RTFSingleCharAction
03249 
03250     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03251     Created:    3/1/96
03252     Purpose:    Processes a em dash - a dash the width of an em
03253 ********************************************************************************************/
03254 RTFEmDashAction::RTFEmDashAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x2014)
03255 {
03256     // BODGE - check that number!
03257 }
03258 
03259 BOOL RTFEmDashAction::IsThisAction(StringBase* pControl)
03260 {
03261     return *pControl == String_16("emdash");
03262 }
03263 
03264 BOOL RTFEmDashAction::CreateAndExecute(RTFTextFilter* pFilter)
03265 {
03266     RTFEmDashAction* pNew = new RTFEmDashAction(pFilter);
03267     return ExecuteControlCarefully(pNew);
03268 }
03269 
03270 
03271 
03272 /********************************************************************************************
03273 >   class RTFEnDashAction : public RTFSingleCharAction
03274 
03275     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03276     Created:    3/1/96
03277     Purpose:    Processes a en dash - a dash the width of an en
03278 ********************************************************************************************/
03279 RTFEnDashAction::RTFEnDashAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x2013)
03280 {
03281     // BODGE - check that number!
03282 }
03283 
03284 BOOL RTFEnDashAction::IsThisAction(StringBase* pControl)
03285 {
03286     return *pControl == String_16("endash");
03287 }
03288 
03289 BOOL RTFEnDashAction::CreateAndExecute(RTFTextFilter* pFilter)
03290 {
03291     RTFEnDashAction* pNew = new RTFEnDashAction(pFilter);
03292     return ExecuteControlCarefully(pNew);
03293 }
03294 
03295 
03296 
03297 /********************************************************************************************
03298 >   class RTFEmSpaceAction : public RTFSingleCharAction
03299 
03300     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03301     Created:    3/1/96
03302     Purpose:    Processes an em space - a space the width of an em
03303 ********************************************************************************************/
03304 RTFEmSpaceAction::RTFEmSpaceAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x0020)
03305 {
03306     // BODGE - prehaps use a kern to simulate an em space?
03307 }
03308 
03309 BOOL RTFEmSpaceAction::IsThisAction(StringBase* pControl)
03310 {
03311     return *pControl == String_16("emspace");
03312 }
03313 
03314 BOOL RTFEmSpaceAction::CreateAndExecute(RTFTextFilter* pFilter)
03315 {
03316     RTFEmSpaceAction* pNew = new RTFEmSpaceAction(pFilter);
03317     return ExecuteControlCarefully(pNew);
03318 }
03319 
03320 
03321 
03322 /********************************************************************************************
03323 >   class RTFEnSpaceAction : public RTFSingleCharAction
03324 
03325     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03326     Created:    3/1/96
03327     Purpose:    Processes an en space - a space the width of an en
03328 ********************************************************************************************/
03329 RTFEnSpaceAction::RTFEnSpaceAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x0020)
03330 {
03331     // BODGE - prehaps use a kern to simulate an en space?
03332 }
03333 
03334 BOOL RTFEnSpaceAction::IsThisAction(StringBase* pControl)
03335 {
03336     return *pControl == String_16("enspace");
03337 }
03338 
03339 BOOL RTFEnSpaceAction::CreateAndExecute(RTFTextFilter* pFilter)
03340 {
03341     RTFEnSpaceAction* pNew = new RTFEnSpaceAction(pFilter);
03342     return ExecuteControlCarefully(pNew);
03343 }
03344 
03345 
03346 
03347 /********************************************************************************************
03348 >   class RTFBulletAction : public RTFSingleCharAction
03349 
03350     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03351     Created:    3/1/96
03352     Purpose:    Processes a bullet symbol
03353 ********************************************************************************************/
03354 RTFBulletAction::RTFBulletAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x2022)
03355 {
03356 }
03357 
03358 BOOL RTFBulletAction::IsThisAction(StringBase* pControl)
03359 {
03360     return *pControl == String_16("bullet");
03361 }
03362 
03363 BOOL RTFBulletAction::CreateAndExecute(RTFTextFilter* pFilter)
03364 {
03365     RTFBulletAction* pNew = new RTFBulletAction(pFilter);
03366     return ExecuteControlCarefully(pNew);
03367 }
03368 
03369 
03370 
03371 /********************************************************************************************
03372 >   class RTFSingleLeftQuoteAction : public RTFSingleCharAction
03373 
03374     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03375     Created:    3/1/96
03376     Purpose:    Processes single left sexed quote
03377 ********************************************************************************************/
03378 RTFSingleLeftQuoteAction::RTFSingleLeftQuoteAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x2018)
03379 {
03380 }
03381 
03382 BOOL RTFSingleLeftQuoteAction::IsThisAction(StringBase* pControl)
03383 {
03384     return *pControl == String_16("lquote");
03385 }
03386 
03387 BOOL RTFSingleLeftQuoteAction::CreateAndExecute(RTFTextFilter* pFilter)
03388 {
03389     RTFSingleLeftQuoteAction* pNew = new RTFSingleLeftQuoteAction(pFilter);
03390     return ExecuteControlCarefully(pNew);
03391 }
03392 
03393 
03394 
03395 /********************************************************************************************
03396 >   class RTFSingleRightQuoteAction : public RTFSingleCharAction
03397 
03398     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03399     Created:    3/1/96
03400     Purpose:    Processes single right sexed quote
03401 ********************************************************************************************/
03402 RTFSingleRightQuoteAction::RTFSingleRightQuoteAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x2019)
03403 {
03404 }
03405 
03406 BOOL RTFSingleRightQuoteAction::IsThisAction(StringBase* pControl)
03407 {
03408     return *pControl == String_16("rquote");
03409 }
03410 
03411 BOOL RTFSingleRightQuoteAction::CreateAndExecute(RTFTextFilter* pFilter)
03412 {
03413     RTFSingleRightQuoteAction* pNew = new RTFSingleRightQuoteAction(pFilter);
03414     return ExecuteControlCarefully(pNew);
03415 }
03416 
03417 
03418 
03419 /********************************************************************************************
03420 >   class RTFDoubleLeftQuoteAction : public RTFSingleCharAction
03421 
03422     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03423     Created:    3/1/96
03424     Purpose:    Processes double left sexed quote
03425 ********************************************************************************************/
03426 RTFDoubleLeftQuoteAction::RTFDoubleLeftQuoteAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x201c)
03427 {
03428 }
03429 
03430 BOOL RTFDoubleLeftQuoteAction::IsThisAction(StringBase* pControl)
03431 {
03432     return *pControl == String_16("ldblquote");
03433 }
03434 
03435 BOOL RTFDoubleLeftQuoteAction::CreateAndExecute(RTFTextFilter* pFilter)
03436 {
03437     RTFDoubleLeftQuoteAction* pNew = new RTFDoubleLeftQuoteAction(pFilter);
03438     return ExecuteControlCarefully(pNew);
03439 }
03440 
03441 
03442 
03443 /********************************************************************************************
03444 >   class RTFDoubleRightQuoteAction : public RTFSingleCharAction
03445 
03446     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03447     Created:    3/1/96
03448     Purpose:    Processes double right sexed quote
03449 ********************************************************************************************/
03450 RTFDoubleRightQuoteAction::RTFDoubleRightQuoteAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x201d)
03451 {
03452 }
03453 
03454 BOOL RTFDoubleRightQuoteAction::IsThisAction(StringBase* pControl)
03455 {
03456     return *pControl == String_16("rdblquote");
03457 }
03458 
03459 BOOL RTFDoubleRightQuoteAction::CreateAndExecute(RTFTextFilter* pFilter)
03460 {
03461     RTFDoubleRightQuoteAction* pNew = new RTFDoubleRightQuoteAction(pFilter);
03462     return ExecuteControlCarefully(pNew);
03463 }
03464 
03465 
03466 
03467 /********************************************************************************************
03468 >   class RTFNonBreakSpaceAction : public RTFSingleCharAction
03469 
03470     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03471     Created:    3/1/96
03472     Purpose:    Processes double right sexed quote
03473 ********************************************************************************************/
03474 RTFNonBreakSpaceAction::RTFNonBreakSpaceAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x00a0)
03475 {
03476 }
03477 
03478 BOOL RTFNonBreakSpaceAction::IsThisAction(StringBase* pControl)
03479 {
03480     return *pControl == String_16("~");
03481 }
03482 
03483 BOOL RTFNonBreakSpaceAction::CreateAndExecute(RTFTextFilter* pFilter)
03484 {
03485     RTFNonBreakSpaceAction* pNew = new RTFNonBreakSpaceAction(pFilter);
03486     return ExecuteControlCarefully(pNew);
03487 }
03488 
03489 #endif  // #if BUILD_OTHER_TEXT_FILTER
03490 
03491 #endif  // #if BUILD_TEXT_FILTERS

Generated on Sat Nov 10 03:47:09 2007 for Camelot by  doxygen 1.4.4