]> source.dussan.org Git - poi.git/commitdiff
fix LVL#xst definition and processing
authorSergey Vladimirov <sergey@apache.org>
Sun, 23 Sep 2012 13:29:31 +0000 (13:29 +0000)
committerSergey Vladimirov <sergey@apache.org>
Sun, 23 Sep 2012 13:29:31 +0000 (13:29 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1389053 13f79535-47bb-0310-9956-ffa450edef68

src/scratchpad/src/org/apache/poi/hwpf/model/ListLevel.java
src/scratchpad/src/org/apache/poi/hwpf/model/Xst.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hwpf/usermodel/Paragraph.java

index e33ccb2d96de4b327caf27d4b8649a5bcffe40b9..7bdd1fcd9a40366316ecc5250653a0d378c3ec3c 100644 (file)
@@ -20,7 +20,6 @@ package org.apache.poi.hwpf.model;
 import java.util.Arrays;
 
 import org.apache.poi.util.Internal;
-import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
 
@@ -44,7 +43,22 @@ public final class ListLevel
     private byte[] _grpprlChpx;
     private byte[] _grpprlPapx;
     private LVLF _lvlf;
-    private char[] _xst = {};
+    /**
+     * An Xst that specifies the number text that begins each paragraph in this
+     * level. This can contain placeholders for level numbers that are inherited
+     * from the other paragraphs in the list. Any element in the rgtchar field
+     * of this Xst can be a placeholder. Each placeholder is an unsigned 2-byte
+     * integer that specifies the zero-based level that the placeholder is for.
+     * 
+     * Each placeholder MUST have a value that is less than or equal to the
+     * zero-based level of the list that this LVL represents. The indexes of the
+     * placeholders are specified by lvlf.rgbxchNums. Placeholders that
+     * correspond to levels that do not have a number sequence (see lvlf.nfc)
+     * MUST be ignored. If this level uses bullets (see lvlf.nfc), the cch field
+     * of this Xst MUST be equal to 0x0001, and this MUST NOT contain any
+     * placeholders.
+     */
+    private Xst _xst = new Xst();
 
     ListLevel()
     {
@@ -67,11 +81,11 @@ public final class ListLevel
         if ( numbered )
         {
             _lvlf.getRgbxchNums()[0] = 1;
-            _xst = new char[] { (char) level, '.' };
+            _xst = new Xst("" + (char) level + ".");
         }
         else
         {
-            _xst = new char[] { '\u2022' };
+            _xst = new Xst("\u2022");
         }
     }
 
@@ -84,7 +98,7 @@ public final class ListLevel
         _lvlf.setJc( (byte) alignment );
         _grpprlChpx = numberProperties;
         _grpprlPapx = entryProperties;
-        _xst = numberText.toCharArray();
+        _xst = new Xst(numberText);
     }
 
     public boolean equals( Object obj )
@@ -96,7 +110,7 @@ public final class ListLevel
         return lvl._lvlf.equals( this._lvlf )
                 && Arrays.equals( lvl._grpprlChpx, _grpprlChpx )
                 && Arrays.equals( lvl._grpprlPapx, _grpprlPapx )
-                && Arrays.equals( lvl._xst, _xst );
+                && lvl._xst.equals( this._xst );
     }
 
     /**
@@ -132,17 +146,13 @@ public final class ListLevel
 
     public String getNumberText()
     {
-        if ( _xst.length < 2 )
-            return null;
-
-        return new String( _xst, 0, _xst.length - 1 );
+        return _xst.getAsJavaString();
     }
 
     public int getSizeInBytes()
     {
         return LVLF.getSize() + _lvlf.getCbGrpprlChpx()
-                + _lvlf.getCbGrpprlPapx() + LittleEndian.SHORT_SIZE
-                + _xst.length * LittleEndian.SHORT_SIZE;
+                + _lvlf.getCbGrpprlPapx() + _xst.getSize();
     }
 
     public int getStartAt()
@@ -173,6 +183,9 @@ public final class ListLevel
         System.arraycopy( data, offset, _grpprlChpx, 0, _lvlf.getCbGrpprlChpx() );
         offset += _lvlf.getCbGrpprlChpx();
 
+        _xst = new Xst( data, offset );
+        offset += _xst.getSize();
+
         /*
          * "If this level uses bullets (see lvlf.nfc), the cch field of this Xst
          * MUST be equal to 0x0001, and this MUST NOT contain any placeholders."
@@ -181,45 +194,12 @@ public final class ListLevel
          */
         if ( _lvlf.getNfc() == 0x17 )
         {
-            int cch = LittleEndian.getUShort( data, offset );
-            offset += LittleEndian.SHORT_SIZE;
-
-            if ( cch != 1 )
+            if ( _xst.getCch() != 1 )
             {
                 logger.log( POILogger.WARN, "LVL at offset ",
                         Integer.valueOf( startOffset ),
                         " has nfc == 0x17 (bullets), but cch != 1 (",
-                        Integer.valueOf( cch ), ")" );
-            }
-
-            _xst = new char[cch];
-            for ( int x = 0; x < cch; x++ )
-            {
-                _xst[x] = (char) LittleEndian.getShort( data, offset );
-                offset += LittleEndian.SHORT_SIZE;
-            }
-        }
-        else
-        {
-            int cch = LittleEndian.getUShort( data, offset );
-            offset += LittleEndian.SHORT_SIZE;
-
-            if ( cch > 0 )
-            {
-                _xst = new char[cch];
-                for ( int x = 0; x < cch; x++ )
-                {
-                    _xst[x] = (char) LittleEndian.getShort( data, offset );
-                    offset += LittleEndian.SHORT_SIZE;
-                }
-            }
-            else
-            {
-                logger.log( POILogger.WARN, "LVL.xst.cch <= 0: ",
-                        Integer.valueOf( cch ) );
-                /* sometimes numberTextLength<0 */
-                /* by derjohng */
-                _xst = new char[] {};
+                        Integer.valueOf( _xst.getCch() ), ")" );
             }
         }
 
@@ -271,24 +251,8 @@ public final class ListLevel
         System.arraycopy( _grpprlChpx, 0, buf, offset, _grpprlChpx.length );
         offset += _grpprlChpx.length;
 
-        if ( _lvlf.getNfc() == 0x17 )
-        {
-            LittleEndian.putUShort( buf, offset, 1 );
-            offset += LittleEndian.SHORT_SIZE;
-
-            LittleEndian.putUShort( buf, offset, _xst[0] );
-            offset += LittleEndian.SHORT_SIZE;
-        }
-        else
-        {
-            LittleEndian.putUShort( buf, offset, _xst.length );
-            offset += LittleEndian.SHORT_SIZE;
-            for ( char c : _xst )
-            {
-                LittleEndian.putUShort( buf, offset, c );
-                offset += LittleEndian.SHORT_SIZE;
-            }
-        }
+        _xst.serialize( buf, offset );
+        offset += _xst.getSize();
 
         return buf;
     }
@@ -300,6 +264,6 @@ public final class ListLevel
                 + "\n"
                 + ( "PAPX's grpprl: " + Arrays.toString( _grpprlPapx ) + "\n" )
                 + ( "CHPX's grpprl: " + Arrays.toString( _grpprlChpx ) + "\n" )
-                + ( "xst: " + Arrays.toString( _xst ) + "\n" );
+                + ( "xst: " + _xst + "\n" );
     }
 }
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/Xst.java b/src/scratchpad/src/org/apache/poi/hwpf/model/Xst.java
new file mode 100644 (file)
index 0000000..6a596a4
--- /dev/null
@@ -0,0 +1,131 @@
+package org.apache.poi.hwpf.model;
+
+import java.util.Arrays;
+
+import org.apache.poi.util.LittleEndian;
+
+/**
+ * The Xst structure is a string. The string is prepended by its length and is
+ * not null-terminated.
+ * <p>
+ * Documentation quoted from Page 424 of 621. [MS-DOC] -- v20110315 Word (.doc)
+ * Binary File Format
+ * 
+ * @author Sergey Vladimirov (vlsergey {at} gmail {dot} com)
+ */
+public class Xst
+{
+
+    /**
+     * An unsigned integer that specifies the number of characters that are
+     * contained in the rgtchar array.
+     */
+    private int _cch;
+
+    /**
+     * An array of 16-bit Unicode characters that make up a string.
+     */
+    private char[] _rgtchar;
+
+    public Xst()
+    {
+        _cch = 0;
+        _rgtchar = new char[0];
+    }
+
+    public Xst( byte[] data, int startOffset )
+    {
+        int offset = startOffset;
+
+        _cch = LittleEndian.getUShort( data, offset );
+        offset += LittleEndian.SHORT_SIZE;
+
+        _rgtchar = new char[_cch];
+        for ( int x = 0; x < _cch; x++ )
+        {
+            _rgtchar[x] = (char) LittleEndian.getShort( data, offset );
+            offset += LittleEndian.SHORT_SIZE;
+        }
+
+    }
+
+    public Xst( String str )
+    {
+        _cch = str.length();
+        _rgtchar = str.toCharArray();
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        if ( this == obj )
+            return true;
+        if ( obj == null )
+            return false;
+        if ( getClass() != obj.getClass() )
+            return false;
+        Xst other = (Xst) obj;
+        if ( _cch != other._cch )
+            return false;
+        if ( !Arrays.equals( _rgtchar, other._rgtchar ) )
+            return false;
+        return true;
+    }
+
+    public String getAsJavaString()
+    {
+        return new String( _rgtchar );
+    }
+
+    /**
+     * An unsigned integer that specifies the number of characters that are
+     * contained in the rgtchar array.
+     */
+    public int getCch()
+    {
+        return _cch;
+    }
+
+    /**
+     * An array of 16-bit Unicode characters that make up a string.
+     */
+    public char[] getRgtchar()
+    {
+        return _rgtchar;
+    }
+
+    public int getSize()
+    {
+        return LittleEndian.SHORT_SIZE + _rgtchar.length * 2;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + _cch;
+        result = prime * result + Arrays.hashCode( _rgtchar );
+        return result;
+    }
+
+    public void serialize( byte[] data, int startOffset )
+    {
+        int offset = startOffset;
+
+        LittleEndian.putUShort( data, offset, _cch );
+        offset += LittleEndian.SHORT_SIZE;
+
+        for ( char c : _rgtchar )
+        {
+            LittleEndian.putShort( data, offset, (short) c );
+            offset += LittleEndian.SHORT_SIZE;
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        return new String( "Xst [" + _cch + "; " + _rgtchar + "]" );
+    }
+}
index 6f2d21fdd988a31b48b854f46773284286e0e411..65f907691ba906a94eae6953ce4f617373140fd6 100644 (file)
@@ -607,7 +607,7 @@ public short getStyleIndex()
 
     public boolean isInList()
     {
-        return getIlvl() != 0 && getIlfo() != 0x000 && getIlfo() != 0xF801;
+        return getIlfo() != 0x000 && getIlfo() != 0xF801;
     }
 
   /**