From 1ab0e33b9dcf12c206a328218a46820e884d27b7 Mon Sep 17 00:00:00 2001 From: Sergey Vladimirov Date: Mon, 5 Nov 2012 14:38:12 +0000 Subject: [PATCH] 52311 - Conversion to html : Problem in titles number git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1405808 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/status.xml | 1 + .../poi/hwpf/converter/AbstractWordUtils.java | 41 ++++--- .../hwpf/model/types/GrfhicAbstractType.java | 12 +- .../poi/hwpf/model/types/LFOAbstractType.java | 89 ++++++++------- .../apache/poi/hwpf/usermodel/HWPFList.java | 15 +++ .../converter/TestWordToTextConverter.java | 15 +++ src/types/styles/hdftype.xsl | 104 ++++++++++++------ test-data/document/Bug52311.doc | Bin 0 -> 32768 bytes 8 files changed, 177 insertions(+), 100 deletions(-) create mode 100644 test-data/document/Bug52311.doc diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index f1b386fb2..bfbabdf77 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 52311 - Conversion to html : Problem in titles number 53914 - TableRow#getTopBorder() return bottom's border 53282 - Avoid exception when parsing OPC relationships with non-breaking spaces 54016 - Avoid exception when parsing workbooks with DConRefRecord in row aggregate diff --git a/src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordUtils.java b/src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordUtils.java index 83fe7987a..89ac7e563 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordUtils.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordUtils.java @@ -226,13 +226,15 @@ public class AbstractWordUtils return stringBuilder.toString(); } - public static class NumberingState { - + public static class NumberingState + { + private final Map levels = new HashMap(); - + } - - public static String getBulletText(NumberingState numberingState, HWPFList list, char level ) + + public static String getBulletText( NumberingState numberingState, + HWPFList list, char level ) { StringBuffer bulletBuffer = new StringBuffer(); char[] xst = list.getNumberText( level ).toCharArray(); @@ -240,25 +242,38 @@ public class AbstractWordUtils { if ( element < 9 ) { - final String key = list.getLsid() + "#" + ( (int) element ); + int lsid = list.getLsid(); + final String key = lsid + "#" + ( (int) element ); int num; - if ( numberingState.levels.containsKey( key ) ) + + if ( !list.isStartAtOverriden( element ) + && numberingState.levels.containsKey( key ) ) { num = numberingState.levels.get( key ).intValue(); + if ( level == element ) + { + num++; + numberingState.levels.put( key, Integer.valueOf( num ) ); + } } else { - num = list.getStartAt( level ); + num = list.getStartAt( element ); numberingState.levels.put( key, Integer.valueOf( num ) ); } - bulletBuffer.append( NumberFormatter.getNumber( num, - list.getNumberFormat( level ) ) ); - if ( level == element ) { - numberingState.levels.put( key, Integer.valueOf( num + 1 ) ); + // cleaning states of nested levels to reset numbering + for ( int i = element + 1; i < 9; i++ ) + { + final String childKey = lsid + "#" + i; + numberingState.levels.remove( childKey ); + } } + + bulletBuffer.append( NumberFormatter.getNumber( num, + list.getNumberFormat( level ) ) ); } else { @@ -266,7 +281,7 @@ public class AbstractWordUtils } } - byte follow = list.getTypeOfCharFollowingTheNumber(level); + byte follow = list.getTypeOfCharFollowingTheNumber( level ); switch ( follow ) { case 0: diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/GrfhicAbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/GrfhicAbstractType.java index a20283970..6f3c82378 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/types/GrfhicAbstractType.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/types/GrfhicAbstractType.java @@ -14,11 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ + package org.apache.poi.hwpf.model.types; -import org.apache.poi.util.BitField; -import org.apache.poi.util.Internal; +import org.apache.poi.hwpf.usermodel.*; +import org.apache.poi.util.*; /** * The grfhic structure is a set of HTML incompatibility flags that specify the HTML @@ -108,9 +109,10 @@ public abstract class GrfhicAbstractType public String toString() { StringBuilder builder = new StringBuilder(); + builder.append("[Grfhic]\n"); - builder.append(" .grfhic = "); - builder.append(" (").append(getGrfhic()).append(" )\n"); + builder.append( " .grfhic = " ); + builder.append(" ( ").append( field_1_grfhic ).append( " )\n" ); builder.append(" .fHtmlChecked = ").append(isFHtmlChecked()).append('\n'); builder.append(" .fHtmlUnsupported = ").append(isFHtmlUnsupported()).append('\n'); builder.append(" .fHtmlListTextNotSharpDot = ").append(isFHtmlListTextNotSharpDot()).append('\n'); @@ -120,7 +122,7 @@ public abstract class GrfhicAbstractType builder.append(" .fHtmlHangingIndentBeneathNumber = ").append(isFHtmlHangingIndentBeneathNumber()).append('\n'); builder.append(" .fHtmlBuiltInBullet = ").append(isFHtmlBuiltInBullet()).append('\n'); - builder.append("[/Grfhic]\n"); + builder.append("[/Grfhic]"); return builder.toString(); } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/LFOAbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/LFOAbstractType.java index e36017e65..0289ef28a 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/types/LFOAbstractType.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/types/LFOAbstractType.java @@ -21,20 +21,19 @@ import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; /** - * List Format Override (LFO). + * List Format Override (LFO).

Class and fields descriptions are quoted from + [MS-DOC] --v20110315; Word (.doc) Binary File Format + *

- * Class and fields descriptions are quoted from [MS-DOC] --v20110315; Word - * (.doc) Binary File Format - * + * NOTE: This source is automatically generated please do not modify this file. Either subclass or + * remove the record in src/types/definitions. *

- * NOTE: This source is automatically generated please do not modify this file. - * Either subclass or remove the record in src/types/definitions. - *

- * This class is internal. It content or properties may change without notice + * This class is internal. It content or properties may change without notice * due to changes in our knowledge of internal Microsoft Word binary structures. - * - * @author Sergey Vladimirov; according to [MS-DOC] --v20110315; Word (.doc) - * Binary File Format; Copyright (c) Microsoft Corporation + + * @author Sergey Vladimirov; according to [MS-DOC] --v20110315; Word (.doc) Binary File Format; + Copyright (c) Microsoft Corporation + */ @Internal public abstract class LFOAbstractType @@ -55,13 +54,13 @@ public abstract class LFOAbstractType protected void fillFields( byte[] data, int offset ) { - field_1_lsid = LittleEndian.getInt( data, 0x0 + offset ); - field_2_unused1 = LittleEndian.getInt( data, 0x4 + offset ); - field_3_unused2 = LittleEndian.getInt( data, 0x8 + offset ); - field_4_clfolvl = data[0xc + offset]; - field_5_ibstFltAutoNum = data[0xd + offset]; - field_6_grfhic = new Grfhic( data, 0xe + offset ); - field_7_unused3 = data[0xf + offset]; + field_1_lsid = LittleEndian.getInt( data, 0x0 + offset ); + field_2_unused1 = LittleEndian.getInt( data, 0x4 + offset ); + field_3_unused2 = LittleEndian.getInt( data, 0x8 + offset ); + field_4_clfolvl = data[ 0xc + offset ]; + field_5_ibstFltAutoNum = data[ 0xd + offset ]; + field_6_grfhic = new Grfhic( data, 0xe + offset ); + field_7_unused3 = data[ 0xf + offset ]; } public void serialize( byte[] data, int offset ) @@ -69,15 +68,15 @@ public abstract class LFOAbstractType LittleEndian.putInt( data, 0x0 + offset, field_1_lsid ); LittleEndian.putInt( data, 0x4 + offset, field_2_unused1 ); LittleEndian.putInt( data, 0x8 + offset, field_3_unused2 ); - data[0xc + offset] = field_4_clfolvl; - data[0xd + offset] = field_5_ibstFltAutoNum; + data[ 0xc + offset ] = field_4_clfolvl; + data[ 0xd + offset ] = field_5_ibstFltAutoNum; field_6_grfhic.serialize( data, 0xe + offset ); - data[0xf + offset] = field_7_unused3; + data[ 0xf + offset ] = field_7_unused3; } public byte[] serialize() { - final byte[] result = new byte[getSize()]; + final byte[] result = new byte[ getSize() ]; serialize( result, 0 ); return result; } @@ -132,7 +131,8 @@ public abstract class LFOAbstractType result = prime * result + field_3_unused2; result = prime * result + field_4_clfolvl; result = prime * result + field_5_ibstFltAutoNum; - result = prime * result + field_6_grfhic.hashCode(); + result = prime * result + + ((field_6_grfhic == null) ? 0 : field_6_grfhic.hashCode()); result = prime * result + field_7_unused3; return result; } @@ -140,30 +140,29 @@ public abstract class LFOAbstractType public String toString() { StringBuilder builder = new StringBuilder(); - builder.append( "[LFO]\n" ); - builder.append( " .lsid = " ); - builder.append( " (" ).append( getLsid() ).append( " )\n" ); - builder.append( " .unused1 = " ); - builder.append( " (" ).append( getUnused1() ).append( " )\n" ); - builder.append( " .unused2 = " ); - builder.append( " (" ).append( getUnused2() ).append( " )\n" ); - builder.append( " .clfolvl = " ); - builder.append( " (" ).append( getClfolvl() ).append( " )\n" ); - builder.append( " .ibstFltAutoNum = " ); - builder.append( " (" ).append( getIbstFltAutoNum() ).append( " )\n" ); - builder.append( " .grfhic = " ); - builder.append( " (" ).append( getGrfhic() ).append( " )\n" ); - builder.append( " .unused3 = " ); - builder.append( " (" ).append( getUnused3() ).append( " )\n" ); - builder.append( "[/LFO]\n" ); + builder.append("[LFO]\n"); + builder.append( " .lsid = " ); + builder.append(" ( ").append( field_1_lsid ).append( " )\n" ); + builder.append( " .unused1 = " ); + builder.append(" ( ").append( field_2_unused1 ).append( " )\n" ); + builder.append( " .unused2 = " ); + builder.append(" ( ").append( field_3_unused2 ).append( " )\n" ); + builder.append( " .clfolvl = " ); + builder.append(" ( ").append( field_4_clfolvl ).append( " )\n" ); + builder.append( " .ibstFltAutoNum = " ); + builder.append(" ( ").append( field_5_ibstFltAutoNum ).append( " )\n" ); + builder.append( " .grfhic = " ); + builder.append(" ( ").append( field_6_grfhic == null ? "null" : field_6_grfhic.toString().replaceAll( "\n", "\n " ) ).append( " )\n" ); + builder.append( " .unused3 = " ); + builder.append(" ( ").append( field_7_unused3 ).append( " )\n" ); + + builder.append("[/LFO]"); return builder.toString(); } /** - * A signed integer that specifies the list identifier of an LSTF. This LFO - * corresponds to the LSTF in PlfLst.rgLstf that has an lsid whose value is - * equal to this value.. + * A signed integer that specifies the list identifier of an LSTF. This LFO corresponds to the LSTF in PlfLst.rgLstf that has an lsid whose value is equal to this value.. */ @Internal public int getLsid() @@ -172,9 +171,7 @@ public abstract class LFOAbstractType } /** - * A signed integer that specifies the list identifier of an LSTF. This LFO - * corresponds to the LSTF in PlfLst.rgLstf that has an lsid whose value is - * equal to this value.. + * A signed integer that specifies the list identifier of an LSTF. This LFO corresponds to the LSTF in PlfLst.rgLstf that has an lsid whose value is equal to this value.. */ @Internal public void setLsid( int field_1_lsid ) @@ -290,4 +287,4 @@ public abstract class LFOAbstractType this.field_7_unused3 = field_7_unused3; } -} // END OF CLASS +} // END OF CLASS diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/HWPFList.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/HWPFList.java index 06e8ed2e7..41bcb9652 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/HWPFList.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/HWPFList.java @@ -28,6 +28,7 @@ import org.apache.poi.util.Internal; import org.apache.poi.hwpf.model.LFO; import org.apache.poi.hwpf.model.LFOData; import org.apache.poi.hwpf.model.ListData; +import org.apache.poi.hwpf.model.ListFormatOverrideLevel; import org.apache.poi.hwpf.model.ListLevel; import org.apache.poi.hwpf.model.StyleSheet; import org.apache.poi.hwpf.sprm.CharacterSprmCompressor; @@ -167,6 +168,11 @@ public final class HWPFList public int getStartAt( char level ) { + if ( isStartAtOverriden( level ) ) + { + return _lfoData.getRgLfoLvl()[level].getIStartAt(); + } + return getLVL( level ).getStartAt(); } @@ -183,6 +189,15 @@ public final class HWPFList return _ignoreLogicalLeftIdentation; } + public boolean isStartAtOverriden( char level ) + { + ListFormatOverrideLevel lfolvl = _lfoData.getRgLfoLvl().length > level ? _lfoData + .getRgLfoLvl()[level] : null; + + return lfolvl != null && lfolvl.getIStartAt() != 0 + && !lfolvl.isFormatting(); + } + public void setIgnoreLogicalLeftIdentation( boolean ignoreLogicalLeftIdentation ) { diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToTextConverter.java b/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToTextConverter.java index 11d5976bb..00a46f642 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToTextConverter.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToTextConverter.java @@ -36,6 +36,21 @@ public class TestWordToTextConverter extends TestCase .contains( "Soak the rice in water for three to four hours" ) ); } + public void testBug52311() throws Exception + { + HWPFDocument doc = HWPFTestDataSamples.openSampleFile( "Bug52311.doc" ); + String result = WordToTextConverter.getText( doc ); + + assertTrue( result.contains( "2.1\tHeader 2.1" ) ); + assertTrue( result.contains( "2.2\tHeader 2.2" ) ); + assertTrue( result.contains( "2.3\tHeader 2.3" ) ); + assertTrue( result.contains( "2.3.1\tHeader 2.3.1" ) ); + assertTrue( result.contains( "2.99\tHeader 2.99" ) ); + assertTrue( result.contains( "2.99.1\tHeader 2.99.1" ) ); + assertTrue( result.contains( "2.100\tHeader 2.100" ) ); + assertTrue( result.contains( "2.101\tHeader 2.101" ) ); + } + public void testBug53380_3() throws Exception { HWPFDocument doc = HWPFTestDataSamples diff --git a/src/types/styles/hdftype.xsl b/src/types/styles/hdftype.xsl index 027323dfe..ab923d192 100644 --- a/src/types/styles/hdftype.xsl +++ b/src/types/styles/hdftype.xsl @@ -381,27 +381,8 @@ public abstract class - - public String toString() - { - StringBuilder builder = new StringBuilder(); - - - - builder.append("[ - - ]\n"); - - - - - - builder.append("[/ - - ]\n"); - return builder.toString(); - } - + + @@ -549,21 +530,72 @@ public abstract class - - - - builder.append(" . - - = "); - - - - builder.append(" (").append(get - - ()).append(" )\n"); - - - + + + public String toString() + + + + { + + + + + StringBuilder builder = new StringBuilder(); + + + + + + builder.append("[ + + ]\n"); + + + + + + + + builder.append("[/ + + ]"); + return builder.toString(); + } + + + + + + + + + builder.append( " . + + = " ); + + + + + builder.append(" ( ").append( + + + + + + + == null ? "null" : + + .toString().replaceAll( "\n", "\n " ) + + + ).append( " )\n" ); + + + + diff --git a/test-data/document/Bug52311.doc b/test-data/document/Bug52311.doc new file mode 100644 index 0000000000000000000000000000000000000000..16f55688aa7a80474f2363f456c7b36706d07a1a GIT binary patch literal 32768 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 ibdAf6brkp8nsn!2bjAFF)D< literal 0 HcmV?d00001