This commit is contained in:
Green
2025-01-24 04:26:44 +03:00
parent bd76adc97f
commit f057a16bc1
10 changed files with 270 additions and 39 deletions

View File

@ -50,6 +50,7 @@ SOURCES += \
HwpDoc/HwpFileHeader.cpp \
HwpDoc/OLEdoc/CompoundFile.cpp \
HwpDoc/OLEdoc/DirectoryEntry.cpp \
HwpDoc/Paragraph/CCtrlField.cpp \
HwpDoc/Paragraph/CapParagraph.cpp \
HwpDoc/Paragraph/CellParagraph.cpp \
HwpDoc/Paragraph/CharShape.cpp \
@ -134,6 +135,7 @@ HEADERS += \
HwpDoc/OLEdoc/DirectoryEntry.h \
HwpDoc/OLEdoc/Sector.h \
HwpDoc/OLEdoc/SectorType.h \
HwpDoc/Paragraph/CCtrlField.h \
HwpDoc/Paragraph/CapParagraph.h \
HwpDoc/Paragraph/CellParagraph.h \
HwpDoc/Paragraph/CharShape.h \

View File

@ -261,7 +261,14 @@ void CConverter2OOXML::Close()
oRelsWriter.WriteStringUTF8(L"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">");
for (const TRelationship& oRelationship : m_arRelationships)
oRelsWriter.WriteStringUTF8(L"<Relationship Id=\"" + oRelationship.m_wsID + L"\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/" + oRelationship.m_wsType + L"\" Target=\"" + oRelationship.m_wsTarget + L"\"/>");
{
oRelsWriter.WriteStringUTF8(L"<Relationship Id=\"" + oRelationship.m_wsID + L"\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/" + oRelationship.m_wsType + L"\" Target=\"" + oRelationship.m_wsTarget + L'\"');
if (L"hyperlink" == oRelationship.m_wsType)
oRelsWriter.WriteStringUTF8(L" TargetMode=\"External\"/>");
else
oRelsWriter.WriteStringUTF8(L"/>");
}
oRelsWriter.WriteStringUTF8(L"</Relationships>");
@ -388,6 +395,68 @@ void CConverter2OOXML::WriteNote(const CCtrlNote* pNote, short shParaShapeID, NS
oBuilder.WriteString(L"</w:r>");
}
void CConverter2OOXML::WriteField(const CCtrlField* pShape, short shParaShapeID, NSStringUtils::CStringBuilder& oBuilder, TConversionState& oState)
{
if (nullptr == pShape)
return;
switch (pShape->GetType())
{
case EFieldType::Hyperlink:
{
HWP_STRING sCommand = pShape->GetCommand();
if (sCommand.empty())
break;
sCommand = sCommand.substr(0, sCommand.find(L';'));
size_t unFound = sCommand.find(L'\\');
while (HWP_STRING::npos != unFound)
{
sCommand.erase(unFound, 1);
unFound = sCommand.find(L'\\', unFound);
}
const HWP_STRING wsID = AddRelationship(L"hyperlink", sCommand);
OpenParagraph(shParaShapeID, oBuilder, oState);
oBuilder.WriteString(L"<w:hyperlink r:id=\"" + wsID + L"\">");
oState.m_mOpenField.insert(std::make_pair(pShape->GetInstanceID(), pShape));
break;
}
case EFieldType::HyperlinkClosing:
{
oBuilder.WriteString(L"</w:hyperlink>");
break;
}
//TODO:: как-будто хочется определить тип закрывающей field на этапе парса hwpx
case EFieldType::Unknown:
{
std::map<unsigned int, const CCtrlField*>::const_iterator itFound = oState.m_mOpenField.find(pShape->GetInstanceID());
if (oState.m_mOpenField.cend() != itFound)
{
switch (itFound->second->GetType())
{
case EFieldType::Hyperlink:
{
oBuilder.WriteString(L"</w:hyperlink>");
break;
}
default:
break;
}
}
break;
}
}
}
void CConverter2OOXML::WriteParagraph(const CHWPPargraph* pParagraph, NSStringUtils::CStringBuilder& oBuilder, TConversionState& oState)
{
if (nullptr == pParagraph)
@ -468,6 +537,11 @@ void CConverter2OOXML::WriteParagraph(const CHWPPargraph* pParagraph, NSStringUt
WriteAutoNumber((const CCtrlAutoNumber*)pCtrl, pParagraph->GetShapeID(), ((const CParaText*)pCtrl)->GetCharShapeID(), oBuilder, oState);
break;
}
case ECtrlObjectType::Field:
{
WriteField((const CCtrlField*)pCtrl, pParagraph->GetShapeID(), oBuilder, oState);
break;
}
default:
break;
}
@ -1172,6 +1246,9 @@ bool CConverter2OOXML::SaveSVGFile(const HWP_STRING& sSVG, HWP_STRING& sFileName
pSvgReader->SetTempDirectory(m_sTempDirectory);
pSvgReader->DrawOnRenderer(pGrRenderer, 0, 0, dWidth, dHeight);
sFileName = sFileName.substr(0, sFileName.find(L'.'));
sFileName += L".png";
oFrame.SaveFile(m_sTempDirectory + L"/word/media/" + sFileName, 4);
oFrame.put_Data(NULL);

View File

@ -1,9 +1,9 @@
#ifndef CONVERTER2OOXML_H
#define CONVERTER2OOXML_H
#include "../HWPFile.h"
#include "../../../DesktopEditor/common/StringBuilder.h"
#include "../Paragraph/CCtrlField.h"
#include "../Paragraph/CtrlAutoNumber.h"
#include "../Paragraph/CtrlSectionDef.h"
#include "../Paragraph/CtrlShapeVideo.h"
@ -13,6 +13,8 @@
#include "../Paragraph/CtrlShapeOle.h"
#include "../Paragraph/CtrlEqEdit.h"
#include "../Paragraph/CtrlTable.h"
#include "../Paragraph/CtrlNote.h"
#include "../Paragraph/TblCell.h"
#include "FootnoteConverter.h"
@ -44,6 +46,8 @@ struct TConversionState
None
} m_eBreakType;
std::map<unsigned int, const CCtrlField*> m_mOpenField;
TConversionState();
};
@ -139,6 +143,9 @@ class CConverter2OOXML
void WriteNote(const CCtrlNote* pNote, short shParaShapeID, NSStringUtils::CStringBuilder& oBuilder, TConversionState& oState);
void WriteField(const CCtrlField* pHyperlink, short shParaShapeID, NSStringUtils::CStringBuilder& oBuilder, TConversionState& oState);
void CloseField(const CCtrlField* pHyperlink, NSStringUtils::CStringBuilder& oBuilder, TConversionState& oState);
HWP_STRING AddRelationship(const HWP_STRING& wsType, const HWP_STRING& wsTarget);
void AddContentType(const HWP_STRING& wsName, const HWP_STRING& wsType);
void AddDefaultContentType(const HWP_STRING& wsName);

View File

@ -48,48 +48,65 @@ ELang GetLang(int nValue)
EUnderline GetUnderline(int nValue)
{
switch(static_cast<EUnderline>(nValue))
SWITCH(EUnderline, nValue)
{
case EUnderline::NONE:
case EUnderline::BOTTOM:
case EUnderline::CENTER:
case EUnderline::TOP:
return static_cast<EUnderline>(nValue);
default:
return EUnderline::NONE;
DEFAULT(EUnderline::NONE);
CASE(EUnderline::BOTTOM);
CASE(EUnderline::CENTER);
CASE(EUnderline::TOP);
}
}
EUnderline GetUnderline(const HWP_STRING& sValue)
{
IF_STRING_IN_ENUM(BOTTOM, sValue, EUnderline);
ELSE_IF_STRING_IN_ENUM(CENTER, sValue, EUnderline);
ELSE_IF_STRING_IN_ENUM(TOP, sValue, EUnderline);
ELSE_STRING_IN_ENUM(NONE, EUnderline);
}
EOutline GetOutline(int nValue)
{
switch(static_cast<EOutline>(nValue))
SWITCH(EOutline, nValue)
{
case EOutline::NONE:
case EOutline::SOLID:
case EOutline::DOTTED:
case EOutline::BOLD:
case EOutline::DASHED:
case EOutline::DASH_DOT:
case EOutline::DASH_2DOT:
return static_cast<EOutline>(nValue);
default:
return EOutline::NONE;
DEFAULT(EOutline::NONE);
CASE(EOutline::SOLID);
CASE(EOutline::DOTTED);
CASE(EOutline::BOLD);
CASE(EOutline::DASHED);
CASE(EOutline::DASH_DOT);
CASE(EOutline::DASH_2DOT);
}
}
EOutline GetOutline(const HWP_STRING& sValue)
{
IF_STRING_IN_ENUM(SOLID, sValue, EOutline);
ELSE_IF_STRING_IN_ENUM(DOTTED, sValue, EOutline);
ELSE_IF_STRING_IN_ENUM(BOLD, sValue, EOutline);
ELSE_IF_STRING_IN_ENUM(DASHED, sValue, EOutline);
ELSE_IF_STRING_IN_ENUM(DASH_DOT, sValue, EOutline);
ELSE_IF_STRING_IN_ENUM(DASH_2DOT, sValue, EOutline);
ELSE_STRING_IN_ENUM(NONE, EOutline);
}
EShadow GetShadow(int nValue)
{
switch(static_cast<EShadow>(nValue))
SWITCH(EShadow, nValue)
{
case EShadow::NONE:
case EShadow::DISCRETE:
case EShadow::CONTINUOUS:
return static_cast<EShadow>(nValue);
default:
return EShadow::NONE;
DEFAULT(EShadow::NONE);
CASE(EShadow::DISCRETE);
CASE(EShadow::CONTINUOUS);
}
}
EShadow GetShadow(const HWP_STRING& sValue)
{
IF_STRING_IN_ENUM(DISCRETE, sValue, EShadow);
ELSE_IF_STRING_IN_ENUM(CONTINUOUS, sValue, EShadow);
ELSE_STRING_IN_ENUM(NONE, EShadow);
}
void CHWPRecordCharShape::ReadContainerData(CXMLNode& oNode, short arValues[], int nDefaultValue)
{
arValues[(int)ELang::HANGUL] = oNode.GetAttributeInt(L"hangul", nDefaultValue);
@ -231,7 +248,7 @@ CHWPRecordCharShape::CHWPRecordCharShape(CHWPDocInfo& oDocInfo, CXMLNode& oNode,
ReadContainerData(oChild, m_arCharOffset);
else if (L"hh:underline" == oChild.GetName())
{
m_eUnderline = GetUnderline(oChild.GetAttributeInt(L"type"));
m_eUnderline = GetUnderline(oChild.GetAttribute(L"type"));
m_eUnderLineShape = GetLineStyle1(oChild.GetAttribute(L"shape"));
m_nUnderlineColor = oChild.GetAttributeColor(L"color");
}
@ -245,7 +262,7 @@ CHWPRecordCharShape::CHWPRecordCharShape(CHWPDocInfo& oDocInfo, CXMLNode& oNode,
}
else if (L"hh:outline" == oChild.GetName())
{
m_eOutline = GetOutline(oChild.GetAttributeInt(L"type"));
m_eOutline = GetOutline(oChild.GetAttribute(L"type"));
}
else if (L"hh:shadow" == oChild.GetName())
{

View File

@ -13,6 +13,7 @@
#include "../Paragraph/CtrlSectionDef.h"
#include "../Paragraph/CtrlTable.h"
#include "../Paragraph/CtrlEmpty.h"
#include "../Paragraph/CCtrlField.h"
namespace HWP
{
@ -77,6 +78,11 @@ CCtrl* CHWPRecordCtrlHeader::Parse(int nTagNum, int nLevel, int nSize, CHWPStrea
pCtrl = new CCtrlPageNumPos(sCtrlID, nSize - oBuffer.GetDistanceToLastPos(), oBuffer, 0, nVersion);
pCtrl->SetFullFilled();
}
else if (L"klh%" == sCtrlID)
{
pCtrl = new CCtrlField(sCtrlID, nSize - oBuffer.GetDistanceToLastPos(), oBuffer, 0, nVersion);
pCtrl->SetFullFilled();
}
// else if (L"klh%" == sCtrlID || // hyperlink
// L"frx%" == sCtrlID || // FIELD_CROSSREF
// L"knu%" == sCtrlID || // FIELD_UNKNOWN

View File

@ -12,6 +12,7 @@
#include "../Paragraph/CtrlGeneralShape.h"
#include "../Paragraph/CtrlTable.h"
#include "../Paragraph/CtrlEqEdit.h"
#include "../Paragraph/CCtrlField.h"
#include <regex>
@ -36,6 +37,7 @@ LIST<CCtrl*> CHWPRecordParaText::Parse(int nTagNum, int nLevel, int nSize, CHWPS
return LIST<CCtrl*>();
}
//TODO:: перейти на обычный проход по символам
std::wregex oRegex(L"([\\u0000-\\u001f]|.{2}[\\u0000-\u0017]{4})"); // [\\u0000\\u000a\\u000d\\u0018-\\u001f]|[\\u0001\\u0002-\\u0009\\u000b-\\u000c\\u000e-\\u0017].{6}[\\u0001\\u0002-\\u0009\\u000b-\\u000c\\u000e-\\u0017]
std::wsregex_iterator itCurrent(sText.begin(), sText.end(), oRegex);
std::wsregex_iterator itEnd = std::wsregex_iterator();
@ -51,7 +53,7 @@ LIST<CCtrl*> CHWPRecordParaText::Parse(int nTagNum, int nLevel, int nSize, CHWPS
do { \
if (!sCurrentText.empty()) \
{ \
arParas.push_back(new CParaText(L"____", sCurrentText, nPrevIndex)); \
arParas.push_back(new CParaText(L"____", sCurrentText, nPrevIndex + 1)); \
sCurrentText.clear(); \
}} while (false)
@ -69,9 +71,6 @@ LIST<CCtrl*> CHWPRecordParaText::Parse(int nTagNum, int nLevel, int nSize, CHWPS
{
case 0x00:
case 0x02:
case 0x13:
// case 0x03:
// case 0x04:
// case 0x17:
// case 0x19:
{
@ -79,13 +78,9 @@ LIST<CCtrl*> CHWPRecordParaText::Parse(int nTagNum, int nLevel, int nSize, CHWPS
break;
}
case 0x03:
{
UPDATE_CURRENT_TEXT();
break;
}
case 0x04:
{
bEnd = true;
UPDATE_CURRENT_TEXT();
break;
}
case 0x08:
@ -147,6 +142,9 @@ LIST<CCtrl*> CHWPRecordParaText::Parse(int nTagNum, int nLevel, int nSize, CHWPS
sType[2] = (sInfo[1] & 0xFF);
sType[3] = ((sInfo[1] >> 8) & 0xFF);
if (0x00 == sType[3])
sType[3] = L' ';
//TODO:: более подробно разобраться в данном моменте
if (L"daeh" == sType ||
L"tood" == sType)
@ -170,6 +168,9 @@ LIST<CCtrl*> CHWPRecordParaText::Parse(int nTagNum, int nLevel, int nSize, CHWPS
arParas.push_back(new CCtrlTable(sType));
else if (L"deqe" == sType)
arParas.push_back(new CCtrlEqEdit(sType));
else if (L"klh%" == sType ||
L"klh " == sType)
arParas.push_back(new CCtrlField(sType));
}
nPrevIndex = itCurrent->position() + itCurrent->length();

View File

@ -0,0 +1,78 @@
#include "CCtrlField.h"
namespace HWP
{
CCtrlField::CCtrlField(const HWP_STRING& sCtrlID)
: CCtrl(sCtrlID), m_eType(EFieldType::Unknown)
{
if (L"klh%" == sCtrlID)
m_eType = EFieldType::Hyperlink;
else if (L"klh " == sCtrlID)
m_eType = EFieldType::HyperlinkClosing;
}
CCtrlField::CCtrlField(const HWP_STRING& sCtrlID, int nSize, CHWPStream& oBuffer, int nOff, int nVersion)
: CCtrl(sCtrlID), m_eType(EFieldType::Unknown)
{
if (L"klh%" == sCtrlID)
m_eType = EFieldType::Hyperlink;
else if (L"klh " == sCtrlID)
m_eType = EFieldType::HyperlinkClosing;
oBuffer.ReadInt(m_nProperty);
oBuffer.ReadByte(m_chEtcProperty);
oBuffer.ReadString(m_sCommand, EStringCharacter::UTF16);
oBuffer.ReadInt(m_nInstanceID);
}
CCtrlField::CCtrlField(const HWP_STRING& sCtrlID, CXMLNode& oNode, int nVersion)
: CCtrl(sCtrlID), m_eType(EFieldType::Unknown)
{
if (L"hp:fieldBegin" == oNode.GetName())
{
HWP_STRING sType = oNode.GetAttribute(L"type");
if (sType == L"HYPERLINK")
m_eType = EFieldType::Hyperlink;
m_nInstanceID = oNode.GetAttributeInt(L"fieldid");
for (CXMLNode& oChild : oNode.GetChild(L"hp:parameters").GetChilds(L"hp:stringParam"))
{
if (L"Command" == oChild.GetAttribute(L"name"))
m_sCommand = oChild.GetText();
}
for (CXMLNode& oChild : oNode.GetChild(L"hp:parameters").GetChilds(L"hp:integerParam"))
{
if (L"Prop" == oChild.GetAttribute(L"name"))
m_chEtcProperty = stoi(oChild.GetText());
}
}
else if (L"hp:fieldEnd" == oNode.GetName())
{
m_nInstanceID = oNode.GetAttributeInt(L"fieldid");
}
}
ECtrlObjectType CCtrlField::GetCtrlType() const
{
return ECtrlObjectType::Field;
}
int CCtrlField::GetInstanceID() const
{
return m_nInstanceID;
}
EFieldType CCtrlField::GetType() const
{
return m_eType;
}
HWP_STRING CCtrlField::GetCommand() const
{
return m_sCommand;
}
}

View File

@ -0,0 +1,38 @@
#ifndef CCTRLFIELD_H
#define CCTRLFIELD_H
#include "Ctrl.h"
#include "../HWPStream.h"
namespace HWP
{
enum class EFieldType
{
Hyperlink,
HyperlinkClosing,
Unknown
};
class CCtrlField : public CCtrl
{
int m_nProperty;
HWP_BYTE m_chEtcProperty;
HWP_STRING m_sCommand;
int m_nInstanceID;
EFieldType m_eType;
public:
CCtrlField(const HWP_STRING& sCtrlID);
CCtrlField(const HWP_STRING& sCtrlID, int nSize, CHWPStream& oBuffer, int nOff, int nVersion);
CCtrlField(const HWP_STRING& sCtrlID, CXMLNode& oNode, int nVersion);
ECtrlObjectType GetCtrlType() const override;
int GetInstanceID() const;
EFieldType GetType() const;
HWP_STRING GetCommand() const;
};
}
#endif // CCTRLFIELD_H

View File

@ -6,6 +6,7 @@
#include "CtrlNewNumber.h"
#include "CtrlNote.h"
#include "CtrlPageNumPos.h"
#include "CCtrlField.h"
namespace HWP
{
@ -67,6 +68,9 @@ CCtrl* CCtrl::GetCtrl(CXMLNode& oNode, int nVersion)
return new CCtrlNewNumber(L"onwn", oNode, nVersion);
else if (L"hp:pageNum" == oNode.GetName())
return new CCtrlPageNumPos(L"pngp", oNode, nVersion);
else if (L"hp:fieldBegin" == oNode.GetName() ||
L"hp:fieldEnd" == oNode.GetName())
return new CCtrlField(L"", oNode, nVersion);
return nullptr;
}

View File

@ -22,6 +22,7 @@ enum class ECtrlObjectType
Table,
ParaText,
Common,
Field,
Empty
};