// $Id: textfltr.cpp 1282 2006-06-09 09:46:49Z alex $ /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE ================================XARAHEADERSTART=========================== Xara LX, a vector drawing and manipulation program. Copyright (C) 1993-2006 Xara Group Ltd. Copyright on certain contributions may be held in joint with their respective authors. See AUTHORS file for details. LICENSE TO USE AND MODIFY SOFTWARE ---------------------------------- This file is part of Xara LX. Xara LX is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. Xara LX and its component source files are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Xara LX (see the file GPL in the root directory of the distribution); if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ADDITIONAL RIGHTS ----------------- Conditional upon your continuing compliance with the GNU General Public License described above, Xara Group Ltd grants to you certain additional rights. The additional rights are to use, modify, and distribute the software together with the wxWidgets library, the wxXtra library, and the "CDraw" library and any other such library that any version of Xara LX relased by Xara Group Ltd requires in order to compile and execute, including the static linking of that library to XaraLX. In the case of the "CDraw" library, you may satisfy obligation under the GNU General Public License to provide source code by providing a binary copy of the library concerned and a copy of the license accompanying it. Nothing in this section restricts any of the rights you have under the GNU General Public License. SCOPE OF LICENSE ---------------- This license applies to this program (XaraLX) and its constituent source files only, and does not necessarily apply to other Xara products which may in part share the same code base, and are subject to their own licensing terms. This license does not apply to files in the wxXtra directory, which are built into a separate library, and are subject to the wxWindows license contained within that directory in the file "WXXTRA-LICENSE". This license does not apply to the binary libraries (if any) within the "libs" directory, which are subject to a separate license contained within that directory in the file "LIBS-LICENSE". ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS ---------------------------------------------- Subject to the terms of the GNU Public License (see above), you are free to do whatever you like with your modifications. However, you may (at your option) wish contribute them to Xara's source tree. You can find details of how to do this at: http://www.xaraxtreme.org/developers/ Prior to contributing your modifications, you will need to complete our contributor agreement. This can be found at: http://www.xaraxtreme.org/developers/contribute/ Please note that Xara will not accept modifications which modify any of the text between the start and end of this header (marked XARAHEADERSTART and XARAHEADEREND). MARKS ----- Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara designs are registered or unregistered trademarks, design-marks, and/or service marks of Xara Group Ltd. All rights in these marks are reserved. Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. http://www.xara.com/ =================================XARAHEADEREND============================ */ // An input filter for importing text files. #include "camtypes.h" #include "textfltr.h" #if BUILD_TEXT_FILTERS //#include "filtrres.h" // code headers //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "clipmap.h" //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "fontman.h" #include "nodetxts.h" #include "nodetext.h" #include "nodetxtl.h" //#include "oilfltrs.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "page.h" //#include "pathname.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "progress.h" //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "textfuns.h" // resource headers //#include "mario.h" //#include "peter.h" //#include "tim.h" DECLARE_SOURCE("$Revision: 1282 $"); CC_IMPLEMENT_DYNAMIC(BaseTextFilter, TextFilter) #if BUILD_OTHER_TEXT_FILTER CC_IMPLEMENT_DYNAMIC(ANSITextFilter, BaseTextFilter) CC_IMPLEMENT_DYNAMIC(UnicodeTextFilter, ANSITextFilter) CC_IMPLEMENT_DYNAMIC(RTFTextFilter, BaseTextFilter) // RTF implementation classes CC_IMPLEMENT_DYNAMIC(StateStore, ListItem) CC_IMPLEMENT_DYNAMIC(RTFColourTable, List); CC_IMPLEMENT_DYNAMIC(RTFColourTableEntry, ListItem); CC_IMPLEMENT_DYNAMIC(RTFFontTable, List); CC_IMPLEMENT_DYNAMIC(RTFFontTableEntry, ListItem); CC_IMPLEMENT_MEMDUMP(RTFControlAction, CC_CLASS_MEMDUMP) CC_IMPLEMENT_MEMDUMP(RTFEnterSkipDest, RTFControlAction) CC_IMPLEMENT_MEMDUMP(RTFNewParaAction, RTFControlAction) CC_IMPLEMENT_MEMDUMP(RTFColourTableAction, RTFControlAction) CC_IMPLEMENT_MEMDUMP(RTFFontTableAction, RTFControlAction) CC_IMPLEMENT_MEMDUMP(RTFPaperWidth, RTFControlAction) CC_IMPLEMENT_MEMDUMP(RTFPaperHeight, RTFControlAction) CC_IMPLEMENT_MEMDUMP(RTFLeftMargin, RTFControlAction) CC_IMPLEMENT_MEMDUMP(RTFRightMargin, RTFControlAction) CC_IMPLEMENT_MEMDUMP(RTFTopMargin, RTFControlAction) CC_IMPLEMENT_MEMDUMP(RTFBottomMargin, RTFControlAction) CC_IMPLEMENT_MEMDUMP(RTFResetCharAttrs, RTFControlAction) CC_IMPLEMENT_MEMDUMP(RTFResetParaAttrs, RTFControlAction) CC_IMPLEMENT_MEMDUMP(RTFTableCellAction, RTFControlAction) CC_IMPLEMENT_MEMDUMP(RTFTableRowAction, RTFControlAction) CC_IMPLEMENT_MEMDUMP(RTFTabAction, RTFControlAction) CC_IMPLEMENT_MEMDUMP(RTFSingleCharAction, RTFControlAction) CC_IMPLEMENT_MEMDUMP(RTFAttributeAction, RTFControlAction) CC_IMPLEMENT_MEMDUMP(RTFBoldAttribute, RTFAttributeAction) CC_IMPLEMENT_MEMDUMP(RTFTextSizeAttribute, RTFAttributeAction) CC_IMPLEMENT_MEMDUMP(RTFTextColourAttribute, RTFAttributeAction) CC_IMPLEMENT_MEMDUMP(RTFTextFontAttribute, RTFAttributeAction) CC_IMPLEMENT_MEMDUMP(RTFItalicAttribute, RTFAttributeAction) CC_IMPLEMENT_MEMDUMP(RTFNoscriptAttribute, RTFAttributeAction) CC_IMPLEMENT_MEMDUMP(RTFSubscriptAttribute, RTFAttributeAction) CC_IMPLEMENT_MEMDUMP(RTFSuperscriptAttribute, RTFAttributeAction) CC_IMPLEMENT_MEMDUMP(RTFTWIPTrackingAttribute, RTFAttributeAction) CC_IMPLEMENT_MEMDUMP(RTFQPTrackingAttribute, RTFAttributeAction) CC_IMPLEMENT_MEMDUMP(RTFHexCharAction, RTFSingleCharAction) CC_IMPLEMENT_MEMDUMP(RTFEmDashAction, RTFSingleCharAction) CC_IMPLEMENT_MEMDUMP(RTFEnDashAction, RTFSingleCharAction) CC_IMPLEMENT_MEMDUMP(RTFEmSpaceAction, RTFSingleCharAction) CC_IMPLEMENT_MEMDUMP(RTFEnSpaceAction, RTFSingleCharAction) CC_IMPLEMENT_MEMDUMP(RTFBulletAction, RTFSingleCharAction) CC_IMPLEMENT_MEMDUMP(RTFSingleLeftQuoteAction, RTFSingleCharAction) CC_IMPLEMENT_MEMDUMP(RTFSingleRightQuoteAction, RTFSingleCharAction) CC_IMPLEMENT_MEMDUMP(RTFDoubleLeftQuoteAction, RTFSingleCharAction) CC_IMPLEMENT_MEMDUMP(RTFDoubleRightQuoteAction, RTFSingleCharAction) CC_IMPLEMENT_MEMDUMP(RTFNonBreakSpaceAction, RTFSingleCharAction) #endif //#if BUILD_OTHER_TEXT_FILTER #define new CAM_DEBUG_NEW /******************************************************************************************** > BaseTextFilter::BaseTextFilter() Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Purpose: Constructor. Initialises member variables ********************************************************************************************/ BaseTextFilter::BaseTextFilter() { } /******************************************************************************************** > BaseTextFilter::~BaseTextFilter() Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Purpose: Destructor. Frees memory and cleans up. ********************************************************************************************/ BaseTextFilter::~BaseTextFilter() { } /******************************************************************************************** > TextStory* BaseTextFilter::CreateImportStory(DocCoord Pos); Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Inputs: Pos - the position of the top left of the text story Outputs: - Returns: Pointer to a created TextStory object. NULL on error Purpose: Creates an empty text story for importing characters into SeeAlso: BaseTextFilter::AddCharToStory ********************************************************************************************/ TextStory* BaseTextFilter::CreateImportStory(DocCoord Pos) { return TextStory::CreateTextObject(Pos); } /******************************************************************************************** > VisibleTextNode* BaseTextFilter::AddCharToStory(TextStory* pStory, WCHAR NewChar); Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Inputs: pStory - pointer to the story to add character to NewChar - the character (Unicode value) Outputs: - Returns: Pointer to the new character, NULL for error Purpose: Adds the given character to the story. It is added as the last character on the last line. The filters current attributes are applied to the new character. SeeAlso: BaseTextFilter::AddNewLineToStory ********************************************************************************************/ VisibleTextNode* BaseTextFilter::AddCharToStory(TextStory* pStory, WCHAR NewChar) { ERROR2IF(pStory == NULL, NULL, "NULL Story pointer"); // Find the EOLNode on the last line VisibleTextNode* pLastNode = pStory->FindLastVTN(); ERROR2IF(pLastNode == NULL, NULL, "Story was (very) empty"); // Create a new character, inserting into the story at the same time VisibleTextNode* pNew = new TextChar(pLastNode, PREV, NewChar); if (pNew != NULL) { if (!AttributeManager::ApplyBasedOnDefaults(pNew, CurrentAttrs)) { delete pNew; pNew = NULL; } } return pNew; } /******************************************************************************************** > BOOL BaseTextFilter::AddNewLineToStory(TextStory* pStory) Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Inputs: pStory - pointer to the story to add the line to Outputs: - Returns: TRUE/FALSE for success/failure Purpose: Adds a new (empty) line to the end of the story SeeAlso: BaseTextFilter::AddCharToStory ********************************************************************************************/ BOOL BaseTextFilter::AddNewLineToStory(TextStory* pStory) { ERROR2IF(pStory == NULL, NULL, "NULL Story pointer"); // Create the new line as the last child of the story TextLine* pNewLine = new TextLine(pStory, LASTCHILD); // Create an EOL node for the new line EOLNode* pEOL = NULL; if (pNewLine != NULL) { pEOL = new EOLNode(pNewLine, LASTCHILD); if ( (pEOL == NULL) || (!AttributeManager::ApplyBasedOnDefaults(pEOL, CurrentAttrs)) ) { pNewLine->CascadeDelete(); delete pNewLine; pNewLine = NULL; } } return ((pNewLine != NULL) && (pEOL != NULL)); } /******************************************************************************************** > BOOL BaseTextFilter::AddTabToStory(TextStory* pStory, MILLIPOINT TabLength = 50000) Author: Peter_Arnold (Xara Group Ltd) Created: 25/11/95 Inputs: pStory - pointer to the story to add the tab to TabLength - the length of the tab Outputs: - Returns: TRUE/FALSE for success/failure Purpose: Adds a TAB character to the story. As stories currently don't have tabs a kern character of the appropiate size is added instead SeeAlso: BaseTextFilter::AddCharToStory ********************************************************************************************/ BOOL BaseTextFilter::AddTabToStory(TextStory* pStory, MILLIPOINT TabLength) { ERROR2IF(pStory == NULL, FALSE, "NULL Story pointer"); // Find the EOLNode on the last line VisibleTextNode* pLastNode = pStory->FindLastVTN(); ERROR2IF(pLastNode == NULL, FALSE, "Story was (very) empty"); // Create a new kern, inserting into the story at the same time KernCode* pNewKern = new KernCode(pLastNode, PREV, DocCoord(TabLength, 0)); if (pNewKern != NULL) return AttributeManager::ApplyBasedOnDefaults(pNewKern, CurrentAttrs); else return FALSE; } #if BUILD_OTHER_TEXT_FILTER /******************************************************************************************** > ANSITextFilter::ANSITextFilter() Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Purpose: Filter constructor - this initialises the default attributes and the input buffer. ********************************************************************************************/ ANSITextFilter::ANSITextFilter() { Flags.CanImport = TRUE; Flags.CanExport = FALSE; // Set up filter descriptions. FilterName.Load(_R(IDT_TEXT_FILTERNAME)); FilterInfo.Load(_R(IDT_TEXT_FILTERINFO)); FilterID = FILTERID_TEXT_ASCII; BytesReadSoFar = 0; EscapeWasPressed = FALSE; }; /******************************************************************************************** > ANSITextFilter::~ANSITextFilter() Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Purpose: Destructor for the filter ********************************************************************************************/ ANSITextFilter::~ANSITextFilter() { } /******************************************************************************************** > BOOL ANSITextFilter::Init() Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Returns: TRUE for successful initialisation, FALSE if error occured Purpose: Initialise the filter (attaches a TextOILFilter object). SeeAlso: TextOILFilter ********************************************************************************************/ BOOL ANSITextFilter::Init() { // Get the OILFilter object pOILFilter = new ANSITextOILFilter(this); if (pOILFilter == NULL) return FALSE; // All ok return TRUE; } /******************************************************************************************** > virtual BOOL ANSITextFilter::IsDefaultDocRequired(const TCHAR* pcszPathName) Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Inputs: pcszPathName - pointer to the pathname to check Returns: TRUE if the filter requires a default document, FALSE if not. Purpose: Works out if opening a file of this type requires a default document to be loaded. This filter always returns TRUE as ANSI text files have no page information SeeAlso: Filter::IsDefaultDocRequired ********************************************************************************************/ BOOL ANSITextFilter::IsDefaultDocRequired(const TCHAR* pcszPathName) { return TRUE; } /******************************************************************************************** > INT32 ANSITextFilter::HowCompatible(PathName& Filename, ADDR HeaderStart, UINT32 HeaderSize, UINT32 FileSize) Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Inputs: Filename - name of the file. HeaderStart - Address of the first few bytes of the file. HeaderSize - the number of bytes in the header pointed to by FileStart. FileSize - the size of the whole file, in bytes. Returns: Compatibility: 0 => Not an ANSI text file; 10 => It is an ANSI text file Purpose: Analyse a file to see if it contains ANSI text. SeeAlso: TextOILFilter::HowCompatible ********************************************************************************************/ INT32 ANSITextFilter::HowCompatible(PathName& Filename, ADDR HeaderStart, UINT32 HeaderSize, UINT32 FileSize) { PORTNOTE("byteorder", "TODO: Check byte ordering") if (pOILFilter == NULL) { ERROR3("No oil filter!"); return 0; } // check the file type against the type for text files. If it matches only return 9 so the // more specialised text files (eg Unicode) can claim it by returning 10. if (pOILFilter->DoesExtensionOfPathNameMatch(&Filename)) return 9; // We can have a stab at loading any file as text as a last resort return 1; } /******************************************************************************************** > BOOL ANSITextFilter::PrepareToImport() Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Returns: TRUE if it succeeds, FALSE if not. Purpose: Sets up the filter so it can attempt to read in a file. SeeAlso: ANSITextFilter::CleanUpAfterImport ********************************************************************************************/ BOOL ANSITextFilter::PrepareToImport() { // Get a default set of attributes for ink objects. if (!SetUpCurrentAttrs()) return FALSE; BytesReadSoFar = 0; EscapeWasPressed = FALSE; return TRUE; } /******************************************************************************************** > void ANSITextFilter::CleanUpAfterImport() Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Purpose: Delete dynamic objects used in the import process. SeeAlso: ANSITextFilter::PrepareToImport; ANSITextFilter::DoImport ********************************************************************************************/ void ANSITextFilter::CleanUpAfterImport() { DeleteCurrentAttrs(); } /******************************************************************************************** > BOOL ANSITextFilter::DoImport(SelOperation *Op, CCLexFile* pFile, Document *DestDoc, BOOL AutoChosen, ImportPosition *Pos) Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/93 Inputs: Op - pointer to the operation that this read process is associated with. pFile - The file that we are trying to import DestDoc - pointer to the document to insert the file data into. AutoChosen - Pos - pointer to the position to insert the text file at Returns: TRUE if the read was successful, FALSE if not. Purpose: Import the named text file into the specified document. If the read is successful, the End() function of the 'Op' operation is called, otherwise it is not called. Errors: Unable to open file, corrupted document tree found. ********************************************************************************************/ BOOL ANSITextFilter::DoImport(SelOperation *Op, CCLexFile* pFile, Document *DestDoc, BOOL AutoChosen, ImportPosition *Pos) { ERROR2IF((Op == NULL) || (pFile == NULL) || (DestDoc == NULL), FALSE, "NULL Parameter"); // Let's get ready if (!PrepareToImport()) return FALSE; // Get spread and import position Spread *pSpread = NULL; DocCoord ImportPos(0,0); if (Pos == NULL) { pSpread = GetFirstSpread(DestDoc); ERROR2IF(pSpread == NULL, FALSE, "No spread in document"); Page* pPage = pSpread->FindFirstPageInSpread(); ERROR2IF(pPage == NULL, FALSE, "No page in spread"); ImportPos = DocCoord(pPage->GetPageRect().lox, pPage->GetPageRect().hiy); } else { pSpread = Pos->pSpread; ImportPos = Pos->Position; } // Create a text story object to add the characters into. TextStory* pStory = CreateImportStory(ImportPos); if (pStory == NULL) return FALSE; //FlagChangedByOp() modified to mModifiedByOp() pStory->mModifiedByOp(); if (!DestDoc->GetAttributeMgr().ApplyCurrentAttribsToNode(pStory)) { pStory->CascadeDelete(); delete pStory; return FALSE; } // Initialise our handling of the file pFile->SetReportErrors(FALSE); pFile->SetThrowExceptions(FALSE); // Call the virtual import function BOOL Success = DoInternalImport(pStory, pFile); // Clean up after importing EndSlowJob(); CleanUpAfterImport(); // Insert the new sub-tree into the document if (!EscapeWasPressed) { if (Success) Success = pStory->FormatAndChildren(); if (Success) Success = Op->DoInsertNewNode(pStory, pSpread, TRUE); } // If the load failed for any reason, delete the subtree we have created if (!Success || EscapeWasPressed) { pStory->CascadeDelete(); delete pStory; } return Success; } /******************************************************************************************** > BOOL ANSITextFilter::DoExport(Operation*, CCLexFile*, PathName*, Document*) Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Inputs: As base class version. Returns: TRUE/FALSE for success/failure Purpose: Exports the document as an ANSI text file. SeeAlso: Filter::DoExport ********************************************************************************************/ BOOL ANSITextFilter::DoExport(Operation*, CCLexFile*, PathName* pPath, Document*) { ERROR3("ANSITextFilter::DoExport is not implemented"); return FALSE; } /******************************************************************************************** > virtual BOOL ANSITextFilter::DoInternalImport(TextStory* pImportStory, CCLexFile* pFile) Author: Peter_Arnold (Xara Group Ltd) Created: 25/11/95 Inputs: pImportStory - the TextStory to import into pFile - the file to read the characters from Returns: TRUE/FALSE for success/failure Purpose: Imports ANSI and multi-byte characters from the file into the text story. SeeAlso: ANSITextFilter::DoImport ********************************************************************************************/ BOOL ANSITextFilter::DoInternalImport(TextStory* pImportStory, CCLexFile* pFile) { ERROR2IF((pImportStory == NULL) || (pFile == NULL), FALSE, "NULL entry parameter"); UINT32 FileSize = pFile->Size(); // Set the progress indicator for a nice percentage display String_64 ImportMessage(_R(IDT_IMPORTMSG_TEXT)); ImportMessage = GetImportProgressString(pFile, _R(IDT_IMPORTMSG_TEXT)); BeginSlowJob(FileSize, TRUE, &ImportMessage); // Skip over any header that may be on the file if (!SkipHeader(pFile)) return FALSE; // Process the file character by character, adding it to the story each time WCHAR PrevChar = ' '; WCHAR NewChar = ' ' ; BOOL ok = TRUE; do { // Read and process each character PrevChar = NewChar; NewChar = GetNextCharacter(pFile); if (NewChar < ' ') { switch (NewChar) { case 0x00: // Error in reading ok = FALSE; break; case 0x09: // Tab ok = AddTabToStory(pImportStory); break; case 0x0A: // NewLine if (PrevChar != 0x0D) ok = AddNewLineToStory(pImportStory); break; case 0x0D: // CR if (PrevChar != 0x0A) ok = AddNewLineToStory(pImportStory); break; default: ; // Ignore the character } } else ok = (AddCharToStory(pImportStory, NewChar) != NULL); if (!ContinueSlowJob(BytesReadSoFar)) { EscapeWasPressed = TRUE; return TRUE; } } while ((BytesReadSoFar < FileSize) && ok && pFile->good()); return pFile->good() && ok; } /******************************************************************************************** > WCHAR ANSITextFilter::GetNextCharacter(CCLexFile* pFile) Author: Peter_Arnold (Xara Group Ltd) Created: 25/11/95 Inputs: pImportStory - the TextStory to import into pFile - the file to read the characters from Returns: Next character from file. 0 if error Purpose: Gets the next character from the import file SeeAlso: ANSITextFilter::DoInternalImport ********************************************************************************************/ WCHAR ANSITextFilter::GetNextCharacter(CCLexFile* pFile) { ERROR2IF((pOILFilter == NULL), 0, "No Text OIL filter"); UINT32 BytesRead = 0; WCHAR ReadChar = ((ANSITextOILFilter*)pOILFilter)->ReadMultiByteChar(pFile, &BytesRead); BytesReadSoFar += BytesRead; return ReadChar; } /******************************************************************************************** > virtual BOOL ANSITextFilter::SkipHeader(CCLexFile* pFile) Author: Peter_Arnold (Xara Group Ltd) Created: 25/11/95 Inputs: pFile - the file to read the characters from Returns: TRUE/FALSE for success/failure Purpose: Does nothing as ANSI text files have no header ********************************************************************************************/ BOOL ANSITextFilter::SkipHeader(CCLexFile* pFile) { return TRUE; } /******************************************************************************************** > UnicodeTextFilter::UnicodeTextFilter() Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Purpose: Filter constructor - this initialises the default attributes and the input buffer. ********************************************************************************************/ UnicodeTextFilter::UnicodeTextFilter() { Flags.CanImport = TRUE; Flags.CanExport = FALSE; // Set up filter descriptions. FilterName.Load(_R(IDT_TEXT_FILTERNAME)); FilterInfo.Load(_R(IDT_TEXT_FILTERINFO)); FilterID = FILTERID_TEXT_UNICODE; }; /******************************************************************************************** > UnicodeTextFilter::~UnicodeTextFilter() Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Purpose: Destructor for the filter - this deallocates the input buffer. ********************************************************************************************/ UnicodeTextFilter::~UnicodeTextFilter() { } /******************************************************************************************** > BOOL UnicodeTextFilter::Init() Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Returns: TRUE for successful initialisation, FALSE if error occured Purpose: Initialise the filter (attaches an OILFilter object). SeeAlso: UnicodeTextOILFilter ********************************************************************************************/ BOOL UnicodeTextFilter::Init() { // Get the OILFilter object pOILFilter = new UnicodeTextOILFilter(this); if (pOILFilter == NULL) return FALSE; // All ok return TRUE; } /******************************************************************************************** > INT32 UnicodeTextFilter::HowCompatible(PathName& Filename, ADDR HeaderStart, UINT32 HeaderSize, UINT32 FileSize) Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Inputs: Filename - name of the file. HeaderStart - Address of the first few bytes of the file. HeaderSize - the number of bytes in the header pointed to by FileStart. FileSize - the size of the whole file, in bytes. Returns: Compatibility: 0 => Not a Unicode text file; 10 => It is a Unicode text file Purpose: Analyse a file to see if it contains Unicode text. SeeAlso: ANSITextFilter::HowCompatible ********************************************************************************************/ INT32 UnicodeTextFilter::HowCompatible(PathName& Filename, ADDR HeaderStart, UINT32 HeaderSize, UINT32 FileSize) { PORTNOTE("byteorder", "TODO: Check byte ordering") if (pOILFilter == NULL) { ERROR3("No oil filter!"); return 0; } // To load Unicode text the extension must match if (pOILFilter->DoesExtensionOfPathNameMatch(&Filename)) { // The first two bytes must be 0xFFFE too if ( (*HeaderStart == 0xFF) && (*(HeaderStart+1) == 0xFE) ) return 10; } return 0; } /******************************************************************************************** > WCHAR UnicodeTextFilter::GetNextCharacter(CCLexFile* pFile) Author: Peter_Arnold (Xara Group Ltd) Created: 25/11/95 Inputs: pImportStory - the TextStory to import into pFile - the file to read the characters from Returns: Next character from file. 0 if error Purpose: Gets the next character from the import file SeeAlso: UnicodeTextFilter::DoInternalImport ********************************************************************************************/ WCHAR UnicodeTextFilter::GetNextCharacter(CCLexFile* pFile) { ERROR2IF((pOILFilter == NULL), 0, "No Text OIL filter"); BytesReadSoFar += 2; return ((UnicodeTextOILFilter*)pOILFilter)->ReadUnicodeChar(pFile); } /******************************************************************************************** > virtual BOOL UnicodeTextFilter::SkipHeader(CCLexFile* pFile) Author: Peter_Arnold (Xara Group Ltd) Created: 25/11/95 Inputs: pFile - the file to read the characters from Returns: TRUE/FALSE for success/failure Purpose: Skips over the header on Unicode files ********************************************************************************************/ BOOL UnicodeTextFilter::SkipHeader(CCLexFile* pFile) { BYTE Dummy[2]; pFile->read(Dummy, 2); BytesReadSoFar += 2; return pFile->good(); } /******************************************************************************************** > StateStore::StateStore() Author: Peter_Arnold (Xara Group Ltd) Created: 15/12/95 Purpose: Constructor - initialises member variables ********************************************************************************************/ StateStore::StateStore() { DestinationState = rdsNorm; InternalState = risNorm; InterCharGap = 0; } StateStore::~StateStore() {} StateStore& StateStore::operator=(const StateStore& rhs) { this->DestinationState = rhs.DestinationState; this->InternalState = rhs.InternalState; this->InterCharGap = rhs.InterCharGap; return *this; } /******************************************************************************************** > RTFTextFilter::RTFTextFilter() Author: Peter_Arnold (Xara Group Ltd) Created: 25/11/95 Purpose: Filter constructor ********************************************************************************************/ RTFTextFilter::RTFTextFilter() { Flags.CanImport = TRUE; Flags.CanExport = FALSE; // Set up filter descriptions. FilterName.Load(_R(IDT_RTF_FILTERNAME)); FilterInfo.Load(_R(IDT_RTF_FILTERINFO)); FilterID = FILTERID_TEXT_RTF; // Init member vars to safe values EscapeWasPressed = FALSE; pImportStory = NULL; BytesReadSoFar = 0; ImportHasFinished = FALSE; }; /******************************************************************************************** > RTFTextFilter::~RTFTextFilter() Author: Peter_Arnold (Xara Group Ltd) Created: 25/11/95 Purpose: Destructor for the filter ********************************************************************************************/ RTFTextFilter::~RTFTextFilter() { } /******************************************************************************************** > BOOL RTFTextFilter::Init() Author: Peter_Arnold (Xara Group Ltd) Created: 25/11/95 Returns: TRUE for successful initialisation, FALSE if error occured Purpose: Initialise the filter (attaches a TextOILFilter object). SeeAlso: RTFTextOILFilter ********************************************************************************************/ BOOL RTFTextFilter::Init() { // Get the OILFilter object pOILFilter = new RTFTextOILFilter(this); if (pOILFilter == NULL) return FALSE; return ((RTFTextOILFilter*)pOILFilter)->RegisterWithClipboard(this); } /******************************************************************************************** > virtual BOOL RTFTextFilter::IsDefaultDocRequired(const TCHAR* pcszPathName) Author: Peter_Arnold (Xara Group Ltd) Created: 25/11/95 Inputs: pcszPathName pointer to the pathname to check Returns: TRUE if the filter requires a default document, FALSE if not. Purpose: Works out if opening a file of this type requires a default document to be loaded. This filter always returns TRUE as RTF files have no page information SeeAlso: Filter::IsDefaultDocRequired ********************************************************************************************/ BOOL RTFTextFilter::IsDefaultDocRequired(const TCHAR* pcszPathName) { return TRUE; } /******************************************************************************************** > INT32 RTFTextFilter::HowCompatible(PathName& Filename, ADDR HeaderStart, UINT32 HeaderSize, UINT32 FileSize) Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Inputs: Filename - name of the file. HeaderStart - Address of the first few bytes of the file. HeaderSize - the number of bytes in the header pointed to by FileStart. FileSize - the size of the whole file, in bytes. Returns: Compatibility: 0 => Not a RTF file; 10 => It is a RTF file Purpose: Analyse a file to see if it contains RTF information ********************************************************************************************/ INT32 RTFTextFilter::HowCompatible(PathName& Filename, ADDR HeaderStart, UINT32 HeaderSize, UINT32 FileSize) { PORTNOTE("byteorder", "TODO: Check byte ordering") if (pOILFilter == NULL) { ERROR3("No oil filter!"); return 0; } // File extension must be RTF if (pOILFilter->DoesExtensionOfPathNameMatch(&Filename)) { // File must start "{\rtf" if ((*HeaderStart == '{') && (*(HeaderStart+1) == '\\') && (*(HeaderStart+2) == 'r') && (*(HeaderStart+3) == 't') && (*(HeaderStart+4) == 'f') ) return 10; } return 0; } /******************************************************************************************** > BOOL RTFTextFilter::PrepareToImport() Author: Peter_Arnold (Xara Group Ltd) Created: 25/11/95 Returns: TRUE if it succeeds, FALSE if not. Purpose: Sets up the filter so it can attempt to read in a file. SeeAlso: RTFTextFilter::CleanUpAfterImport ********************************************************************************************/ BOOL RTFTextFilter::PrepareToImport() { // Get a default set of attributes for ink objects. if (!SetUpCurrentAttrs()) return FALSE; // Set the fill colour to black and the outline to none SetFillColour(DocColour(COLOUR_BLACK)); SetLineColour(DocColour(COLOUR_TRANS)); BytesReadSoFar = 0; pImportStory = NULL; EscapeWasPressed = FALSE; ImportHasFinished = FALSE; // Ensure the various stacks and tables are empty if (!StateStack.IsEmpty()) { ERROR3("State stack was not empty when import started"); StateStack.DeleteAll(); } if (!PreviousAttributes.GetList()->IsEmpty()) { ERROR3("Attribute stack was not empty when import started"); PreviousAttributes.GetList()->DeleteAll(); } if (!ColourTable.IsEmpty()) { ERROR3("Colour table not empty when import started"); ColourTable.DeleteAll(); } InitialiseInfo(); cbBin = 0; fSkipDestIfUnk = FALSE; return TRUE; } /******************************************************************************************** > void RTFTextFilter::CleanUpAfterImport() Author: Peter_Arnold (Xara Group Ltd) Created: 25/11/95 Purpose: Delete dynamic objects used in the import process. SeeAlso: RTFTextFilter::PrepareToImport; RTFTextFilter::DoImport ********************************************************************************************/ void RTFTextFilter::CleanUpAfterImport() { DeleteCurrentAttrs(); // Ensure the various stacks and tables are empty and memory freed StateStack.DeleteAll(); PreviousAttributes.GetList()->DeleteAll(); ColourTable.DeleteAll(); FontTable.DeleteAll(); } /******************************************************************************************** > BOOL RTFTextFilter::DoImport(SelOperation *Op, CCLexFile* pFile, Document *DestDoc, BOOL AutoChosen, ImportPosition *Pos) Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/93 Inputs: Op - pointer to the operation that this read process is associated with. pFile - The file that we are trying to import DestDoc - pointer to the document to insert the file data into. AutoChosen - Pos - pointer to the position to insert the text file at Returns: TRUE if the read was successful, FALSE if not. Purpose: Import the named text file into the specified document. If the read is successful, the End() function of the 'Op' operation is called, otherwise it is not called. Errors: Unable to open file, corrupted document tree found. ********************************************************************************************/ BOOL RTFTextFilter::DoImport(SelOperation *Op, CCLexFile* pFile, Document* DestDoc, BOOL AutoChosen, ImportPosition* Pos) { ERROR2IF((Op == NULL) || (pFile == NULL) || (DestDoc == NULL), FALSE, "NULL Parameter"); if (!PrepareToImport()) return FALSE; // Get spread and import position Spread *pSpread = NULL; DocCoord ImportPos(0,0); if (Pos == NULL) { pSpread = GetFirstSpread(DestDoc); ERROR2IF(pSpread == NULL, FALSE, "No spread in document"); Page* pPage = pSpread->FindFirstPageInSpread(); ERROR2IF(pPage == NULL, FALSE, "No page in spread"); ImportPos = DocCoord(pPage->GetPageRect().lox, pPage->GetPageRect().hiy); } else { pSpread = Pos->pSpread; ImportPos = Pos->Position; } // Create a text story object to add the characters into. pImportStory = CreateImportStory(ImportPos); if (pImportStory == NULL) return FALSE; // Initialise our handling of the file pFile->SetReportErrors(FALSE); pFile->SetThrowExceptions(FALSE); pImportFile = pFile; // Call the virtual import function BOOL Success = DoInternalImport(); // Clean up after importing EndSlowJob(); CleanUpAfterImport(); // Insert new sub-tree into the document if (!EscapeWasPressed && Success) { if (Success) Success = pImportStory->OptimiseAttributes(); // Optimise up to story level if (Success) Success = pImportStory->FormatAndChildren(); // Initial format to setup char bounds pImportStory->SetImportFormatWidth(PaperWidth - LeftMargin - RightMargin); if (Success) Success = pImportStory->FormatToWidth(); // split paras to story width if (Success) Success = pImportStory->FormatAndChildren(); // Format again for new lines if (Success) Success = Op->DoInsertNewNode(pImportStory, pSpread, TRUE); } // If the load failed for any reason, delete the subtree we have created if (!Success || EscapeWasPressed) { pImportStory->CascadeDelete(); delete pImportStory; } return Success; } /******************************************************************************************** > BOOL RTFTextFilter::DoExport(Operation*, CCLexFile*, PathName*, Document*) Author: Peter_Arnold (Xara Group Ltd) Created: 24/11/95 Inputs: As base class version. Returns: TRUE/FALSE for success/failure Purpose: Exports the document as an ANSI text file. SeeAlso: Filter::DoExport ********************************************************************************************/ BOOL RTFTextFilter::DoExport(Operation*, CCLexFile*, PathName*, Document*) { ERROR3("RTFTextFilter::DoExport is not implemented"); return FALSE; } /******************************************************************************************** > virtual BOOL RTFTextFilter::DoInternalImport() Author: Peter_Arnold (Xara Group Ltd) Created: 25/11/95 Inputs: - Returns: TRUE/FALSE for success/failure Purpose: Parses the RTF file for the text and the control parts SeeAlso: RTFTextFilter::DoImport ********************************************************************************************/ BOOL RTFTextFilter::DoInternalImport() { ERROR2IF((pImportStory == NULL) || (pImportFile == NULL), FALSE, "NULL entry parameter"); UINT32 FileSize = pImportFile->Size(); // Set the progress indicator for a nice percentage display String_64 ImportMessage(_R(IDT_IMPORTMSG_TEXT)); ImportMessage = GetImportProgressString(pImportFile, _R(IDT_IMPORTMSG_TEXT)); BeginSlowJob(FileSize, TRUE, &ImportMessage); BOOL ok = TRUE; CurrentState.InternalState = StateStore::risNorm; CurrentState.DestinationState = StateStore::rdsNorm; TCHAR ReadChar; while (pImportFile->good() && (BytesReadSoFar <= FileSize-1) && !ImportHasFinished) { // Update the percentage, allows users to press escape if (!ContinueSlowJob(BytesReadSoFar)) { EscapeWasPressed = TRUE; return TRUE; } if (!ReadCharFromFile(&ReadChar)) return FALSE; if (CurrentState.InternalState == StateStore::risBin) // if we're parsing binary data, handle it directly { ERROR3("BinaryData not yet handled"); if (!ParseChar(ReadChar)) return FALSE; } else { switch (ReadChar) { case '{': if (!PushRTFState()) return FALSE; break; case '}': if (!PopRTFState()) return FALSE; break; case '\\': if (!ParseRTFKeyword()) return FALSE; break; default: ERROR2IF(CurrentState.InternalState != StateStore::risNorm, FALSE, "In unknown parsing state"); if (!ParseChar(ReadChar)) return FALSE; break; } // switch } // else (ris != risBin) } // while if (!StateStack.IsEmpty()) ERROR1(FALSE, _R(IDE_RTF_DUFFFILE)); // Delete any empty lines at the end of the story if (ok) { VisibleTextNode* pLastNode = pImportStory->FindLastVisibleTextNode(); BOOL LastLineEmpty = FALSE; if (pLastNode != NULL) LastLineEmpty = (pLastNode->FindPrevious() == NULL); while (LastLineEmpty) { Node* pParent = pLastNode->FindParent(); if (pParent != NULL) { pParent->CascadeDelete(); delete pParent; pLastNode = pImportStory->FindLastVisibleTextNode(); if (pLastNode != NULL) LastLineEmpty = (pLastNode->FindPrevious() == NULL); } else LastLineEmpty = FALSE; } } return pImportFile->good() && ok; } /******************************************************************************************** > BOOL RTFTextFilter::PushRTFState(void) Author: Peter_Arnold (Xara Group Ltd) Created: 27/11/95 Inputs: - Returns: TRUE/FALSE for success/failure Purpose: Pushes the current state RTF state onto the state stack SeeAlso: RTFTextFilter::PopRTFState ********************************************************************************************/ BOOL RTFTextFilter::PushRTFState(void) { // Create a new object to store the state in StateStore* pState = new StateStore; if (pState == NULL) return FALSE; *pState = CurrentState; StateStack.Push(pState); // Store the current attribute state if (!PreviousAttributes.SaveContext(CurrentAttrs)) return FALSE; // Reset the current state CurrentState.InternalState = StateStore::risNorm; return TRUE; } /******************************************************************************************** > BOOL RTFTextFilter::PopRTFState(void) Author: Peter_Arnold (Xara Group Ltd) Created: 27/11/95 Inputs: - Returns: TRUE/FALSE for success/failure Purpose: Pops the state off the top of the RTF stack and set the current state to it. SeeAlso: RTFTextFilter::PushRTFState ********************************************************************************************/ BOOL RTFTextFilter::PopRTFState(void) { StateStore* pState = (StateStore*)StateStack.Pop(); ERROR2IF(pState == NULL, FALSE, "State stack was empty"); // Are we going to change destination on this state change? if (CurrentState.DestinationState != pState->DestinationState) { if (!EndGroupAction(CurrentState.DestinationState)) return FALSE; } CurrentState = *pState; delete pState; // Set current state to stored state if (!PreviousAttributes.RestoreContext(CurrentAttrs)) return FALSE; if (StateStack.IsEmpty()) ImportHasFinished = TRUE; return TRUE; } /******************************************************************************************** > BOOL RTFTextFilter::ParseRTFKeyword() Author: Peter_Arnold (Xara Group Ltd) Created: 27/11/95 Inputs: - Returns: TRUE/FALSE for success/failure Purpose: Reads and proccesses a RTF control word and its parameter SeeAlso: RTFTextFilter::TranslateKeyword ********************************************************************************************/ BOOL RTFTextFilter::ParseRTFKeyword() { String_256 Keyword = ""; INT32 Parameter = 0; BOOL ParameterUsed = FALSE; if (RTFTextFilter::ReadKeyword(&Keyword, &Parameter, &ParameterUsed)) return TranslateKeyword(&Keyword, Parameter, ParameterUsed); else return FALSE; } /******************************************************************************************** > BOOL RTFTextFilter::ParseChar(WCHAR ch) Author: Peter_Arnold (Xara Group Ltd) Created: 27/11/95 Inputs: ch - character Returns: TRUE/FALSE for success/failure Purpose: Process a single character from the RTF stream SeeAlso: RTFTextFilter::ParseRTFKeyword, RTFTextFilter::PrintChar ********************************************************************************************/ BOOL RTFTextFilter::ParseChar(WCHAR ch) { // Have we reached the end of the binary skip? if (CurrentState.InternalState == StateStore::risBin && --cbBin <= 0) CurrentState.InternalState = StateStore::risNorm; switch (CurrentState.DestinationState) { case StateStore::rdsSkip: // Toss this character (away 8-). return TRUE; case StateStore::rdsNorm: // Insert a character into the story if (ch >= 32) { // PATRACE( _T("Adding char %c\n"), ch); // Before we insert the char we need to setup some attributes that depend on other // attributes, eg tracking. // Get the current size of an Em if (CurrentState.InterCharGap != 0) { MILLIPOINT Em = 0; if (!((RTFTextOILFilter*)pOILFilter)->GetCurrentEmSize(this, &Em)) return FALSE; else SetTextTracking((INT32)((CurrentState.InterCharGap/(double)Em)*1000)); } else SetTextTracking(0); return (AddCharToStory(pImportStory, ch) != NULL); } default: // handle other destinations.... return TRUE; } } /******************************************************************************************** > BOOL RTFTextFilter::TranslateKeyword(StringBase* pKeyword, INT32 param, BOOL fParam) Author: Peter_Arnold (Xara Group Ltd) Created: 27/11/95 Inputs: pKeyword - the keyword read from the file param - the keywords parameter (0 if no parameter) fParam - TRUE if the keyword uses the parameter, FALSE if unused Returns: TRUE/FALSE for success/failure Purpose: Called to translate a keyword read from the file into an internal object that can be acted upon SeeAlso: RTFTextFilter::ParseRTFKeyword ********************************************************************************************/ BOOL RTFTextFilter::TranslateKeyword(StringBase* pKeyword, INT32 param, BOOL fParam) { // Test the keyword against all the known control handlers BOOL Success = TRUE; // Bold if (RTFBoldAttribute::IsThisAction(pKeyword)) Success = RTFBoldAttribute::CreateAndExecute(param, fParam, this); // Italic else if(RTFItalicAttribute::IsThisAction(pKeyword)) Success = RTFItalicAttribute::CreateAndExecute(param, fParam, this); // Size else if(RTFTextSizeAttribute::IsThisAction(pKeyword)) Success = RTFTextSizeAttribute::CreateAndExecute(param, fParam, this); // Super/Sub script off else if(RTFNoscriptAttribute::IsThisAction(pKeyword)) Success = RTFNoscriptAttribute::CreateAndExecute(this); // Superscript else if(RTFSuperscriptAttribute::IsThisAction(pKeyword)) Success = RTFSuperscriptAttribute::CreateAndExecute(this); // Subscript else if(RTFSubscriptAttribute::IsThisAction(pKeyword)) Success = RTFSubscriptAttribute::CreateAndExecute(this); // Colour else if(RTFTextColourAttribute::IsThisAction(pKeyword)) Success = RTFTextColourAttribute::CreateAndExecute(param, fParam, this); // Font else if(RTFTextFontAttribute::IsThisAction(pKeyword)) Success = RTFTextFontAttribute::CreateAndExecute(param, fParam, this); // Tracking in twips else if(RTFTWIPTrackingAttribute::IsThisAction(pKeyword)) Success = RTFTWIPTrackingAttribute::CreateAndExecute(param, fParam, this); // Tracking in quarter points else if(RTFQPTrackingAttribute::IsThisAction(pKeyword)) Success = RTFQPTrackingAttribute::CreateAndExecute(param, fParam, this); // New line else if(RTFNewParaAction::IsThisAction(pKeyword)) Success = RTFNewParaAction::CreateAndExecute(this); // Tab else if(RTFTabAction::IsThisAction(pKeyword)) Success = RTFTabAction::CreateAndExecute(this); // Start skipping text else if(RTFEnterSkipDest::IsThisAction(pKeyword)) Success = RTFEnterSkipDest::CreateAndExecute(this); // Single character definied as two hex digits else if(RTFHexCharAction::IsThisAction(pKeyword)) Success = RTFHexCharAction::CreateAndExecute(this); // An Em dash else if(RTFEmDashAction::IsThisAction(pKeyword)) Success = RTFEmDashAction::CreateAndExecute(this); // An en dash else if(RTFEnDashAction::IsThisAction(pKeyword)) Success = RTFEnDashAction::CreateAndExecute(this); // An em space else if(RTFEmSpaceAction::IsThisAction(pKeyword)) Success = RTFEmSpaceAction::CreateAndExecute(this); // An en space else if(RTFEnSpaceAction::IsThisAction(pKeyword)) Success = RTFEnSpaceAction::CreateAndExecute(this); // A bullet symbol else if(RTFBulletAction::IsThisAction(pKeyword)) Success = RTFBulletAction::CreateAndExecute(this); // Single left sexed quote else if(RTFSingleLeftQuoteAction::IsThisAction(pKeyword)) Success = RTFSingleLeftQuoteAction::CreateAndExecute(this); // Single right sexed quote else if(RTFSingleRightQuoteAction::IsThisAction(pKeyword)) Success = RTFSingleRightQuoteAction::CreateAndExecute(this); // Double left sexed quote else if(RTFDoubleLeftQuoteAction::IsThisAction(pKeyword)) Success = RTFDoubleLeftQuoteAction::CreateAndExecute(this); // Double right sexed quote else if(RTFDoubleRightQuoteAction::IsThisAction(pKeyword)) Success = RTFDoubleRightQuoteAction::CreateAndExecute(this); // Non-breaking space else if(RTFNonBreakSpaceAction::IsThisAction(pKeyword)) Success = RTFNonBreakSpaceAction::CreateAndExecute(this); // New cell in table else if(RTFTableCellAction::IsThisAction(pKeyword)) Success = RTFTableCellAction::CreateAndExecute(this); // New row in table else if(RTFTableRowAction::IsThisAction(pKeyword)) Success = RTFTableRowAction::CreateAndExecute(this); // Reset character attributes else if(RTFResetCharAttrs::IsThisAction(pKeyword)) Success = RTFResetCharAttrs::CreateAndExecute(this); // Reset paragraph attributes else if(RTFResetParaAttrs::IsThisAction(pKeyword)) Success = RTFResetParaAttrs::CreateAndExecute(this); // Colour table else if(RTFColourTableAction::IsThisAction(pKeyword)) Success = RTFColourTableAction::CreateAndExecute(this); // Font table else if(RTFFontTableAction::IsThisAction(pKeyword)) Success = RTFFontTableAction::CreateAndExecute(this); // Paper width else if(RTFPaperWidth::IsThisAction(pKeyword)) { ERROR1IF(!fParam, FALSE, _R(IDE_RTF_DUFFFILE)); Success = RTFPaperWidth::CreateAndExecute(this, param); } // Paper height else if(RTFPaperHeight::IsThisAction(pKeyword)) { ERROR1IF(!fParam, FALSE, _R(IDE_RTF_DUFFFILE)); Success = RTFPaperHeight::CreateAndExecute(this, param); } // Left margin else if(RTFLeftMargin::IsThisAction(pKeyword)) { ERROR1IF(!fParam, FALSE, _R(IDE_RTF_DUFFFILE)); Success = RTFLeftMargin::CreateAndExecute(this, param); } // Right margin else if(RTFRightMargin::IsThisAction(pKeyword)) { ERROR1IF(!fParam, FALSE, _R(IDE_RTF_DUFFFILE)); Success = RTFRightMargin::CreateAndExecute(this, param); } // Top margin else if(RTFTopMargin::IsThisAction(pKeyword)) { ERROR1IF(!fParam, FALSE, _R(IDE_RTF_DUFFFILE)); Success = RTFTopMargin::CreateAndExecute(this, param); } // Bottom margin else if(RTFBottomMargin::IsThisAction(pKeyword)) { ERROR1IF(!fParam, FALSE, _R(IDE_RTF_DUFFFILE)); Success = RTFBottomMargin::CreateAndExecute(this, param); } else { // if this is a new destination skip the destination, else just discard it if (fSkipDestIfUnk) CurrentState.DestinationState = StateStore::rdsSkip; fSkipDestIfUnk = FALSE; } return Success; } /******************************************************************************************** > BOOL RTFTextFilter::EndGroupAction(StateStore::DestinationStateTypes rds) Author: Peter_Arnold (Xara Group Ltd) Created: 27/11/95 Inputs: rds - the current destination Returns: TRUE/FALSE for success/failure Purpose: Called at the end of a group to allow cleanup SeeAlso: - ********************************************************************************************/ BOOL RTFTextFilter::EndGroupAction(StateStore::DestinationStateTypes rds) { return TRUE; } /******************************************************************************************** > BOOL RTFTextFilter::SetSuperscript() Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Inputs: - Returns: TRUE/FALSE for success/failure Purpose: Set the filters current attributes to have superscript on SeeAlso: RTFTextFilter::SetSubscript() ********************************************************************************************/ BOOL RTFTextFilter::SetSuperscript() { return SetTextScript((INT32)(Text_SuperScriptOffset*GetTextSize()), (INT32)(Text_SuperScriptSize*GetTextSize())); } /******************************************************************************************** > BOOL RTFTextFilter::SetSubscript() Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Inputs: - Returns: TRUE/FALSE for success/failure Purpose: Set the filters current attributes to have subscript on SeeAlso: RTFTextFilter::SetSuperscript() ********************************************************************************************/ BOOL RTFTextFilter::SetSubscript() { return SetTextScript((INT32)(Text_SubScriptOffset*GetTextSize()), (INT32)(Text_SubScriptSize*GetTextSize())); } /******************************************************************************************** > BOOL RTFTextFilter::ReadKeyword(StringBase* pKeyword, INT32* pParam, BOOL* pParamUsed) Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Inputs: pKeyword - return pointer for the keyword string pParam - return pointer for the parameter pParamUsed - return pointer for the flag saying wether the parameter is used. Returns: TRUE/FALSE for success/failure Purpose: Reads an RTF keyword and its optional parameter SeeAlso: - ********************************************************************************************/ BOOL RTFTextFilter::ReadKeyword(StringBase* pKeyword, INT32* pParam, BOOL* pParamUsed) { TCHAR ch = 0; BOOL fNegative = FALSE; *pParam = 0; *pParamUsed = FALSE; *pKeyword = ""; String_256 Parameter = ""; // Read the first character of the control word if (!ReadCharFromFile(&ch)) return FALSE; // If it's a control symbol there is no delimiter, its just one character if (!camIsalpha(ch)) { *pKeyword = ch; // PATRACE( _T("Control symbol \\%s\n"), (TCHAR*)(*pKeyword)); return TRUE; } // Read in the rest of the control word while (camIsalpha(ch)) { *pKeyword += ch; if (!ReadCharFromFile(&ch)) return FALSE; } // PATRACE( _T("Control word \\%s\n"), (TCHAR*)(*pKeyword)); // If the delimeter was '-' then the following parameter is negative if (ch == '-') { fNegative = TRUE; if (!ReadCharFromFile(&ch)) return FALSE; } // Read the numeric parameter (if there is one) if (camIsdigit(ch)) { *pParamUsed = TRUE; while (camIsdigit(ch)) { Parameter += ch; if (!ReadCharFromFile(&ch)) return FALSE; } TCHAR* pChar = (TCHAR*)Parameter; *pParam = camStrtol(pChar); // BODGE - use string class conversions if (fNegative) *pParam = -*pParam; // PATRACE( _T("Parameter %d\n"), *pParam); } // If the delimeter was non-space then this character is part of the following text! if (ch != ' ') return SkipBackChar(); else return TRUE; } /******************************************************************************************** > BOOL RTFTextFilter::ReadColourTable() Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Inputs: - Returns: TRUE/FALSE for success/failure Purpose: Reads the RTF colour table, storing it within the filter for future use SeeAlso: - ********************************************************************************************/ BOOL RTFTextFilter::ReadColourTable() { // Ensure the colour table is empty before we start if (!ColourTable.IsEmpty()) { ERROR3("Color table was not empty"); ColourTable.DeleteAll(); } TCHAR CurrentChar=0; //TCHAR CurrentChar = 0;- adapted for DBCS if (!ReadCharFromFile(&CurrentChar)) return FALSE; String_256 Keyword = ""; INT32 Parameter = 0; BOOL ParamUsed = FALSE; while (CurrentChar != '}') { // Create a new entry for the colour table RTFColourTableEntry* pNew = new RTFColourTableEntry; if (pNew == NULL) return FALSE; if (CurrentChar == _T(';')) //if (CurrentChar == ';')-adapted for DBCS { // Default colour required pNew->Colour = DocColour(COLOUR_BLACK); } else { BOOL TableError = FALSE; if (CurrentChar == _T('\\')) //if (CurrentChar ==';')-adapted for DBCS { // read colour definition INT32 Red = 0; INT32 Blue = 0; INT32 Green = 0; // read Red, Green and Blue values (will be in that order). if (!ReadKeyword(&Keyword, &Parameter, &ParamUsed)) return FALSE; if ((Keyword == String_8("red")) && ParamUsed) Red = Parameter; else TableError = TRUE; // Read slash at start of next keyword if (!ReadCharFromFile(&CurrentChar) || (CurrentChar != _T('\\'))) TableError = TRUE; if (!TableError) { if (!ReadKeyword(&Keyword, &Parameter, &ParamUsed)) return FALSE; if ((Keyword == String_8("green")) && ParamUsed) Green = Parameter; else TableError = TRUE; if (!ReadCharFromFile(&CurrentChar) || (CurrentChar != _T('\\'))) TableError = TRUE; } if (!TableError) { if (!ReadKeyword(&Keyword, &Parameter, &ParamUsed)) return FALSE; if ((Keyword == String_8("blue")) && ParamUsed) Blue = Parameter; else TableError = TRUE; if (!ReadCharFromFile(&CurrentChar) || (CurrentChar != _T(';'))) TableError = TRUE; } pNew->Colour = DocColour(Red, Green, Blue); } else TableError = TRUE; ERROR3IF(TableError, "Error in colour table"); ERROR1IF(TableError, FALSE, _R(IDE_RTF_DUFFFILE)); } // Add the colour to the table ColourTable.AddTail(pNew); // Read in the next char if (!ReadCharFromFile(&CurrentChar)) return FALSE; } // Put the '}' back into the input stream return SkipBackChar(); } /********************************************************************************************* > BOOL RTFTextFilter::ReadCharFromFile(TCHAR* pCh, BOOL SkipCR = TRUE) Author: Peter_Arnold (Xara Group Ltd) Created: 28/11/95 Inputs: pCh - return pointer SkipCR - TRUE if CRs and LFs should be skipped over Outputs: pCh contains the read character Returns: TRUE id character read ok, FALSE if file error occured Purpose: Reads a character from the input file and increments the bytes read counter. **********************************************************************************************/ BOOL RTFTextFilter::ReadCharFromFile(TCHAR* pCh, BOOL SkipCR) { do { pImportFile->read(pCh); BytesReadSoFar++; if (pImportFile->bad()) { Error::SetError(_R(IDE_FILE_READ_ERROR)); return FALSE; } } while (SkipCR && ((*pCh==13) || (*pCh==10)) ); return TRUE; } /********************************************************************************************* > BOOL RTFTextFilter::SkipBackChar(INT32 Count = 1) Author: Peter_Arnold (Xara Group Ltd) Created: 28/11/95 Inputs: Count - number of bytes to skip back Outputs: - Returns: TRUE/FALSE for success/failure Purpose: Skips the import files position back a number of characters **********************************************************************************************/ BOOL RTFTextFilter::SkipBackChar(INT32 Count) { FilePos NewPos = pImportFile->tellIn() - Count; pImportFile->seekIn(NewPos); BytesReadSoFar -= Count; return pImportFile->good(); } /******************************************************************************************** > BOOL RTFTextFilter::ReadFontTable() Author: Peter_Arnold (Xara Group Ltd) Created: 7/12/95 Inputs: - Returns: TRUE/FALSE for success/failure Purpose: Reads the RTF font table, storing it within the filter for future use SeeAlso: RTFFilter::ReadOneFontFromTable ********************************************************************************************/ BOOL RTFTextFilter::ReadFontTable() { // Ensure the font table is empty before we start if (!FontTable.IsEmpty()) { ERROR3("Font table was not empty"); FontTable.DeleteAll(); } TCHAR CurrentChar = 0; if (!ReadCharFromFile(&CurrentChar)) return FALSE; if (CurrentChar == _T('\\')) { // one entry in the font table // BODGE - (just to get your attention - Test one item font tables!) if (!ReadOneFontFromTable()) return FALSE; } else { if (CurrentChar != _T('{')) { ERROR3("Error in font table"); ERROR1(FALSE, _R(IDE_RTF_DUFFFILE)); } // multiple entries in font table while (CurrentChar != _T('}')) { if (CurrentChar == _T('{')) { if (!ReadCharFromFile(&CurrentChar)) return FALSE; } if (!ReadOneFontFromTable()) return FALSE; // now eat whitespace until we hit either '}' (end of font group) or '{' (another font item) do { if (!ReadCharFromFile(&CurrentChar)) return FALSE; } while ( (CurrentChar != _T('}')) && (CurrentChar != _T('{')) ); } } // Put the close group symbol back into the input stream return SkipBackChar(); } /******************************************************************************************** > BOOL RTFTextFilter::ReadOneFontFromTable() Author: Peter_Arnold (Xara Group Ltd) Created: 7/12/95 Inputs: - Returns: TRUE/FALSE for success/failure Purpose: Reads one font item from the font table in the RTF font table. When called the file must be at the f of the 'f' (fontnum) keyword SeeAlso: RTFFilter::ReadFontTable ********************************************************************************************/ BOOL RTFTextFilter::ReadOneFontFromTable() { // Optional data that may not be present in the file INT32 CharacterSet = -1; INT32 CodePage = -1; String_256 Keyword = ""; TCHAR ReadChar; INT32 Parameter = 0; BOOL ParamUsed = FALSE; // Read the font index (must be specified) if (!ReadKeyword(&Keyword, &Parameter, &ParamUsed)) return FALSE; if ((Keyword != String_8("f")) || !ParamUsed) ERROR1(FALSE, _R(IDE_RTF_DUFFFILE)); INT32 FontIndex = Parameter; // Read the font family (must be specified) RTFFontTableEntry::FontFamilyType FontFamily = RTFFontTableEntry::FamNil; if (!ReadCharFromFile(&ReadChar)) return FALSE; if (ReadChar != _T('\\')) ERROR1(FALSE, _R(IDE_RTF_DUFFFILE)); if (!ReadKeyword(&Keyword, &Parameter, &ParamUsed)) return FALSE; if (Keyword == String_8("fnil")) FontFamily = RTFFontTableEntry::FamNil; else if (Keyword == String_16("froman")) FontFamily = RTFFontTableEntry::FamRoman; else if (Keyword == String_16("fswiss")) FontFamily = RTFFontTableEntry::FamSwiss; else if (Keyword == String_16("fmodern")) FontFamily = RTFFontTableEntry::FamModern; else if (Keyword == String_16("fscript")) FontFamily = RTFFontTableEntry::FamScript; else if (Keyword == String_16("fdecor")) FontFamily = RTFFontTableEntry::FamDecor; else if (Keyword == String_16("ftech")) FontFamily = RTFFontTableEntry::FamTech; else if (Keyword == String_16("fbidi")) FontFamily = RTFFontTableEntry::FamBiDi; else { ERROR3("Unknown font family type"); FontFamily = RTFFontTableEntry::FamNil; } // Now (possibly) comes some optional keyword before the fontname if (!ReadCharFromFile(&ReadChar)) return FALSE; while (ReadChar == _T('\\')) { if (!ReadKeyword(&Keyword, &Parameter, &ParamUsed)) return FALSE; if (Keyword == String_16("fcharset")) { if (ParamUsed) CharacterSet = Parameter; else ERROR1(FALSE, _R(IDE_RTF_DUFFFILE)); } else if (Keyword == String_16("cpg")) { if (ParamUsed) CodePage = Parameter; else ERROR1(FALSE, _R(IDE_RTF_DUFFFILE)); } if (!ReadCharFromFile(&ReadChar)) return FALSE; } // Now comes the font name, terminated by either a close brace or a slash or a semi-colon String_64 FontName = ""; while ( (ReadChar != _T('}')) && (ReadChar != _T('\\')) && (ReadChar != _T(';')) ) { FontName += ReadChar; if (!ReadCharFromFile(&ReadChar)) return FALSE; } // Munch the remaining control words down to the close brace while (ReadChar != '}') { if (!ReadCharFromFile(&ReadChar)) return FALSE; } // Create the font entry and put it into the font table RTFFontTableEntry* pNewFont = new RTFFontTableEntry; if (pNewFont == NULL) return FALSE; pNewFont->RealFontName = FontName; pNewFont->ApplyFontName = FontName; pNewFont->FontFamily = FontFamily; pNewFont->FontIndex = FontIndex; if (CharacterSet != -1) pNewFont->CharacterSet = CharacterSet; if (CodePage != -1) pNewFont->CodePage = CodePage; FontTable.AddTail(pNewFont); return TRUE; } /******************************************************************************************** > BOOL RTFTextFilter::InitialiseInfo() Author: Peter_Arnold (Xara Group Ltd) Created: 14/12/95 Inputs: - Returns: TRUE/FALSE for success/failure Purpose: Initialises the RTF document values to their defaults SeeAlso: - ********************************************************************************************/ BOOL RTFTextFilter::InitialiseInfo() { PaperWidth = 12240*50; PaperHeight = 15840*50; LeftMargin = 1800*50; RightMargin = 1800*50; TopMargin = 1440*50; BottomMargin =1440*50; CurrentState.InterCharGap = 0; return TRUE; } /******************************************************************************************** > BOOL RTFTextFilter::ResetCharacterAttributes() Author: Peter_Arnold (Xara Group Ltd) Created: 18/12/95 Inputs: - Returns: TRUE/FALSE for success/failure Purpose: Resets all the character attributes back to their defaults SeeAlso: - ********************************************************************************************/ BOOL RTFTextFilter::ResetCharacterAttributes() { BOOL ok = TRUE; if (ok) ok = SetTextBold(FALSE); if (ok) ok = SetTextItalic(FALSE); if (ok) ok = SetTextSize(12000); if (ok) ok = SetTextColour(DocColour(COLOUR_BLACK)); if (ok) ok = SetFont(&DefaultAttrs.FontName); return ok; } /******************************************************************************************** > BOOL RTFTextFilter::ResetParagraphAttributes() Author: Peter_Arnold (Xara Group Ltd) Created: 18/12/95 Inputs: - Returns: TRUE/FALSE for success/failure Purpose: Resets all the paragraph attributes back to their defaults SeeAlso: - ********************************************************************************************/ BOOL RTFTextFilter::ResetParagraphAttributes() { return TRUE; } /********************************************************************************************* > DocColour RTFColourTable::GetColourAt(INT32 TableIndex) Author: Peter_Arnold (Xara Group Ltd) Created: 28/11/95 Inputs: TableIndex - the index into the RTF filter's colour table Outputs: - Returns: A DocColour describing the colour at that position in the colour table Purpose: Gets a colour from the colour table. If the index into the table is not valid then the colour black is returned. (It's not an error) **********************************************************************************************/ DocColour RTFColourTable::GetColourAt(INT32 TableIndex) { RTFColourTableEntry* pItem = (RTFColourTableEntry*)FindItem(TableIndex); if (pItem == NULL) return DocColour(COLOUR_BLACK); else return pItem->Colour; } /********************************************************************************************* > BOOL RTFFontTable::GetIndexedFont(INT32 TableIndex, String_64* pFontName) Author: Peter_Arnold (Xara Group Ltd) Created: 7/12/95 Inputs: TableIndex - the index into the RTF filter's font table pFontName - return pointer for the name of the font at that index. Outputs: - Returns: TRUE/FALSE for success/failure Purpose: Gets a font from the font table. If the index into the table is not valid then a default font is returned **********************************************************************************************/ BOOL RTFFontTable::GetIndexedFont(INT32 TableIndex, String_64* pFontName) { ERROR2IF(pFontName == NULL, FALSE, "Null entry param"); // We have to look through all the items in the table to find one with a matching index RTFFontTableEntry* pItem = (RTFFontTableEntry*)GetHead(); while (pItem != NULL) { if (pItem->FontIndex == TableIndex) { *pFontName = pItem->ApplyFontName; return TRUE; } pItem = (RTFFontTableEntry*)GetNext(pItem); } return TRUE; } /********************************************************************************************* > RTFFontTableEntry::RTFFontTableEntry() Author: Peter_Arnold (Xara Group Ltd) Created: 7/12/95 Purpose: Constructor - initialises member variables to sensible values **********************************************************************************************/ RTFFontTableEntry::RTFFontTableEntry() { RealFontName = "Times New Roman"; // BODGE - get default from font manager ApplyFontName = RealFontName; FontFamily = FamNil; CharacterSet = 0; CodePage = 819; FontIndex = 0; } /********************************************************************************************* > RTFFontTableEntry::~RTFFontTableEntry() Author: Peter_Arnold (Xara Group Ltd) Created: 7/12/95 Purpose: Destructor **********************************************************************************************/ RTFFontTableEntry::~RTFFontTableEntry() { } /********************************************************************************************* > RTFControlAction::RTFControlAction(INT32 Param, RTFTextFilter* pFilt) Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Purpose: Base constructor of all RTF control handlers **********************************************************************************************/ RTFControlAction::RTFControlAction(RTFTextFilter* pFilt, INT32 Param) { Parameter = Param; pFilter = pFilt; } /********************************************************************************************* > BOOL RTFControlAction::ExecuteControlCarefully(RTFControlAction* pAction) Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Inputs: pAction - pointer to the created action (may be NULL) Returns: TRUE/FALSE for success/failure Purpose: Common code for executing a newly created control handler. **********************************************************************************************/ BOOL RTFControlAction::ExecuteControlCarefully(RTFControlAction* pAction) { if (pAction != NULL) { BOOL Success = pAction->ExecuteControl(); delete pAction; return Success; } else return FALSE; // Error will have already been set! } /********************************************************************************************* > RTFAttributeAction::RTFAttributeAction(RTFTextFilter* pFilt, INT32 Param) : RTFControlAction(pFilt, Param) Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Purpose: Base constructor of all RTF attribute control handlers **********************************************************************************************/ RTFAttributeAction::RTFAttributeAction(RTFTextFilter* pFilt, INT32 Param) : RTFControlAction(pFilt, Param) { } /********************************************************************************************* > RTFBoldAttribute Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Purpose: Deals with the bold character property in importing RTF Parameter is 0 to turn bold off, otherwise turn it on **********************************************************************************************/ RTFBoldAttribute::RTFBoldAttribute(RTFTextFilter* pFilt, INT32 Param) : RTFAttributeAction(pFilt, Param) { } BOOL RTFBoldAttribute::IsThisAction(StringBase* pControl) { return (*pControl == String_8("b")); } BOOL RTFBoldAttribute::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); return pFilter->SetBold(Parameter); } BOOL RTFBoldAttribute::CreateAndExecute(INT32 Param, BOOL UseParam, RTFTextFilter* pFilter) { RTFBoldAttribute* pNew = NULL; if (UseParam) pNew = new RTFBoldAttribute(pFilter, Param); else pNew = new RTFBoldAttribute(pFilter); return ExecuteControlCarefully(pNew); } /********************************************************************************************* > RTFItalicAttribute Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Purpose: Deals with the italic character property in importing RTF Parameter is 0 to turn italic off, otherwise turn it on **********************************************************************************************/ RTFItalicAttribute::RTFItalicAttribute(RTFTextFilter* pFilt, INT32 Param) : RTFAttributeAction(pFilt, Param) { } BOOL RTFItalicAttribute::IsThisAction(StringBase* pControl) { return (*pControl == String_8("i")); } BOOL RTFItalicAttribute::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); return pFilter->SetItalic(Parameter); } BOOL RTFItalicAttribute::CreateAndExecute(INT32 Param, BOOL UseParam, RTFTextFilter* pFilter) { RTFItalicAttribute* pNew = NULL; if (UseParam) pNew = new RTFItalicAttribute(pFilter, Param); else pNew = new RTFItalicAttribute(pFilter); return ExecuteControlCarefully(pNew); } /********************************************************************************************* > RTFTextSizeAttribute Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Purpose: Deals with the text size character property in importing RTF. Parameter if the new text size (defined in half-point units) **********************************************************************************************/ RTFTextSizeAttribute::RTFTextSizeAttribute(RTFTextFilter* pFilt, INT32 Param) : RTFAttributeAction(pFilt, Param) { } BOOL RTFTextSizeAttribute::IsThisAction(StringBase* pControl) { return (*pControl == String_8("fs")); } BOOL RTFTextSizeAttribute::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); return pFilter->SetSize(Parameter); } BOOL RTFTextSizeAttribute::CreateAndExecute(TWIP Param, BOOL UseParam, RTFTextFilter* pFilter) { RTFTextSizeAttribute* pNew = NULL; if (UseParam) pNew = new RTFTextSizeAttribute(pFilter, Param*500); else pNew = new RTFTextSizeAttribute(pFilter, 24*500); // 12 point default return ExecuteControlCarefully(pNew); } /********************************************************************************************* > RTFSubscriptAttribute Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Purpose: Deals with the subscript character property in importing RTF. No parameter **********************************************************************************************/ RTFSubscriptAttribute::RTFSubscriptAttribute(RTFTextFilter* pFilt) : RTFAttributeAction(pFilt, 0) { } BOOL RTFSubscriptAttribute::IsThisAction(StringBase* pControl) { return (*pControl == String_8("sub")); } BOOL RTFSubscriptAttribute::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); return pFilter->SetSubscript(); } BOOL RTFSubscriptAttribute::CreateAndExecute(RTFTextFilter* pFilter) { RTFSubscriptAttribute* pNew = NULL; pNew = new RTFSubscriptAttribute(pFilter); return ExecuteControlCarefully(pNew); } /********************************************************************************************* > RTFSuperscriptAttribute Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Purpose: Deals with the superscript character property in importing RTF. No parameter **********************************************************************************************/ RTFSuperscriptAttribute::RTFSuperscriptAttribute(RTFTextFilter* pFilt) : RTFAttributeAction(pFilt, 0) { } BOOL RTFSuperscriptAttribute::IsThisAction(StringBase* pControl) { return (*pControl == String_8("super")); } BOOL RTFSuperscriptAttribute::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); return pFilter->SetSuperscript(); } BOOL RTFSuperscriptAttribute::CreateAndExecute(RTFTextFilter* pFilter) { RTFSuperscriptAttribute* pNew = NULL; pNew = new RTFSuperscriptAttribute(pFilter); return ExecuteControlCarefully(pNew); } /********************************************************************************************* > RTFSuperscriptAttribute Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Purpose: Deals with the no superscript/subscript character property in importing RTF. No parameter **********************************************************************************************/ RTFNoscriptAttribute::RTFNoscriptAttribute(RTFTextFilter* pFilt) : RTFAttributeAction(pFilt, 0) { } BOOL RTFNoscriptAttribute::IsThisAction(StringBase* pControl) { return (*pControl == String_16("Nosupersub")); } BOOL RTFNoscriptAttribute::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); return pFilter->SetNoscript(); } BOOL RTFNoscriptAttribute::CreateAndExecute(RTFTextFilter* pFilter) { RTFNoscriptAttribute* pNew = NULL; pNew = new RTFNoscriptAttribute(pFilter); return ExecuteControlCarefully(pNew); } /********************************************************************************************* > RTFTextColourAttribute Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Purpose: Deals with the foreground colour character property in importing RTF. Parameter is the index into the colour tale of the new text colour **********************************************************************************************/ RTFTextColourAttribute::RTFTextColourAttribute(RTFTextFilter* pFilt, INT32 Param) : RTFAttributeAction(pFilt, Param) { } BOOL RTFTextColourAttribute::IsThisAction(StringBase* pControl) { return (*pControl == String_8("cf")); } BOOL RTFTextColourAttribute::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); DocColour TableColour = pFilter->GetColourTable()->GetColourAt(Parameter); return pFilter->SetTextColour(TableColour); } BOOL RTFTextColourAttribute::CreateAndExecute(INT32 Param, BOOL UseParam, RTFTextFilter* pFilter) { RTFTextColourAttribute* pNew = NULL; if (UseParam) pNew = new RTFTextColourAttribute(pFilter, Param); else pNew = new RTFTextColourAttribute(pFilter); return ExecuteControlCarefully(pNew); } /********************************************************************************************* > RTFTextFontAttribute Author: Peter_Arnold (Xara Group Ltd) Created: 7/12/95 Purpose: Deals with the font character property in importing RTF. Parameter is the index into the font tale of the new font **********************************************************************************************/ RTFTextFontAttribute::RTFTextFontAttribute(RTFTextFilter* pFilt, INT32 Param) : RTFAttributeAction(pFilt, Param) { } BOOL RTFTextFontAttribute::IsThisAction(StringBase* pControl) { return (*pControl == String_8("f")); } BOOL RTFTextFontAttribute::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); String_64 FontName; if (!pFilter->GetFontTable()->GetIndexedFont(Parameter, &FontName)) return FALSE; else { if ((FONTMANAGER->CacheNamedFont(&FontName, FC_TRUETYPE) != ILLEGALFHANDLE)) return pFilter->SetFont(&FontName); else return FALSE; } } BOOL RTFTextFontAttribute::CreateAndExecute(INT32 Param, BOOL UseParam, RTFTextFilter* pFilter) { RTFTextFontAttribute* pNew = NULL; if (UseParam) pNew = new RTFTextFontAttribute(pFilter, Param); else pNew = new RTFTextFontAttribute(pFilter); return ExecuteControlCarefully(pNew); } /********************************************************************************************* > RTFQPTrackingAttribute Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Purpose: Deals with the old-style tracking character property in importing RTF. Parameter is tracking size in quarter-point units **********************************************************************************************/ RTFQPTrackingAttribute::RTFQPTrackingAttribute(RTFTextFilter* pFilt, INT32 Param) : RTFAttributeAction(pFilt, Param) { } BOOL RTFQPTrackingAttribute::IsThisAction(StringBase* pControl) { return (*pControl == String_8("expnd")); } BOOL RTFQPTrackingAttribute::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); pFilter->SetInterCharGap(Parameter); return TRUE; } BOOL RTFQPTrackingAttribute::CreateAndExecute(MILLIPOINT Param, BOOL UseParam, RTFTextFilter* pFilter) { RTFQPTrackingAttribute* pNew = NULL; if (UseParam) pNew = new RTFQPTrackingAttribute(pFilter, Param*250); // Convert 1/4 point to millipoint else pNew = new RTFQPTrackingAttribute(pFilter); return ExecuteControlCarefully(pNew); } /********************************************************************************************* > RTFTWIPTrackingAttribute Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Purpose: Deals with the new-style tracking character property in importing RTF. Parameter is tracking size in twips **********************************************************************************************/ RTFTWIPTrackingAttribute::RTFTWIPTrackingAttribute(RTFTextFilter* pFilt, INT32 Param) : RTFAttributeAction(pFilt, Param) { } BOOL RTFTWIPTrackingAttribute::IsThisAction(StringBase* pControl) { return (*pControl == String_8("expndtw")); } BOOL RTFTWIPTrackingAttribute::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); pFilter->SetInterCharGap(Parameter); return TRUE; } BOOL RTFTWIPTrackingAttribute::CreateAndExecute(TWIP Param, BOOL UseParam, RTFTextFilter* pFilter) { RTFTWIPTrackingAttribute* pNew = NULL; if (UseParam) pNew = new RTFTWIPTrackingAttribute(pFilter, Param*TwipToMillpoint); else pNew = new RTFTWIPTrackingAttribute(pFilter); return ExecuteControlCarefully(pNew); } /********************************************************************************************* > RTFEnterSkipDest Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Purpose: Deals skipping text following unknown control words No parameter **********************************************************************************************/ RTFEnterSkipDest::RTFEnterSkipDest(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0) { } BOOL RTFEnterSkipDest::IsThisAction(StringBase* pControl) { return ((*pControl == String_16("author")) || (*pControl == String_16("buptim")) || (*pControl == String_16("comment")) || (*pControl == String_16("creatim")) || (*pControl == String_16("doccomm")) || (*pControl == String_16("footer")) || (*pControl == String_16("footerf")) || (*pControl == String_16("footerl")) || (*pControl == String_16("footerr")) || (*pControl == String_16("footnote")) || (*pControl == String_16("ftncn")) || (*pControl == String_16("ftnsep")) || (*pControl == String_16("ftnsepc")) || (*pControl == String_16("header")) || (*pControl == String_16("headerf")) || (*pControl == String_16("headerl")) || (*pControl == String_16("headerr")) || (*pControl == String_16("info")) || (*pControl == String_16("keywords")) || (*pControl == String_16("operator")) || (*pControl == String_16("pict")) || (*pControl == String_16("printim")) || (*pControl == String_16("private1")) || (*pControl == String_16("revtim")) || (*pControl == String_16("rxe")) || (*pControl == String_16("stylesheet")) || (*pControl == String_16("subject")) || (*pControl == String_16("tc")) || (*pControl == String_16("title")) || (*pControl == String_16("txe")) || (*pControl == String_16("*")) || (*pControl == String_16("xe")) ); } BOOL RTFEnterSkipDest::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); pFilter->SetSkipping(); return TRUE; } BOOL RTFEnterSkipDest::CreateAndExecute(RTFTextFilter* pFilter) { RTFEnterSkipDest* pNew = new RTFEnterSkipDest(pFilter); return ExecuteControlCarefully(pNew); } /********************************************************************************************* > RTFNewParaAction Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Purpose: Deals with the text in the RTF file starting a new paragraph No parameter **********************************************************************************************/ RTFNewParaAction ::RTFNewParaAction(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0) { } BOOL RTFNewParaAction::IsThisAction(StringBase* pControl) { return (*pControl == String_8("par")) || (*pControl == String_8("sect")); } BOOL RTFNewParaAction::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); return pFilter->StartNewLine(); } BOOL RTFNewParaAction::CreateAndExecute(RTFTextFilter* pFilter) { RTFNewParaAction* pNew = new RTFNewParaAction(pFilter); return ExecuteControlCarefully(pNew); } /********************************************************************************************* > RTFColourTableAction Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Purpose: Deals with reading the colour table from a RTF file No parameter **********************************************************************************************/ RTFColourTableAction::RTFColourTableAction(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0) { } BOOL RTFColourTableAction::IsThisAction(StringBase* pControl) { return *pControl == String_16("colortbl"); } BOOL RTFColourTableAction::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); return pFilter->ReadColourTable(); } BOOL RTFColourTableAction::CreateAndExecute(RTFTextFilter* pFilter) { RTFColourTableAction* pNew = new RTFColourTableAction(pFilter); return ExecuteControlCarefully(pNew); } /********************************************************************************************* > RTFFontTableAction Author: Peter_Arnold (Xara Group Ltd) Created: 6/12/95 Purpose: Deals with reading the font table from a RTF file No parameter **********************************************************************************************/ RTFFontTableAction::RTFFontTableAction(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0) { } BOOL RTFFontTableAction::IsThisAction(StringBase* pControl) { return *pControl == String_16("fonttbl"); } BOOL RTFFontTableAction::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); return pFilter->ReadFontTable(); } BOOL RTFFontTableAction::CreateAndExecute(RTFTextFilter* pFilter) { RTFFontTableAction* pNew = new RTFFontTableAction(pFilter); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFPaperWidth : public RTFControlAction Author: Peter_Arnold (Xara Group Ltd) Created: 14/12/95 Purpose: Reads RTF document's paper width. Parameter is width of paper in twips ********************************************************************************************/ RTFPaperWidth::RTFPaperWidth(RTFTextFilter* pFilt, MILLIPOINT Width) : RTFControlAction(pFilt, Width) { } BOOL RTFPaperWidth::IsThisAction(StringBase* pControl) { return *pControl == String_16("paperw"); } BOOL RTFPaperWidth::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); pFilter->SetPaperWidth(Parameter); return TRUE; } BOOL RTFPaperWidth::CreateAndExecute(RTFTextFilter* pFilter, TWIP Width) { RTFPaperWidth* pNew = new RTFPaperWidth(pFilter, Width*TwipToMillpoint); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFPaperHeight : public RTFControlAction Author: Peter_Arnold (Xara Group Ltd) Created: 14/12/95 Purpose: Read RTF document's paper height ********************************************************************************************/ RTFPaperHeight::RTFPaperHeight(RTFTextFilter* pFilt, MILLIPOINT Height) : RTFControlAction(pFilt, Height) { } BOOL RTFPaperHeight::IsThisAction(StringBase* pControl) { return *pControl == String_16("paperh"); } BOOL RTFPaperHeight::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); pFilter->SetPaperHeight(Parameter); return TRUE; } BOOL RTFPaperHeight::CreateAndExecute(RTFTextFilter* pFilter, TWIP Height) { RTFPaperHeight* pNew = new RTFPaperHeight(pFilter, Height*TwipToMillpoint); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFLeftMargin : public RTFControlAction Author: Peter_Arnold (Xara Group Ltd) Created: 14/12/95 Purpose: Sets the width of the left-hand page margin ********************************************************************************************/ RTFLeftMargin::RTFLeftMargin(RTFTextFilter* pFilt, MILLIPOINT Width) : RTFControlAction(pFilt, Width) { } BOOL RTFLeftMargin::IsThisAction(StringBase* pControl) { return *pControl == String_16("margl"); } BOOL RTFLeftMargin::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); pFilter->SetLeftMargin(Parameter); return TRUE; } BOOL RTFLeftMargin::CreateAndExecute(RTFTextFilter* pFilter, TWIP Width) { RTFLeftMargin* pNew = new RTFLeftMargin(pFilter, Width*TwipToMillpoint); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFRightMargin : public RTFControlAction Author: Peter_Arnold (Xara Group Ltd) Created: 14/12/95 Purpose: Sets the width of the right-hand page margin ********************************************************************************************/ RTFRightMargin::RTFRightMargin(RTFTextFilter* pFilt, MILLIPOINT Width) : RTFControlAction(pFilt, Width) { } BOOL RTFRightMargin::IsThisAction(StringBase* pControl) { return *pControl == String_16("margr"); } BOOL RTFRightMargin::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); pFilter->SetRightMargin(Parameter); return TRUE; } BOOL RTFRightMargin::CreateAndExecute(RTFTextFilter* pFilter, TWIP Width) { RTFRightMargin* pNew = new RTFRightMargin(pFilter, Width*TwipToMillpoint); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFTopMargin : public RTFControlAction Author: Peter_Arnold (Xara Group Ltd) Created: 14/12/95 Purpose: Sets the height of the margin at the top of the page ********************************************************************************************/ RTFTopMargin::RTFTopMargin(RTFTextFilter* pFilt, MILLIPOINT Height) : RTFControlAction(pFilt, Height) { } BOOL RTFTopMargin::IsThisAction(StringBase* pControl) { return *pControl == String_16("margt"); } BOOL RTFTopMargin::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); pFilter->SetTopMargin(Parameter); return TRUE; } BOOL RTFTopMargin::CreateAndExecute(RTFTextFilter* pFilter, TWIP Height) { RTFTopMargin* pNew = new RTFTopMargin(pFilter, Height*TwipToMillpoint); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFBottomMargin : public RTFControlAction Author: Peter_Arnold (Xara Group Ltd) Created: 14/12/95 Purpose: Sets the height of the margin at the bottom of the page ********************************************************************************************/ RTFBottomMargin::RTFBottomMargin(RTFTextFilter* pFilt, MILLIPOINT Height) : RTFControlAction(pFilt, Height) { } BOOL RTFBottomMargin::IsThisAction(StringBase* pControl) { return *pControl == String_16("margb"); } BOOL RTFBottomMargin::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); pFilter->SetBottomMargin(Parameter); return TRUE; } BOOL RTFBottomMargin::CreateAndExecute(RTFTextFilter* pFilter, TWIP Height) { RTFBottomMargin* pNew = new RTFBottomMargin(pFilter, Height*TwipToMillpoint); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFResetCharAttrs : public RTFControlAction Author: Peter_Arnold (Xara Group Ltd) Created: 18/12/95 Purpose: Dispatches the reset character attributes command. No parameter. ********************************************************************************************/ RTFResetCharAttrs::RTFResetCharAttrs(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0) { } BOOL RTFResetCharAttrs::IsThisAction(StringBase* pControl) { return *pControl == String_16("plain"); } BOOL RTFResetCharAttrs::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); pFilter->ResetCharacterAttributes(); return TRUE; } BOOL RTFResetCharAttrs::CreateAndExecute(RTFTextFilter* pFilter) { RTFResetCharAttrs* pNew = new RTFResetCharAttrs(pFilter); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFResetParaAttrs : public RTFControlAction Author: Peter_Arnold (Xara Group Ltd) Created: 18/12/95 Purpose: Dispatches the reset paragraph attributes command. No parameter. ********************************************************************************************/ RTFResetParaAttrs::RTFResetParaAttrs(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0) { } BOOL RTFResetParaAttrs::IsThisAction(StringBase* pControl) { return *pControl == String_16("pard"); } BOOL RTFResetParaAttrs::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); pFilter->ResetParagraphAttributes(); return TRUE; } BOOL RTFResetParaAttrs::CreateAndExecute(RTFTextFilter* pFilter) { RTFResetParaAttrs* pNew = new RTFResetParaAttrs(pFilter); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFTableCellAction : public RTFControlAction Author: Peter_Arnold (Xara Group Ltd) Created: 19/12/95 Purpose: Dispatches a 'cell' command in a table No parameter. ********************************************************************************************/ RTFTableCellAction::RTFTableCellAction(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0) { } BOOL RTFTableCellAction::IsThisAction(StringBase* pControl) { return *pControl == String_16("cell"); } BOOL RTFTableCellAction::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); return pFilter->InsertTab(); } BOOL RTFTableCellAction::CreateAndExecute(RTFTextFilter* pFilter) { RTFTableCellAction* pNew = new RTFTableCellAction(pFilter); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFTableRowAction : public RTFControlAction Author: Peter_Arnold (Xara Group Ltd) Created: 19/12/95 Purpose: Dispatches a 'row' command in a table No parameter. ********************************************************************************************/ RTFTableRowAction::RTFTableRowAction(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0) { } BOOL RTFTableRowAction::IsThisAction(StringBase* pControl) { return *pControl == String_16("row"); } BOOL RTFTableRowAction::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); return pFilter->StartNewLine(); } BOOL RTFTableRowAction::CreateAndExecute(RTFTextFilter* pFilter) { RTFTableRowAction* pNew = new RTFTableRowAction(pFilter); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFTabAction : public RTFControlAction Author: Peter_Arnold (Xara Group Ltd) Created: 19/12/95 Purpose: Processes a tab character ********************************************************************************************/ RTFTabAction::RTFTabAction(RTFTextFilter* pFilt) : RTFControlAction(pFilt, 0) { } BOOL RTFTabAction::IsThisAction(StringBase* pControl) { return *pControl == String_16("tab"); } BOOL RTFTabAction::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); return pFilter->InsertTab(); } BOOL RTFTabAction::CreateAndExecute(RTFTextFilter* pFilter) { RTFTabAction* pNew = new RTFTabAction(pFilter); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFSingleCharAction : public RTFControlAction Author: Peter_Arnold (Xara Group Ltd) Created: 2/1/96 Purpose: Inserts a single 'special' character into the import story This class cannot be created and executed; only classes derived from it ********************************************************************************************/ RTFSingleCharAction::RTFSingleCharAction(RTFTextFilter* pFilt, WCHAR Character) : RTFControlAction(pFilt, Character) { } BOOL RTFSingleCharAction::ExecuteControl() { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); return pFilter->InsertChar((WCHAR)Parameter); } /******************************************************************************************** > class RTFHexCharAction : public RTFSingleCharAction Author: Peter_Arnold (Xara Group Ltd) Created: 2/1/96 Purpose: Processes a character defined by two hex chars ********************************************************************************************/ RTFHexCharAction::RTFHexCharAction(RTFTextFilter* pFilt, WCHAR Character) : RTFSingleCharAction(pFilt, Character) { } BOOL RTFHexCharAction::IsThisAction(StringBase* pControl) { return *pControl == String_16("'"); } BOOL RTFHexCharAction::CreateAndExecute(RTFTextFilter* pFilter) { ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL"); // read the two hex digits defining this character BYTE Digits = 0; for (INT32 loop = 1; loop<=2; loop++) { Digits = Digits << 4; INT32 Base = 0; TCHAR ReadChar = 0; if (!pFilter->ReadCharFromFile(&ReadChar)) return FALSE; if (ReadChar >= '0' && ReadChar <= '9') Base = '0'; else { if (ReadChar >= 'a' && ReadChar <= 'f') Base = 'a' - 10; else { if (ReadChar >= 'A' && ReadChar <= 'F') Base = 'A' - 10; else { Error::SetError(_R(IDE_RTF_DUFFFILE)); return FALSE; } } } Digits += ReadChar - Base; } WCHAR Character = TextManager::MultiByteToUnicode(Digits); RTFHexCharAction* pNew = new RTFHexCharAction(pFilter, Character); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFEmDashAction : public RTFSingleCharAction Author: Peter_Arnold (Xara Group Ltd) Created: 3/1/96 Purpose: Processes a em dash - a dash the width of an em ********************************************************************************************/ RTFEmDashAction::RTFEmDashAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x2014) { // BODGE - check that number! } BOOL RTFEmDashAction::IsThisAction(StringBase* pControl) { return *pControl == String_16("emdash"); } BOOL RTFEmDashAction::CreateAndExecute(RTFTextFilter* pFilter) { RTFEmDashAction* pNew = new RTFEmDashAction(pFilter); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFEnDashAction : public RTFSingleCharAction Author: Peter_Arnold (Xara Group Ltd) Created: 3/1/96 Purpose: Processes a en dash - a dash the width of an en ********************************************************************************************/ RTFEnDashAction::RTFEnDashAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x2013) { // BODGE - check that number! } BOOL RTFEnDashAction::IsThisAction(StringBase* pControl) { return *pControl == String_16("endash"); } BOOL RTFEnDashAction::CreateAndExecute(RTFTextFilter* pFilter) { RTFEnDashAction* pNew = new RTFEnDashAction(pFilter); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFEmSpaceAction : public RTFSingleCharAction Author: Peter_Arnold (Xara Group Ltd) Created: 3/1/96 Purpose: Processes an em space - a space the width of an em ********************************************************************************************/ RTFEmSpaceAction::RTFEmSpaceAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x0020) { // BODGE - prehaps use a kern to simulate an em space? } BOOL RTFEmSpaceAction::IsThisAction(StringBase* pControl) { return *pControl == String_16("emspace"); } BOOL RTFEmSpaceAction::CreateAndExecute(RTFTextFilter* pFilter) { RTFEmSpaceAction* pNew = new RTFEmSpaceAction(pFilter); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFEnSpaceAction : public RTFSingleCharAction Author: Peter_Arnold (Xara Group Ltd) Created: 3/1/96 Purpose: Processes an en space - a space the width of an en ********************************************************************************************/ RTFEnSpaceAction::RTFEnSpaceAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x0020) { // BODGE - prehaps use a kern to simulate an en space? } BOOL RTFEnSpaceAction::IsThisAction(StringBase* pControl) { return *pControl == String_16("enspace"); } BOOL RTFEnSpaceAction::CreateAndExecute(RTFTextFilter* pFilter) { RTFEnSpaceAction* pNew = new RTFEnSpaceAction(pFilter); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFBulletAction : public RTFSingleCharAction Author: Peter_Arnold (Xara Group Ltd) Created: 3/1/96 Purpose: Processes a bullet symbol ********************************************************************************************/ RTFBulletAction::RTFBulletAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x2022) { } BOOL RTFBulletAction::IsThisAction(StringBase* pControl) { return *pControl == String_16("bullet"); } BOOL RTFBulletAction::CreateAndExecute(RTFTextFilter* pFilter) { RTFBulletAction* pNew = new RTFBulletAction(pFilter); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFSingleLeftQuoteAction : public RTFSingleCharAction Author: Peter_Arnold (Xara Group Ltd) Created: 3/1/96 Purpose: Processes single left sexed quote ********************************************************************************************/ RTFSingleLeftQuoteAction::RTFSingleLeftQuoteAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x2018) { } BOOL RTFSingleLeftQuoteAction::IsThisAction(StringBase* pControl) { return *pControl == String_16("lquote"); } BOOL RTFSingleLeftQuoteAction::CreateAndExecute(RTFTextFilter* pFilter) { RTFSingleLeftQuoteAction* pNew = new RTFSingleLeftQuoteAction(pFilter); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFSingleRightQuoteAction : public RTFSingleCharAction Author: Peter_Arnold (Xara Group Ltd) Created: 3/1/96 Purpose: Processes single right sexed quote ********************************************************************************************/ RTFSingleRightQuoteAction::RTFSingleRightQuoteAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x2019) { } BOOL RTFSingleRightQuoteAction::IsThisAction(StringBase* pControl) { return *pControl == String_16("rquote"); } BOOL RTFSingleRightQuoteAction::CreateAndExecute(RTFTextFilter* pFilter) { RTFSingleRightQuoteAction* pNew = new RTFSingleRightQuoteAction(pFilter); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFDoubleLeftQuoteAction : public RTFSingleCharAction Author: Peter_Arnold (Xara Group Ltd) Created: 3/1/96 Purpose: Processes double left sexed quote ********************************************************************************************/ RTFDoubleLeftQuoteAction::RTFDoubleLeftQuoteAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x201c) { } BOOL RTFDoubleLeftQuoteAction::IsThisAction(StringBase* pControl) { return *pControl == String_16("ldblquote"); } BOOL RTFDoubleLeftQuoteAction::CreateAndExecute(RTFTextFilter* pFilter) { RTFDoubleLeftQuoteAction* pNew = new RTFDoubleLeftQuoteAction(pFilter); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFDoubleRightQuoteAction : public RTFSingleCharAction Author: Peter_Arnold (Xara Group Ltd) Created: 3/1/96 Purpose: Processes double right sexed quote ********************************************************************************************/ RTFDoubleRightQuoteAction::RTFDoubleRightQuoteAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x201d) { } BOOL RTFDoubleRightQuoteAction::IsThisAction(StringBase* pControl) { return *pControl == String_16("rdblquote"); } BOOL RTFDoubleRightQuoteAction::CreateAndExecute(RTFTextFilter* pFilter) { RTFDoubleRightQuoteAction* pNew = new RTFDoubleRightQuoteAction(pFilter); return ExecuteControlCarefully(pNew); } /******************************************************************************************** > class RTFNonBreakSpaceAction : public RTFSingleCharAction Author: Peter_Arnold (Xara Group Ltd) Created: 3/1/96 Purpose: Processes double right sexed quote ********************************************************************************************/ RTFNonBreakSpaceAction::RTFNonBreakSpaceAction(RTFTextFilter* pFilt) : RTFSingleCharAction(pFilt, (WCHAR)0x00a0) { } BOOL RTFNonBreakSpaceAction::IsThisAction(StringBase* pControl) { return *pControl == String_16("~"); } BOOL RTFNonBreakSpaceAction::CreateAndExecute(RTFTextFilter* pFilter) { RTFNonBreakSpaceAction* pNew = new RTFNonBreakSpaceAction(pFilter); return ExecuteControlCarefully(pNew); } #endif // #if BUILD_OTHER_TEXT_FILTER #endif // #if BUILD_TEXT_FILTERS