diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml index e353ecb435..a487fbba94 100644 --- a/src/documentation/content/xdocs/changes.xml +++ b/src/documentation/content/xdocs/changes.xml @@ -37,6 +37,7 @@ + 45252 - Improvement for HWPF Range.replaceText() 45001 - Further fix for HWPF Range.delete() and unicode characters 45175 - Support for variable length operands in org.apache.poi.hwpf.sprm.SprmOperation Avoid spurious missing lines with the MissingRecordAware event code, and odd files that contain RowRecords in the middle of the cell Records. diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 7e2d951568..bc94621ef1 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 45252 - Improvement for HWPF Range.replaceText() 45001 - Further fix for HWPF Range.delete() and unicode characters 45175 - Support for variable length operands in org.apache.poi.hwpf.sprm.SprmOperation Avoid spurious missing lines with the MissingRecordAware event code, and odd files that contain RowRecords in the middle of the cell Records. diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java index 80e9b7526c..0ef944f136 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java @@ -333,7 +333,7 @@ public class Range _doc.getCharacterTable().adjustForInsert(_charStart, adjustedLength); _doc.getParagraphTable().adjustForInsert(_parStart, adjustedLength); _doc.getSectionTable().adjustForInsert(_sectionStart, adjustedLength); - adjustForInsert(text.length()); + adjustForInsert(adjustedLength); // update the FIB.CCPText field adjustFIB(text.length()); @@ -656,8 +656,15 @@ public class Range ); } + // this Range isn't a proper parent of the subRange() so we'll have to keep + // track of an updated endOffset on our own + int previousEndOffset = subRange.getEndOffset(); + subRange.insertBefore(pValue); + if (subRange.getEndOffset() != previousEndOffset) + _end += (subRange.getEndOffset() - previousEndOffset); + // re-create the sub-range so we can delete it subRange = new Range( (absPlaceHolderIndex + pValue.length()), @@ -671,9 +678,30 @@ public class Range (pValue.length() * 2)), getDocument() ); + // deletes are automagically propagated subRange.delete(); } + /** + * Replace (all instances of) a piece of text with another... + * + * @param pPlaceHolder The text to be replaced (e.g., "${organization}") + * @param pValue The replacement text (e.g., "Apache Software Foundation") + */ + public void replaceText(String pPlaceHolder, String pValue) + { + boolean keepLooking = true; + while (keepLooking) { + + String text = text(); + int offset = text.indexOf(pPlaceHolder); + if (offset >= 0) + replaceText(pPlaceHolder, pValue, offset); + else + keepLooking = false; + } + } + /** * Gets the character run at index. The index is relative to this range. * @@ -915,7 +943,7 @@ public class Range /** * adjust this range after an insert happens. - * @param length the length to adjust for + * @param length the length to adjust for (expected to be a count of code-points, not necessarily chars) */ private void adjustForInsert(int length) { diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestRangeReplacement.java b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestRangeReplacement.java index 4b2b9ce370..bda615e943 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestRangeReplacement.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestRangeReplacement.java @@ -39,8 +39,9 @@ public class TestRangeReplacement extends TestCase { "It is used to confirm that text replacement works even if Unicode characters (such as \u201c\u2014\u201d (U+2014), \u201c\u2e8e\u201d (U+2E8E), or \u201c\u2714\u201d (U+2714)) are present. Everybody should be thankful to the ${organization} and all the POI contributors for their assistance in this matter.\r"; private String searchText = "${organization}"; private String replacementText = "Apache Software Foundation"; - private String expectedText = + private String expectedText2 = "It is used to confirm that text replacement works even if Unicode characters (such as \u201c\u2014\u201d (U+2014), \u201c\u2e8e\u201d (U+2E8E), or \u201c\u2714\u201d (U+2714)) are present. Everybody should be thankful to the Apache Software Foundation and all the POI contributors for their assistance in this matter.\r"; + private String expectedText3 = "Thank you, Apache Software Foundation!\r"; private String illustrativeDocFile; @@ -84,7 +85,7 @@ public class TestRangeReplacement extends TestCase { /** * Test that we can replace text in our Range with Unicode text. */ - public void testRangeReplacement() throws Exception { + public void testRangeReplacementOne() throws Exception { HWPFDocument daDoc = new HWPFDocument(new FileInputStream(illustrativeDocFile)); @@ -104,16 +105,46 @@ public class TestRangeReplacement extends TestCase { para.replaceText(searchText, replacementText, offset); - // we need to let the model re-calculate the Range before we evaluate it - range = daDoc.getRange(); - assertEquals(1, range.numSections()); section = range.getSection(0); - assertEquals(5, section.numParagraphs()); + assertEquals(4, section.numParagraphs()); para = section.getParagraph(2); text = para.text(); - assertEquals(expectedText, text); + assertEquals(expectedText2, text); + } + + /** + * Test that we can replace text in our Range with Unicode text. + */ + public void testRangeReplacementAll() throws Exception { + + HWPFDocument daDoc = new HWPFDocument(new FileInputStream(illustrativeDocFile)); + + Range range = daDoc.getRange(); + assertEquals(1, range.numSections()); + + Section section = range.getSection(0); + assertEquals(5, section.numParagraphs()); + + Paragraph para = section.getParagraph(2); + + String text = para.text(); + assertEquals(originalText, text); + + range.replaceText(searchText, replacementText); + + assertEquals(1, range.numSections()); + section = range.getSection(0); + assertEquals(5, section.numParagraphs()); + + para = section.getParagraph(2); + text = para.text(); + assertEquals(expectedText2, text); + + para = section.getParagraph(3); + text = para.text(); + assertEquals(expectedText3, text); } }