]> source.dussan.org Git - poi.git/commitdiff
A few text handling related fixes
authorAndreas Beeker <kiwiwings@apache.org>
Wed, 20 May 2015 23:07:08 +0000 (23:07 +0000)
committerAndreas Beeker <kiwiwings@apache.org>
Wed, 20 May 2015 23:07:08 +0000 (23:07 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/common_sl@1680695 13f79535-47bb-0310-9956-ffa450edef68

src/scratchpad/src/org/apache/poi/hslf/model/textproperties/TextPropCollection.java
src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java
src/scratchpad/src/org/apache/poi/hslf/record/TxMasterStyleAtom.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java
src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestCounts.java
src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestNotesText.java

index d856614eb3ebc3ce4855f296e2c333ca2cbdc8a0..a5af73b3d3d834d096ae941de78d3109f0281e6a 100644 (file)
 
 package org.apache.poi.hslf.model.textproperties;
 
-import java.io.IOException;
-import java.io.OutputStream;
+import java.io.*;
 import java.util.*;
 
 import org.apache.poi.hslf.record.StyleTextPropAtom;
+import org.apache.poi.util.HexDump;
 import org.apache.poi.util.LittleEndian;
 
 /**
@@ -33,8 +33,9 @@ import org.apache.poi.util.LittleEndian;
 public class TextPropCollection {
        private int charactersCovered;
        private short reservedField;
-       private List<TextProp> textPropList;
+       private final List<TextProp> textPropList = new ArrayList<TextProp>();
     private int maskSpecial = 0;
+    private final TextProp[] potentialPropList;
     
     public int getSpecialMask() { return maskSpecial; }
 
@@ -45,8 +46,7 @@ public class TextPropCollection {
        
        /** Fetch the TextProp with this name, or null if it isn't present */
        public TextProp findByName(String textPropName) {
-               for(int i=0; i<textPropList.size(); i++) {
-                       TextProp prop = textPropList.get(i);
+               for(TextProp prop : textPropList) {
                        if(prop.getName().equals(textPropName)) {
                                return prop;
                        }
@@ -57,45 +57,73 @@ public class TextPropCollection {
        /** Add the TextProp with this name to the list */
        public TextProp addWithName(String name) {
                // Find the base TextProp to base on
+               TextProp existing = findByName(name);
+               if (existing != null) return existing;
+               
                TextProp base = null;
-               for(int i=0; i < StyleTextPropAtom.characterTextPropTypes.length; i++) {
-                       if(StyleTextPropAtom.characterTextPropTypes[i].getName().equals(name)) {
-                               base = StyleTextPropAtom.characterTextPropTypes[i];
-                       }
-               }
-               for(int i=0; i < StyleTextPropAtom.paragraphTextPropTypes.length; i++) {
-                       if(StyleTextPropAtom.paragraphTextPropTypes[i].getName().equals(name)) {
-                               base = StyleTextPropAtom.paragraphTextPropTypes[i];
-                       }
+               for (TextProp tp : potentialPropList) {
+                   if (tp.getName().equals(name)) {
+                       base = tp;
+                       break;
+                   }
                }
+               
                if(base == null) {
-                       throw new IllegalArgumentException("No TextProp with name " + name + " is defined to add from");
+                       throw new IllegalArgumentException("No TextProp with name " + name + " is defined to add from. "
+                       + "Character and paragraphs have their own properties/names.");
                }
                
                // Add a copy of this property, in the right place to the list
                TextProp textProp = base.clone();
-               int pos = 0;
-               for(int i=0; i<textPropList.size(); i++) {
-                       TextProp curProp = textPropList.get(i);
-                       if(textProp.getMask() > curProp.getMask()) {
-                               pos++;
-                       }
-               }
-               textPropList.add(pos, textProp);
+               addProp(textProp);
                return textProp;
        }
+       
+       /**
+        * Add the property at the correct position. Replaces an existing property with the same name.
+        *
+        * @param textProp the property to be added
+        */
+       public void addProp(TextProp textProp) {
+           assert(textProp != null);
+           
+        int pos = 0;
+        boolean found = false;
+        for (TextProp curProp : potentialPropList) {
+            String potName = curProp.getName();
+            if (pos == textPropList.size() || potName.equals(textProp.getName())) {
+                if (textPropList.size() > pos && potName.equals(textPropList.get(pos).getName())) {
+                    // replace existing prop (with same name)
+                    textPropList.set(pos, textProp);
+                } else {
+                    textPropList.add(pos, textProp);
+                }
+                found = true;
+                break;
+            }
+            
+            if (potName.equals(textPropList.get(pos).getName())) {
+                pos++;
+            }
+        }
+
+        if(!found) {
+            String err = "TextProp with name " + textProp.getName() + " doesn't belong to this collection.";
+            throw new IllegalArgumentException(err);
+        }
+       }
 
        /**
         * For an existing set of text properties, build the list of 
         *  properties coded for in a given run of properties.
         * @return the number of bytes that were used encoding the properties list
         */
-       public int buildTextPropList(int containsField, TextProp[] potentialProperties, byte[] data, int dataOffset) {
+       public int buildTextPropList(int containsField, byte[] data, int dataOffset) {
                int bytesPassed = 0;
 
                // For each possible entry, see if we match the mask
                // If we do, decode that, save it, and shuffle on
-               for(TextProp tp : potentialProperties) {
+               for(TextProp tp : potentialPropList) {
                        // Check there's still data left to read
 
                        // Check if this property is found in the mask
@@ -123,7 +151,7 @@ public class TextPropCollection {
                 }
                                prop.setValue(val);
                                bytesPassed += prop.getSize();
-                               textPropList.add(prop);
+                               addProp(prop);
                        }
                }
 
@@ -136,20 +164,18 @@ public class TextPropCollection {
         *  or character) which will be groked via a subsequent call to
         *  buildTextPropList().
         */
-       public TextPropCollection(int charactersCovered, short reservedField) {
+       public TextPropCollection(int charactersCovered, short reservedField, TextProp[] potentialPropList) {
                this.charactersCovered = charactersCovered;
                this.reservedField = reservedField;
-               textPropList = new ArrayList<TextProp>();
+               this.potentialPropList = potentialPropList;
        }
 
        /**
         * Create a new collection of text properties (be they paragraph
         *  or character) for a run of text without any
         */
-       public TextPropCollection(int textSize) {
-               charactersCovered = textSize;
-               reservedField = -1;
-               textPropList = new ArrayList<TextProp>();
+       public TextPropCollection(int textSize, TextProp[] potentialPropList) {
+           this(textSize, (short)-1, potentialPropList);
        }
        
     /**
@@ -158,12 +184,13 @@ public class TextPropCollection {
        public void copy(TextPropCollection other) {
         this.charactersCovered = other.charactersCovered;
         this.reservedField = other.reservedField;
+        this.maskSpecial = other.maskSpecial;
         this.textPropList.clear();
         for (TextProp tp : other.textPropList) {
             TextProp tpCopy = (tp instanceof BitMaskTextProp)
                 ? ((BitMaskTextProp)tp).cloneAll()
                 : tp.clone();
-            this.textPropList.add(tpCopy);
+            addProp(tpCopy);
         }
        }
        
@@ -178,7 +205,7 @@ public class TextPropCollection {
        /**
         * Writes out to disk the header, and then all the properties
         */
-       public void writeOut(OutputStream o, TextProp[] potentialProperties) throws IOException {
+       public void writeOut(OutputStream o) throws IOException {
                // First goes the number of characters we affect
                StyleTextPropAtom.writeLittleEndian(charactersCovered,o);
 
@@ -201,12 +228,17 @@ public class TextPropCollection {
                StyleTextPropAtom.writeLittleEndian(mask,o);
 
                // Then the contents of all the properties
-               for (TextProp potProp : potentialProperties) {
+               for (TextProp potProp : potentialPropList) {
                for(TextProp textProp : textPropList) {
                    if (!textProp.getName().equals(potProp.getName())) continue;
                 int val = textProp.getValue();
-                if (textProp instanceof BitMaskTextProp && val == 0) {
+                if (textProp instanceof BitMaskTextProp && val == 0
+                    && !(textProp instanceof ParagraphFlagsTextProp)
+//                    && !(textProp instanceof CharFlagsTextProp)
+                ) {
                     // don't add empty properties, as they can't be recognized while reading
+                    // strangely this doesn't apply for ParagraphFlagsTextProp in contrast
+                    // to the documentation in 2.9.20 TextPFException
                     continue;
                 } else if (textProp.getSize() == 2) {
                                StyleTextPropAtom.writeLittleEndian((short)val,o);
@@ -264,4 +296,26 @@ public class TextPropCollection {
         return true;
     }
 
+    public String toString() {
+        StringBuilder out = new StringBuilder();
+        out.append("  chars covered: " + getCharactersCovered());
+        out.append("  special mask flags: 0x" + HexDump.toHex(getSpecialMask()) + "\n");
+        for(TextProp p : getTextPropList()) {
+            out.append("    " + p.getName() + " = " + p.getValue() );
+            out.append(" (0x" + HexDump.toHex(p.getValue()) + ")\n");
+        }
+
+        out.append("  bytes that would be written: \n");
+
+        try {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            writeOut(baos);
+            byte[] b = baos.toByteArray();
+            out.append(HexDump.dump(b, 0, 0));
+        } catch (Exception e ) {
+            e.printStackTrace();
+        }
+        
+        return out.toString();
+    }
 }
index 0e347446821962deb74b4489341cb81be0b6ad66..e2f765723b761c00c137b34b977d3130b23415ef 100644 (file)
@@ -218,15 +218,23 @@ public final class StyleTextPropAtom extends RecordAtom
         charStyles = new ArrayList<TextPropCollection>();
 
         TextPropCollection defaultParagraphTextProps =
-                new TextPropCollection(parentTextSize, (short)0);
+                new TextPropCollection(parentTextSize, (short)0, paragraphTextPropTypes);
+        defaultParagraphTextProps.addWithName("paragraph_flags");
         paragraphStyles.add(defaultParagraphTextProps);
 
         TextPropCollection defaultCharacterTextProps =
-                new TextPropCollection(parentTextSize);
+                new TextPropCollection(parentTextSize, characterTextPropTypes);
+        defaultCharacterTextProps.addWithName("char_flags");
         charStyles.add(defaultCharacterTextProps);
 
         // Set us as now initialised
         initialised = true;
+
+        try {
+            updateRawContents();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
     }
 
 
@@ -245,10 +253,6 @@ public final class StyleTextPropAtom extends RecordAtom
         //  on the properties
         updateRawContents();
 
-        // Now ensure that the header size is correct
-        int newSize = rawContents.length + reserved.length;
-        LittleEndian.putInt(_header,4,newSize);
-
         // Write out the (new) header
         out.write(_header);
 
@@ -265,9 +269,14 @@ public final class StyleTextPropAtom extends RecordAtom
      *  contains, so we can go ahead and initialise ourselves.
      */
     public void setParentTextSize(int size) {
+        // if (initialised) return;
+        
         int pos = 0;
         int textHandled = 0;
 
+        paragraphStyles.clear();
+        charStyles.clear();
+        
         // While we have text in need of paragraph stylings, go ahead and
         // grok the contents as paragraph formatting data
         int prsize = size;
@@ -286,9 +295,8 @@ public final class StyleTextPropAtom extends RecordAtom
             pos += 4;
 
             // Now make sense of those properties
-            TextPropCollection thisCollection = new TextPropCollection(textLen, indent);
-            int plSize = thisCollection.buildTextPropList(
-                    paraFlags, paragraphTextPropTypes, rawContents, pos);
+            TextPropCollection thisCollection = new TextPropCollection(textLen, indent, paragraphTextPropTypes);
+            int plSize = thisCollection.buildTextPropList(paraFlags, rawContents, pos);
             pos += plSize;
 
             // Save this properties set
@@ -323,9 +331,8 @@ public final class StyleTextPropAtom extends RecordAtom
 
             // Now make sense of those properties
             // (Assuming we actually have some)
-            TextPropCollection thisCollection = new TextPropCollection(textLen, no_val);
-            int chSize = thisCollection.buildTextPropList(
-                               charFlags, characterTextPropTypes, rawContents, pos);
+            TextPropCollection thisCollection = new TextPropCollection(textLen, no_val, characterTextPropTypes);
+            int chSize = thisCollection.buildTextPropList(charFlags, rawContents, pos);
             pos += chSize;
 
             // Save this properties set
@@ -363,33 +370,32 @@ public final class StyleTextPropAtom extends RecordAtom
      * Updates the cache of the raw contents. Serialised the styles out.
      */
     private void updateRawContents() throws IOException {
-        if(!initialised) {
-            // We haven't groked the styles since creation, so just stick
-            // with what we found
-            return;
-        }
+        if (initialised) {
+            // Only update the style bytes, if the styles have been potentially
+            // changed
 
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
-        // First up, we need to serialise the paragraph properties
-        for(int i=0; i<paragraphStyles.size(); i++) {
-            TextPropCollection tpc = paragraphStyles.get(i);
-            tpc.writeOut(baos, paragraphTextPropTypes);
-        }
-
-        // Now, we do the character ones
-        for(int i=0; i<charStyles.size(); i++) {
-            TextPropCollection tpc = charStyles.get(i);
-            tpc.writeOut(baos, characterTextPropTypes);
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    
+            // First up, we need to serialise the paragraph properties
+            for(TextPropCollection tpc : paragraphStyles) {
+                // ensure, that the paragraphs flags exist, no matter if anthing is set
+                tpc.addWithName(ParagraphFlagsTextProp.NAME);
+                tpc.writeOut(baos);
+            }
+    
+            // Now, we do the character ones
+            for(TextPropCollection tpc : charStyles) {
+                // ditto for the char flags
+                tpc.addWithName(CharFlagsTextProp.NAME);
+                tpc.writeOut(baos);
+            }
+    
+            rawContents = baos.toByteArray();
         }
-
-        rawContents = baos.toByteArray();
-    }
-
-    public void setRawContents(byte[] bytes) {
-        rawContents = bytes;
-        reserved = new byte[0];
-        initialised = false;
+        
+        // Now ensure that the header size is correct
+        int newSize = rawContents.length + reserved.length;
+        LittleEndian.putInt(_header,4,newSize);
     }
 
     /**
@@ -398,6 +404,8 @@ public final class StyleTextPropAtom extends RecordAtom
     public void clearStyles() {
         paragraphStyles.clear();
         charStyles.clear();
+        reserved = new byte[0];
+        initialised = true;
     }
     
     /**
@@ -406,7 +414,7 @@ public final class StyleTextPropAtom extends RecordAtom
      * @return the new TextPropCollection, which will then be in the list
      */
     public TextPropCollection addParagraphTextPropCollection(int charactersCovered) {
-        TextPropCollection tpc = new TextPropCollection(charactersCovered, (short)0);
+        TextPropCollection tpc = new TextPropCollection(charactersCovered, (short)0, paragraphTextPropTypes);
         paragraphStyles.add(tpc);
         return tpc;
     }
@@ -416,7 +424,7 @@ public final class StyleTextPropAtom extends RecordAtom
      * @return the new TextPropCollection, which will then be in the list
      */
     public TextPropCollection addCharacterTextPropCollection(int charactersCovered) {
-        TextPropCollection tpc = new TextPropCollection(charactersCovered);
+        TextPropCollection tpc = new TextPropCollection(charactersCovered, characterTextPropTypes);
         charStyles.add(tpc);
         return tpc;
     }
@@ -438,51 +446,25 @@ public final class StyleTextPropAtom extends RecordAtom
         } else {
 
             out.append("Paragraph properties\n");
-
             for(TextPropCollection pr : getParagraphStyles()) {
-                out.append("  chars covered: " + pr.getCharactersCovered());
-                out.append("  special mask flags: 0x" + HexDump.toHex(pr.getSpecialMask()) + "\n");
-                for(TextProp p : pr.getTextPropList()) {
-                    out.append("    " + p.getName() + " = " + p.getValue() );
-                    out.append(" (0x" + HexDump.toHex(p.getValue()) + ")\n");
-                }
-
-                out.append("  para bytes that would be written: \n");
-
-                try {
-                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                    pr.writeOut(baos, paragraphTextPropTypes);
-                    byte[] b = baos.toByteArray();
-                    out.append(HexDump.dump(b, 0, 0));
-                } catch (Exception e ) {
-                    e.printStackTrace();
-                }
+                out.append(pr);
             }
 
             out.append("Character properties\n");
             for(TextPropCollection pr : getCharacterStyles()) {
-                out.append("  chars covered: " + pr.getCharactersCovered() );
-                out.append("  special mask flags: 0x" + HexDump.toHex(pr.getSpecialMask()) + "\n");
-                for(TextProp p : pr.getTextPropList()) {
-                    out.append("    " + p.getName() + " = " + p.getValue() );
-                    out.append(" (0x" + HexDump.toHex(p.getValue()) + ")\n");
-                }
-
-                out.append("  char bytes that would be written: \n");
-
-                try {
-                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                    pr.writeOut(baos, characterTextPropTypes);
-                    byte[] b = baos.toByteArray();
-                    out.append(HexDump.dump(b, 0, 0));
-                } catch (Exception e ) {
-                    e.printStackTrace();
-                }
+                out.append(pr);
             }
+            
+            out.append("Reserved bytes\n");
+            out.append( HexDump.dump(reserved, 0, 0) );
         }
 
         out.append("  original byte stream \n");
-        out.append( HexDump.dump(rawContents, 0, 0) );
+        
+        byte buf[] = new byte[rawContents.length+reserved.length];
+        System.arraycopy(rawContents, 0, buf, 0, rawContents.length);
+        System.arraycopy(reserved, 0, buf, rawContents.length, reserved.length);
+        out.append( HexDump.dump(buf, 0, 0) );
 
         return out.toString();
     }
index 4037d11e44edfc1c31c95561c25ef7e0e254fc0c..8d6626dc2b26cd93bd49d5f00ec9581d6500c01c 100644 (file)
@@ -182,14 +182,14 @@ public final class TxMasterStyleAtom extends RecordAtom {
 
             head = LittleEndian.getInt(_data, pos);
             pos += LittleEndian.INT_SIZE;
-            TextPropCollection prprops = new TextPropCollection(0);
-            pos += prprops.buildTextPropList( head, getParagraphProps(type, j), _data, pos);
+            TextPropCollection prprops = new TextPropCollection(0, getParagraphProps(type, j));
+            pos += prprops.buildTextPropList( head, _data, pos);
             prstyles[j] = prprops;
 
             head = LittleEndian.getInt(_data, pos);
             pos += LittleEndian.INT_SIZE;
-            TextPropCollection chprops = new TextPropCollection(0);
-            pos += chprops.buildTextPropList( head, getCharacterProps(type, j), _data, pos);
+            TextPropCollection chprops = new TextPropCollection(0, getCharacterProps(type, j));
+            pos += chprops.buildTextPropList( head, _data, pos);
             chstyles[j] = chprops;
         }
 
index b9c02dc7f34c6f4e2f0d6a2b32d4e0933065efa1..a6d6e5b49bccccf9f64d538d09749929d44bb4b6 100644 (file)
@@ -18,6 +18,8 @@
 package org.apache.poi.hslf.usermodel;\r
 \r
 import java.awt.Color;\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.IOException;\r
 import java.util.*;\r
 \r
 import org.apache.poi.hslf.model.PPFont;\r
@@ -36,7 +38,7 @@ import org.apache.poi.util.*;
 \r
 public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {\r
     protected static POILogger logger = POILogFactory.getLogger(HSLFTextParagraph.class);\r
-    \r
+\r
     /**\r
      * How to align the text\r
      */\r
@@ -44,16 +46,16 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
     /* package */ static final int AlignCenter = 1;\r
     /* package */ static final int AlignRight = 2;\r
     /* package */ static final int AlignJustify = 3;\r
-    \r
-    \r
+\r
+\r
     // Note: These fields are protected to help with unit testing\r
        //   Other classes shouldn't really go playing with them!\r
        private final TextHeaderAtom _headerAtom;\r
-       private final TextBytesAtom  _byteAtom;\r
-       private final TextCharsAtom  _charAtom;\r
+       private TextBytesAtom  _byteAtom;\r
+       private TextCharsAtom  _charAtom;\r
        private StyleTextPropAtom _styleAtom;\r
-       private TextPropCollection _paragraphStyle = new TextPropCollection(1);\r
-       \r
+       private TextPropCollection _paragraphStyle = new TextPropCollection(1, StyleTextPropAtom.paragraphTextPropTypes);\r
+\r
     protected TextRulerAtom _ruler;\r
        protected List<HSLFTextRun> _runs = new ArrayList<HSLFTextRun>();\r
        protected HSLFTextShape _parentShape;\r
@@ -70,7 +72,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
 \r
        /**\r
     * Constructs a Text Run from a Unicode text block.\r
-    * Either a {@link TextCharsAtom} or a {@link TextBytesAtom} needs to be provided. \r
+    * Either a {@link TextCharsAtom} or a {@link TextBytesAtom} needs to be provided.\r
     *\r
     * @param tha the TextHeaderAtom that defines what's what\r
     * @param tba the TextBytesAtom containing the text or null if {@link TextCharsAtom} is provided\r
@@ -105,7 +107,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
        public void addTextRun(HSLFTextRun run) {\r
            _runs.add(run);\r
        }\r
-       \r
+\r
        /**\r
         * Fetch the rich text runs (runs of text with the same styling) that\r
         *  are contained within this block of text\r
@@ -117,11 +119,11 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
        public TextPropCollection getParagraphStyle() {\r
            return _paragraphStyle;\r
        }\r
-       \r
+\r
        public void setParagraphStyle(TextPropCollection paragraphStyle) {\r
            _paragraphStyle = paragraphStyle;\r
        }\r
-       \r
+\r
        /**\r
      * Supply the Sheet we belong to, which might have an assigned SlideShow\r
      * Also passes it on to our child RichTextRuns\r
@@ -161,14 +163,14 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
     }\r
 \r
     /**\r
-     * Sets the index of the paragraph in the SLWT container \r
+     * Sets the index of the paragraph in the SLWT container\r
      *\r
      * @param index\r
      */\r
     protected void setIndex(int index) {\r
         if (_headerAtom != null) _headerAtom.setIndex(index);\r
     }\r
-    \r
+\r
     /**\r
     * Returns the type of the text, from the TextHeaderAtom.\r
     * Possible values can be seen from TextHeaderAtom\r
@@ -177,7 +179,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
     public int getRunType() {\r
         return (_headerAtom != null) ? _headerAtom.getTextType() : -1;\r
     }\r
-    \r
+\r
     /**\r
      * Is this Text Run one from a {@link PPDrawing}, or is it\r
      *  one from the {@link SlideListWithText}?\r
@@ -208,12 +210,12 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
     public Record[] getRecords(){\r
         return _records;\r
     }\r
-    \r
+\r
     /** Numbered List info */\r
        public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) {\r
                this.styleTextProp9Atom = styleTextProp9Atom;\r
        }\r
-       \r
+\r
     /** Numbered List info */\r
        public StyleTextProp9Atom getStyleTextProp9Atom() {\r
                return this.styleTextProp9Atom;\r
@@ -221,7 +223,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
 \r
     /** Characters covered */\r
        public StyleTextPropAtom getStyleTextPropAtom() {\r
-               return this._styleAtom;         \r
+               return this._styleAtom;\r
        }\r
 \r
        /**\r
@@ -258,56 +260,14 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
     public void setParaTextPropVal(String propName, int val) {\r
         // Ensure we have the StyleTextProp atom we're going to need\r
         if(_paragraphStyle == null) {\r
-            ensureStyleAtomPresent();\r
-            // paragraphStyle will now be defined\r
+            _styleAtom = findStyleAtomPresent(_headerAtom, -1);\r
+            _paragraphStyle = _styleAtom.getParagraphStyles().get(0);\r
         }\r
 \r
         assert(_paragraphStyle!=null);\r
         TextProp tp = fetchOrAddTextProp(_paragraphStyle, propName);\r
         tp.setValue(val);\r
     }\r
-       \r
-    /**\r
-     * Ensure a StyleTextPropAtom is present for this run,\r
-     *  by adding if required. Normally for internal TextRun use.\r
-     */\r
-    protected StyleTextPropAtom ensureStyleAtomPresent() {\r
-        if (_styleAtom != null) {\r
-            return _styleAtom;\r
-        }\r
-        \r
-        _styleAtom = ensureStyleAtomPresent(_headerAtom, _byteAtom, _charAtom);\r
-        _paragraphStyle = _styleAtom.getParagraphStyles().get(0);\r
-        \r
-        return _styleAtom;\r
-    }\r
-\r
-    protected static StyleTextPropAtom ensureStyleAtomPresent(TextHeaderAtom header, TextBytesAtom tbytes, TextCharsAtom tchars) {\r
-        RecordContainer wrapper = header.getParentRecord();\r
-        StyleTextPropAtom styleAtom = null;\r
-        \r
-        boolean afterHeader = false;\r
-        for (Record record : wrapper.getChildRecords()) {\r
-            if (afterHeader && record.getRecordType() == RecordTypes.TextHeaderAtom.typeID) break;\r
-            afterHeader |= (header == record);\r
-            if (afterHeader && record.getRecordType() == RecordTypes.StyleTextPropAtom.typeID) {\r
-                styleAtom = (StyleTextPropAtom)record;\r
-                break;\r
-            }\r
-        }\r
-        \r
-        if (styleAtom != null) return styleAtom;\r
-        \r
-        String rawText = (tchars != null) ? tchars.getText() : tbytes.getText();\r
-        \r
-        // Create a new one at the right size\r
-        styleAtom = new StyleTextPropAtom(rawText.length()+1);\r
-\r
-        // Add the new StyleTextPropAtom after the TextCharsAtom / TextBytesAtom\r
-        wrapper.addChildAfter(styleAtom, (tbytes == null ? tchars : tbytes));\r
-\r
-        return styleAtom;\r
-    }\r
 \r
     @Override\r
     public Iterator<HSLFTextRun> iterator() {\r
@@ -325,7 +285,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
         int val = (int)(leftMargin*HSLFShape.MASTER_DPI/HSLFShape.POINT_DPI);\r
         setParaTextPropVal("text.offset", val);\r
     }\r
-    \r
+\r
     @Override\r
     public double getRightMargin() {\r
         // TODO: find out, how to determine this value\r
@@ -336,7 +296,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
     public void setRightMargin(double rightMargin) {\r
         // TODO: find out, how to set this value\r
     }\r
-    \r
+\r
     @Override\r
     public double getIndent() {\r
         int val = getParaTextPropVal("bullet.offset");\r
@@ -378,7 +338,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
         }\r
         setParaTextPropVal("alignment", alignInt);\r
     }\r
-    \r
+\r
     @Override\r
     public org.apache.poi.sl.usermodel.TextParagraph.TextAlign getTextAlign() {\r
         switch (getParaTextPropVal("alignment")) {\r
@@ -408,7 +368,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
     @Override\r
     public BulletStyle getBulletStyle() {\r
         if (getBulletChar() == 0) return null;\r
-        \r
+\r
         return new BulletStyle() {\r
             public String getBulletCharacter() {\r
                 char chr =  HSLFTextParagraph.this.getBulletChar();\r
@@ -441,7 +401,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
         _parentShape = parentShape;\r
     }\r
 \r
-       \r
+\r
     /**\r
     *\r
     * @return indentation level\r
@@ -622,7 +582,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
        int val = getParaTextPropVal("spaceafter");\r
        return val == -1 ? 0 : val;\r
    }\r
-       \r
+\r
    /**\r
     * Returns the named TextProp, either by fetching it (if it exists) or adding it\r
     *  (if it didn't)\r
@@ -661,7 +621,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
    protected void setFlag(int index, boolean value) {\r
        // Ensure we have the StyleTextProp atom we're going to need\r
        if(_paragraphStyle == null) {\r
-           _paragraphStyle = new TextPropCollection(1);\r
+           _paragraphStyle = new TextPropCollection(1, StyleTextPropAtom.paragraphTextPropTypes);\r
        }\r
 \r
        BitMaskTextProp prop = (BitMaskTextProp) fetchOrAddTextProp(_paragraphStyle, ParagraphFlagsTextProp.NAME);\r
@@ -685,81 +645,120 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
            }\r
            lastRun = ltr.get(ltr.size()-1);\r
            assert(lastRun.getRawText() != null);\r
-       }       \r
+       }\r
    }\r
-   \r
+\r
+   /**\r
+    * Search for a StyleTextPropAtom is for this text header (list of paragraphs)\r
+    * \r
+    * @param header the header\r
+    * @param textLen the length of the rawtext, or -1 if the length is not known\r
+    */\r
+   private static StyleTextPropAtom findStyleAtomPresent(TextHeaderAtom header, int textLen) {\r
+       boolean afterHeader = false;\r
+       StyleTextPropAtom style = null;\r
+       for (Record record : header.getParentRecord().getChildRecords()) {\r
+           if (afterHeader && record.getRecordType() == RecordTypes.TextHeaderAtom.typeID) {\r
+               // already on the next header, quit searching\r
+               break;\r
+           }\r
+           afterHeader |= (header == record);\r
+           if (afterHeader && record.getRecordType() == RecordTypes.StyleTextPropAtom.typeID) {\r
+               // found it\r
+               style = (StyleTextPropAtom)record;\r
+           }\r
+       }\r
+\r
+       if (style == null) {\r
+           logger.log(POILogger.INFO, "styles atom doesn't exist. Creating dummy record for later saving.");\r
+           style = new StyleTextPropAtom((textLen < 0) ? 1 : textLen);\r
+       } else {\r
+           if (textLen >= 0) {\r
+               style.setParentTextSize(textLen);\r
+           }\r
+       }\r
+       \r
+       return style;\r
+   }\r
+\r
+\r
    /**\r
     * Saves the modified paragraphs/textrun to the records.\r
     * Also updates the styles to the correct text length.\r
     */\r
    protected static void storeText(List<HSLFTextParagraph> paragraphs) {\r
        fixLineEndings(paragraphs);\r
-       \r
+\r
        String rawText = toInternalString(getRawText(paragraphs));\r
 \r
        // Will it fit in a 8 bit atom?\r
        boolean isUnicode = StringUtil.hasMultibyte(rawText);\r
-       \r
+       // isUnicode = true;\r
+\r
        TextHeaderAtom headerAtom = paragraphs.get(0)._headerAtom;\r
        TextBytesAtom byteAtom = paragraphs.get(0)._byteAtom;\r
        TextCharsAtom charAtom = paragraphs.get(0)._charAtom;\r
+       StyleTextPropAtom styleAtom = findStyleAtomPresent(headerAtom, rawText.length());\r
 \r
        // Store in the appropriate record\r
        Record oldRecord = null, newRecord = null;\r
-       if (isUnicode) { \r
-           if (byteAtom != null) {\r
+       if (isUnicode) {\r
+           if (byteAtom != null || charAtom == null) {\r
                oldRecord = byteAtom;\r
-               newRecord = charAtom = new TextCharsAtom();\r
+               charAtom = new TextCharsAtom();\r
            }\r
+           newRecord = charAtom;\r
            charAtom.setText(rawText);\r
        } else {\r
-           if (charAtom != null) {\r
+           if (charAtom != null || byteAtom == null) {\r
                oldRecord = charAtom;\r
-               newRecord = byteAtom = new TextBytesAtom();\r
+               byteAtom = new TextBytesAtom();\r
            }\r
+           newRecord = byteAtom;\r
            byte[] byteText = new byte[rawText.length()];\r
            StringUtil.putCompressedUnicode(rawText,byteText,0);\r
            byteAtom.setText(byteText);\r
        }\r
-\r
+       assert(newRecord != null);\r
+       \r
        RecordContainer _txtbox = headerAtom.getParentRecord();\r
+       Record[] cr = _txtbox.getChildRecords();\r
+       int headerIdx = -1, textIdx = -1, styleIdx = -1;\r
+       for (int i=0; i<cr.length; i++) {\r
+           Record r = cr[i];\r
+           if (r == headerAtom) headerIdx = i;\r
+           else if (r == oldRecord || r == newRecord) textIdx = i;\r
+           else if (r == styleAtom) styleIdx = i;\r
+       }\r
+\r
+       if (textIdx == -1) {\r
+           // the old record was never registered, ignore it\r
+           _txtbox.addChildAfter(newRecord, headerAtom);\r
+           textIdx = headerIdx+1;\r
+       } else {\r
+           // swap not appropriated records - noop if unchanged\r
+           cr[textIdx] = newRecord;\r
+       }\r
+\r
+       if (styleIdx == -1) {\r
+           // Add the new StyleTextPropAtom after the TextCharsAtom / TextBytesAtom\r
+           _txtbox.addChildAfter(styleAtom, newRecord);\r
+       }\r
        \r
-       if (oldRecord != null) {\r
-           // swap not appropriated records\r
-           Record[] cr = _txtbox.getChildRecords();\r
-           int idx=0;\r
-           for (Record r : cr) {\r
-               if(r.equals(oldRecord)) break;\r
-               idx++;\r
-           }\r
-           if (idx >= cr.length) {\r
-               throw new RuntimeException("child record not found - malformed container record");\r
-           }\r
-           cr[idx] = newRecord;\r
-           \r
+       for (HSLFTextParagraph p : paragraphs) {\r
            if (newRecord == byteAtom) {\r
-               charAtom = null;\r
+               p._charAtom = null;\r
            } else {\r
-               byteAtom = null;\r
+               p._byteAtom = null;\r
            }\r
        }\r
-\r
-       // Ensure a StyleTextPropAtom is present, adding if required\r
-       StyleTextPropAtom styleAtom = ensureStyleAtomPresent(headerAtom, byteAtom, charAtom);\r
-\r
+       \r
        // Update the text length for its Paragraph and Character stylings\r
-       // If it's shared:\r
-       //   * calculate the new length based on the run's old text\r
-       //   * this should leave in any +1's for the end of block if needed\r
-       // If it isn't shared:\r
        //   * reset the length, to the new string's length\r
        //   * add on +1 if the last block\r
-       // The last run needs its stylings to be 1 longer than the raw\r
-       //  text is. This is to define the stylings that any new text\r
-       //  that is added will inherit\r
-       \r
+\r
        styleAtom.clearStyles();\r
-       \r
+\r
        TextPropCollection lastPTPC = null, lastRTPC = null, ptpc = null, rtpc = null;\r
        for (HSLFTextParagraph para : paragraphs) {\r
            ptpc = para.getParagraphStyle();\r
@@ -782,13 +781,13 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
                lastRTPC.updateTextSize(lastRTPC.getCharactersCovered()+len);\r
            }\r
        }\r
-       \r
+\r
        assert(lastPTPC != null && lastRTPC != null && ptpc != null && rtpc != null);\r
        ptpc.updateTextSize(ptpc.getCharactersCovered()+1);\r
        rtpc.updateTextSize(rtpc.getCharactersCovered()+1);\r
        lastPTPC.updateTextSize(lastPTPC.getCharactersCovered()+1);\r
        lastRTPC.updateTextSize(lastRTPC.getCharactersCovered()+1);\r
-       \r
+\r
        /**\r
         * If TextSpecInfoAtom is present, we must update the text size in it,\r
         * otherwise the ppt will be corrupted\r
@@ -803,7 +802,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
    /**\r
     * Adds the supplied text onto the end of the TextParagraphs,\r
     * creating a new RichTextRun for it to sit in.\r
-    * \r
+    *\r
     * @param text the text string used by this object.\r
     */\r
    protected static HSLFTextRun appendText(List<HSLFTextParagraph> paragraphs, String text, boolean newParagraph) {\r
@@ -811,14 +810,10 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
 \r
        // check paragraphs\r
        assert(!paragraphs.isEmpty() && !paragraphs.get(0).getTextRuns().isEmpty());\r
-       \r
+\r
        HSLFTextParagraph htp = paragraphs.get(paragraphs.size()-1);\r
        HSLFTextRun htr = htp.getTextRuns().get(htp.getTextRuns().size()-1);\r
 \r
-       if (newParagraph) {\r
-           htr.setText(htr.getRawText()+"\n");\r
-       }\r
-       \r
        boolean isFirst = !newParagraph;\r
        for (String rawText : text.split("(?<=\r)")) {\r
            if (!isFirst) {\r
@@ -832,6 +827,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
                paragraphs.add(htp);\r
                isFirst = false;\r
            }\r
+           \r
            TextPropCollection tpc = htr.getCharacterStyle();\r
            // special case, last text run is empty, we will reuse it\r
            if (htr.getLength() > 0) {\r
@@ -841,21 +837,19 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
            }\r
            htr.setText(rawText);\r
        }\r
-\r
-       storeText(paragraphs);\r
        \r
+       storeText(paragraphs);\r
+\r
        return htr;\r
    }\r
-   \r
+\r
    /**\r
     * Sets (overwrites) the current text.\r
     * Uses the properties of the first paragraph / textrun\r
-    * \r
+    *\r
     * @param text the text string used by this object.\r
     */\r
    public static HSLFTextRun setText(List<HSLFTextParagraph> paragraphs, String text) {\r
-       text = HSLFTextParagraph.toInternalString(text);\r
-       \r
        // check paragraphs\r
        assert(!paragraphs.isEmpty() && !paragraphs.get(0).getTextRuns().isEmpty());\r
 \r
@@ -866,7 +860,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
            paraIter.next();\r
            paraIter.remove();\r
        }\r
-       \r
+\r
        Iterator<HSLFTextRun> runIter = htp.getTextRuns().iterator();\r
        HSLFTextRun htr = runIter.next();\r
        htr.setText("");\r
@@ -875,10 +869,10 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
            runIter.next();\r
            runIter.remove();\r
        }\r
-       \r
+\r
        return appendText(paragraphs, text, false);\r
    }\r
-   \r
+\r
    public static String getRawText(List<HSLFTextParagraph> paragraphs) {\r
        StringBuilder sb = new StringBuilder();\r
        for (HSLFTextParagraph p : paragraphs) {\r
@@ -886,9 +880,9 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
                sb.append(r.getRawText());\r
            }\r
        }\r
-       return sb.toString();        \r
+       return sb.toString();\r
    }\r
-   \r
+\r
    /**\r
     * Returns a new string with line breaks converted into internal ppt\r
     * representation\r
@@ -948,7 +942,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
     * @param found   vector to add any found to\r
     */\r
    protected static List<List<HSLFTextParagraph>> findTextParagraphs(final Record[] records) {\r
-       return findTextParagraphs(records, null); \r
+       return findTextParagraphs(records, null);\r
    }\r
    /**\r
     * Scans through the supplied record array, looking for\r
@@ -980,41 +974,40 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
     */\r
     protected static List<List<HSLFTextParagraph>> findTextParagraphs(Record[] records, StyleTextProp9Atom styleTextProp9Atom) {\r
         List<List<HSLFTextParagraph>> paragraphCollection = new ArrayList<List<HSLFTextParagraph>>();\r
-        \r
+\r
         if (records == null) {\r
             throw new NullPointerException("records need to be filled.");\r
         }\r
-        \r
+\r
         int recordIdx;\r
         for (recordIdx = 0; recordIdx < records.length; recordIdx++) {\r
             if (records[recordIdx] instanceof TextHeaderAtom) break;\r
         }\r
-        \r
+\r
         if (recordIdx == records.length) {\r
             logger.log(POILogger.INFO, "No text records found.");\r
             return paragraphCollection;\r
         }\r
-        \r
+\r
         for (int slwtIndex = 0; recordIdx < records.length; slwtIndex++) {\r
             List<HSLFTextParagraph> paragraphs = new ArrayList<HSLFTextParagraph>();\r
             paragraphCollection.add(paragraphs);\r
-            \r
+\r
             TextHeaderAtom    header = (TextHeaderAtom)records[recordIdx++];\r
             TextBytesAtom     tbytes = null;\r
             TextCharsAtom     tchars = null;\r
-            StyleTextPropAtom styles = null;\r
             TextRulerAtom     ruler  = null;\r
             MasterTextPropAtom indents = null;\r
-            \r
+\r
             List<Record> otherRecordList = new ArrayList<Record>();\r
-            \r
+\r
             for (; recordIdx < records.length; recordIdx++) {\r
                 Record r = records[recordIdx];\r
                 long rt = r.getRecordType();\r
                 if (RecordTypes.TextHeaderAtom.typeID == rt) break;\r
                 else if (RecordTypes.TextBytesAtom.typeID == rt) tbytes = (TextBytesAtom)r;\r
                 else if (RecordTypes.TextCharsAtom.typeID == rt) tchars = (TextCharsAtom)r;\r
-                else if (RecordTypes.StyleTextPropAtom.typeID == rt) styles = (StyleTextPropAtom)r;\r
+                // don't search for RecordTypes.StyleTextPropAtom.typeID here ... see findStyleAtomPresent below\r
                 else if (RecordTypes.TextRulerAtom.typeID == rt) ruler = (TextRulerAtom)r;\r
                 else if (RecordTypes.MasterTextPropAtom.typeID == rt) {\r
                     indents = (MasterTextPropAtom)r;\r
@@ -1023,23 +1016,24 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
                     otherRecordList.add(r);\r
                 }\r
             }\r
-        \r
+\r
             assert(header != null);\r
             if (header.getParentRecord() instanceof SlideListWithText) {\r
                 // runs found in PPDrawing are not linked with SlideListWithTexts\r
                 header.setIndex(slwtIndex);\r
             }\r
-            \r
+\r
             Record otherRecords[] = otherRecordList.toArray(new Record[otherRecordList.size()]);\r
-            \r
+\r
             if (tbytes == null && tchars == null) {\r
                 tbytes = new TextBytesAtom();\r
-                header.getParentRecord().addChildAfter(tbytes, header);\r
+                // header.getParentRecord().addChildAfter(tbytes, header);\r
                 logger.log(POILogger.INFO, "bytes nor chars atom doesn't exist. Creating dummy record for later saving.");\r
             }\r
-        \r
+\r
             String rawText = (tchars != null) ? tchars.getText() : tbytes.getText();\r
-        \r
+            StyleTextPropAtom styles = findStyleAtomPresent(header, rawText.length());\r
+\r
             // split, but keep delimiter\r
             for (String para : rawText.split("(?<=\r)")) {\r
                 HSLFTextParagraph tpara = new HSLFTextParagraph(header, tbytes, tchars, styles);\r
@@ -1048,32 +1042,26 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
                 tpara._ruler = ruler;\r
                 tpara._records = otherRecords;\r
                 tpara.getParagraphStyle().updateTextSize(para.length());\r
-        \r
+\r
                 HSLFTextRun trun = new HSLFTextRun(tpara);\r
                 tpara.addTextRun(trun);\r
                 trun.setText(para);\r
             }\r
-            \r
-            if (styles == null) {\r
-                styles = ensureStyleAtomPresent(header, tbytes, tchars);\r
-            } else {\r
-                styles.setParentTextSize(rawText.length());\r
-            }\r
-            \r
+\r
             applyCharacterStyles(paragraphs, styles.getCharacterStyles());\r
             applyParagraphStyles(paragraphs, styles.getParagraphStyles());\r
             if (indents != null) {\r
                 applyParagraphIndents(paragraphs, indents.getIndents());\r
             }\r
         }\r
-        \r
+\r
         return paragraphCollection;\r
     }\r
 \r
     protected static void applyCharacterStyles(List<HSLFTextParagraph> paragraphs, List<TextPropCollection> charStyles) {\r
         int paraIdx = 0, runIdx = 0;\r
         HSLFTextRun trun;\r
-        \r
+\r
         for (int csIdx=0; csIdx<charStyles.size(); csIdx++) {\r
             TextPropCollection p = charStyles.get(csIdx);\r
             for (int ccRun = 0, ccStyle = p.getCharactersCovered(); ccRun < ccStyle; ) {\r
@@ -1081,21 +1069,21 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
                 List<HSLFTextRun> runs = para.getTextRuns();\r
                 trun = runs.get(runIdx);\r
                 int len = trun.getLength();\r
-                \r
+\r
                 if (ccRun+len <= ccStyle) {\r
                     ccRun += len;\r
                 } else {\r
                     String text = trun.getRawText();\r
                     trun.setText(text.substring(0,ccStyle-ccRun));\r
-                    \r
+\r
                     HSLFTextRun nextRun = new HSLFTextRun(para);\r
                     nextRun.setText(text.substring(ccStyle-ccRun));\r
                     runs.add(runIdx+1, nextRun);\r
-                    \r
+\r
                     ccRun += ccStyle-ccRun;\r
                 }\r
 \r
-                TextPropCollection pCopy = new TextPropCollection(0);\r
+                TextPropCollection pCopy = new TextPropCollection(0, StyleTextPropAtom.characterTextPropTypes);\r
                 pCopy.copy(p);\r
                 trun.setCharacterStyle(pCopy);\r
 \r
@@ -1113,7 +1101,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
                     }\r
                 }\r
                 pCopy.updateTextSize(len);\r
-                \r
+\r
                 // need to compare it again, in case a run has been added after\r
                 if (++runIdx == runs.size()) {\r
                     paraIdx++;\r
@@ -1122,14 +1110,14 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
             }\r
         }\r
     }\r
-    \r
+\r
     protected static void applyParagraphStyles(List<HSLFTextParagraph> paragraphs, List<TextPropCollection> paraStyles) {\r
         int paraIdx = 0;\r
         for (TextPropCollection p : paraStyles) {\r
             for (int ccPara = 0, ccStyle = p.getCharactersCovered(); ccPara < ccStyle; paraIdx++) {\r
                 if (paraIdx >= paragraphs.size() || ccPara >= ccStyle-1) return;\r
                 HSLFTextParagraph htp = paragraphs.get(paraIdx);\r
-                TextPropCollection pCopy = new TextPropCollection(0);\r
+                TextPropCollection pCopy = new TextPropCollection(0, StyleTextPropAtom.paragraphTextPropTypes);\r
                 pCopy.copy(p);\r
                 htp.setParagraphStyle(pCopy);\r
                 int len = 0;\r
@@ -1142,7 +1130,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
             }\r
         }\r
     }\r
-    \r
+\r
     protected static void applyParagraphIndents(List<HSLFTextParagraph> paragraphs, List<IndentProp> paraStyles) {\r
         int paraIdx = 0;\r
         for (IndentProp p : paraStyles) {\r
@@ -1157,23 +1145,23 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
             }\r
         }\r
     }\r
-    \r
+\r
     protected static List<HSLFTextParagraph> createEmptyParagraph() {\r
         EscherTextboxWrapper wrapper = new EscherTextboxWrapper();\r
-    \r
+\r
         TextHeaderAtom tha = new TextHeaderAtom();\r
         tha.setParentRecord(wrapper);\r
         wrapper.appendChildRecord(tha);\r
-    \r
+\r
         TextBytesAtom tba = new TextBytesAtom();\r
         tba.setText("\r".getBytes());\r
         wrapper.appendChildRecord(tba);\r
-    \r
+\r
         StyleTextPropAtom sta = new StyleTextPropAtom(1);\r
         TextPropCollection paraStyle = sta.addParagraphTextPropCollection(1);\r
         TextPropCollection charStyle = sta.addCharacterTextPropCollection(1);\r
         wrapper.appendChildRecord(sta);\r
-    \r
+\r
         HSLFTextParagraph htp = new HSLFTextParagraph(tha, tba, null, sta);\r
         htp.setParagraphStyle(paraStyle);\r
         htp._records = new Record[0];\r
@@ -1182,16 +1170,16 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
         htp.setLeftMargin(0);\r
         htp.setIndent(0);\r
         // set wrap flags\r
-        \r
+\r
         HSLFTextRun htr = new HSLFTextRun(htp);\r
         htr.setCharacterStyle(charStyle);\r
         htr.setText("\r");\r
         htr.setFontColor(Color.black);\r
         htp.addTextRun(htr);\r
-        \r
+\r
         return Arrays.asList(htp);\r
     }\r
-    \r
+\r
     public EscherTextboxWrapper getTextboxWrapper() {\r
         return (EscherTextboxWrapper)_headerAtom.getParentRecord();\r
     }\r
index d06715b173f43b7364cf9be8207cb458c247bfeb..b4da12c4dc3621f4b4cb44e62e20803970215d36 100644 (file)
@@ -23,6 +23,7 @@ import java.awt.Color;
 
 import org.apache.poi.hslf.model.textproperties.*;
 import org.apache.poi.hslf.record.ColorSchemeAtom;
+import org.apache.poi.hslf.record.StyleTextPropAtom;
 import org.apache.poi.sl.usermodel.TextRun;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
@@ -44,7 +45,7 @@ public final class HSLFTextRun implements TextRun {
         * Our paragraph and character style.
         * Note - we may share these styles with other RichTextRuns
         */
-       private TextPropCollection characterStyle = new TextPropCollection(0);
+       private TextPropCollection characterStyle = new TextPropCollection(0, StyleTextPropAtom.characterTextPropTypes);
 
        /**
         * Create a new wrapper around a rich text string
@@ -163,7 +164,7 @@ public final class HSLFTextRun implements TextRun {
        public void setCharTextPropVal(String propName, int val) {
                // Ensure we have the StyleTextProp atom we're going to need
                if(characterStyle == null) {
-                   characterStyle = new TextPropCollection(1);
+                   characterStyle = new TextPropCollection(1, StyleTextPropAtom.characterTextPropTypes);
                        // characterStyle will now be defined
                }
 
@@ -376,7 +377,7 @@ public final class HSLFTextRun implements TextRun {
     protected void setFlag(int index, boolean value) {
         // Ensure we have the StyleTextProp atom we're going to need
         if (characterStyle == null) {
-            characterStyle = new TextPropCollection(1);
+            characterStyle = new TextPropCollection(1, StyleTextPropAtom.characterTextPropTypes);
         }
 
         BitMaskTextProp prop = (BitMaskTextProp) fetchOrAddTextProp(characterStyle, CharFlagsTextProp.NAME);
index dbee82742fa0d0fb4b8a779b8aea1c2657de1aab..cb51595f5700d0e04ed4c3d8f282dea2106ae4b0 100644 (file)
 package org.apache.poi.hslf.usermodel;
 
 
+import java.util.List;
+
 import junit.framework.TestCase;
 
-import org.apache.poi.hslf.*;
-import org.apache.poi.hslf.model.*;
 import org.apache.poi.POIDataSamples;
 
 /**
@@ -40,39 +40,39 @@ public final class TestCounts extends TestCase {
        }
 
        public void testSheetsCount() {
-               HSLFSlide[] slides = ss.getSlides();
+               List<HSLFSlide> slides = ss.getSlides();
                // Two sheets - master sheet is separate
-               assertEquals(2, slides.length);
+               assertEquals(2, slides.size());
 
                // They are slides 1+2
-               assertEquals(1, slides[0].getSlideNumber());
-               assertEquals(2, slides[1].getSlideNumber());
+               assertEquals(1, slides.get(0).getSlideNumber());
+               assertEquals(2, slides.get(1).getSlideNumber());
 
                // The ref IDs are 4 and 6
-               assertEquals(4, slides[0]._getSheetRefId());
-               assertEquals(6, slides[1]._getSheetRefId());
+               assertEquals(4, slides.get(0)._getSheetRefId());
+               assertEquals(6, slides.get(1)._getSheetRefId());
 
                // These are slides 1+2 -> 256+257
-               assertEquals(256, slides[0]._getSheetNumber());
-               assertEquals(257, slides[1]._getSheetNumber());
+               assertEquals(256, slides.get(0)._getSheetNumber());
+               assertEquals(257, slides.get(1)._getSheetNumber());
        }
 
        public void testNotesCount() {
-               HSLFNotes[] notes = ss.getNotes();
+               List<HSLFNotes> notes = ss.getNotes();
                // Two sheets -> two notes
                // Note: there are also notes on the slide master
                //assertEquals(3, notes.length); // When we do slide masters
-               assertEquals(2, notes.length);
+               assertEquals(2, notes.size());
 
                // First is for master
-               //assertEquals(-2147483648, notes[0]._getSheetNumber());  // When we do slide masters
+               //assertEquals(-2147483648, notes.get(0)._getSheetNumber());  // When we do slide masters
 
                // Next two are for the two slides
-               assertEquals(256, notes[0]._getSheetNumber());
-               assertEquals(257, notes[1]._getSheetNumber());
+               assertEquals(256, notes.get(0)._getSheetNumber());
+               assertEquals(257, notes.get(1)._getSheetNumber());
 
                // They happen to go between the two slides in Ref terms
-               assertEquals(5, notes[0]._getSheetRefId());
-               assertEquals(7, notes[1]._getSheetRefId());
+               assertEquals(5, notes.get(0)._getSheetRefId());
+               assertEquals(7, notes.get(1)._getSheetRefId());
        }
 }
index 570fb5883ab6add08a5a067236a85bb3d869d5d9..8713c09d07c2312d73b48341c7602a807aa76e44 100644 (file)
@@ -40,21 +40,21 @@ public final class TestNotesText extends TestCase {
        }
 
        public void testNotesOne() {
-               HSLFNotes notes = ss.getNotes()[0];
+               HSLFNotes notes = ss.getNotes().get(0);
 
                String[] expectText = new String[] {"These are the notes for page 1"};
-               assertEquals(expectText.length, notes.getTextParagraphs().length);
+               assertEquals(expectText.length, notes.getTextParagraphs().size());
                for(int i=0; i<expectText.length; i++) {
-                       assertEquals(expectText[i], notes.getTextParagraphs()[i].getRawText());
+                       assertEquals(expectText[i], HSLFTextParagraph.getRawText(notes.getTextParagraphs().get(i)));
                }
        }
 
        public void testNotesTwo() {
-               HSLFNotes notes = ss.getNotes()[1];
+               HSLFNotes notes = ss.getNotes().get(1);
                String[] expectText = new String[] {"These are the notes on page two, again lacking formatting"};
-               assertEquals(expectText.length, notes.getTextParagraphs().length);
+               assertEquals(expectText.length, notes.getTextParagraphs().size());
                for(int i=0; i<expectText.length; i++) {
-                       assertEquals(expectText[i], notes.getTextParagraphs()[i].getRawText());
+                       assertEquals(expectText[i], HSLFTextParagraph.getRawText(notes.getTextParagraphs().get(i)));
                }
        }
 }