From c4bf58282ce95b64edf8384add47db95bfe4196a Mon Sep 17 00:00:00 2001 From: "Elena.Subbotina" Date: Wed, 20 Apr 2022 13:26:56 +0300 Subject: [PATCH] rtf formfield, fix odt fields --- .../src/docx/docx_conversion_context.cpp | 2 +- .../src/odf/paragraph_elements.cpp | 70 +++++++++++----- .../source/DestinationCommand.cpp | 60 +++++++++++++- .../RtfFormatLib/source/DestinationCommand.h | 15 ++++ .../RtfFormatLib/source/RtfDefine.h | 2 + .../RtfFormatLib/source/RtfField.cpp | 80 ++++++++++++++++++- .../RtfFormatLib/source/RtfField.h | 45 ++++++++++- 7 files changed, 247 insertions(+), 27 deletions(-) diff --git a/ASCOfficeOdfFile/src/docx/docx_conversion_context.cpp b/ASCOfficeOdfFile/src/docx/docx_conversion_context.cpp index c970df4098..01f317d164 100644 --- a/ASCOfficeOdfFile/src/docx/docx_conversion_context.cpp +++ b/ASCOfficeOdfFile/src/docx/docx_conversion_context.cpp @@ -1284,7 +1284,7 @@ void docx_conversion_context::process_section(std::wostream & strm, odf_reader:: if (!col) continue; double percent = col->style_rel_width_ ? col->style_rel_width_->get_value() : 0; - if (percent > 32767) + if (percent > 0x7FFE) { //auto break; diff --git a/ASCOfficeOdfFile/src/odf/paragraph_elements.cpp b/ASCOfficeOdfFile/src/odf/paragraph_elements.cpp index 5c44a6e3e3..dd7e6d7e81 100644 --- a/ASCOfficeOdfFile/src/odf/paragraph_elements.cpp +++ b/ASCOfficeOdfFile/src/odf/paragraph_elements.cpp @@ -1558,20 +1558,30 @@ void text_drop_down::docx_convert(oox::docx_conversion_context & Context) std::wostream & strm = Context.output_stream(); Context.finish_run(); - strm << L""; + //strm << L""; - strm << L""; + //strm << L""; + //for (size_t i = 0; i < content_.size(); i++) + //{ + // content_[i]->docx_convert(Context); + //} + //strm << L""; + + //strm << L""; + //strm << L"FORMDROPDOWN"; + //strm << L""; + //strm << L"" << text_ << L""; + //strm << L""; + + _UINT32 id = (_UINT32)this; + strm << L""; for (size_t i = 0; i < content_.size(); i++) - { - content_[i]->docx_convert(Context); - } - strm << L""; - - strm << L""; - strm << L"FORMDROPDOWN"; - strm << L""; + { + content_[i]->docx_convert(Context); + } + strm << L""; strm << L"" << text_ << L""; - strm << L""; + strm << L""; } //------------------------------------------------------------------------------------------------------------------- const wchar_t * text_label::ns = L"text"; @@ -1585,7 +1595,7 @@ void text_label::docx_convert(oox::docx_conversion_context & Context) { std::wostream & strm = Context.output_stream(); - strm << L""; + strm << L""; } //------------------------------------------------------------------------------------------------------------------- const wchar_t * sheet_name::ns = L"text"; @@ -2329,19 +2339,37 @@ void field_fieldmark::docx_convert(oox::docx_conversion_context & Context) std::wostream & strm = Context.output_stream(); Context.finish_run(); - strm << L""; + //strm << L""; - strm << L""; + //strm << L""; + //for (size_t i = 0; i < field_params_.size(); i++) + //{ + // field_params_[i]->docx_convert(Context); + //} + //strm << L""; + + //strm << L""; + //strm << L"FORMDROPDOWN"; + //strm << L""; + //strm << L""; + + _UINT32 id = (_UINT32)this; + std::wstring text_; + strm << L""; for (size_t i = 0; i < field_params_.size(); i++) { - field_params_[i]->docx_convert(Context); - } - strm << L""; + field_param* param = dynamic_cast(field_params_[i].get()); + if (!param) continue; + + strm << L"field_value_.get_value_or(L"")) + << L"\" w:displayText=\"" << XmlUtils::EncodeXmlString(param->field_value_.get_value_or(L"")) << L"\"/>"; - strm << L""; - strm << L"FORMDROPDOWN"; - strm << L""; - strm << L""; + if (text_.empty()) + text_ = param->field_value_.get_value_or(L""); + } + strm << L""; + strm << L"" << XmlUtils::EncodeXmlString(text_) << L""; + strm << L""; } else if (std::wstring::npos != field_type_->find(L"FORMTEXT")) { diff --git a/ASCOfficeRtfFile/RtfFormatLib/source/DestinationCommand.cpp b/ASCOfficeRtfFile/RtfFormatLib/source/DestinationCommand.cpp index f99079b224..b188336924 100644 --- a/ASCOfficeRtfFile/RtfFormatLib/source/DestinationCommand.cpp +++ b/ASCOfficeRtfFile/RtfFormatLib/source/DestinationCommand.cpp @@ -1752,9 +1752,7 @@ bool RtfFieldReader::ExecuteCommand(RtfDocument& oDocument, RtfReader& oReader, m_oField.m_pInsert = oNewFieldInst; } } - else if ( "datafield" == sCommand ) - Skip( oDocument, oReader ); - else if ( "fldrslt" == sCommand ) + else if ( "fldrslt" == sCommand ) { RtfFieldInstPtr oNewFieldInst = RtfFieldInstPtr(new RtfFieldInst()); oNewFieldInst->m_oCharProperty = oReader.m_oState->m_oCharProp; @@ -1783,6 +1781,20 @@ bool RtfFieldInstReader::ExecuteCommand(RtfDocument& oDocument, RtfReader& oRead return true; if( "fldrslt" == sCommand ) return true; + else if ("formfield" == sCommand) + { + RtfFormFieldPtr oNewFormField = RtfFormFieldPtr(new RtfFormField()); + + RtfFormFieldReader oFormFieldReader(*oNewFormField.get()); + StartSubReader(oFormFieldReader, oDocument, oReader); + + if (oNewFormField->IsValid()) + { + m_oFieldInst.m_pFormField = oNewFormField; + } + } + else if ("ffdeftext" == sCommand) + Skip(oDocument, oReader); else { RtfCharPropsCommand::ExecuteCommand( oDocument, oReader, sCommand, hasParameter, parameter, &m_oFieldInst.m_oCharProperty ); @@ -1790,6 +1802,48 @@ bool RtfFieldInstReader::ExecuteCommand(RtfDocument& oDocument, RtfReader& oRead return RtfParagraphPropDestination::ExecuteCommand( oDocument, oReader, (*this), sCommand, hasParameter, parameter ); } } +void RtfFormFieldReader::ExecuteText(RtfDocument& oDocument, RtfReader& oReader, std::wstring sText) +{ + if (is_name == m_eInternalState) m_oFormField.name += sText; + else if (is_deftext == m_eInternalState) m_oFormField.deftext += sText; + else if (is_datafield == m_eInternalState) m_oFormField.datafield += sText; + else if (is_format == m_eInternalState) m_oFormField.format += sText; + else if (is_helptext == m_eInternalState) m_oFormField.helptext += sText; + else if (is_stattext == m_eInternalState) m_oFormField.stattext += sText; + else if (is_entrymcr == m_eInternalState) m_oFormField.entrymcr += sText; + else if (is_exitmcr == m_eInternalState) m_oFormField.exitmcr += sText; + else if (is_list == m_eInternalState) m_oFormField.list.push_back(sText); +} +bool RtfFormFieldReader::ExecuteCommand(RtfDocument& oDocument, RtfReader& oReader, std::string sCommand, bool hasParameter, int parameter) +{ + if ("formfield" == sCommand) + return true; + + m_eInternalState = is_none; + if ("datafield" == sCommand) m_eInternalState = is_datafield; + else if ("ffname" == sCommand) m_eInternalState = is_name; + else if ("ffdeftext" == sCommand) m_eInternalState = is_deftext; + else if ("ffformat" == sCommand) m_eInternalState = is_format; + else if ("ffhelptext" == sCommand) m_eInternalState = is_helptext; + else if ("ffstattext" == sCommand) m_eInternalState = is_stattext; + else if ("ffentrymcr" == sCommand) m_eInternalState = is_entrymcr; + else if ("ffexitmcr" == sCommand) m_eInternalState = is_exitmcr; + else if ("ffl" == sCommand) m_eInternalState = is_list; + COMMAND_RTF_INT("fftype", m_oFormField.type, sCommand, hasParameter, parameter) + COMMAND_RTF_INT("ffownhelp", m_oFormField.ownhelp, sCommand, hasParameter, parameter) + COMMAND_RTF_INT("ffownstat", m_oFormField.ownstat, sCommand, hasParameter, parameter) + COMMAND_RTF_INT("ffprot", m_oFormField.prot, sCommand, hasParameter, parameter) + COMMAND_RTF_INT("ffsize", m_oFormField.sizeCheckBox, sCommand, hasParameter, parameter) + COMMAND_RTF_INT("fftypetx", m_oFormField.typetx, sCommand, hasParameter, parameter) + COMMAND_RTF_INT("ffrecalc", m_oFormField.recalc, sCommand, hasParameter, parameter) + COMMAND_RTF_INT("ffhaslistbox", m_oFormField.haslistbox, sCommand, hasParameter, parameter) + COMMAND_RTF_INT("ffmaxlen", m_oFormField.maxlen, sCommand, hasParameter, parameter) + COMMAND_RTF_INT("ffhps", m_oFormField.hps, sCommand, hasParameter, parameter) + COMMAND_RTF_INT("ffdefres", m_oFormField.defres, sCommand, hasParameter, parameter) + COMMAND_RTF_INT("ffres", m_oFormField.res, sCommand, hasParameter, parameter) + + return true; +} bool RtfOleBinReader::ExecuteCommand(RtfDocument& oDocument, RtfReader& oReader, std::string sCommand, bool hasParameter, int parameter) { if ( "objdata" == sCommand ) diff --git a/ASCOfficeRtfFile/RtfFormatLib/source/DestinationCommand.h b/ASCOfficeRtfFile/RtfFormatLib/source/DestinationCommand.h index 0baa264dba..30a760161b 100644 --- a/ASCOfficeRtfFile/RtfFormatLib/source/DestinationCommand.h +++ b/ASCOfficeRtfFile/RtfFormatLib/source/DestinationCommand.h @@ -2652,7 +2652,22 @@ public: m_oParPropDest.Finalize(oReader); } }; +class RtfFormFieldReader : public RtfAbstractReader +{ +public: + RtfFormFieldReader(RtfFormField& oFormField) : m_oFormField(oFormField) {} + + bool ExecuteCommand(RtfDocument& oDocument, RtfReader& oReader, std::string sCommand, bool hasParameter, int parameter); + void RtfFormFieldReader::ExecuteText(RtfDocument& oDocument, RtfReader& oReader, std::wstring sText); +private: + enum _InternalState { + is_none, is_name, is_datafield, is_deftext, is_format, is_helptext, is_stattext, is_entrymcr, is_exitmcr, is_list + }; + + _InternalState m_eInternalState; + RtfFormField& m_oFormField; +}; class RtfFieldInstReader : public RtfAbstractReader, public RtfParagraphPropDestination { diff --git a/ASCOfficeRtfFile/RtfFormatLib/source/RtfDefine.h b/ASCOfficeRtfFile/RtfFormatLib/source/RtfDefine.h index b88dc5215b..bc2f6108dd 100644 --- a/ASCOfficeRtfFile/RtfFormatLib/source/RtfDefine.h +++ b/ASCOfficeRtfFile/RtfFormatLib/source/RtfDefine.h @@ -87,6 +87,8 @@ const long g_cdMaxPercent = 1000000; #define TYPE_RTF_ANNOTVALUE 33 #define TYPE_RTF_ANNOTATION 34 +#define TYPE_OOX_FORMFIELD 35 + #define RENDER_TO_OOX_PARAM_UNKNOWN 0 #define RENDER_TO_OOX_PARAM_LAST 1 #define RENDER_TO_OOX_PARAM_RUN 2 diff --git a/ASCOfficeRtfFile/RtfFormatLib/source/RtfField.cpp b/ASCOfficeRtfFile/RtfFormatLib/source/RtfField.cpp index 19b158c838..847c054d4a 100644 --- a/ASCOfficeRtfFile/RtfFormatLib/source/RtfField.cpp +++ b/ASCOfficeRtfFile/RtfFormatLib/source/RtfField.cpp @@ -219,6 +219,21 @@ std::wstring RtfField::RenderToOOX(RenderParameter oRenderParameter) sResult += m_pResult->RenderToOOX(oNewParam); sResult += L""; } + else if ((m_pInsert->m_pFormField) && (m_pInsert->m_pFormField->type == 2)) + { + _UINT32 id = (_UINT32)this; + std::wstring text_ = m_pInsert->m_pFormField->defres < m_pInsert->m_pFormField->list.size() ? + m_pInsert->m_pFormField->list[m_pInsert->m_pFormField->defres] : L""; + + sResult += L""; + for (size_t i = 0; i < m_pInsert->m_pFormField->list.size(); i++) + { + sResult += L"m_pFormField->list[i]) + L"\" w:displayText=\"" + m_pInsert->m_pFormField->list[i] + L"\"/>"; + } + sResult += L""; + sResult += L"" + XmlUtils::EncodeXmlString(text_) + L""; + sResult += L""; + } else { RenderParameter oNewParametr = oRenderParameter; @@ -231,7 +246,70 @@ std::wstring RtfField::RenderToOOX(RenderParameter oRenderParameter) sResult += L""; if (!props.empty()) sResult += props; - sResult += L""; + sResult += L"m_pFormField) + { + sResult += L">"; + sResult += L"m_pFormField->name) + L"\"/>"; + sResult += L""; + + if (m_pInsert->m_pFormField->recalc == 1) + sResult += L""; + else + sResult += L""; + + if (false == m_pInsert->m_pFormField->entrymcr.empty()) + sResult += L"m_pFormField->entrymcr + L"\"/>"; + if (false == m_pInsert->m_pFormField->exitmcr.empty()) + sResult += L"m_pFormField->exitmcr + L"\"/>"; + + if (false == m_pInsert->m_pFormField->helptext.empty()) + sResult += L"m_pFormField->helptext) + L"\"/>"; + if (false == m_pInsert->m_pFormField->stattext.empty()) + sResult += L"m_pFormField->stattext) + L"\"/>"; + + if (m_pInsert->m_pFormField->type == 0) + { + sResult += L""; + switch (m_pInsert->m_pFormField->typetx) + { + case 1: sResult += L""; break; + case 2: sResult += L""; break; + case 3: sResult += L""; break; + case 4: sResult += L""; break; + case 5: sResult += L""; break; + } + if (false == m_pInsert->m_pFormField->deftext.empty()) + sResult += L"m_pFormField->deftext) + L"\"/>"; + if (false == m_pInsert->m_pFormField->format.empty()) + sResult += L"m_pFormField->format) + L"\"/>"; + if (m_pInsert->m_pFormField->maxlen > 0) + sResult += L"m_pFormField->maxlen) + L"\"/>"; + sResult += L""; + } + else if (m_pInsert->m_pFormField->type == 1) + { + sResult += L""; + if (m_pInsert->m_pFormField->sizeCheckBox == 1) + sResult += L"m_pFormField->hps) + L"\"/>"; + else + sResult += L""; + sResult += L""; + if (m_pInsert->m_pFormField->res == 1) + { + sResult += L""; + } + else + { + sResult += L""; + } + + sResult += L""; + } + sResult += L""; + } + else sResult += L"/>"; + sResult += L""; //----------- sResult += L""; diff --git a/ASCOfficeRtfFile/RtfFormatLib/source/RtfField.h b/ASCOfficeRtfFile/RtfFormatLib/source/RtfField.h index 0c8a264744..9374fe35cd 100644 --- a/ASCOfficeRtfFile/RtfFormatLib/source/RtfField.h +++ b/ASCOfficeRtfFile/RtfFormatLib/source/RtfField.h @@ -112,7 +112,48 @@ public: } }; +class RtfFormField : public IDocumentElement +{ +public: + RtfFormField(){ } + int type = PROP_DEF; + int ownhelp = PROP_DEF; + int ownstat = PROP_DEF; + int prot = PROP_DEF; + int sizeCheckBox = PROP_DEF; //Auto, Exact + int typetx = PROP_DEF; + int recalc = PROP_DEF; + int haslistbox = PROP_DEF; + int maxlen = PROP_DEF; + int hps = PROP_DEF; + int defres = PROP_DEF; + int res = PROP_DEF; + + std::wstring name; + std::wstring deftext; + std::wstring format; + std::wstring helptext; + std::wstring stattext; + std::wstring entrymcr; + std::wstring exitmcr; + std::vector list; + std::wstring datafield; + + int GetType() + { + return TYPE_OOX_FORMFIELD; + } + std::wstring RenderToRtf(RenderParameter oRenderParameter) + { + return L""; + } + std::wstring RenderToOOX(RenderParameter oRenderParameter) + { + return L""; + } +}; +typedef boost::shared_ptr RtfFormFieldPtr; class RtfFieldInst : public IDocumentElement { @@ -139,6 +180,8 @@ public: RtfCharProperty m_oCharProperty; TextItemContainerPtr m_pTextItems; + + RtfFormFieldPtr m_pFormField; }; typedef boost::shared_ptr RtfFieldInstPtr; @@ -156,7 +199,7 @@ public: _FieldMode m_eMode; bool m_bReferenceToEndnote; - std::wstring m_sData; + std::wstring m_sData; RtfFieldInstPtr m_pInsert; RtfFieldInstPtr m_pResult;