716 lines
22 KiB
C++
716 lines
22 KiB
C++
/*
|
|
* (c) Copyright Ascensio System SIA 2010-2023
|
|
*
|
|
* This program is a free software product. You can redistribute it and/or
|
|
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
|
* version 3 as published by the Free Software Foundation. In accordance with
|
|
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
|
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
|
* of any third-party rights.
|
|
*
|
|
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
|
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
|
*
|
|
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
|
* street, Riga, Latvia, EU, LV-1050.
|
|
*
|
|
* The interactive user interfaces in modified source and object code versions
|
|
* of the Program must display Appropriate Legal Notices, as required under
|
|
* Section 5 of the GNU AGPL version 3.
|
|
*
|
|
* Pursuant to Section 7(b) of the License you must retain the original Product
|
|
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
|
* grant you any rights under trademark law for use of our trademarks.
|
|
*
|
|
* All the Product's GUI elements, including illustrations and icon sets, as
|
|
* well as technical writing content are licensed under the terms of the
|
|
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
|
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
|
*
|
|
*/
|
|
|
|
#include "CharacterPropertiesMapping.h"
|
|
|
|
namespace DocFileFormat
|
|
{
|
|
CharacterPropertiesMapping::CharacterPropertiesMapping( XMLTools::CStringXmlWriter* writer, WordDocument* doc, RevisionData* rev, ParagraphPropertyExceptions* currentPapx, bool styleChpx, bool isRunStyleNeeded)
|
|
: PropertiesMapping( writer ), _isRunStyleNeeded(isRunStyleNeeded), _isOwnRPr(true), _isRTL(false)
|
|
{
|
|
_doc = doc;
|
|
_rPr = new XMLTools::XMLElement( L"w:rPr");
|
|
_revisionData = rev;
|
|
_currentPapx = currentPapx;
|
|
_styleChpx = styleChpx;
|
|
_currentIstd = USHRT_MAX;
|
|
_webHidden = false;
|
|
}
|
|
|
|
CharacterPropertiesMapping::CharacterPropertiesMapping( XMLTools::XMLElement* rPr, WordDocument* doc, RevisionData* rev, ParagraphPropertyExceptions* currentPapx, bool styleChpx, bool isRunStyleNeeded )
|
|
: PropertiesMapping( NULL ), _isRunStyleNeeded(isRunStyleNeeded), _isOwnRPr(false), _isRTL(false)
|
|
{
|
|
_doc = doc;
|
|
_rPr = rPr;
|
|
_revisionData = rev;
|
|
_currentPapx = currentPapx;
|
|
_styleChpx = styleChpx;
|
|
_currentIstd = USHRT_MAX;
|
|
_webHidden = false;
|
|
}
|
|
|
|
CharacterPropertiesMapping::~CharacterPropertiesMapping()
|
|
{
|
|
if (_isOwnRPr)
|
|
{
|
|
RELEASEOBJECT(_rPr);
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace DocFileFormat
|
|
{
|
|
void CharacterPropertiesMapping::Apply( IVisitable* chpx )
|
|
{
|
|
//convert the normal SPRMS
|
|
convertSprms( dynamic_cast<CharacterPropertyExceptions*>( chpx )->grpprl, _rPr );
|
|
|
|
// apend revision changes
|
|
if ((_revisionData) && (_revisionData->Type == Changed))
|
|
{
|
|
XMLTools::XMLElement rPrChange( L"w:rPrChange");
|
|
|
|
//todooo date - _revisionData->Dttm.Convert( new DateMapping( rPrChange ) );
|
|
|
|
WideString* author_str = static_cast<WideString*>( _doc->RevisionAuthorTable->operator []( _revisionData->Isbt ));
|
|
|
|
if (author_str)
|
|
{
|
|
XMLTools::XMLAttribute author( L"w:author", FormatUtils::XmlEncode(*author_str));
|
|
rPrChange.AppendAttribute( author );
|
|
}
|
|
XMLTools::XMLAttribute date( L"w:date", _revisionData->Dttm.getString());
|
|
rPrChange.AppendAttribute( date );
|
|
|
|
XMLTools::XMLElement rPr(L"w:rPr");
|
|
//convert revision stack
|
|
convertSprms( _revisionData->Changes, &rPr);
|
|
|
|
rPrChange.AppendChild(rPr);
|
|
|
|
_rPr->AppendChild( rPrChange );
|
|
}
|
|
|
|
//write properties
|
|
if ( ( m_pXmlWriter != NULL ) && ( ( _rPr->GetChildCount() > 0 ) || ( _rPr->GetAttributeCount() > 0 ) ) )
|
|
{
|
|
m_pXmlWriter->WriteString( _rPr->GetXMLString());
|
|
}
|
|
}
|
|
|
|
/*========================================================================================================*/
|
|
|
|
bool CharacterPropertiesMapping::CheckIsSymbolFont()
|
|
{
|
|
//Todo сделать определение симольного шрифта через fontManager
|
|
//Заглушка под Google Docs, они пишут bullet в Arial
|
|
if (-1 != m_sAsciiFont.find (L"Arial") && -1 != m_sEastAsiaFont.find (L"Arial") && -1 != m_shAnsiFont.find (L"Arial"))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/*========================================================================================================*/
|
|
|
|
void CharacterPropertiesMapping::convertSprms( std::vector<SinglePropertyModifier>* sprms, XMLTools::XMLElement* parent )
|
|
{
|
|
XMLTools::XMLElement * rFonts = new XMLTools::XMLElement ( L"w:rFonts" );
|
|
XMLTools::XMLElement * color = new XMLTools::XMLElement ( L"w:color" );
|
|
XMLTools::XMLAttribute * colorVal = new XMLTools::XMLAttribute ( L"w:val" );
|
|
XMLTools::XMLElement * lang = new XMLTools::XMLElement ( L"w:lang" );
|
|
|
|
if (_webHidden)
|
|
{
|
|
XMLTools::XMLElement *webHidden = new XMLTools::XMLElement ( L"w:webHidden" );
|
|
parent->AppendChild( *webHidden );
|
|
RELEASEOBJECT( webHidden );
|
|
}
|
|
if ((sprms) && (!sprms->empty()))
|
|
{
|
|
std::vector<SinglePropertyModifier>::iterator end = sprms->end();
|
|
for (std::vector<SinglePropertyModifier>::iterator iter = sprms->begin(); iter != end; ++iter)
|
|
{
|
|
int nProperty = 0; //for unknown test
|
|
|
|
switch ((int)(iter->OpCode))
|
|
{
|
|
case sprmOldCIstd:
|
|
case sprmCIstd: // style id
|
|
{
|
|
if (_isRunStyleNeeded && !_webHidden)
|
|
{
|
|
_currentIstd = FormatUtils::BytesToUInt16(iter->Arguments, 0, iter->argumentsSize);
|
|
if (_currentIstd < _doc->Styles->Styles->size())
|
|
{
|
|
appendValueElement(parent, L"rStyle", StyleSheetMapping::MakeStyleId(_doc->Styles->Styles->at(_currentIstd)), true);
|
|
}
|
|
}
|
|
}break;
|
|
case sprmCFBiDi:
|
|
{
|
|
appendFlagElement(parent, *iter, L"rtl", true);
|
|
_isRTL = true;
|
|
}break;
|
|
case sprmOldCFBold:
|
|
case sprmCFBold:
|
|
{
|
|
appendFlagElement(parent, *iter, L"b", true);
|
|
}break;
|
|
case sprmCFBoldBi:
|
|
{
|
|
appendFlagElement(parent, *iter, L"bCs", true);
|
|
}break;
|
|
case sprmOldCFCaps:
|
|
case sprmCFCaps:
|
|
{
|
|
appendFlagElement(parent, *iter, L"caps", true);
|
|
}break;
|
|
case sprmCFComplexScripts:
|
|
{
|
|
appendFlagElement(parent, *iter, L"cs", true);
|
|
}break;
|
|
case sprmCFDStrike:
|
|
{
|
|
appendFlagElement(parent, *iter, L"dstrike", true);
|
|
}break;
|
|
case sprmCFEmboss:
|
|
{
|
|
appendFlagElement(parent, *iter, L"emboss", true);
|
|
}break;
|
|
case sprmCFImprint:
|
|
{
|
|
appendFlagElement(parent, *iter, L"imprint", true);
|
|
}break;
|
|
case sprmOldCFItalic:
|
|
case sprmCFItalic:
|
|
{
|
|
appendFlagElement(parent, *iter, L"i", true);
|
|
}break;
|
|
case sprmCFItalicBi:
|
|
{
|
|
appendFlagElement(parent, *iter, L"iCs", true);
|
|
}break;
|
|
case 0x0875:
|
|
{
|
|
appendFlagElement(parent, *iter, L"noProof", true);
|
|
}break;
|
|
case sprmOldCFOutline:
|
|
case sprmCFOutline:
|
|
{
|
|
appendFlagElement(parent, *iter, L"outline", true);
|
|
}break;
|
|
case sprmOldCFShadow:
|
|
case sprmCFShadow:
|
|
{
|
|
appendFlagElement(parent, *iter, L"shadow", true);
|
|
}break;
|
|
case sprmOldCFSmallCaps:
|
|
case sprmCFSmallCaps:
|
|
{
|
|
appendFlagElement(parent, *iter, L"smallCaps", true);
|
|
}break;
|
|
case sprmCFSpecVanish:
|
|
{
|
|
appendFlagElement(parent, *iter, L"specVanish", true);
|
|
}break;
|
|
case sprmOldCFStrike:
|
|
case sprmCFStrike:
|
|
{
|
|
appendFlagElement(parent, *iter, L"strike", true);
|
|
}break;
|
|
case sprmOldCFVanish:
|
|
case sprmCFVanish:
|
|
{
|
|
appendFlagElement(parent, *iter, L"vanish", true);
|
|
}break;
|
|
case 0x0811:
|
|
{
|
|
appendFlagElement(parent, *iter, L"webHidden", true);
|
|
}break;
|
|
case sprmOldCIss:
|
|
case sprmCIss:
|
|
{
|
|
if (iter->argumentsSize > 0 && iter->Arguments[0] < 3) //Metaevan.doc
|
|
appendValueElement(parent, L"vertAlign", FormatUtils::MapValueToWideString(iter->Arguments[0], &SuperscriptIndex[0][0], 3, 12), true);
|
|
}break;
|
|
case sprmCRgLid0_80:
|
|
case sprmCRgLid0:
|
|
{ //latin
|
|
LanguageId langid(FormatUtils::BytesToInt16(iter->Arguments, 0, iter->argumentsSize));
|
|
|
|
std::wstring strLCID = _doc->m_lcidConverter.get_wstring(langid.Id);
|
|
LanguageIdMapping langIDMapping(lang, Default, strLCID);
|
|
langid.Convert(&langIDMapping);
|
|
}break;
|
|
case sprmOldCLid:
|
|
case sprmCRgLid1_80:
|
|
case sprmCRgLid1:
|
|
{ //east asia
|
|
LanguageId langid(FormatUtils::BytesToInt16(iter->Arguments, 0, iter->argumentsSize));
|
|
std::wstring lang_code = _doc->m_lcidConverter.get_wstring(langid.Id);
|
|
LanguageIdMapping langIDMapping(lang, EastAsian, lang_code);
|
|
langid.Convert(&langIDMapping);
|
|
}break;
|
|
case sprmCLidBi:
|
|
{
|
|
LanguageId langid(FormatUtils::BytesToInt16(iter->Arguments, 0, iter->argumentsSize));
|
|
std::wstring lang_code = _doc->m_lcidConverter.get_wstring(langid.Id);
|
|
|
|
LanguageIdMapping* langIDMapping = new LanguageIdMapping(lang, Complex, lang_code);
|
|
|
|
langid.Convert(langIDMapping);
|
|
|
|
RELEASEOBJECT(langIDMapping);
|
|
}break;
|
|
case sprmCBrc80:
|
|
case sprmCBrc:
|
|
{ //borders
|
|
XMLTools::XMLElement bdr(L"w:bdr");
|
|
BorderCode bc(iter->Arguments, iter->argumentsSize);
|
|
appendBorderAttributes(&bc, &bdr);
|
|
parent->AppendChild(bdr);
|
|
}break;
|
|
case sprmCShd80:
|
|
case sprmCShd:
|
|
{ //shading
|
|
ShadingDescriptor desc(iter->Arguments, iter->argumentsSize);
|
|
|
|
appendShading(parent, desc);
|
|
}break;
|
|
case sprmOldCIco:
|
|
case sprmCIco:
|
|
case sprmCIcoBi:
|
|
{//color
|
|
colorVal->SetValue(FormatUtils::MapValueToWideString(iter->Arguments[0], &Global::ColorIdentifier[0][0], 17, 12));
|
|
}break;
|
|
case sprmCCv:
|
|
{
|
|
std::wstringstream sstream;
|
|
|
|
sstream << boost::wformat(L"%02x%02x%02x") % iter->Arguments[0] % /*G*/iter->Arguments[1] % /*B*/iter->Arguments[2];
|
|
colorVal->SetValue(sstream.str());
|
|
}break;
|
|
case sprmCOldHighlight:
|
|
{
|
|
appendValueElement(parent, L"highlight", FormatUtils::MapValueToWideString(iter->Arguments[1], &Global::ColorNameIdentifier[0][0], 17, 12), true);
|
|
}break;
|
|
case sprmCHighlight:
|
|
{
|
|
appendValueElement(parent, L"highlight", FormatUtils::MapValueToWideString(iter->Arguments[0], &Global::ColorNameIdentifier[0][0], 17, 12), true);
|
|
}break;
|
|
case sprmOldCDxaSpace:
|
|
case sprmCDxaSpace:
|
|
{
|
|
appendValueElement(parent, L"spacing", FormatUtils::IntToWideString(FormatUtils::BytesToInt16(iter->Arguments, 0, iter->argumentsSize)), true);
|
|
}break;
|
|
case sprmCFtcBi:
|
|
{//default from FontTable
|
|
size_t nIndex = FormatUtils::BytesToUInt16(iter->Arguments, 0, iter->argumentsSize);
|
|
if (nIndex < _doc->FontTable->Data.size())
|
|
{
|
|
FontFamilyName* ffn = static_cast<FontFamilyName*>(_doc->FontTable->operator [] (nIndex));
|
|
if (ffn)
|
|
{
|
|
m_sCsFont = ffn->xszFtn;
|
|
|
|
XMLTools::XMLAttribute* cs = new XMLTools::XMLAttribute(L"w:cs");
|
|
cs->SetValue(FormatUtils::XmlEncode(m_sCsFont, true));
|
|
rFonts->AppendAttribute(*cs);
|
|
RELEASEOBJECT(cs);
|
|
}
|
|
}
|
|
}break;
|
|
case sprmCHpsBi:
|
|
{
|
|
appendValueElement(parent, L"szCs",
|
|
FormatUtils::IntToWideString(FormatUtils::BytesToInt16(iter->Arguments, 0, iter->argumentsSize)), true);
|
|
}
|
|
break;
|
|
// Font Size in points (2~3276) default 20-half-points
|
|
case sprmOldCHps:
|
|
{
|
|
appendValueElement(parent, L"sz",
|
|
FormatUtils::IntToWideString(FormatUtils::BytesToUChar(iter->Arguments, 0, iter->argumentsSize)),
|
|
true);
|
|
}break;
|
|
case sprmCHps:
|
|
{
|
|
appendValueElement(parent, L"sz",
|
|
FormatUtils::IntToWideString(FormatUtils::BytesToUInt16(iter->Arguments, 0, iter->argumentsSize)), true);
|
|
}break;
|
|
case sprmCMajority:
|
|
{ //for complex props
|
|
}break;
|
|
case sprmOldCHpsPos:
|
|
{ // The vertical position, in half-points, of text relative to the normal position. (MUST be between -3168 and 3168)
|
|
short nVertPos = FormatUtils::BytesToUChar(iter->Arguments, 0, iter->argumentsSize);
|
|
appendValueElement(parent, L"position", nVertPos, true);
|
|
}break;
|
|
case sprmCHpsPos:
|
|
{ // The vertical position, in half-points, of text relative to the normal position. (MUST be between -3168 and 3168)
|
|
short nVertPos = FormatUtils::BytesToInt16(iter->Arguments, 0, iter->argumentsSize);
|
|
appendValueElement(parent, L"position", nVertPos, true);
|
|
}break;
|
|
case sprmOldCHpsKern:
|
|
case sprmCHpsKern:
|
|
{
|
|
appendValueElement(parent, L"kern", FormatUtils::IntToWideString(FormatUtils::BytesToInt16(iter->Arguments, 0, iter->argumentsSize)), true);
|
|
}break;
|
|
case sprmOldCFtc:
|
|
case sprmCRgFtc0:
|
|
{ // font family
|
|
size_t nIndex = FormatUtils::BytesToUInt16(iter->Arguments, 0, iter->argumentsSize);
|
|
|
|
if (nIndex < _doc->FontTable->Data.size())
|
|
{
|
|
XMLTools::XMLAttribute* ascii = new XMLTools::XMLAttribute(L"w:ascii");
|
|
FontFamilyName* ffn = static_cast<FontFamilyName*>(_doc->FontTable->operator [] (nIndex));
|
|
m_sAsciiFont = ffn->xszFtn;
|
|
ascii->SetValue(FormatUtils::XmlEncode(m_sAsciiFont, true));
|
|
rFonts->AppendAttribute(*ascii);
|
|
RELEASEOBJECT(ascii);
|
|
}
|
|
}break;
|
|
case sprmCRgFtc1:
|
|
{
|
|
size_t nIndex = FormatUtils::BytesToUInt16(iter->Arguments, 0, iter->argumentsSize);
|
|
|
|
if (nIndex >= 0 && nIndex < _doc->FontTable->Data.size())
|
|
{
|
|
XMLTools::XMLAttribute* eastAsia = new XMLTools::XMLAttribute(L"w:eastAsia");
|
|
FontFamilyName* ffn = static_cast<FontFamilyName*>(_doc->FontTable->operator [] (nIndex));
|
|
m_sEastAsiaFont = ffn->xszFtn;
|
|
eastAsia->SetValue(FormatUtils::XmlEncode(m_sEastAsiaFont));
|
|
rFonts->AppendAttribute(*eastAsia);
|
|
RELEASEOBJECT(eastAsia);
|
|
}
|
|
}
|
|
break;
|
|
case sprmCRgFtc2:
|
|
{
|
|
size_t nIndex = FormatUtils::BytesToUInt16(iter->Arguments, 0, iter->argumentsSize);
|
|
|
|
if (nIndex >= 0 && nIndex < _doc->FontTable->Data.size())
|
|
{
|
|
XMLTools::XMLAttribute* ansi = new XMLTools::XMLAttribute(L"w:hAnsi");
|
|
FontFamilyName* ffn = static_cast<FontFamilyName*>(_doc->FontTable->operator [] (nIndex));
|
|
m_shAnsiFont = ffn->xszFtn;
|
|
ansi->SetValue(FormatUtils::XmlEncode(m_shAnsiFont));
|
|
rFonts->AppendAttribute(*ansi);
|
|
RELEASEOBJECT(ansi);
|
|
}
|
|
}break;
|
|
case sprmOldCKul:
|
|
case sprmCKul:
|
|
{ //Underlining
|
|
appendValueElement(parent, L"u", FormatUtils::MapValueToWideString(iter->Arguments[0], &Global::UnderlineCode[0][0], 56, 16), true);
|
|
}
|
|
break;
|
|
case sprmCCharScale:
|
|
{ //char width
|
|
appendValueElement(parent, L"w", FormatUtils::IntToWideString(FormatUtils::BytesToInt16(iter->Arguments, 0, iter->argumentsSize)), true);
|
|
}break;
|
|
case sprmCSfxText:
|
|
{ //animation
|
|
appendValueElement(parent, L"effect", FormatUtils::MapValueToWideString(iter->Arguments[0], &Global::TextAnimation[0][0], 7, 16), true);
|
|
}break;
|
|
case sprmCIdctHint:
|
|
{
|
|
XMLTools::XMLAttribute hint(L"w:hint");
|
|
switch (iter->Arguments[0])
|
|
{
|
|
case 1:
|
|
{
|
|
hint.SetValue(L"eastAsia");
|
|
rFonts->AppendAttribute(hint);
|
|
}break;
|
|
case 2:
|
|
{
|
|
hint.SetValue(L"cs");
|
|
rFonts->AppendAttribute(hint);
|
|
}break;
|
|
case 0: break; // default
|
|
case 0xFF: break; //No ST_Hint equivalent
|
|
}
|
|
}break;
|
|
case sprmCPbiIBullet:
|
|
{
|
|
int nIndex = FormatUtils::BytesToInt32(iter->Arguments, 0, iter->argumentsSize);
|
|
if (nIndex >= 0)
|
|
{
|
|
std::map<int, int>::iterator it = _doc->PictureBulletsCPsMap.find(nIndex);
|
|
if (it != _doc->PictureBulletsCPsMap.end())
|
|
{
|
|
//добавить
|
|
}
|
|
}
|
|
}break;
|
|
case sprmCPbiGrf:
|
|
{
|
|
//used picture bullet
|
|
int val = FormatUtils::BytesToUInt16(iter->Arguments, 0, iter->argumentsSize);
|
|
|
|
}break;
|
|
case sprmCRsidProp:
|
|
case sprmCRsidText:
|
|
break;
|
|
case sprmCFUsePgsuSettings:
|
|
{
|
|
appendFlagElement(parent, *iter, L"snapToGrid", true);
|
|
}break;
|
|
default:
|
|
{
|
|
switch (iter->argumentsSize)
|
|
{
|
|
case 1:
|
|
nProperty = FormatUtils::BytesToUChar(iter->Arguments, 0, iter->argumentsSize);
|
|
break;
|
|
case 2:
|
|
nProperty = FormatUtils::BytesToUInt16(iter->Arguments, 0, iter->argumentsSize);
|
|
break;
|
|
case 4:
|
|
nProperty = FormatUtils::BytesToInt32(iter->Arguments, 0, iter->argumentsSize);
|
|
break;
|
|
}
|
|
}break;
|
|
}
|
|
}
|
|
}
|
|
if (_doc->nWordVersion > 0)
|
|
{
|
|
if (false == m_sAsciiFont.empty())
|
|
{
|
|
if (m_sEastAsiaFont.empty())
|
|
{
|
|
m_sEastAsiaFont = m_sAsciiFont;
|
|
XMLTools::XMLAttribute* eastAsia = new XMLTools::XMLAttribute(L"w:eastAsia");
|
|
eastAsia->SetValue(FormatUtils::XmlEncode(m_sEastAsiaFont));
|
|
rFonts->AppendAttribute(*eastAsia);
|
|
RELEASEOBJECT(eastAsia);
|
|
}
|
|
if (m_shAnsiFont.empty())
|
|
{
|
|
m_shAnsiFont = m_sAsciiFont;
|
|
XMLTools::XMLAttribute* ansi = new XMLTools::XMLAttribute(L"w:hAnsi");
|
|
ansi->SetValue(FormatUtils::XmlEncode(m_shAnsiFont));
|
|
rFonts->AppendAttribute(*ansi);
|
|
RELEASEOBJECT(ansi);
|
|
}
|
|
if (m_sCsFont.empty())
|
|
{
|
|
m_sCsFont = m_sAsciiFont;
|
|
XMLTools::XMLAttribute* cs = new XMLTools::XMLAttribute(L"w:cs");
|
|
cs->SetValue(FormatUtils::XmlEncode(m_sCsFont, true));
|
|
rFonts->AppendAttribute(*cs);
|
|
RELEASEOBJECT(cs);
|
|
}
|
|
}
|
|
}
|
|
if ( lang->GetAttributeCount() > 0 )
|
|
{
|
|
parent->AppendChild( *lang );
|
|
}
|
|
if ( rFonts->GetAttributeCount() > 0 )
|
|
{
|
|
parent->AppendChild( *rFonts );
|
|
}
|
|
if ( colorVal->GetValue() != L"")
|
|
{
|
|
color->AppendAttribute( *colorVal );
|
|
parent->AppendChild( *color );
|
|
}
|
|
|
|
RELEASEOBJECT( lang );
|
|
RELEASEOBJECT( colorVal );
|
|
RELEASEOBJECT( color );
|
|
RELEASEOBJECT( rFonts );
|
|
}
|
|
|
|
/*========================================================================================================*/
|
|
|
|
/// CHPX flags are special flags because the can be 0,1,128 and 129,
|
|
/// so this method overrides the appendFlagElement method.
|
|
void CharacterPropertiesMapping::appendFlagElement( XMLTools::XMLElement* node, const SinglePropertyModifier& sprm, const wchar_t* elementName, bool unique )
|
|
{
|
|
unsigned char flag = sprm.Arguments[0];
|
|
|
|
if( flag != 128 )
|
|
{
|
|
XMLTools::XMLElement* ele = new XMLTools::XMLElement( L"w", elementName );
|
|
XMLTools::XMLAttribute* val = new XMLTools::XMLAttribute( L"w:val" );
|
|
|
|
if ( unique )
|
|
{
|
|
node->RemoveChild( *ele );
|
|
}
|
|
|
|
if ( flag == 0 )
|
|
{
|
|
val->SetValue( L"0" );
|
|
ele->AppendAttribute( *val );
|
|
node->AppendChild( *ele );
|
|
}
|
|
else if (flag == 1)
|
|
{
|
|
//dont append attribute val
|
|
//no attribute means true
|
|
node->AppendChild( *ele );
|
|
}
|
|
else if( flag == 129 )
|
|
{
|
|
//Invert the value of the style
|
|
|
|
//determine the style id of the current style
|
|
unsigned short styleId = 0;
|
|
|
|
if ( _currentIstd != USHRT_MAX )
|
|
{
|
|
styleId = _currentIstd;
|
|
}
|
|
else if( _currentPapx != NULL )
|
|
{
|
|
styleId = _currentPapx->istd;
|
|
}
|
|
|
|
//this chpx is the chpx of a style,
|
|
//don't use the id of the chpx or the papx, use the baseOn style
|
|
if ( _styleChpx )
|
|
{
|
|
StyleSheetDescription* thisStyle = _doc->Styles->Styles->at( styleId );
|
|
|
|
if (thisStyle)
|
|
styleId = (unsigned short)thisStyle->istdBase;
|
|
}
|
|
|
|
//build the style hierarchy
|
|
_hierarchy = buildHierarchy( _doc->Styles, styleId );
|
|
|
|
//apply the toggle values to get the real value of the style
|
|
bool stylesVal = applyToggleHierachy( sprm );
|
|
|
|
//invert it
|
|
if ( stylesVal )
|
|
{
|
|
val->SetValue( L"0" );
|
|
ele->AppendAttribute( *val );
|
|
}
|
|
|
|
node->AppendChild( *ele );
|
|
}
|
|
|
|
RELEASEOBJECT(ele);
|
|
RELEASEOBJECT(val);
|
|
}
|
|
}
|
|
|
|
/*========================================================================================================*/
|
|
|
|
std::list<CharacterPropertyExceptions*> CharacterPropertiesMapping::buildHierarchy( const StyleSheet* styleSheet, unsigned short istdStart )
|
|
{
|
|
std::list<CharacterPropertyExceptions*> hierarchy;
|
|
|
|
unsigned int istd = (unsigned int)istdStart;
|
|
bool goOn = true;
|
|
|
|
if ( ( styleSheet != NULL ) && ( styleSheet->Styles != NULL ) )
|
|
{
|
|
while ( goOn )
|
|
{
|
|
try
|
|
{
|
|
if ( istd < styleSheet->Styles->size() )
|
|
{
|
|
StyleSheetDescription* style = styleSheet->Styles->at( istd );
|
|
|
|
if (!style)
|
|
break;
|
|
CharacterPropertyExceptions* baseChpx = style->chpx;
|
|
|
|
if ( baseChpx != NULL )
|
|
{
|
|
hierarchy.push_back( baseChpx );
|
|
istd = (unsigned int)styleSheet->Styles->at( istd )->istdBase;
|
|
}
|
|
else
|
|
{
|
|
goOn = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
goOn = false;
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
goOn = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hierarchy;
|
|
}
|
|
|
|
/*========================================================================================================*/
|
|
|
|
bool CharacterPropertiesMapping::applyToggleHierachy( const SinglePropertyModifier& sprm )
|
|
{
|
|
bool ret = false;
|
|
|
|
for (auto& iter : _hierarchy)
|
|
{
|
|
for (auto& grpprlIter : *(iter->grpprl))
|
|
{
|
|
if (grpprlIter.OpCode == sprm.OpCode)
|
|
{
|
|
unsigned char ancient = grpprlIter.Arguments[0];
|
|
ret = toogleValue(ret, ancient);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*========================================================================================================*/
|
|
|
|
bool CharacterPropertiesMapping::toogleValue(bool currentValue, unsigned char toggle)
|
|
{
|
|
if ( toggle == 1 )
|
|
{
|
|
return true;
|
|
}
|
|
else if ( toggle == 129 )
|
|
{
|
|
//invert the current value
|
|
if ( currentValue )
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
else if ( toggle == 128 )
|
|
{
|
|
//use the current value
|
|
return currentValue;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|