git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1405808 13f79535-47bb-0310-9956-ffa450edef68tags/3.10-beta1
@@ -34,6 +34,7 @@ | |||
<changes> | |||
<release version="3.9-beta1" date="2012-??-??"> | |||
<action dev="poi-developers" type="fix">52311 - Conversion to html : Problem in titles number </action> | |||
<action dev="poi-developers" type="fix">53914 - TableRow#getTopBorder() return bottom's border</action> | |||
<action dev="poi-developers" type="fix">53282 - Avoid exception when parsing OPC relationships with non-breaking spaces</action> | |||
<action dev="poi-developers" type="fix">54016 - Avoid exception when parsing workbooks with DConRefRecord in row aggregate</action> |
@@ -226,13 +226,15 @@ public class AbstractWordUtils | |||
return stringBuilder.toString(); | |||
} | |||
public static class NumberingState { | |||
public static class NumberingState | |||
{ | |||
private final Map<String, Integer> levels = new HashMap<String, Integer>(); | |||
} | |||
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: |
@@ -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(); | |||
} | |||
@@ -21,20 +21,19 @@ import org.apache.poi.util.Internal; | |||
import org.apache.poi.util.LittleEndian; | |||
/** | |||
* List Format Override (LFO). | |||
* List Format Override (LFO). <p>Class and fields descriptions are quoted from | |||
[MS-DOC] --v20110315; Word (.doc) Binary File Format | |||
* <p> | |||
* 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. | |||
* <p> | |||
* NOTE: This source is automatically generated please do not modify this file. | |||
* Either subclass or remove the record in src/types/definitions. | |||
* <p> | |||
* 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("[LFO]\n"); | |||
builder.append( " .lsid = " ); | |||
builder.append( " (" ).append( getLsid() ).append( " )\n" ); | |||
builder.append(" ( ").append( field_1_lsid ).append( " )\n" ); | |||
builder.append( " .unused1 = " ); | |||
builder.append( " (" ).append( getUnused1() ).append( " )\n" ); | |||
builder.append(" ( ").append( field_2_unused1 ).append( " )\n" ); | |||
builder.append( " .unused2 = " ); | |||
builder.append( " (" ).append( getUnused2() ).append( " )\n" ); | |||
builder.append(" ( ").append( field_3_unused2 ).append( " )\n" ); | |||
builder.append( " .clfolvl = " ); | |||
builder.append( " (" ).append( getClfolvl() ).append( " )\n" ); | |||
builder.append(" ( ").append( field_4_clfolvl ).append( " )\n" ); | |||
builder.append( " .ibstFltAutoNum = " ); | |||
builder.append( " (" ).append( getIbstFltAutoNum() ).append( " )\n" ); | |||
builder.append(" ( ").append( field_5_ibstFltAutoNum ).append( " )\n" ); | |||
builder.append( " .grfhic = " ); | |||
builder.append( " (" ).append( getGrfhic() ).append( " )\n" ); | |||
builder.append(" ( ").append( field_6_grfhic == null ? "null" : field_6_grfhic.toString().replaceAll( "\n", "\n " ) ).append( " )\n" ); | |||
builder.append( " .unused3 = " ); | |||
builder.append( " (" ).append( getUnused3() ).append( " )\n" ); | |||
builder.append(" ( ").append( field_7_unused3 ).append( " )\n" ); | |||
builder.append( "[/LFO]\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 |
@@ -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 ) | |||
{ |
@@ -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 |
@@ -381,27 +381,8 @@ public abstract class </xsl:text><xsl:call-template name="outputClassName"/><xsl | |||
<xsl:call-template name="linebreak"/> | |||
<xsl:call-template name="linebreak"/> | |||
<xsl:call-template name="indent"/> | |||
<xsl:text>public String toString() | |||
{ | |||
StringBuilder builder = new StringBuilder(); | |||
</xsl:text> | |||
<xsl:call-template name="indent"/> | |||
<xsl:call-template name="indent"/> | |||
<xsl:text>builder.append("[</xsl:text> | |||
<xsl:value-of select="@name"/> | |||
<xsl:text>]\n");</xsl:text> | |||
<xsl:call-template name="linebreak"/> | |||
<xsl:apply-templates select="//field" mode="tostring"/> | |||
<xsl:call-template name="linebreak"/> | |||
<xsl:call-template name="indent"/> | |||
<xsl:call-template name="indent"/> | |||
<xsl:text>builder.append("[/</xsl:text> | |||
<xsl:value-of select="@name"/> | |||
<xsl:text>]\n"); | |||
return builder.toString(); | |||
} | |||
</xsl:text> | |||
<xsl:call-template name="toString" /> | |||
<xsl:apply-templates select="//field" mode="getset"/> | |||
<xsl:apply-templates select="//field" mode="bits"/> | |||
@@ -549,21 +530,72 @@ public abstract class </xsl:text><xsl:call-template name="outputClassName"/><xsl | |||
} | |||
</xsl:template> | |||
<xsl:template match="field" mode="tostring"> | |||
<xsl:call-template name="indent"/> | |||
<xsl:call-template name="indent"/> | |||
<xsl:text>builder.append(" .</xsl:text> | |||
<xsl:value-of select="recutil:getFieldName(@name,20)"/> | |||
<xsl:text> = ");</xsl:text> | |||
<xsl:call-template name="linebreak"/> | |||
<xsl:call-template name="indent"/> | |||
<xsl:call-template name="indent"/> | |||
<xsl:text>builder.append(" (").append(get</xsl:text> | |||
<xsl:value-of select="recutil:getFieldName1stCap(@name,0)"/> | |||
<xsl:text>()).append(" )\n");</xsl:text> | |||
<xsl:call-template name="linebreak"/> | |||
<xsl:apply-templates select="bit" mode="bittostring"/> | |||
</xsl:template> | |||
<xsl:template name="toString"> | |||
<xsl:call-template name="indent" /> | |||
<xsl:text>public String toString()</xsl:text> | |||
<xsl:call-template name="linebreak" /> | |||
<xsl:call-template name="indent" /> | |||
<xsl:text>{</xsl:text> | |||
<xsl:call-template name="linebreak" /> | |||
<xsl:call-template name="indent" /> | |||
<xsl:call-template name="indent" /> | |||
<xsl:text>StringBuilder builder = new StringBuilder();</xsl:text> | |||
<xsl:call-template name="linebreak" /> | |||
<xsl:call-template name="linebreak" /> | |||
<xsl:call-template name="indent" /> | |||
<xsl:call-template name="indent" /> | |||
<xsl:text>builder.append("[</xsl:text> | |||
<xsl:value-of select="@name" /> | |||
<xsl:text>]\n");</xsl:text> | |||
<xsl:call-template name="linebreak" /> | |||
<xsl:apply-templates select="//field" mode="tostring" /> | |||
<xsl:call-template name="linebreak" /> | |||
<xsl:call-template name="indent" /> | |||
<xsl:call-template name="indent" /> | |||
<xsl:text>builder.append("[/</xsl:text> | |||
<xsl:value-of select="@name" /> | |||
<xsl:text>]"); | |||
return builder.toString(); | |||
} | |||
</xsl:text> | |||
</xsl:template> | |||
<xsl:template match="field" mode="tostring"> | |||
<xsl:variable name="fieldName" | |||
select="recutil:getFieldName(position(),@name,0)" /> | |||
<xsl:call-template name="indent" /> | |||
<xsl:call-template name="indent" /> | |||
<xsl:text>builder.append( " .</xsl:text> | |||
<xsl:value-of select="recutil:getFieldName(@name,20)" /> | |||
<xsl:text> = " );</xsl:text> | |||
<xsl:call-template name="linebreak" /> | |||
<xsl:call-template name="indent" /> | |||
<xsl:call-template name="indent" /> | |||
<xsl:text>builder.append(" ( ").append( </xsl:text> | |||
<xsl:choose> | |||
<xsl:when | |||
test="@type='boolean' or @type='byte' or @type='double' or @type='int' or @type='long' or @type='short'"> | |||
<xsl:value-of select="$fieldName" /> | |||
</xsl:when> | |||
<xsl:otherwise> | |||
<xsl:value-of select="$fieldName" /> | |||
<xsl:text> == null ? "null" : </xsl:text> | |||
<xsl:value-of select="$fieldName" /> | |||
<xsl:text>.toString().replaceAll( "\n", "\n " )</xsl:text> | |||
</xsl:otherwise> | |||
</xsl:choose> | |||
<xsl:text> ).append( " )\n" );</xsl:text> | |||
<xsl:call-template name="linebreak" /> | |||
<xsl:apply-templates select="bit" mode="bittostring" /> | |||
</xsl:template> | |||
<xsl:template match="bit" mode="bittostring"> | |||
<xsl:call-template name="indent"/> |