summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sw/inc/docufld.hxx11
-rwxr-xr-xsw/qa/extras/odfexport/data/tdf43569_conditionalfield.docbin0 -> 22016 bytes
-rw-r--r--sw/qa/extras/odfexport/odfexport.cxx108
-rw-r--r--sw/source/core/fields/docufld.cxx100
-rw-r--r--sw/source/filter/ww8/ww8par5.cxx24
5 files changed, 242 insertions, 1 deletions
diff --git a/sw/inc/docufld.hxx b/sw/inc/docufld.hxx
index 7d986154753e..8e0bf46e9ba6 100644
--- a/sw/inc/docufld.hxx
+++ b/sw/inc/docufld.hxx
@@ -287,7 +287,7 @@ public:
bool GetHiddenFlag() const { return bHidden; }
};
-class SwHiddenTextField : public SwField
+class SW_DLLPUBLIC SwHiddenTextField : public SwField
{
OUString aTRUEText; ///< Text if condition true.
OUString aFALSEText; ///< If condition false.
@@ -317,6 +317,10 @@ public:
const OUString& rFalse,
sal_uInt16 nSubType = TYP_HIDDENTXTFLD);
+ // nSubType = TYP_CONDTXTFLD
+ SwHiddenTextField(SwHiddenTextFieldType*,
+ const OUString& rCondTrueFalse); // value sample: " IF A == B \"TrueText\" \"FalseText\""
+
virtual OUString GetFieldName() const override;
void Evaluate(SwDoc*);
@@ -337,6 +341,11 @@ public:
virtual bool QueryValue( css::uno::Any& rVal, sal_uInt16 nWhich ) const override;
virtual bool PutValue( const css::uno::Any& rVal, sal_uInt16 nWhich ) override;
+
+ static void ParseIfFieldDefinition(const OUString& aFieldDefinition,
+ OUString& rCondition,
+ OUString& rTrue,
+ OUString& rFalse);
};
// Field that expands to an empty line (without height).
diff --git a/sw/qa/extras/odfexport/data/tdf43569_conditionalfield.doc b/sw/qa/extras/odfexport/data/tdf43569_conditionalfield.doc
new file mode 100755
index 000000000000..456a6ed833cf
--- /dev/null
+++ b/sw/qa/extras/odfexport/data/tdf43569_conditionalfield.doc
Binary files differ
diff --git a/sw/qa/extras/odfexport/odfexport.cxx b/sw/qa/extras/odfexport/odfexport.cxx
index eea19faccea8..f571b66cfbe8 100644
--- a/sw/qa/extras/odfexport/odfexport.cxx
+++ b/sw/qa/extras/odfexport/odfexport.cxx
@@ -36,6 +36,7 @@
#include <comphelper/fileformat.h>
#include <comphelper/propertysequence.hxx>
#include <unotools/streamwrap.hxx>
+#include <docufld.hxx> // for SwHiddenTextField::ParseIfFieldDefinition() method call
class Test : public SwModelTestBase
{
@@ -114,6 +115,113 @@ DECLARE_ODFEXPORT_TEST(testMathObjectFlatExport, "2_MathType3.docx")
CPPUNIT_ASSERT_EQUAL(OUString(" size 12{2+2=4} {}"), formula2);
}
+void testTdf43569_CheckIfFieldParse()
+{
+ {
+ const OUString fieldDefinition("IF A B C");
+
+ OUString paramCondition;
+ OUString paramTrue;
+ OUString paramFalse;
+
+ SwHiddenTextField::ParseIfFieldDefinition(fieldDefinition, paramCondition, paramTrue, paramFalse);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("A"), paramCondition);
+ CPPUNIT_ASSERT_EQUAL(OUString("B"), paramTrue);
+ CPPUNIT_ASSERT_EQUAL(OUString("C"), paramFalse);
+ }
+
+ {
+ const OUString fieldDefinition(" IF AAA BBB CCC ");
+
+ OUString paramCondition;
+ OUString paramTrue;
+ OUString paramFalse;
+
+ SwHiddenTextField::ParseIfFieldDefinition(fieldDefinition, paramCondition, paramTrue, paramFalse);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("AAA"), paramCondition);
+ CPPUNIT_ASSERT_EQUAL(OUString("BBB"), paramTrue);
+ CPPUNIT_ASSERT_EQUAL(OUString("CCC"), paramFalse);
+ }
+
+ {
+ const OUString fieldDefinition(" IF AAA \"BBB\" \"CCC\" ");
+
+ OUString paramCondition;
+ OUString paramTrue;
+ OUString paramFalse;
+
+ SwHiddenTextField::ParseIfFieldDefinition(fieldDefinition, paramCondition, paramTrue, paramFalse);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("AAA"), paramCondition);
+ CPPUNIT_ASSERT_EQUAL(OUString("BBB"), paramTrue);
+ CPPUNIT_ASSERT_EQUAL(OUString("CCC"), paramFalse);
+ }
+
+ // true-case and false-case have spaces inside
+ {
+ const OUString fieldDefinition(" IF A A A \"B B B\" \"C C C\" ");
+
+ OUString paramCondition;
+ OUString paramTrue;
+ OUString paramFalse;
+
+ SwHiddenTextField::ParseIfFieldDefinition(fieldDefinition, paramCondition, paramTrue, paramFalse);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("A A A"), paramCondition);
+ CPPUNIT_ASSERT_EQUAL(OUString("B B B"), paramTrue);
+ CPPUNIT_ASSERT_EQUAL(OUString("C C C"), paramFalse);
+ }
+
+ // true-case and false-case have leading/trailing space
+ {
+ const OUString fieldDefinition("IF A1 A2 A3 \"B1 B2 \" \" C1 C2\" ");
+
+ OUString paramCondition;
+ OUString paramTrue;
+ OUString paramFalse;
+
+ SwHiddenTextField::ParseIfFieldDefinition(fieldDefinition, paramCondition, paramTrue, paramFalse);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("A1 A2 A3"), paramCondition);
+ CPPUNIT_ASSERT_EQUAL(OUString("B1 B2 "), paramTrue);
+ CPPUNIT_ASSERT_EQUAL(OUString(" C1 C2"), paramFalse);
+ }
+
+ // true-case and false-case are empty
+ {
+ const OUString fieldDefinition("IF condition \"\" \"\" ");
+
+ OUString paramCondition;
+ OUString paramTrue;
+ OUString paramFalse;
+
+ SwHiddenTextField::ParseIfFieldDefinition(fieldDefinition, paramCondition, paramTrue, paramFalse);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("condition"), paramCondition);
+ CPPUNIT_ASSERT_EQUAL(OUString(""), paramTrue);
+ CPPUNIT_ASSERT_EQUAL(OUString(""), paramFalse);
+ }
+}
+
+// Input document contains only one IF-field,
+// and it should be imported as com.sun.star.text.TextField.ConditionalText in any case,
+// instead of insertion of the the pair of two field-marks: <field:fieldmark-start> + <field:fieldmark-end>.
+DECLARE_ODFEXPORT_TEST(testTdf43569, "tdf43569_conditionalfield.doc")
+{
+ // check if our parser is valid
+ testTdf43569_CheckIfFieldParse();
+
+ // now check field creation during import
+ uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields());
+ uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
+
+ // at least one field should be detected
+ CPPUNIT_ASSERT(xFields->hasMoreElements());
+}
+
DECLARE_ODFEXPORT_TEST(testTdf103567, "tdf103567.odt")
{
uno::Reference<drawing::XShape> const xShape(getShape(1));
diff --git a/sw/source/core/fields/docufld.cxx b/sw/source/core/fields/docufld.cxx
index a53c16882c34..8e360155f1b8 100644
--- a/sw/source/core/fields/docufld.cxx
+++ b/sw/source/core/fields/docufld.cxx
@@ -1541,6 +1541,106 @@ OUString SwHiddenTextField::GetDBName(const OUString& rName, SwDoc *pDoc)
return aData.sDataSource + OUStringLiteral1(DB_DELIM) + aData.sCommand;
}
+// [aFieldDefinition] value sample : " IF A == B \"TrueText\" \"FalseText\""
+void SwHiddenTextField::ParseIfFieldDefinition(const OUString& aFieldDefinition,
+ OUString& rCondition,
+ OUString& rTrue,
+ OUString& rFalse)
+{
+ // get all positions inside the input string where words are started
+ //
+ // In: " IF A == B \"TrueText\" \"FalseText\""
+ // 0 1 2 3
+ // 01234567890 123456789 01 2345678901 2
+ //
+ // result:
+ // [1, 4, 6, 9, 11, 22]
+ std::vector<sal_Int32> wordPosition;
+ {
+ bool quoted = false;
+ bool insideWord = false;
+ for (sal_Int32 i = 0; i < aFieldDefinition.getLength(); i++)
+ {
+ if (quoted)
+ {
+ if (aFieldDefinition[i] == '\"')
+ {
+ quoted = false;
+ insideWord = false;
+ }
+ }
+ else
+ {
+ if (aFieldDefinition[i] == ' ')
+ {
+ // word delimiter
+ insideWord = false;
+ }
+ else
+ {
+ if (insideWord)
+ {
+ quoted = (aFieldDefinition[i] == '\"');
+ }
+ else
+ {
+ insideWord = true;
+ wordPosition.push_back(i);
+ quoted = (aFieldDefinition[i] == '\"');
+ }
+ }
+ }
+ }
+ }
+
+ // first word is always "IF"
+ // last two words are: true-case and false-case,
+ // everything before is treated as condition expression
+ // => we need at least 4 words to be inside the input string
+ if (wordPosition.size() < 4)
+ {
+ return;
+ }
+
+
+ const sal_Int32 conditionBegin = wordPosition[1];
+ const sal_Int32 trueBegin = wordPosition[wordPosition.size() - 2];
+ const sal_Int32 falseBegin = wordPosition[wordPosition.size() - 1];
+
+ const sal_Int32 conditionLength = trueBegin - conditionBegin;
+ const sal_Int32 trueLength = falseBegin - trueBegin;
+
+ // Syntax
+ // OUString::copy( sal_Int32 beginIndex, sal_Int32 count )
+ rCondition = aFieldDefinition.copy(conditionBegin, conditionLength);
+ rTrue = aFieldDefinition.copy(trueBegin, trueLength);
+ rFalse = aFieldDefinition.copy(falseBegin);
+
+ // trim
+ rCondition = rCondition.trim();
+ rTrue = rTrue.trim();
+ rFalse = rFalse.trim();
+
+ // remove quotes
+ if (rCondition.getLength() >= 2)
+ {
+ if (rCondition[0] == '\"' && rCondition[rCondition.getLength() - 1] == '\"')
+ rCondition = rCondition.copy(1, rCondition.getLength() - 2);
+ }
+ if (rTrue.getLength() >= 2)
+ {
+ if (rTrue[0] == '\"' && rTrue[rTrue.getLength() - 1] == '\"')
+ rTrue = rTrue.copy(1, rTrue.getLength() - 2);
+ }
+ if (rFalse.getLength() >= 2)
+ {
+ if (rFalse[0] == '\"' && rFalse[rFalse.getLength() - 1] == '\"')
+ rFalse = rFalse.copy(1, rFalse.getLength() - 2);
+ }
+
+ // Note: do not make trim once again, while this is a user defined data
+}
+
// field type for line height 0
SwHiddenParaFieldType::SwHiddenParaFieldType()
diff --git a/sw/source/filter/ww8/ww8par5.cxx b/sw/source/filter/ww8/ww8par5.cxx
index e6dee54d5d50..eb04cb5a50d0 100644
--- a/sw/source/filter/ww8/ww8par5.cxx
+++ b/sw/source/filter/ww8/ww8par5.cxx
@@ -589,6 +589,30 @@ sal_uInt16 SwWW8ImplReader::End_Field()
//Move outside the section associated with this type of field
*m_pPaM->GetPoint() = m_aFieldStack.back().maStartPos;
break;
+ case 7: // IF-field
+ {
+ // conditional field parameters
+ const OUString& fieldDefinition = m_aFieldStack.back().GetBookmarkCode();
+
+ OUString paramCondition;
+ OUString paramTrue;
+ OUString paramFalse;
+
+ SwHiddenTextField::ParseIfFieldDefinition(fieldDefinition, paramCondition, paramTrue, paramFalse);
+
+ // create new field
+ SwFieldType* pFieldType = m_rDoc.getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::HiddenText);
+ SwHiddenTextField *const pHTField = new SwHiddenTextField(
+ static_cast<SwHiddenTextFieldType*>(pFieldType),
+ paramCondition,
+ paramTrue,
+ paramFalse,
+ static_cast<sal_uInt16>(TYP_CONDTXTFLD));
+
+ // insert new field into document
+ m_rDoc.getIDocumentContentOperations().InsertPoolItem(*m_pPaM, SwFormatField(*pHTField));
+ break;
+ }
default:
OUString aCode = m_aFieldStack.back().GetBookmarkCode();
if ( !aCode.isEmpty() )