diff --git a/OpenXmlFormats/Wordprocessing/Paragraph.cs b/OpenXmlFormats/Wordprocessing/Paragraph.cs
index 4369db897..5ec6569b8 100644
--- a/OpenXmlFormats/Wordprocessing/Paragraph.cs
+++ b/OpenXmlFormats/Wordprocessing/Paragraph.cs
@@ -1229,6 +1229,11 @@ public bool IsSetSectPr()
{
return this.sectPr != null;
}
+
+ public void UnsetJc()
+ {
+ this.jc=null;
+ }
}
diff --git a/ooxml/XWPF/Usermodel/XWPFParagraph.cs b/ooxml/XWPF/Usermodel/XWPFParagraph.cs
index c3b522752..fa983d410 100644
--- a/ooxml/XWPF/Usermodel/XWPFParagraph.cs
+++ b/ooxml/XWPF/Usermodel/XWPFParagraph.cs
@@ -569,18 +569,27 @@ public String FootnoteText
///
/// Returns the paragraph alignment which shall be applied to text in this paragraph.
///
- public ParagraphAlignment Alignment
+ public ParagraphAlignment? Alignment
{
get
{
- CT_PPr pr = GetCTPPr();
- return pr == null || !pr.IsSetJc() ? ParagraphAlignment.LEFT : EnumConverter.ValueOf(pr.jc.val);
+ CT_PPr pr = GetCTPPr(false);
+ return (pr == null || !pr.IsSetJc()) ? ParagraphAlignment.LEFT : EnumConverter.ValueOf(pr.jc.val);
}
set
{
- CT_PPr pr = GetCTPPr();
- CT_Jc jc = pr.IsSetJc() ? pr.jc : pr.AddNewJc();
- jc.val = EnumConverter.ValueOf(value);
+ if(value==null)
+ {
+ CT_PPr pr = GetCTPPr(false);
+ if(pr!=null)
+ pr.UnsetJc();
+ }
+ else
+ {
+ CT_PPr pr = GetCTPPr(true);
+ CT_Jc jc = pr.IsSetJc() ? pr.jc : pr.AddNewJc();
+ jc.val = EnumConverter.ValueOf((ParagraphAlignment) value);
+ }
}
}
@@ -621,7 +630,7 @@ public TextAlignment VerticalAlignment
{
get
{
- CT_PPr pr = GetCTPPr();
+ CT_PPr pr = GetCTPPr(false);
return (pr == null || !pr.IsSetTextAlignment()) ? TextAlignment.AUTO
: EnumConverter.ValueOf(pr.textAlignment.val);
}
@@ -1242,8 +1251,8 @@ public bool IsWordWrapped
{
get
{
- CT_OnOff wordWrap = GetCTPPr().IsSetWordWrap() ? GetCTPPr()
- .wordWrap : null;
+ var ppr = GetCTPPr(false);
+ CT_OnOff wordWrap = ppr!=null && ppr.IsSetWordWrap() ? ppr.wordWrap : null;
if (wordWrap != null)
{
return wordWrap.val;
@@ -1274,15 +1283,28 @@ public String Style
{
get
{
- CT_PPr pr = GetCTPPr();
+ CT_PPr pr = GetCTPPr(false);
+ if(pr==null)
+ {
+ return null;
+ }
CT_String style = pr.IsSetPStyle() ? pr.pStyle : null;
return style != null ? style.val : null;
}
set
{
- CT_PPr pr = GetCTPPr();
- CT_String style = pr.pStyle != null ? pr.pStyle : pr.AddNewPStyle();
- style.val = value;
+ if(value==null)
+ {
+ var pr= GetCTPPr(false);
+ if(pr!=null)
+ pr.jc = null;
+ }
+ else
+ {
+ CT_PPr pr = GetCTPPr(true);
+ CT_String style = pr.pStyle != null ? pr.pStyle : pr.AddNewPStyle();
+ style.val = value;
+ }
}
}
@@ -1292,12 +1314,15 @@ public String Style
*/
private CT_PBdr GetCTPBrd(bool create)
{
- CT_PPr pr = GetCTPPr();
+ CT_PPr pr = GetCTPPr(create);
+ if(pr==null)
+ {
+ return null;
+ }
CT_PBdr ct = pr.IsSetPBdr() ? pr.pBdr : null;
- if (create && ct == null)
+ if(create && ct == null)
ct = pr.AddNewPBdr();
return ct;
-
}
/**
@@ -1306,7 +1331,7 @@ private CT_PBdr GetCTPBrd(bool create)
*/
private CT_Spacing GetCTSpacing(bool create)
{
- CT_PPr pr = GetCTPPr();
+ CT_PPr pr = GetCTPPr(create);
CT_Spacing ct = pr.spacing == null ? null : pr.spacing;
if (create && ct == null)
ct = pr.AddNewSpacing();
@@ -1319,20 +1344,23 @@ private CT_Spacing GetCTSpacing(bool create)
*/
private CT_Ind GetCTInd(bool create)
{
- CT_PPr pr = GetCTPPr();
+ CT_PPr pr = GetCTPPr(create);
CT_Ind ct = pr.ind == null ? null : pr.ind;
if (create && ct == null)
ct = pr.AddNewInd();
return ct;
}
-
+ internal CT_PPr GetCTPPr()
+ {
+ return GetCTPPr(true);
+ }
/**
* Get a copy of the currently used CTPPr, if none is used, return
* a new instance.
*/
- internal CT_PPr GetCTPPr()
+ internal CT_PPr GetCTPPr(bool create)
{
- CT_PPr pr = paragraph.pPr == null ? paragraph.AddNewPPr()
+ CT_PPr pr = (paragraph.pPr == null||!create) ? paragraph.AddNewPPr()
: paragraph.pPr;
return pr;
}
@@ -1862,6 +1890,17 @@ private bool IsTheOnlyCTFieldInRuns(XWPFFieldRun run)
&& ctField == ((XWPFFieldRun) r).GetCTField());
return count <= 1;
}
+
+ ///
+ /// Returns true if the paragraph has a paragraph alignment value of its own
+ /// or false in case it should fall back to the alignment value set by the paragraph style.
+ ///
+ ///
+ public bool IsAlignmentSet()
+ {
+ var pr = GetCTPPr(false);
+ return pr != null && pr.IsSetJc();
+ }
}
}
diff --git a/testcases/ooxml/XWPF/TestXWPFBugs.cs b/testcases/ooxml/XWPF/TestXWPFBugs.cs
index 21d1ff2f0..b6e6b4017 100644
--- a/testcases/ooxml/XWPF/TestXWPFBugs.cs
+++ b/testcases/ooxml/XWPF/TestXWPFBugs.cs
@@ -27,6 +27,7 @@ namespace TestCases.XWPF
using NUnit.Framework;using NUnit.Framework.Legacy;
using System;
using System.IO;
+ using System.Reflection.Metadata;
using System.Xml;
using TestCases;
@@ -287,6 +288,20 @@ private static void addNumberingWithAbstractId(XWPFNumbering documentNumbering,
documentNumbering.AddNum(abstractNumID);
}
+
+ [Test]
+ public void CorrectParagraphAlignment()
+ {
+ using (var document = XWPFTestDataSamples.OpenSampleDocument("bug-paragraph-alignment.docx")) {
+ XWPFParagraph centeredParagraph = document.GetParagraphArray(0);
+ ClassicAssert.IsFalse(centeredParagraph.IsAlignmentSet());
+ ClassicAssert.AreEqual(ParagraphAlignment.LEFT, centeredParagraph.Alignment); // LEFT is a fallback value here.
+
+ XWPFParagraph leftParagraph = document.GetParagraphArray(1);
+ ClassicAssert.IsTrue(leftParagraph.IsAlignmentSet());
+ ClassicAssert.AreEqual(ParagraphAlignment.LEFT, leftParagraph.Alignment); // LEFT is the real alignment value.
+ }
+ }
}
}
diff --git a/testcases/ooxml/XWPF/UserModel/TestXWPFParagraph.cs b/testcases/ooxml/XWPF/UserModel/TestXWPFParagraph.cs
index 1947b95d0..229eb2179 100644
--- a/testcases/ooxml/XWPF/UserModel/TestXWPFParagraph.cs
+++ b/testcases/ooxml/XWPF/UserModel/TestXWPFParagraph.cs
@@ -105,23 +105,32 @@ public void TestSetBorderTop()
}
[Test]
- public void TestSetAlignment()
+ public void TestSetGetAlignment()
{
//new clean instance of paragraph
- XWPFDocument doc = new XWPFDocument();
- XWPFParagraph p = doc.CreateParagraph();
+ using(XWPFDocument doc = new XWPFDocument())
+ {
+ XWPFParagraph p = doc.CreateParagraph();
- ClassicAssert.AreEqual(ParagraphAlignment.LEFT, p.Alignment);
+ ClassicAssert.AreEqual(ParagraphAlignment.LEFT, p.Alignment);
+ ClassicAssert.IsFalse(p.IsAlignmentSet());
- CT_P ctp = p.GetCTP();
- CT_PPr ppr = ctp.pPr == null ? ctp.AddNewPPr() : ctp.pPr;
+ CT_P ctp = p.GetCTP();
+ CT_PPr ppr = ctp.pPr == null ? ctp.AddNewPPr() : ctp.pPr;
- CT_Jc align = ppr.AddNewJc();
- align.val = (ST_Jc.center);
- ClassicAssert.AreEqual(ParagraphAlignment.CENTER, p.Alignment);
+ CT_Jc align = ppr.AddNewJc();
+ align.val = (ST_Jc.center);
+ ClassicAssert.AreEqual(ParagraphAlignment.CENTER, p.Alignment);
+ ClassicAssert.IsTrue(p.IsAlignmentSet());
- p.Alignment = (ParagraphAlignment.BOTH);
- ClassicAssert.AreEqual((int)ST_Jc.both, (int)ppr.jc.val);
+ p.Alignment = (ParagraphAlignment.BOTH);
+ ClassicAssert.AreEqual((int) ST_Jc.both, (int) ppr.jc.val);
+ ClassicAssert.IsTrue(p.IsAlignmentSet());
+
+ p.Alignment=null;
+ ClassicAssert.AreEqual(ParagraphAlignment.LEFT, p.Alignment);
+ ClassicAssert.IsFalse(p.IsAlignmentSet());
+ }
}
[Test]
diff --git a/testcases/test-data/document/bug-paragraph-alignment.docx b/testcases/test-data/document/bug-paragraph-alignment.docx
new file mode 100644
index 000000000..de4a46855
Binary files /dev/null and b/testcases/test-data/document/bug-paragraph-alignment.docx differ