Files
Yajbir Singh f1b860b25c
Some checks failed
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

2267 lines
66 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* (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 "DocumentMapping.h"
#include "ParagraphPropertiesMapping.h"
#include "CommentsMapping.h"
#include "TablePropertiesMapping.h"
#include "MainDocumentMapping.h"
#include "DrawingPrimitives.h"
#include "../Common/Base/TextMark.h"
#include "../Common/Base/FormatUtils.h"
#include <boost/algorithm/string.hpp>
namespace DocFileFormat
{
DocumentMapping::DocumentMapping(ConversionContext* context, IMapping* caller) : _skipRuns(0), _lastValidPapx(NULL), _lastValidSepx(NULL),
AbstractOpenXmlMapping( new XMLTools::CStringXmlWriter() ), _sectionNr(0), _footnoteNr(0),
_endnoteNr(0), _commentNr(1), _caller(caller), _permissionNr(1)
{
m_document = NULL;
m_context = context;
m_bInternalXmlWriter = false;
_writeWebHidden = false;
_isTextBoxContent = false;
m_context->_docx->_isSectionPageBreak = 0;
//--------------------------------------------
_embeddedObject = false;
}
DocumentMapping::DocumentMapping(ConversionContext* context, XMLTools::CStringXmlWriter* writer, IMapping* caller):_skipRuns(0), _lastValidPapx(NULL), _lastValidSepx(NULL),
AbstractOpenXmlMapping(writer), _sectionNr(0), _footnoteNr(0), _endnoteNr(0),
_commentNr(1), _caller(caller)
{
m_document = NULL;
m_context = context;
m_bInternalXmlWriter = false;
_writeWebHidden = false;
_isTextBoxContent = false;
_embeddedObject = false;
_cacheListNum = -1;
m_context->_docx->_isSectionPageBreak = 0;
}
DocumentMapping::~DocumentMapping()
{
if (m_bInternalXmlWriter)
{
RELEASEOBJECT(m_pXmlWriter);
}
}
// Looks into the section table to find out if this CP is the end & current of a sections
int DocumentMapping::getCurrentSection(int cp)
{
//if cp is the last char of a section, the next section will start at cp +1
size_t current = 0;
if (m_document->SectionPlex->CharacterPositions.empty())
{
return cp;
}
for (std::vector<int>::iterator iter = m_document->SectionPlex->CharacterPositions.begin() + 1; iter != m_document->SectionPlex->CharacterPositions.end(); ++iter)
{
if (cp < *iter)
{
break;
}
current++;
}
if (current + 1 >= m_document->SectionPlex->CharacterPositions.size())
current = m_document->SectionPlex->CharacterPositions.size() - 2;
return m_document->SectionPlex->CharacterPositions[current + 1];
}
int DocumentMapping::getListNumCache(int fc, int fc_end)
{
if ( !m_document->ListPlex ) return -1;
for (size_t i = 1; i < m_document->ListPlex->CharacterPositions.size(); i++)
{
if ((fc >= m_document->ListPlex->CharacterPositions[i-1]) && (fc_end <= m_document->ListPlex->CharacterPositions[i]))
{
ListNumCache* listNum = dynamic_cast<ListNumCache*> (m_document->ListPlex->Elements[i - 1]);
return listNum->value;
}
}
return -1;
}
bool DocumentMapping::isSectionEnd(int cp)
{
bool result = false;
//if cp is the last char of a section, the next section will start at cp +1
int search = cp + 1;
for (std::vector<int>::iterator iter = m_document->SectionPlex->CharacterPositions.begin(); iter != m_document->SectionPlex->CharacterPositions.end(); ++iter)
{
if (*iter == search)
{
result = true;
break;
}
}
return result;
}
std::vector<std::pair<int, int>> DocumentMapping::get_subsequence( int cpStart, int cpEnd, int fcStars, int fcEnd )
{
std::vector<std::pair<int, int>> outptu;
int currentFc = fcStars;
int currentCp = cpStart;
int oldElem = fcStars;
int currentStart = fcStars;
int currentStartcp = cpStart;
while ( cpEnd > currentCp)
{
currentCp ++;
currentFc = m_document->FindFileCharPos(currentCp);
if (currentFc < oldElem)
{
currentStart = currentFc;
outptu.emplace_back(currentStartcp, currentCp - 1);
currentStartcp = currentCp;
}
/*else if (currentFc > oldElem)
{
}
else
{
// -1 //че-нить в лог написать
}*/
oldElem = currentFc;
}
outptu.emplace_back(currentStartcp, currentCp);
return outptu;
}
// Writes a Paragraph that starts at the given cp and
// ends at the next paragraph end mark or section end mark
int DocumentMapping::writeParagraph(int cp, int cpEnd)
{
//search the paragraph end
int cpParaEnd = cp;
if ((m_document->Text) && (cpParaEnd < (int)m_document->Text->size()))
{
while (true)
{
if (m_document->m_mapBadCP.end() != m_document->m_mapBadCP.find(cpParaEnd))
{
cpParaEnd++;
continue;
}
if ((m_document->Text->at(cpParaEnd) == TextMark::ParagraphEnd) ||
(m_document->Text->at(cpParaEnd) == TextMark::CellOrRowMark) ||
((m_document->Text->at(cpParaEnd) == TextMark::PageBreakOrSectionMark) &&
isSectionEnd(cpParaEnd)))
break;
if (cpParaEnd >= (int)m_document->Text->size()-1) break;
cpParaEnd++;
}
if (TextMark::PageBreakOrSectionMark == m_document->Text->at(cpParaEnd))
{
// there is a page break OR section mark,
// write the section only if it's a section mark
bool sectionEnd = isSectionEnd(cpParaEnd);
cpParaEnd++;
return writeParagraph(cp, cpParaEnd, sectionEnd, false, START_END_PARAGRAPH);
}
else
{
cpParaEnd++;
int inpCpEnd = ( std::min )( cpEnd, cpParaEnd );
int fc = m_document->FindFileCharPos( cp );
int fcEnd = m_document->FindFileCharPos( inpCpEnd );
if ( fc < 0 || fcEnd < 0 || fc == fcEnd )
return -1;
std::vector<std::pair<int, int>> cpStartEnd = get_subsequence( cp, inpCpEnd, fc, fcEnd );
if (cpStartEnd.empty())
{
return -1;
}
if ( cpStartEnd.size() == 1 )
{
return writeParagraph(cpStartEnd.front().first, cpStartEnd.front().second, false, false, START_END_PARAGRAPH);
}
int retCp = cpParaEnd;
for (auto elem : cpStartEnd)
{
int curCpStart = elem.first;
int curCpEnd = elem.second;
if (elem == cpStartEnd.front())
{
retCp = writeParagraph(curCpStart, curCpEnd, false, false, START_PARAGRAPH);
}
else if (elem == cpStartEnd.back())
{
retCp = writeParagraph(curCpStart, curCpEnd, false, false, END_PARAGRAPH);
}
else
{
retCp = writeParagraph(curCpStart, curCpEnd, false, false, NOSTART_NOEND_PARAGRAPH);
}
}
return retCp;
}
}
return cpParaEnd;
}
// Writes a Paragraph that starts at the given cpStart and
// ends at the given cpEnd
int DocumentMapping::writeParagraph( int initialCp, int cpEnd, bool sectionEnd, bool lastBad, int paragraphState )
{
int cp = initialCp;
int fc = m_document->FindFileCharPos(cp);
int fcEnd = m_document->FindFileCharPos(cpEnd);
ParagraphPropertyExceptions* papx = findValidPapx(fc);
// get all CHPX between these boundaries to determine the count of runs
std::vector<CharacterPropertyExceptions*>* chpxs = m_document->GetCharacterPropertyExceptions(fc, fcEnd);
std::vector<int>* chpxFcs = m_document->GetFileCharacterPositions(fc, fcEnd);
CharacterPropertyExceptions* paraEndChpx = NULL;
if (chpxs)
{
// the last of these CHPX formats the paragraph end mark
paraEndChpx = *(chpxs->rbegin());
}
// start paragraph
if ( paragraphState & START_PARAGRAPH )
{
m_pXmlWriter->WriteNodeBegin(L"w:p", true);
if (false == _paraId.empty())
{
m_pXmlWriter->WriteAttribute(L"w14:paraId", _paraId);
}
writeParagraphRsid(papx);
}
// ----------- check for section properties
bool isBidi = false;
SectionPropertyExceptions* currentSection = findValidSepx(getCurrentSection(cp));
if (currentSection)
{
isBidi = currentSection->isBidi;
}
//-----------------------------------------------------------
//_cacheListNum = getListNumCache(fc, fcEnd);
m_context->_docx->_isSectionPageBreak = 0;
if (sectionEnd)
{
// this is the last paragraph of this section
// write properties with section properties
if ( papx && ( paragraphState & START_PARAGRAPH ) )
{
ParagraphPropertiesMapping oMapping(m_pXmlWriter, m_context, m_document, paraEndChpx, isBidi, findValidSepx(cpEnd), _sectionNr);
papx->Convert(&oMapping);
m_context->_docx->_isSectionPageBreak = oMapping.get_section_page_break();
}
++_sectionNr;
}
else
{
// write properties
if ( papx && ( paragraphState & START_PARAGRAPH ) )
{
ParagraphPropertiesMapping oMapping(m_pXmlWriter, m_context, m_document, paraEndChpx, isBidi);
papx->Convert(&oMapping);
}
}
if ((chpxs != NULL) && (chpxFcs != NULL) && !chpxFcs->empty())//? второе
{
size_t i = 0;
// write a runs for each CHPX
for (size_t it = 0; it < chpxs->size(); ++it)
{
//get the FC range for this run
int fcChpxStart = ((chpxFcs) && (i < chpxFcs->size())) ? chpxFcs->at(i) : fc;
int fcChpxEnd = fcEnd;
if ((chpxFcs) && ( i < chpxFcs->size() - 1))
fcChpxEnd = chpxFcs->at(i + 1);
//it's the first chpx and it starts before the paragraph
if ( ( i == 0 ) && ( fcChpxStart < fc ) )
{
//so use the FC of the paragraph
fcChpxStart = fc;
}
//it's the last chpx and it exceeds the paragraph
if ( ( i == ( chpxs->size() - 1 ) ) && ( fcChpxEnd > fcEnd ) )//todooo убрать обращение к size() !!!
{
//so use the FC of the paragraph
fcChpxEnd = fcEnd;
}
std::vector<wchar_t>* chpxChars = m_document->GetChars(fcChpxStart, fcChpxEnd, cp);
std::vector<int> annot = searchAnnotation(chpxChars, cp);
if (false == annot.empty())
{
std::vector<std::vector<wchar_t>>* runs = splitCharList(chpxChars, &annot);
if (runs)
{
for (std::vector<std::vector<wchar_t> >::iterator iter = runs->begin(); iter != runs->end(); ++iter)
{
if (writeAnnotations(cp))
{
cp = writeRun(&(*iter), chpxs->at(it), cp);
}
}
RELEASEOBJECT(runs);
}
}
else
{
std::vector<int> bookmarks = searchBookmarks(chpxChars, cp);
if (false == bookmarks.empty())
{
std::vector<std::vector<wchar_t>>* runs = splitCharList(chpxChars, &bookmarks);
if (runs)
{
for (std::vector<std::vector<wchar_t> >::iterator iter = runs->begin(); iter != runs->end(); ++iter)
{
if (writeBookmarks(cp))
{
cp = writeRun(&(*iter), chpxs->at(it), cp);
}
}
RELEASEOBJECT(runs);
}
}
else
{
std::vector<int> permissions = searchPermission(chpxChars, cp);
if (false == permissions.empty())
{
std::vector<std::vector<wchar_t>>* runs = splitCharList(chpxChars, &permissions);
if (runs)
{
for (std::vector<std::vector<wchar_t> >::iterator iter = runs->begin(); iter != runs->end(); ++iter)
{
if (writePermissions(cp))
{
cp = writeRun(&(*iter), chpxs->at(it), cp);
}
}
RELEASEOBJECT(runs);
}
}
else
{
cp = writeRun(chpxChars, chpxs->at(it), cp);
}
}
}
RELEASEOBJECT(chpxChars);
i++;
}
//end paragraph
if ( paragraphState & END_PARAGRAPH ) m_pXmlWriter->WriteNodeEnd( L"w:p" );
}
else
{
//end paragraph
if ( paragraphState & END_PARAGRAPH ) m_pXmlWriter->WriteNodeEnd( L"w:p" );
}
RELEASEOBJECT(chpxFcs);
RELEASEOBJECT(chpxs);
return cpEnd;
return (std::max)(cp, cpEnd); //ralph_scovile.doc
}
void DocumentMapping::writeParagraphRsid (const ParagraphPropertyExceptions* papx)
{
if (papx)
{
for (std::vector<SinglePropertyModifier>::const_iterator iter = papx->grpprl->begin(); iter != papx->grpprl->end(); ++iter)
{
// rsid for paragraph property enditing (write to parent element)
if (DocFileFormat::sprmPRsid == iter->OpCode)
{
std::wstring id = FormatUtils::IntToFormattedWideString(FormatUtils::BytesToInt32(iter->Arguments, 0, iter->argumentsSize), L"%08X");
m_context->AddRsid(id);
m_pXmlWriter->WriteAttribute(L"w:rsidP", id);
break;
}
}
}
m_pXmlWriter->WriteNodeEnd(L"", true, false);
}
// Writes a run with the given characters and CHPX
int DocumentMapping::writeRun (std::vector<wchar_t>* chars, CharacterPropertyExceptions* chpx, int initialCp)
{
int cp = initialCp;
int result_cp = cp + (int)chars->size();
if ((_skipRuns <= 0) && (chars->size() > 0))
{
RevisionData rev = RevisionData(chpx);
if (Deleted == rev.Type)
{
WideString* author = dynamic_cast<WideString*>(m_document->RevisionAuthorTable->operator[](rev.Isbt));
m_pXmlWriter->WriteNodeBegin(L"w:del", true);
m_pXmlWriter->WriteAttribute(L"w:author", FormatUtils::XmlEncode(*author));
m_pXmlWriter->WriteAttribute(L"w:date", FormatUtils::XmlEncode(rev.Dttm.getString()));
m_pXmlWriter->WriteNodeEnd(L"", true, false);
}
else if ( rev.Type == Inserted )
{
WideString* author = dynamic_cast<WideString*>(m_document->RevisionAuthorTable->operator[](rev.Isbt));
m_pXmlWriter->WriteNodeBegin(L"w:ins", true);
m_pXmlWriter->WriteAttribute(L"w:author", FormatUtils::XmlEncode(*author));
m_pXmlWriter->WriteAttribute(L"w:date", FormatUtils::XmlEncode(rev.Dttm.getString()));
m_pXmlWriter->WriteNodeEnd(L"", true, false);
}
//start run
m_pXmlWriter->WriteNodeBegin(L"w:r", true);
//append rsids
if (0 != rev.Rsid)
{
std::wstring rsid = FormatUtils::IntToFormattedWideString(rev.Rsid, L"%08X");
m_pXmlWriter->WriteAttribute(L"w:rsidR", rsid);
m_context->AddRsid(rsid);
}
if (0 != rev.RsidDel)
{
std::wstring rsidDel = FormatUtils::IntToFormattedWideString(rev.RsidDel, L"%08X");
m_pXmlWriter->WriteAttribute(L"w:rsidDel", rsidDel);
m_context->AddRsid(rsidDel);
}
if (0 != rev.RsidProp)
{
std::wstring rsidProp = FormatUtils::IntToFormattedWideString(rev.RsidProp, L"%08X");
m_pXmlWriter->WriteAttribute(L"w:rsidRPr", rsidProp);
m_context->AddRsid(rsidProp);
}
m_pXmlWriter->WriteNodeEnd(L"", true, false);
/// <w:rPr>
CharacterPropertiesMapping* rPr = new CharacterPropertiesMapping(m_pXmlWriter, m_document, &rev, _lastValidPapx, false);
if (rPr)
{
rPr->_webHidden = _writeWebHidden;
chpx->Convert(rPr);
RELEASEOBJECT(rPr);
}
if (Deleted == rev.Type)
{
writeText(chars, cp, chpx, true);
}
else
{
int new_result_cp = writeText(chars, cp, chpx, false);
if (new_result_cp > result_cp)
result_cp = new_result_cp;
}
//end run
m_pXmlWriter->WriteNodeEnd(L"w:r");
if (Deleted == rev.Type)
{
m_pXmlWriter->WriteNodeEnd(L"w:del");
}
else if (Inserted == rev.Type)
{
m_pXmlWriter->WriteNodeEnd(L"w:ins");
}
if (!_writeAfterRun.empty())
{
m_pXmlWriter->WriteString(_writeAfterRun);
_writeAfterRun.clear();
}
}
else
{
--_skipRuns;
}
return result_cp;
}
void DocumentMapping::writeField(const std::wstring& sFieldString, int cpFieldStart, int cpFieldEnd)
{
_fieldLevels.push_back(fieldLevels());
std::vector<std::wstring> arField;
boost::algorithm::split(arField, sFieldString, boost::algorithm::is_any_of(L"\\"), boost::algorithm::token_compress_on);
std::wstring f;
std::wstring EMBED ( L"EMBED" );
std::wstring embed ( L"embed" );
std::wstring LINK ( L"LINK" );
std::wstring FORM ( L"FORM" );
std::wstring Excel ( L"Excel" );
std::wstring Word ( L"Word" );
std::wstring opendocument(L"opendocument" );
std::wstring Equation ( L"Equation" );
std::wstring MERGEFORMAT( L"MERGEFORMAT" );
std::wstring QUOTE ( L"QUOTE" );
std::wstring chart ( L"Chart" );
std::wstring PBrush ( L"PBrush" );
std::wstring TOC ( L"TOC" );
std::wstring HYPERLINK ( L"HYPERLINK" );
std::wstring PAGEREF ( L"PAGEREF" );
std::wstring PAGE ( L"PAGE" );
std::wstring SHAPE ( L"SHAPE" );
std::wstring NREF ( L"NREF");
if (arField.empty() == false)
f = arField[0];
else
f = sFieldString;
bool bChart = search( f.begin(), f.end(), chart.begin(), chart.end()) != f.end();
bool bEMBED = search( f.begin(), f.end(), EMBED.begin(), EMBED.end()) != f.end() ||
search( f.begin(), f.end(), embed.begin(), embed.end()) != f.end();
bool bLINK = search( f.begin(), f.end(), LINK.begin(), LINK.end()) != f.end();
bool bOpendocument = search( f.begin(), f.end(), opendocument.begin(), opendocument.end()) != f.end();
bool bFORM = search( f.begin(), f.end(), FORM.begin(), FORM.end()) != f.end();
bool bMERGEFORMAT = search( f.begin(), f.end(), MERGEFORMAT.begin(), MERGEFORMAT.end()) != f.end();
bool bExcel = search( f.begin(), f.end(), Excel.begin(), Excel.end()) != f.end();
bool bWord = search( f.begin(), f.end(), Word.begin(), Word.end()) != f.end();
bool bHYPERLINK = search( f.begin(), f.end(), HYPERLINK.begin(), HYPERLINK.end()) != f.end();
bool bQUOTE = search( f.begin(), f.end(), QUOTE.begin(), QUOTE.end()) != f.end();
bool bEquation = search( f.begin(), f.end(), Equation.begin(), Equation.end()) != f.end();
bool bPAGE = search( f.begin(), f.end(), PAGE.begin(), PAGE.end()) != f.end();
bool bTOC = search( f.begin(), f.end(), TOC.begin(), TOC.end()) != f.end();
bool bSHAPE = search( f.begin(), f.end(), SHAPE.begin(), SHAPE.end()) != f.end();
bool bNREF = search( f.begin(), f.end(), NREF.begin(), NREF.end()) != f.end();
bool bPAGEREF = false;
if (bHYPERLINK && arField.size() > 1)
{
std::wstring f1 = arField[1];
bPAGEREF = search( f1.begin(), f1.end(), PAGEREF.begin(), PAGEREF.end()) != f1.end();
}
if (bTOC)
_bContentWrite = true;
if ( bFORM )
{
std::wstring FORMTEXT ( L" FORMTEXT" );
std::wstring FORMCHECKBOX ( L" FORMCHECKBOX" );
std::wstring FORMDROPDOWN ( L" FORMDROPDOWN" );
m_pXmlWriter->WriteNodeBegin( L"w:fldChar" , true );
m_pXmlWriter->WriteAttribute( L"w:fldCharType" , L"begin" );
m_pXmlWriter->WriteNodeEnd( L"", true, false );
bool bFORMTEXT = search( f.begin(), f.end(), FORMTEXT.begin(), FORMTEXT.end()) != f.end();
bool bFORMCHECKBOX = search( f.begin(), f.end(), FORMCHECKBOX.begin(), FORMCHECKBOX.end()) != f.end();
bool bFORMDROPDOWN = search( f.begin(), f.end(), FORMDROPDOWN.begin(), FORMDROPDOWN.end()) != f.end();
if (bFORMTEXT || bFORMCHECKBOX || bFORMDROPDOWN)
{
int cpPic = searchNextTextMark( m_document->Text, cpFieldStart, TextMark::Picture );
if (cpPic < cpFieldEnd)
{
int fcPic = m_document->FindFileCharPos( cpPic );
std::vector<CharacterPropertyExceptions*>* chpxs = m_document->GetCharacterPropertyExceptions(fcPic, fcPic + 1);
if (chpxs)
{
CharacterPropertyExceptions* chpxSep = chpxs->front();
FormFieldData ffdata (2, chpxSep, m_document->DataStream, false);
FormFieldDataMapping data_mapping(m_pXmlWriter, m_context, _caller);
ffdata.Convert(&data_mapping);
RELEASEOBJECT( chpxs );
}
}
}
m_pXmlWriter->WriteNodeEnd( L"w:fldChar" );
_fieldLevels.back().bBegin = true;
}
else if ( ( bMERGEFORMAT || bExcel || bWord || bOpendocument )
&&
( ( bEMBED || bLINK ) && bChart) )
{
m_pXmlWriter->WriteNodeBegin( L"w:fldChar", true );
m_pXmlWriter->WriteAttribute( L"w:fldCharType", L"begin" );
m_pXmlWriter->WriteNodeEnd( L"", true, false );
int cpPic = searchNextTextMark( m_document->Text, cpFieldStart, TextMark::Picture );
m_pXmlWriter->WriteNodeEnd( L"w:fldChar" );
_fieldLevels.back().bBegin = true;
}
else if (bHYPERLINK && bPAGEREF)
{
int cpFieldSep2 = cpFieldStart, cpFieldSep1 = cpFieldStart;
std::vector<std::wstring> toc;
if (arField.size() > 1)
f = arField[1];
if ( _bContentWrite )
{
m_pXmlWriter->WriteNodeBegin( L"w:fldChar", true );
m_pXmlWriter->WriteAttribute( L"w:fldCharType", L"begin" );
m_pXmlWriter->WriteNodeEnd( L"", true );
_fieldLevels.back().bBegin = true;
}
else
{
for (size_t i = 1; i < arField.size(); i++)
{
std::wstring f1 = arField[1];
int d = (int)f1.find(PAGEREF);
if (d > 0)
{
_writeWebHidden = true;
std::wstring _writeTocLink =f1.substr(d + 9);
d = (int)_writeTocLink.find(L" ");
_writeTocLink = _writeTocLink.substr(0, d);
_writeAfterRun = std::wstring (L"<w:hyperlink w:anchor=\"");
_writeAfterRun += XmlUtils::EncodeXmlString(_writeTocLink);
_writeAfterRun += std::wstring (L"\" w:history=\"1\">");
break;
//cp = cpFieldSep1;
}
//cpFieldSep1 = cpFieldSep2;
}
_skipRuns = 5; //with separator
}
}
else if ( bEMBED || (bLINK && !bHYPERLINK)/*|| bQUOTE*/)
{
int cpPic = searchNextTextMark(m_document->Text, cpFieldStart, TextMark::Picture);
int cpFieldSep = searchNextTextMark(m_document->Text, cpFieldStart, TextMark::FieldSeparator);
if (cpPic < cpFieldEnd)
{
int fcPic = m_document->FindFileCharPos( cpPic );
std::vector<CharacterPropertyExceptions*>* chpxs = m_document->GetCharacterPropertyExceptions(fcPic, fcPic + 1);
CharacterPropertyExceptions* chpxObj = chpxs->front();
RevisionData oData = RevisionData(chpxObj);
CharacterPropertiesMapping* rPr = new CharacterPropertiesMapping(m_pXmlWriter, m_document, &oData, _lastValidPapx, false);
if(rPr)
{
chpxObj->Convert(rPr);
RELEASEOBJECT(rPr);
}
XMLTools::CStringXmlWriter oleWriter;
XMLTools::CStringXmlWriter oleObjectWriter;
VMLPictureMapping oVmlMapper (m_context, &oleWriter, true, _caller);
if (false == m_shapeIdOwner.empty()) //4571833.doc
oVmlMapper.m_shapeId = m_shapeIdOwner;
if (m_document->nWordVersion > 0)
{
OleObject ole ( chpxObj, m_document);
oleWriter.WriteNodeBegin (L"w:object", true);
oleWriter.WriteAttribute( L"w:dxaOrig", FormatUtils::IntToWideString( ( ole.pictureDesciptor.dxaGoal + ole.pictureDesciptor.dxaOrigin ) ));
oleWriter.WriteAttribute( L"w:dyaOrig", FormatUtils::IntToWideString( ( ole.pictureDesciptor.dyaGoal + ole.pictureDesciptor.dyaOrigin ) ));
oleWriter.WriteNodeEnd( L"", true, false );
ole.pictureDesciptor.Convert(&oVmlMapper);
OleObjectMapping oleObjectMapping( &oleObjectWriter, m_context, &ole.pictureDesciptor, _caller, oVmlMapper.m_shapeId);
ole.Convert( &oleObjectMapping );
_lastOLEObject = oleObjectWriter.GetXmlString();
}
else
{
PictureDescriptor pic(chpxObj, m_document->DataStream, 0x7fffffff, m_document->nWordVersion);
oleWriter.WriteNodeBegin (L"w:object", true);
oleWriter.WriteAttribute( L"w:dxaOrig", FormatUtils::IntToWideString( ( pic.dxaGoal + pic.dxaOrigin ) ) );
oleWriter.WriteAttribute( L"w:dyaOrig", FormatUtils::IntToWideString( ( pic.dyaGoal + pic.dyaOrigin ) ) );
oleWriter.WriteNodeEnd( L"", true, false );
pic.Convert(&oVmlMapper);
RELEASEOBJECT(chpxs);
if ( cpFieldSep < cpFieldEnd && m_document->m_PieceTable)
{
int fcFieldSep = m_document->m_PieceTable->FileCharacterPositions->operator []( cpFieldSep );
int fcFieldSep1 = m_document->FindFileCharPos( cpFieldSep );
std::vector<CharacterPropertyExceptions*>* chpxs = m_document->GetCharacterPropertyExceptions( fcFieldSep, ( fcFieldSep + 1 ) );
CharacterPropertyExceptions* chpxSep = chpxs->front();
OleObject ole ( chpxSep, m_document);
OleObjectMapping oleObjectMapping( &oleObjectWriter, m_context, &pic, _caller, oVmlMapper.m_shapeId );
if (oVmlMapper.m_isEmbedded)
{
ole.isEquation = oVmlMapper.m_isEquation;
ole.isEmbedded = oVmlMapper.m_isEmbedded;
ole.embeddedData = oVmlMapper.m_embeddedData;
}
ole.Convert( &oleObjectMapping );
_lastOLEObject = oleObjectWriter.GetXmlString();
RELEASEOBJECT( chpxs );
}
}
oleWriter.WriteString( _lastOLEObject );
if (false == m_bOleInPicture)
_lastOLEObject.clear();
oleWriter.WriteNodeEnd( L"w:object" );
if (!oVmlMapper.m_isEmbedded && oVmlMapper.m_isEquation)
{
//нельзя в Run писать oMath
//m_pXmlWriter->WriteString(oVmlMapper.m_equationXml);
_writeAfterRun = oVmlMapper.m_equationXml;
}
else
{
m_pXmlWriter->WriteString(oleWriter.GetXmlString());
}
}
_skipRuns = 3;
_embeddedObject = true;
}
else
{
m_pXmlWriter->WriteNodeBegin( L"w:fldChar", true );
m_pXmlWriter->WriteAttribute( L"w:fldCharType", L"begin" );
m_pXmlWriter->WriteNodeEnd( L"", true );
_fieldLevels.back().bBegin = true;
}
}
// Writes the given text to the document
int DocumentMapping::writeText(std::vector<wchar_t>* chars, int initialCp, CharacterPropertyExceptions* chpx, bool writeDeletedText)
{
int cp = initialCp;
bool fSpec = isSpecial (chpx);
//detect text type
std::wstring textType = L"t";
std::wstring text;
if (writeDeletedText)
{
textType = std::wstring(L"delText");
}
else if ((!_fieldLevels.empty()) && (_fieldLevels.back().bBegin && !_fieldLevels.back().bSeparate))
{
textType = std::wstring(L"instrText");
}
//write text
for (size_t i = 0; i < chars->size(); ++i)
{
wchar_t c = chars->at(i), code = c;
if (TextMark::Tab == code)
{
writeTextElement(text, textType);
text.clear();
XMLTools::XMLElement elem(L"w:tab");
m_pXmlWriter->WriteString(elem.GetXMLString());
}
else if (TextMark::HardLineBreak == code)
{
writeTextElement(text, textType);
text.clear();
if (textType == L"instrText")
{
m_pXmlWriter->WriteNodeEnd(L"w:r");
m_pXmlWriter->WriteNodeBegin(L"w:r");
CharacterPropertiesMapping* rPr = new CharacterPropertiesMapping(m_pXmlWriter, m_document, NULL, _lastValidPapx, false);
if (rPr)
{
rPr->_webHidden = _writeWebHidden;
chpx->Convert(rPr);
RELEASEOBJECT(rPr);
}
}
XMLTools::XMLElement elem(L"w:br");
//СЗ в МРФ Техноград о предоставлении ТП 1 квартал 2019_MO_Q31.doc
//Документ на бланке 2.doc
elem.AppendAttribute(L"w:type", L"textWrapping");
elem.AppendAttribute(L"w:clear", L"all");
m_pXmlWriter->WriteString(elem.GetXMLString());
}
else if (TextMark::ParagraphEnd == code)
{
//do nothing
}
else if (TextMark::PageBreakOrSectionMark == code)
{
if (m_context->_docx->_isSectionPageBreak == 0/* || m_context->_docx->_isSectionPageBreak == 2*/)
{
m_context->_docx->_isSectionPageBreak = -1;
writeTextElement(text, textType);
text.clear();
XMLTools::XMLElement elem(L"w:br");
elem.AppendAttribute(L"w:type", L"page");
m_pXmlWriter->WriteString(elem.GetXMLString());
}
m_context->_docx->_isSectionPageBreak = -1;
}
else if (TextMark::ColumnBreak == code)
{
writeTextElement(text, textType);
text.clear();
XMLTools::XMLElement elem(L"w:br");
elem.AppendAttribute(L"w:type", L"column");
m_pXmlWriter->WriteString(elem.GetXMLString());
}
else if (TextMark::FieldBeginMark == code)
{
_embeddedObject = false;
int cpFieldStart = initialCp + i;
int cpFieldEnd = searchNextTextMark( m_document->Text, cpFieldStart, TextMark::FieldEndMark );
std::wstring sFieldString;
if (cpFieldEnd < (int)m_document->Text->size())
sFieldString = std::wstring( ( m_document->Text->begin() + cpFieldStart ), ( m_document->Text->begin() + cpFieldEnd + 1 ) );
writeField(sFieldString, cpFieldStart, cpFieldEnd);
}
else if (TextMark::FieldSeparator == code)
{
if (!_fieldLevels.empty())
{
_fieldLevels.back().bSeparate = true;
XMLTools::XMLElement elem( L"w:fldChar" );
elem.AppendAttribute( L"w:fldCharType", L"separate" );
m_pXmlWriter->WriteString( elem.GetXMLString() );
}
if (_embeddedObject) _skipRuns += 2;
}
else if (TextMark::FieldEndMark == code)
{
if (!_fieldLevels.empty())
{
if (!text.empty())
{
writeTextElement(text, textType);
text.clear();
}
if (_fieldLevels.back().bBegin)
{
_fieldLevels.back().bEnd = true;
XMLTools::XMLElement elem( L"w:fldChar" );
elem.AppendAttribute( L"w:fldCharType", L"end" );
m_pXmlWriter->WriteString( elem.GetXMLString());
}
_fieldLevels.pop_back();
}
if (_writeWebHidden)
{
_writeAfterRun = std::wstring (L"</w:hyperlink>");
}
_writeWebHidden = false;
_embeddedObject = false;
if (_fieldLevels.empty())
_bContentWrite = false;
}
else if ((TextMark::Symbol == code) && fSpec)
{
writeNotesReferences(cp);//for word95 & non-automatic notes
Symbol s = getSymbol( chpx );
//<w:sym w:font="Symbol" w:char="F062"/>
if (false == s.HexValue.empty()) //09FluGuide.doc - поврежденный
{
m_pXmlWriter->WriteNodeBegin(L"w:sym", true);
if (false == s.FontName.empty()) // ??? default
m_pXmlWriter->WriteAttribute(L"w:font", FormatUtils::XmlEncode(s.FontName));
m_pXmlWriter->WriteAttribute(L"w:char", FormatUtils::XmlEncode(s.HexValue));
m_pXmlWriter->WriteNodeEnd(L"", true);
}
}
else if ((TextMark::DrawnObject == code) && fSpec)
{
Spa* pSpa = NULL;
if (typeid(*this) == typeid(MainDocumentMapping))
{
pSpa = static_cast<Spa*>(m_document->OfficeDrawingPlex->GetStructByCP(cp));
}
else if ((typeid(*this) == typeid(HeaderMapping) ) || ( typeid(*this) == typeid(FooterMapping)))
{
int headerCp = ( cp - m_document->FIB->m_RgLw97.ccpText - m_document->FIB->m_RgLw97.ccpFtn );
pSpa = static_cast<Spa*>(m_document->OfficeDrawingPlexHeader->GetStructByCP(headerCp));
}
bool bPicture = false;
if (pSpa)
{
PictureDescriptor pictDiscr(chpx, m_document->WordDocumentStream, 0x7fffffff, m_document->nWordVersion);
ShapeContainer* pShape = m_document->GetOfficeArt()->GetShapeContainer(pSpa->GetShapeID());
if (pShape) ///*&& (false == pShape->isLastIdentify())
{
VMLShapeMapping oVmlWriter (m_context, m_pXmlWriter, pSpa, &pictDiscr, _caller);
std::wstring strNode = pShape->m_bOLE ? L"w:object" : L"w:pict";
pShape->m_bOleInPicture = pShape->m_bOLE ? true : false;
m_pXmlWriter->WriteNodeBegin (strNode);
pShape->Convert(&oVmlWriter);
m_pXmlWriter->WriteNodeEnd (strNode);
bPicture = true;
}
if (!pSpa->primitives.empty())
{
m_pXmlWriter->WriteNodeBegin (L"w:pict");
VMLShapeMapping oVmlWriter (m_context, m_pXmlWriter, pSpa, &pictDiscr, _caller);
pSpa->primitives.Convert(&oVmlWriter);
m_pXmlWriter->WriteNodeEnd (L"w:pict");
bPicture = true;
}
}
if ((false == _fieldLevels.empty()) && (_fieldLevels.back().bSeparate))
_fieldLevels.back().bResult = bPicture;
}
else if (TextMark::Picture == code && fSpec)
{
PictureDescriptor oPicture (chpx, m_document->nWordVersion > 0 ? m_document->WordDocumentStream : m_document->DataStream, 0x7fffffff, m_document->nWordVersion);
bool isInline = _isTextBoxContent;
if (oPicture.embeddedData && oPicture.embeddedDataSize > 0)
{
m_pXmlWriter->WriteNodeBegin (L"w:pict");
VMLPictureMapping oVmlMapper(m_context, m_pXmlWriter, false, _caller, isInline);
oPicture.Convert (&oVmlMapper);
m_pXmlWriter->WriteNodeEnd (L"w:pict");
}
else if ((oPicture.mfp.mm > 98) && (NULL != oPicture.shapeContainer)/* && (false == oPicture.shapeContainer->isLastIdentify())*/)
{
bool bPicture = true;
bool m_bSkip = false;
if (oPicture.shapeContainer)
{
if (oPicture.shapeContainer->m_nShapeType != msosptPictureFrame)
bPicture = false;//шаблон 1.doc картинка в колонтитуле
m_bSkip = oPicture.shapeContainer->m_bSkip;
}
if (!m_bSkip)
{
bool bFormula = false;
XMLTools::CStringXmlWriter pictWriter;
pictWriter.WriteNodeBegin (L"w:pict");
if (bPicture)
{
VMLPictureMapping oVmlMapper(m_context, &pictWriter, false, _caller, isInline);
oPicture.Convert (&oVmlMapper);
if (oVmlMapper.m_isEmbedded)
{
OleObject ole ( chpx, m_document);
OleObjectMapping oleObjectMapping( &pictWriter, m_context, &oPicture, _caller, oVmlMapper.m_shapeId );
ole.isEquation = oVmlMapper.m_isEquation;
ole.isEmbedded = oVmlMapper.m_isEmbedded;
ole.embeddedData = oVmlMapper.m_embeddedData;
ole.Convert( &oleObjectMapping );
}
else if (oVmlMapper.m_isEquation)
{
//нельзя в Run писать oMath
//m_pXmlWriter->WriteString(oVmlMapper.m_equationXml);
_writeAfterRun = oVmlMapper.m_equationXml;
bFormula = true;
}
else if (oVmlMapper.m_isBlob)
{
_writeAfterRun = oVmlMapper.m_blobXml;
bFormula = true;
}
}
else
{
VMLShapeMapping oVmlMapper(m_context, &pictWriter, NULL, &oPicture, _caller, isInline, false);
oPicture.shapeContainer->Convert(&oVmlMapper);
}
pictWriter.WriteNodeEnd (L"w:pict");
if (!bFormula)
{
m_pXmlWriter->WriteString(pictWriter.GetXmlString());
if ((false == _fieldLevels.empty()) && (_fieldLevels.back().bSeparate && !_fieldLevels.back().bResult)) //ege15.doc
{
_fieldLevels.back().bResult = true;
}//imrtemplate(endnotes).doc
}
}
}
}
else if ((TextMark::AutoNumberedFootnoteReference == code) && fSpec)
{
writeNotesReferences(cp);
}
else if (TextMark::AnnotationReference == code)
{
if (typeid(*this) == typeid(CommentsMapping))
{
m_pXmlWriter->WriteNodeBegin( L"w:annotationRef", true );
m_pXmlWriter->WriteNodeEnd( L"", true );
}
else if (m_document->AnnotationsReferencePlex)
{
m_pXmlWriter->WriteNodeBegin( L"w:commentReference", true );
AnnotationReferenceDescriptor* atrdPre10 = dynamic_cast<AnnotationReferenceDescriptor*>( m_document->AnnotationsReferencePlex->GetStructByCP(cp));
if (atrdPre10)
{
if (atrdPre10->m_CommentId < 0)
{
if (atrdPre10->m_BookmarkId < 0)
{
atrdPre10->m_CommentId = _commentNr++;
}
else
{
std::map<int, int>::iterator pFind = m_document->mapAnnotBookmarks.find(atrdPre10->m_BookmarkId);
if (pFind == m_document->mapAnnotBookmarks.end())
{
atrdPre10->m_CommentId = _commentNr++;
m_document->mapAnnotBookmarks.insert(std::make_pair(atrdPre10->m_BookmarkId, atrdPre10->m_CommentId));
}
else
{
atrdPre10->m_CommentId = pFind->second;
}
}
}
m_pXmlWriter->WriteAttribute( L"w:id", FormatUtils::IntToWideString(atrdPre10->m_CommentId));
}
m_pXmlWriter->WriteNodeEnd( L"", true );
}
}
else if (!FormatUtils::IsControlSymbol(c) && ((int)c != 0xFFFF))
{
text += FormatUtils::GetXMLSymbol(c);
//non-automatic notes
if ((m_document->IndividualFootnotesPlex != NULL) && (m_document->IndividualFootnotesPlex->IsCpExists(cp - m_document->FIB->m_RgLw97.ccpText)))
{
_writeNoteRef = L"<w:footnoteRef/>";
}
else if ((m_document->IndividualEndnotesPlex != NULL) &&
(m_document->IndividualEndnotesPlex->IsCpExists(cp - m_document->FIB->m_RgLw97.ccpAtn - m_document->FIB->m_RgLw97.ccpHdr - m_document->FIB->m_RgLw97.ccpFtn - m_document->FIB->m_RgLw97.ccpText)))
{
_writeNoteRef = L"<w:endnoteRef/>";
}
else
writeNotesReferences(cp);//for word95
}
cp++;
}
if (std::wstring::npos != text.find(L"EMBED"))
{//если есть мааркер конца поля и маркер замещающей картинки и нету маркера начала
//О реорганизации территориальных органов ПФР с 01.11.2018.doc
int cpFieldStart = initialCp;
int cpPic = searchNextTextMark(m_document->Text, cpFieldStart, TextMark::Picture);
int cpFieldEnd = searchNextTextMark( m_document->Text, cpFieldStart, TextMark::FieldEndMark );
bool bStartField = _fieldLevels.empty() ? false : (_fieldLevels.back().bBegin && !_fieldLevels.back().bSeparate);
if (cpFieldStart < cpPic && cpPic < cpFieldEnd && !bStartField)
{
writeField(text, cpFieldStart, cpFieldEnd);
text.clear();
}
}
if (!text.empty())
{
//bool preserve_space = (text.find(L"\x20")) != text.npos) ? true : false;
writeTextStart(textType, true/*preserve_space*/);
m_pXmlWriter->WriteString(text);
writeTextEnd(textType);
}
return cp;
}
void DocumentMapping::writeTextElement(const std::wstring& text, const std::wstring& textType)
{
if ( !text.empty() )
{
bool preserve_space = true;//(text.find(L"\x20")) != text.npos) ? true : false;
if (textType == L"instrText")
preserve_space = false;
writeTextStart( textType, preserve_space );
m_pXmlWriter->WriteString( text);
writeTextEnd( textType );
}
}
void DocumentMapping::writeTextStart(const std::wstring& textType, bool preserve_space)
{
std::wstring str = ( L"w:" + textType );
m_pXmlWriter->WriteNodeBegin( str, true );
if (preserve_space)
{
m_pXmlWriter->WriteAttribute( L"xml:space", L"preserve" );
}
m_pXmlWriter->WriteNodeEnd( L"", true, false );
}
void DocumentMapping::writeTextEnd(const std::wstring& textType)
{
std::wstring str = ( std::wstring( L"w:" ) + textType );
m_pXmlWriter->WriteNodeEnd( str );
}
// Searches for bookmarks in the list of characters.
std::vector<int> DocumentMapping::searchBookmarks(std::vector<wchar_t>* chars, int initialCp)
{
std::vector<int> ret;
if (m_document->BookmarkStartPlex->IsValid())
{
int cp = initialCp;
size_t count = chars->size();
for (size_t i = 0; i < count; ++i)
{
if ((m_document->BookmarkStartPlex->IsCpExists(cp)) || (m_document->BookmarkEndPlex->IsCpExists(cp)))
{
ret.push_back((int)i);
}
++cp;
}
}
return ret;
}
std::vector<int> DocumentMapping::searchAnnotation(std::vector<wchar_t>* chars, int initialCp)
{
std::vector<int> ret;
if (m_document->AnnotStartPlex->IsValid())
{
int cp = initialCp;
size_t count = chars->size();
for (size_t i = 0; i < count; ++i)
{
if ((m_document->AnnotStartPlex->IsCpExists(cp)) || (m_document->AnnotEndPlex->IsCpExists(cp)))
{
ret.push_back((int)i);
}
++cp;
}
}
return ret;
}
std::vector<int> DocumentMapping::searchPermission(std::vector<wchar_t>* chars, int initialCp)
{
std::vector<int> ret;
if (m_document->BookmarkProtStartPlex->IsValid())
{
int cp = initialCp;
size_t count = chars->size();
for (size_t i = 0; i < count; ++i)
{
if ((m_document->BookmarkProtStartPlex->IsCpExists(cp)) || (m_document->BookmarkProtEndPlex->IsCpExists(cp)))
{
ret.push_back((int)i);
}
++cp;
}
}
return ret;
}
ParagraphPropertyExceptions* DocumentMapping::findValidPapx(int fc)
{
ParagraphPropertyExceptions* ret = NULL;
std::vector<int>* pVector = m_document->AllPapxVector;
int nMin = 0;
int nMax = (int)pVector->size();
if( nMax > 0 )
{
while( nMin + 1 < nMax )
{
int nCurPos = (nMax + nMin) / 2;
int nCurVal = pVector->at(nCurPos);
if( nCurVal > fc )
nMax = nCurPos;
else if( nCurVal < fc )
nMin = nCurPos;
else
{
nMin = nCurPos;
break;
}
}
int nMinVal = pVector->at(nMin);
if ( fc >= nMinVal )
{
ret = m_document->AllPapx->find(nMinVal)->second;
_lastValidPapx = ret;
}
}
return ret;
}
std::vector<std::vector<wchar_t> >* DocumentMapping::splitCharList(std::vector<wchar_t>* chars, std::vector<int>* splitIndices)
{
std::vector<std::vector<wchar_t> >* ret = new std::vector<std::vector<wchar_t> >();
std::vector<wchar_t> wcharVector;
int startIndex = 0;
// add the parts
for (size_t i = 0; i < splitIndices->size(); ++i)
{
int cch = splitIndices->at( i ) - startIndex;
if ( cch > 0 )
{
wcharVector = std::vector<wchar_t>( cch );
copy( chars->begin() + startIndex, chars->begin() + startIndex + cch, wcharVector.begin() );
ret->push_back( wcharVector );
}
wcharVector.clear();
startIndex += cch;
}
//add the last part
wcharVector = std::vector<wchar_t>( chars->size() - startIndex );
copy( chars->begin() + startIndex, chars->end(), wcharVector.begin() );
ret->push_back( wcharVector );
wcharVector.clear();
return ret;
}
// Writes the table starts at the given cp value
int DocumentMapping::writeTable(int initialCp, unsigned int nestingLevel)
{
int cp = initialCp;
int fc2 = m_document->FindFileCharPos( cp );
int fc = m_document->m_PieceTable->FileCharacterPositions->operator []( cp );
ParagraphPropertyExceptions* papx = findValidPapx( fc );
TableInfo tai( papx, m_document->nWordVersion );
//build the table grid
std::vector<short> grid;
buildTableGrid( cp, nestingLevel, grid);
//find first row end
int fcRowEnd = findRowEndFc( cp, nestingLevel );
TablePropertyExceptions row1Tapx( findValidPapx( fcRowEnd ), m_document->DataStream, m_document->nWordVersion);
//start table
m_pXmlWriter->WriteNodeBegin( L"w:tbl" );
//Convert it
TablePropertiesMapping *tpMapping = new TablePropertiesMapping( m_pXmlWriter, m_document->Styles, &grid);
row1Tapx.Convert( tpMapping );
RELEASEOBJECT( tpMapping );
//convert all rows
if ( nestingLevel > 1 )
{
//It's an inner table
//only convert the cells with the given nesting level
while ( tai.iTap == nestingLevel )
{
cp = writeTableRow( cp, &grid, nestingLevel );
//?fc = m_document->FindFileCharPos(cp );
fc = m_document->m_PieceTable->FileCharacterPositions->operator []( cp );
papx = findValidPapx( fc );
tai = TableInfo( papx, m_document->nWordVersion );
}
}
else
{
//It's a outer table (nesting level 1)
//convert until the end of table is reached
while ( tai.fInTable )
{
cp = writeTableRow( cp, &grid, nestingLevel );
fc = m_document->FindFileCharPos( cp );
papx = findValidPapx( fc );
tai = TableInfo( papx, m_document->nWordVersion );
}
}
//close w:tbl
m_pXmlWriter->WriteNodeEnd( L"w:tbl" );
return cp;
}
// Builds a list that contains the width of the several columns of the table.
bool DocumentMapping::buildTableGrid(int initialCp, unsigned int nestingLevel, std::vector<short>& grid)
{
ParagraphPropertyExceptions* backup = _lastValidPapx;
std::map<short, short> mapBoundaries;
int cp = initialCp;
int fc = m_document->FindFileCharPos( cp );
ParagraphPropertyExceptions* papx = findValidPapx( fc );
TableInfo tai( papx, m_document->nWordVersion );
int fcRowEnd = findRowEndFc( cp, cp, nestingLevel );
ParagraphPropertyExceptions* papx_prev = NULL;
short max_boundary = -1;
bool fEndNestingLevel = false;
unsigned int iTap_current = 1;
while ( tai.fInTable )
{
fEndNestingLevel = false;
for ( std::vector<SinglePropertyModifier>::iterator iter = papx->grpprl->begin(); !fEndNestingLevel && iter != papx->grpprl->end(); iter++ )
{
DWORD code = iter->OpCode;
switch(iter->OpCode)
{
case sprmPFInnerTableCell:
case sprmPFInnerTtp:
{
fEndNestingLevel = ( iter->Arguments[0] == 1 ) ? (true) : (false);
}break;
case sprmOldPFInTable:
case sprmPItap:
{
iTap_current = FormatUtils::BytesToUInt32( iter->Arguments, 0, iter->argumentsSize );
}break;
default:
break;
}
}
fEndNestingLevel == (nestingLevel == iTap_current) ? fEndNestingLevel : false;
if (nestingLevel == iTap_current)
{
bool bPresent = false; //118854.doc
for ( std::vector<SinglePropertyModifier>::reverse_iterator iter = papx->grpprl->rbegin(); !bPresent && iter != papx->grpprl->rend(); iter++ )
{
//find the tDef SPRM
DWORD code = iter->OpCode;
switch(iter->OpCode)
{
case sprmTDefTable:
case sprmOldTDefTable:
{
unsigned char itcMac = iter->Arguments[0];
short boundary1, boundary2;
for (unsigned char i = 0; i < itcMac; i++)
{
boundary1 = FormatUtils::BytesToInt16( iter->Arguments + 1, i * 2 , iter->argumentsSize );
boundary2 = FormatUtils::BytesToInt16( iter->Arguments + 1, ( i + 1 ) * 2, iter->argumentsSize );
mapBoundaries.insert(std::make_pair(boundary1, 0));
mapBoundaries.insert(std::make_pair(boundary2, 0));
}
bPresent = true;
}break;
default:
break;
}
}
}
if ((nestingLevel != iTap_current && fEndNestingLevel) && !mapBoundaries.empty())
break;
//get the next papx
papx = findValidPapx( fcRowEnd );
tai = TableInfo( papx, m_document->nWordVersion );
fcRowEnd = findRowEndFc( cp, cp, nestingLevel );
if (papx_prev && papx_prev == papx )
break;//file(12).doc
papx_prev = papx;
}
if ( !mapBoundaries.empty() )
{
std::map<short, short>::iterator it = mapBoundaries.begin();
std::map<short, short>::iterator it_next = it; it_next++;
for ( ; it_next != mapBoundaries.end(); ++it_next, ++it)
{
int sz = it_next->first - it->first;
if (sz > 2)
grid.push_back(it_next->first - it->first);
}
}
_lastValidPapx = backup;
return true;
}
void DocumentMapping::AddBoundary(short boundary1, short boundary2, std::map<short, short> &boundaries)
{
if (boundary2 - boundary1 < 3)
return;
std::map<short, short>::iterator pFind = boundaries.find(boundary1);
while(true)
{
if (pFind == boundaries.end())
{
boundaries.insert(std::make_pair(boundary1, boundary2 - boundary1));
break;
}
else if (pFind->second != boundary2 - boundary1)
{
if (pFind->second > boundary2 - boundary1)
{
short new_size = boundary2 - boundary1;
boundary1 = boundary2;
boundary2 = pFind->second + pFind->first;
pFind->second = new_size;
}
else
{
boundary1 = pFind->second + pFind->first;
}
pFind = boundaries.find(boundary1);
}
else
break;
}
}
// Finds the FC of the next row end mark.
int DocumentMapping::findRowEndFc(int initialCp, int& rowEndCp, unsigned int nestingLevel )
{
int cp = initialCp;
int fc = m_document->FindFileCharPos( cp );
ParagraphPropertyExceptions* papx = findValidPapx( fc );
TableInfo tai( papx, m_document->nWordVersion );
if ( nestingLevel > 1 )
{
//Its an inner table.
//Search the "inner table trailer paragraph"
while ( ( tai.fInnerTtp == false ) && ( tai.fInTable == true ) )
{
while ( m_document->Text->at( cp ) != TextMark::ParagraphEnd )
{
cp++;
}
fc = m_document->FindFileCharPos( cp );
papx = findValidPapx( fc );
tai = TableInfo( papx, m_document->nWordVersion );
cp++;
}
}
else
{
//Its an outer table.
//Search the "table trailer paragraph"
while ( ( tai.fTtp == false ) && ( tai.fInTable == true ) )
{
while ( true )
{
if (cp >= m_document->Text->size())
break;
if (m_document->Text->at( cp ) == TextMark::CellOrRowMark)
break;
cp++;
}
fc = m_document->FindFileCharPos( cp );
papx = findValidPapx( fc );
tai = TableInfo( papx, m_document->nWordVersion );
cp++;
}
}
rowEndCp = cp;
return fc;
}
// Finds the FC of the next row end mark.
int DocumentMapping::findRowEndFc(int initialCp, unsigned int nestingLevel )
{
if ( initialCp > m_document->Text->size() - 1)
return initialCp;
int cp = initialCp;
int fc = m_document->FindFileCharPos( cp );
ParagraphPropertyExceptions* papx = findValidPapx( fc );
TableInfo tai( papx, m_document->nWordVersion );
if ( nestingLevel > 1 )
{
//Its an inner table.
//Search the "inner table trailer paragraph"
while ( ( tai.fInnerTtp == false ) && ( tai.fInTable == true ) )
{
while ( true )
{
if (cp > m_document->Text->size() - 1 )
break;
if (m_document->Text->at( cp ) == TextMark::ParagraphEnd)
break;
cp++;
}
fc = m_document->FindFileCharPos( cp );
papx = findValidPapx( fc );
tai = TableInfo( papx, m_document->nWordVersion );
cp++;
}
}
else
{
//Its an outer table.
//Search the "table trailer paragraph"
while ( ( tai.fTtp == false ) && ( tai.fInTable == true ) )
{
while (true)
{
if (cp > m_document->Text->size() - 1 )
break;
if (m_document->Text->at( cp ) == TextMark::CellOrRowMark)
break;
cp++;
}
fc = m_document->FindFileCharPos( cp );
papx = findValidPapx( fc );
tai = TableInfo( papx, m_document->nWordVersion );
cp++;
}
}
return fc;
}
/// Writes the table row that starts at the given cp value and ends at the next row end mark
int DocumentMapping::writeTableRow(int initialCp, std::vector<short>* grid, unsigned int nestingLevel)
{
int cp = initialCp;
int fc = m_document->FindFileCharPos( cp );
ParagraphPropertyExceptions* papx = findValidPapx( fc );
TableInfo tai( papx, m_document->nWordVersion );
//start w:tr
m_pXmlWriter->WriteNodeBegin( L"w:tr" );
//convert the properties
int fcRowEnd = findRowEndFc( cp, nestingLevel );
TablePropertyExceptions tapx( findValidPapx( fcRowEnd ), m_document->DataStream, m_document->nWordVersion);
std::vector<CharacterPropertyExceptions*>* chpxs = m_document->GetCharacterPropertyExceptions( fcRowEnd, fcRowEnd + 1 );
TableRowPropertiesMapping* trpMapping = new TableRowPropertiesMapping( m_pXmlWriter, *(chpxs->begin()) );
tapx.Convert( trpMapping );
RELEASEOBJECT( trpMapping );
int gridIndex = 0;
int cellIndex = 0;
if ( nestingLevel > 1 )
{
//It's an inner table.
//Write until the first "inner trailer paragraph" is reached
while ( !( ( m_document->Text->at( cp ) == TextMark::ParagraphEnd ) && ( tai.fInnerTtp ) ) && tai.fInTable )
{
cp = writeTableCell( cp, &tapx, grid, gridIndex, cellIndex, nestingLevel );
cellIndex++;
//each cell has it's own PAPX
fc = m_document->FindFileCharPos(cp );
papx = findValidPapx( fc );
tai = TableInfo( papx, m_document->nWordVersion );
}
}
else
{
//It's a outer table
//Write until the first "row end trailer paragraph" is reached
while ( !( ( m_document->Text->at( cp ) == TextMark::CellOrRowMark ) && ( tai.fTtp ) )
&& tai.fInTable )
{
cp = writeTableCell( cp, &tapx, grid, gridIndex, cellIndex, nestingLevel );
cellIndex++;
//each cell has it's own PAPX
fc = m_document->FindFileCharPos( cp );
papx = findValidPapx( fc );
tai = TableInfo( papx, m_document->nWordVersion );
}
}
//end w:tr
m_pXmlWriter->WriteNodeEnd( L"w:tr" );
//skip the row end mark
cp++;
RELEASEOBJECT( chpxs );
return cp;
}
/// Writes the table cell that starts at the given cp value and ends at the next cell end mark
int DocumentMapping::writeTableCell(int initialCp, TablePropertyExceptions* tapx, std::vector<short>* grid, int& gridIndex, int cellIndex, unsigned int nestingLevel )
{
int cp = initialCp;
int cpCellEnd = findCellEndCp( initialCp, nestingLevel );
XMLTools::CStringXmlWriter writerTcPr;
TableCellPropertiesMapping* tcpMapping = new TableCellPropertiesMapping( &writerTcPr, grid, gridIndex, cellIndex, nestingLevel );
if ( tapx != NULL )
{
tapx->Convert( tcpMapping );
}
gridIndex = gridIndex + tcpMapping->GetGridSpan();
bool bCoverCell = tcpMapping->IsCoverCell();
RELEASEOBJECT( tcpMapping );
if (bCoverCell)
{
return cpCellEnd;
}
//start w:tc
m_pXmlWriter->WriteNodeBegin( L"w:tc" );
m_pXmlWriter->WriteString(writerTcPr.GetXmlString());
//write the paragraphs of the cell
while ( cp < cpCellEnd )
{
//cp = writeParagraph(cp);
int fc = m_document->FindFileCharPos( cp );
ParagraphPropertyExceptions* papx = findValidPapx( fc );
TableInfo tai( papx, m_document->nWordVersion );
if ( tai.iTap > nestingLevel )
{
cp = writeTable( cp, tai.iTap );
}
else
{
//this PAPX is for a normal paragraph
cp = writeParagraph( cp, 0x7fffffff );
}
}
//end w:tc
m_pXmlWriter->WriteNodeEnd( L"w:tc" );
return cp;
}
int DocumentMapping::findCellEndCp(int initialCp, unsigned int nestingLevel)
{
int cpCellEnd = initialCp;
if ( nestingLevel > 1 )
{
int fc = m_document->FindFileCharPos( initialCp );
ParagraphPropertyExceptions* papx = findValidPapx( fc );
TableInfo tai( papx, m_document->nWordVersion );
while ( !tai.fInnerTableCell )
{
cpCellEnd++;
fc = m_document->FindFileCharPos( cpCellEnd );
papx = findValidPapx( fc );
tai = TableInfo( papx, m_document->nWordVersion );
}
cpCellEnd++;
}
else
{
while ( m_document->Text->at( cpCellEnd ) != TextMark::CellOrRowMark )
{
cpCellEnd++;
}
cpCellEnd++;
}
return cpCellEnd;
}
bool DocumentMapping::writeNotesReferences(int cp)
{
if ((m_document->FootnoteReferenceCharactersPlex != NULL) && (m_document->FootnoteReferenceCharactersPlex->IsCpExists(cp)))
{
FootnoteDescriptor* desc = NULL;
if (_footnoteNr < m_document->FootnoteReferenceCharactersPlex->Elements.size())
desc = dynamic_cast<FootnoteDescriptor*>(m_document->FootnoteReferenceCharactersPlex->Elements[_footnoteNr]);
if ((desc) && (false == desc->bUsed))
{
desc->bUsed = true;
m_pXmlWriter->WriteNodeBegin( L"w:footnoteReference", true );
//if (desc->aFtnIdx == 0)
//{
// m_pXmlWriter->WriteAttribute( L"w:customMarkFollows", L"1");
//}
m_pXmlWriter->WriteAttribute( L"w:id", FormatUtils::IntToWideString(_footnoteNr++ ) );
m_pXmlWriter->WriteNodeEnd( L"", true );
}
}
else if ((m_document->IndividualFootnotesPlex != NULL) && (m_document->IndividualFootnotesPlex->IsCpExists(cp - m_document->FIB->m_RgLw97.ccpText)))
{
m_pXmlWriter->WriteNodeBegin( L"w:footnoteRef", true );
m_pXmlWriter->WriteNodeEnd( L"", true );
}
else if ((m_document->EndnoteReferenceCharactersPlex != NULL) && (m_document->EndnoteReferenceCharactersPlex->IsCpExists(cp)))
{
EndnoteDescriptor* desc = dynamic_cast<EndnoteDescriptor*>(m_document->EndnoteReferenceCharactersPlex->Elements[_endnoteNr]);
if ((desc) && (false == desc->bUsed))
{
desc->bUsed = true;
m_pXmlWriter->WriteNodeBegin( L"w:endnoteReference", true );
//if (desc->aEndIdx == 0)
//{
// m_pXmlWriter->WriteAttribute( L"w:customMarkFollows", L"1");
//}
m_pXmlWriter->WriteAttribute( L"w:id", FormatUtils::IntToWideString(_endnoteNr++ ));
m_pXmlWriter->WriteNodeEnd( L"", true );
}
}
else if ((m_document->IndividualEndnotesPlex != NULL) &&
(m_document->IndividualEndnotesPlex->IsCpExists(cp - m_document->FIB->m_RgLw97.ccpAtn - m_document->FIB->m_RgLw97.ccpHdr - m_document->FIB->m_RgLw97.ccpFtn - m_document->FIB->m_RgLw97.ccpText)))
{
m_pXmlWriter->WriteNodeBegin( L"w:endnoteRef", true );
m_pXmlWriter->WriteNodeEnd( L"", true );
}
else if (false == _writeNoteRef.empty())
{
m_pXmlWriter->WriteString(_writeNoteRef);
_writeNoteRef.clear();
}
return true;
}
bool DocumentMapping::writeBookmarks(int cp)
{
bool result = true;
for (size_t b = 0; b < m_document->BookmarkStartEndCPs.size(); ++b)
{
if (m_document->BookmarkStartEndCPs[b].start == cp)
{
result = writeBookmarkStart(b);
}
if (m_document->BookmarkStartEndCPs[b].end == cp)
{
result = writeBookmarkEnd(b);
}
}
return result;
}
bool DocumentMapping::writeAnnotations(int cp)
{
bool result = true;
for (size_t i = 0; i < m_document->AnnotStartEndCPs.size(); i++)
{
if (m_document->AnnotStartEndCPs[i].start == cp)
{
int index = -1;
std::map<int, int>::iterator pFind = m_document->mapAnnotBookmarks.find(m_document->AnnotStartEndCPs[i].bookmarkId);
if (pFind == m_document->mapAnnotBookmarks.end())
{
index = _commentNr++;
m_document->mapAnnotBookmarks.insert(std::make_pair(m_document->AnnotStartEndCPs[i].bookmarkId, index ));
}
else index = pFind->second;
result = writeAnnotationStart(index);
}
if (m_document->AnnotStartEndCPs[i].end == cp)
{
int index = -1;
std::map<int, int>::iterator pFind = m_document->mapAnnotBookmarks.find(m_document->AnnotStartEndCPs[i].bookmarkId);
if (pFind == m_document->mapAnnotBookmarks.end())
{
index = _commentNr++;
m_document->mapAnnotBookmarks.insert(std::make_pair(m_document->AnnotStartEndCPs[i].bookmarkId, index ));
}
else index = pFind->second;
result = writeAnnotationEnd(index);
}
}
return result;
}
bool DocumentMapping::writePermissions(int cp)
{
bool result = true;
for (size_t i = 0; i < m_document->BookmarkProtStartEndCPs.size(); i++)
{
if (m_document->BookmarkProtStartEndCPs[i].start == cp)
{
int index = -1;
std::map<int, int>::iterator pFind = m_document->mapProtBookmarks.find(m_document->BookmarkProtStartEndCPs[i].bookmarkId);
if (pFind == m_document->mapProtBookmarks.end())
{
index = _permissionNr++;
m_document->mapProtBookmarks.insert(std::make_pair(m_document->BookmarkProtStartEndCPs[i].bookmarkId, index));
}
else index = pFind->second;
result = writePermissionStart(index, i);
}
if (m_document->BookmarkProtStartEndCPs[i].end == cp)
{
int index = -1;
std::map<int, int>::iterator pFind = m_document->mapProtBookmarks.find(m_document->BookmarkProtStartEndCPs[i].bookmarkId);
if (pFind == m_document->mapProtBookmarks.end())
{
index = _permissionNr++;
m_document->mapProtBookmarks.insert(std::make_pair(m_document->BookmarkProtStartEndCPs[i].bookmarkId, index));
}
else index = pFind->second;
result = writePermissionEnd(index);
}
}
return result;
}
bool DocumentMapping::writeBookmarkStart(short id)
{
WideString* bookmarkName = static_cast<WideString*>(m_document->BookmarkNames->operator [](id));
if ((bookmarkName != NULL) && (*bookmarkName != L"_PictureBullets"))
{
XMLTools::XMLElement bookmarkElem(L"w:bookmarkStart");
bookmarkElem.AppendAttribute(L"w:id", FormatUtils::IntToWideString(id));
bookmarkElem.AppendAttribute(L"w:name", XmlUtils::EncodeXmlString(*bookmarkName));
m_pXmlWriter->WriteString(bookmarkElem.GetXMLString());
return true;
}
return false;
}
bool DocumentMapping::writeBookmarkEnd(short id)
{
WideString* bookmarkName = static_cast<WideString*>( m_document->BookmarkNames->operator [] ( id ) );
if ( ( bookmarkName != NULL ) && ( *bookmarkName != L"_PictureBullets" ) )
{
XMLTools::XMLElement bookmarkElem( L"w:bookmarkEnd" );
bookmarkElem.AppendAttribute( L"w:id", FormatUtils::IntToWideString( id ));
m_pXmlWriter->WriteString( bookmarkElem.GetXMLString());
return true;
}
return false;
}
bool DocumentMapping::writeAnnotationStart(short id)
{
XMLTools::XMLElement bookmarkElem(L"w:commentRangeStart");
bookmarkElem.AppendAttribute(L"w:id", FormatUtils::IntToWideString(id));
m_pXmlWriter->WriteString(bookmarkElem.GetXMLString());
return true;
}
bool DocumentMapping::writeAnnotationEnd(short id)
{
XMLTools::XMLElement bookmarkElem(L"w:commentRangeEnd");
bookmarkElem.AppendAttribute(L"w:id", FormatUtils::IntToWideString(id));
m_pXmlWriter->WriteString(bookmarkElem.GetXMLString());
return true;
}
bool DocumentMapping::writePermissionStart(short id, size_t index)
{
XMLTools::XMLElement bookmarkElem(L"w:permStart");
bookmarkElem.AppendAttribute(L"w:id", FormatUtils::IntToWideString(id));
ProtInfoBookmark *prot = static_cast<ProtInfoBookmark*>(m_document->BkmkProt->operator[](index));
BookmarkFirst *prot_base = static_cast<BookmarkFirst*>(m_document->BookmarkProtStartPlex->GetStruct(index));
if (prot_base && prot_base->fCol)
{
bookmarkElem.AppendAttribute(L"w:colFirst", FormatUtils::IntToWideString(prot_base->itcFirst));
bookmarkElem.AppendAttribute(L"w:colLast", FormatUtils::IntToWideString(prot_base->itcLim - 1));
}
if (prot && (prot->uidSel == 0 || prot->uidSel > 0xfff0))
{
switch (prot->uidSel)
{
case 0xFFFF: bookmarkElem.AppendAttribute(L"w:edGrp", L"everyone");
case 0xFFFE: bookmarkElem.AppendAttribute(L"w:edGrp", L"administrators");
case 0xFFFD: bookmarkElem.AppendAttribute(L"w:edGrp", L"contributors");
case 0xFFFC: bookmarkElem.AppendAttribute(L"w:edGrp", L"owners");
case 0xFFFB: bookmarkElem.AppendAttribute(L"w:edGrp", L"editors");
case 0xFFFA: bookmarkElem.AppendAttribute(L"w:edGrp", L"current");
case 0x0000: bookmarkElem.AppendAttribute(L"w:edGrp", L"none");
}
}
if (prot && (prot->uidSel > 0 && prot->uidSel < 0xfff0))
{
WideString* user = static_cast<WideString*>(m_document->BkmkProtUser->operator[](prot->uidSel - 1));
if (user && false == user->empty())
bookmarkElem.AppendAttribute(L"w:ed", *user);
}
m_pXmlWriter->WriteString(bookmarkElem.GetXMLString());
return true;
}
bool DocumentMapping::writePermissionEnd(short id)
{
XMLTools::XMLElement bookmarkElem(L"w:permEnd");
bookmarkElem.AppendAttribute(L"w:id", FormatUtils::IntToWideString(id));
m_pXmlWriter->WriteString(bookmarkElem.GetXMLString());
return true;
}
bool DocumentMapping::isSpecial(CharacterPropertyExceptions* chpx)
{
if (!chpx) return false;
if (!chpx->grpprl) return false;
for (std::vector<SinglePropertyModifier>::iterator iter = chpx->grpprl->begin(); iter != chpx->grpprl->end(); ++iter)
{
if ((sprmCPicLocation == iter->OpCode) || (sprmCHsp == iter->OpCode)) // PICTURE
{
return true;
}
else if ( sprmCSymbol == iter->OpCode ||
sprmOldCSymbol == iter->OpCode) // SYMBOL
{
return true;
}
else if ( sprmOldCFSpec == iter->OpCode ||
sprmCFSpec == iter->OpCode) // SPECIAL OBJECT
{
return ((0 != iter->Arguments[0]) ? true : false);
}
}
return false;
}
Symbol DocumentMapping::getSymbol(const CharacterPropertyExceptions* chpx)
{
Symbol ret;
for (std::vector<SinglePropertyModifier>::const_iterator iter = chpx->grpprl->begin(); iter != chpx->grpprl->end(); ++iter)
{
if (DocFileFormat::sprmCSymbol == iter->OpCode)
{
short fontIndex = FormatUtils::BytesToInt16( iter->Arguments, 0, iter->argumentsSize );
short code = FormatUtils::BytesToInt16( iter->Arguments, 2, iter->argumentsSize );
FontFamilyName* ffn = static_cast<FontFamilyName*>( m_document->FontTable->operator [] ( fontIndex ) );
ret.FontName = ffn->xszFtn;
ret.HexValue = FormatUtils::IntToFormattedWideString( code, L"%04X" );
break;
}
else if (DocFileFormat::sprmOldCSymbol == iter->OpCode)
{
short fontIndex = FormatUtils::BytesToInt16( iter->Arguments, 0, iter->argumentsSize ) ;
short code = FormatUtils::BytesToUChar( iter->Arguments, 2, iter->argumentsSize );
FontFamilyName* ffn = static_cast<FontFamilyName*>( m_document->FontTable->operator [] ( fontIndex ) );
ret.FontName = ffn->xszFtn;
ret.HexValue = L"f0" + FormatUtils::IntToFormattedWideString( code, L"%02x" );//-123 - ShortToFormattedWideString
break;
}
}
if (ret.HexValue.length() > 4)
{
ret.HexValue = ret.HexValue.substr(ret.HexValue.length() - 4, 4);
}
return ret;
}
/// Finds the SEPX that is valid for the given CP.
SectionPropertyExceptions* DocumentMapping::findValidSepx (int cp)
{
SectionPropertyExceptions* ret = NULL;
if (!m_document->AllSepx)
{
return ret;
}
try
{
ret = m_document->AllSepx->operator [](cp);
_lastValidSepx = ret;
}
///!!!TODO!!!
catch ( ... )
{
//there is no SEPX at this position,
//so the previous SEPX is valid for this cp
int lastKey = m_document->SectionPlex->CharacterPositions[1];
for (std::map<int, SectionPropertyExceptions*>::iterator iter = m_document->AllSepx->begin(); iter != m_document->AllSepx->end(); ++iter)
{
if ( ( cp > lastKey ) && ( cp < iter->first ) )
{
ret = m_document->AllSepx->operator []( lastKey );
break;
}
else
{
lastKey = iter->first;
}
}
}
return ret;
}
// Searches the given vector for the next FieldEnd character.
int DocumentMapping::searchNextTextMark (std::vector<wchar_t>* chars, int initialCp, wchar_t mark)
{
int ret = initialCp;
size_t count = chars->size();
for (size_t i = initialCp; i < count; ++i)
{
if (chars->at(i) == mark)
{
ret = i;
break;
}
}
return ret;
}
}