You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ye...@apache.org on 2008/06/21 14:03:49 UTC

svn commit: r670186 [5/7] - in /poi/tags/REL_3_1_FINAL: ./ legal/ src/documentation/content/xdocs/ src/examples/src/org/apache/poi/hslf/ src/examples/src/org/apache/poi/hslf/usermodel/ src/examples/src/org/apache/poi/hslf/usermodel/examples/ src/java/o...

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java Sat Jun 21 05:03:44 2008
@@ -683,4 +683,13 @@
         String ns = s.replaceAll("\\r?\\n", "\r");
         return ns;
     }
+
+    /**
+     * Returns records that make up this text run
+     *
+     * @return text run records
+     */
+    public Record[] getRecords(){
+        return _records;
+    }
 }

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java Sat Jun 21 05:03:44 2008
@@ -1,537 +1,545 @@
-
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-==================================================================== */
-
-package org.apache.poi.hslf.model;
-
-import org.apache.poi.ddf.*;
-import org.apache.poi.hslf.record.*;
-import org.apache.poi.hslf.usermodel.RichTextRun;
-import org.apache.poi.hslf.exceptions.HSLFException;
-import org.apache.poi.util.POILogger;
-
-import java.awt.*;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.AffineTransform;
-import java.awt.font.FontRenderContext;
-import java.awt.font.TextLayout;
-import java.io.IOException;
-
-/**
- * A common superclass of all shapes that can hold text.
- *
- * @author Yegor Kozlov
- */
-public abstract class TextShape extends SimpleShape {
-
-    /**
-     * How to anchor the text
-     */
-    public static final int AnchorTop = 0;
-    public static final int AnchorMiddle = 1;
-    public static final int AnchorBottom = 2;
-    public static final int AnchorTopCentered = 3;
-    public static final int AnchorMiddleCentered = 4;
-    public static final int AnchorBottomCentered = 5;
-    public static final int AnchorTopBaseline = 6;
-    public static final int AnchorBottomBaseline = 7;
-    public static final int AnchorTopCenteredBaseline = 8;
-    public static final int AnchorBottomCenteredBaseline = 9;
-
-    /**
-     * How to wrap the text
-     */
-    public static final int WrapSquare = 0;
-    public static final int WrapByPoints = 1;
-    public static final int WrapNone = 2;
-    public static final int WrapTopBottom = 3;
-    public static final int WrapThrough = 4;
-
-    /**
-     * How to align the text
-     */
-    public static final int AlignLeft = 0;
-    public static final int AlignCenter = 1;
-    public static final int AlignRight = 2;
-    public static final int AlignJustify = 3;
-
-    /**
-     * TextRun object which holds actual text and format data
-     */
-    protected TextRun _txtrun;
-
-    /**
-     * Escher container which holds text attributes such as
-     * TextHeaderAtom, TextBytesAtom ot TextCharsAtom, StyleTextPropAtom etc.
-     */
-    protected EscherTextboxWrapper _txtbox;
-
-    /**
-     * Used to calculate text bounds
-     */
-    protected static final FontRenderContext _frc = new FontRenderContext(null, true, true);
-
-    /**
-     * Create a TextBox object and initialize it from the supplied Record container.
-     * 
-     * @param escherRecord       <code>EscherSpContainer</code> container which holds information about this shape
-     * @param parent    the parent of the shape
-     */
-   protected TextShape(EscherContainerRecord escherRecord, Shape parent){
-        super(escherRecord, parent);
-
-    }
-
-    /**
-     * Create a new TextBox. This constructor is used when a new shape is created.
-     *
-     * @param parent    the parent of this Shape. For example, if this text box is a cell
-     * in a table then the parent is Table.
-     */
-    public TextShape(Shape parent){
-        super(null, parent);
-        _escherContainer = createSpContainer(parent instanceof ShapeGroup);
-    }
-
-    /**
-     * Create a new TextBox. This constructor is used when a new shape is created.
-     *
-     */
-    public TextShape(){
-        this(null);
-    }
-
-    public TextRun createTextRun(){
-        _txtbox = getEscherTextboxWrapper();
-        if(_txtbox == null) _txtbox = new EscherTextboxWrapper();
-
-        _txtrun = getTextRun();
-        if(_txtrun == null){
-            TextHeaderAtom tha = new TextHeaderAtom();
-            tha.setParentRecord(_txtbox);
-            _txtbox.appendChildRecord(tha);
-
-            TextCharsAtom tca = new TextCharsAtom();
-            _txtbox.appendChildRecord(tca);
-
-            StyleTextPropAtom sta = new StyleTextPropAtom(0);
-            _txtbox.appendChildRecord(sta);
-
-            _txtrun = new TextRun(tha,tca,sta);
-            _txtrun.setText("");
-
-            _escherContainer.addChildRecord(_txtbox.getEscherRecord());
-
-            setDefaultTextProperties(_txtrun);
-        }
-
-        return _txtrun;
-    }
-
-    /**
-     * Set default properties for the  TextRun.
-     * Depending on the text and shape type the defaults are different:
-     *   TextBox: align=left, valign=top
-     *   AutoShape: align=center, valign=middle
-     *
-     */
-    protected void setDefaultTextProperties(TextRun _txtrun){
-
-    }
-
-    /**
-     * Returns the text contained in this text frame.
-     *
-     * @return the text string for this textbox.
-     */
-     public String getText(){
-        TextRun tx = getTextRun();
-        return tx == null ? null : tx.getText();
-    }
-
-    /**
-     * Sets the text contained in this text frame.
-     *
-     * @param text the text string used by this object.
-     */
-    public void setText(String text){
-        TextRun tx = getTextRun();
-        if(tx == null){
-            tx = createTextRun();
-        }
-        tx.setText(text);
-        setTextId(text.hashCode());
-    }
-
-    /**
-     * When a textbox is added to  a sheet we need to tell upper-level
-     * <code>PPDrawing</code> about it.
-     *
-     * @param sh the sheet we are adding to
-     */
-    protected void afterInsert(Sheet sh){
-        super.afterInsert(sh);
-
-        EscherTextboxWrapper _txtbox = getEscherTextboxWrapper();
-        if(_txtbox != null){
-            PPDrawing ppdrawing = sh.getPPDrawing();
-            ppdrawing.addTextboxWrapper(_txtbox);
-            // Ensure the escher layer knows about the added records
-            try {
-                _txtbox.writeOut(null);
-            } catch (IOException e){
-                throw new HSLFException(e);
-            }
-            if(getAnchor().equals(new Rectangle()) && !"".equals(getText())) resizeToFitText();
-        }
-    }
-
-    protected EscherTextboxWrapper getEscherTextboxWrapper(){
-        if(_txtbox == null){
-            EscherTextboxRecord textRecord = (EscherTextboxRecord)Shape.getEscherChild(_escherContainer, EscherTextboxRecord.RECORD_ID);
-            if(textRecord != null) _txtbox = new EscherTextboxWrapper(textRecord);
-        }
-        return _txtbox;
-    }
-    /**
-     * Adjust the size of the TextShape so it encompasses the text inside it.
-     *
-     * @return a <code>Rectangle2D</code> that is the bounds of this <code>TextShape</code>.
-     */
-    public Rectangle2D resizeToFitText(){
-        String txt = getText();
-        if(txt == null || txt.length() == 0) return new Rectangle2D.Float();
-
-        RichTextRun rt = getTextRun().getRichTextRuns()[0];
-        int size = rt.getFontSize();
-        int style = 0;
-        if (rt.isBold()) style |= Font.BOLD;
-        if (rt.isItalic()) style |= Font.ITALIC;
-        String fntname = rt.getFontName();
-        Font font = new Font(fntname, style, size);
-
-        float width = 0, height = 0;
-        String[] lines = txt.split("\r");
-        for (int i = 0; i < lines.length; i++) {
-            if(lines[i].length() == 0) continue;
-
-            TextLayout layout = new TextLayout(lines[i], font, _frc);
-
-            width = Math.max(width, layout.getAdvance());
-
-            /**
-             * Even if top and bottom margins are set to 0 PowerPoint
-             * always sets extra space between the text and its bounding box.
-             *
-             * The approximation height = ascent*2 works good enough in most cases
-             */
-            height = Math.max(height, 2*layout.getAscent());
-        }
-
-        width += getMarginLeft() + getMarginRight();
-        height += getMarginTop() + getMarginBottom();
-
-        Rectangle2D anchor = getAnchor2D();
-        anchor.setRect(anchor.getX(), anchor.getY(), width, height);
-        setAnchor(anchor);
-
-        return anchor;
-    }
-
-    /**
-     * Returns the type of vertical alignment for the text.
-     * One of the <code>Anchor*</code> constants defined in this class.
-     *
-     * @return the type of alignment
-     */
-    public int getVerticalAlignment(){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT);
-        int valign = TextShape.AnchorTop;
-        if (prop == null){
-            /**
-             * If vertical alignment was not found in the shape properties then try to
-             * fetch the master shape and search for the align property there.
-             */
-            int type = getTextRun().getRunType();
-            MasterSheet master = getSheet().getMasterSheet();
-            if(master != null){
-                TextShape masterShape = master.getPlaceholder(type);
-                if(masterShape != null) valign = masterShape.getVerticalAlignment();
-            } else {
-                //not found in the master sheet. Use the hardcoded defaults.
-                switch (type){
-                     case TextHeaderAtom.TITLE_TYPE:
-                     case TextHeaderAtom.CENTER_TITLE_TYPE:
-                         valign = TextShape.AnchorMiddle;
-                         break;
-                     default:
-                         valign = TextShape.AnchorTop;
-                         break;
-                 }
-            }
-        } else {
-            valign = prop.getPropertyValue();
-        }
-        return valign;
-    }
-
-    /**
-     * Sets the type of vertical alignment for the text.
-     * One of the <code>Anchor*</code> constants defined in this class.
-     *
-     * @param align - the type of alignment
-     */
-    public void setVerticalAlignment(int align){
-        setEscherProperty(EscherProperties.TEXT__ANCHORTEXT, align);
-    }
-
-    /**
-     * Sets the type of horizontal alignment for the text.
-     * One of the <code>Align*</code> constants defined in this class.
-     *
-     * @param align - the type of horizontal alignment
-     */
-    public void setHorizontalAlignment(int align){
-        TextRun tx = getTextRun();
-        if(tx != null) tx.getRichTextRuns()[0].setAlignment(align);
-    }
-
-    /**
-     * Gets the type of horizontal alignment for the text.
-     * One of the <code>Align*</code> constants defined in this class.
-     *
-     * @return align - the type of horizontal alignment
-     */
-    public int getHorizontalAlignment(){
-        TextRun tx = getTextRun();
-        return tx == null ? -1 : tx.getRichTextRuns()[0].getAlignment();
-    }
-
-    /**
-     * Returns the distance (in points) between the bottom of the text frame
-     * and the bottom of the inscribed rectangle of the shape that contains the text.
-     * Default value is 1/20 inch.
-     *
-     * @return the botom margin
-     */
-    public float getMarginBottom(){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
-        int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
-        return (float)val/EMU_PER_POINT;
-    }
-
-    /**
-     * Sets the botom margin.
-     * @see #getMarginBottom()
-     *
-     * @param margin    the bottom margin
-     */
-    public void setMarginBottom(float margin){
-        setEscherProperty(EscherProperties.TEXT__TEXTBOTTOM, (int)(margin*EMU_PER_POINT));
-    }
-
-    /**
-     *  Returns the distance (in points) between the left edge of the text frame
-     *  and the left edge of the inscribed rectangle of the shape that contains
-     *  the text.
-     *  Default value is 1/10 inch.
-     *
-     * @return the left margin
-     */
-    public float getMarginLeft(){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
-        int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
-        return (float)val/EMU_PER_POINT;
-    }
-
-    /**
-     * Sets the left margin.
-     * @see #getMarginLeft()
-     *
-     * @param margin    the left margin
-     */
-    public void setMarginLeft(float margin){
-        setEscherProperty(EscherProperties.TEXT__TEXTLEFT, (int)(margin*EMU_PER_POINT));
-    }
-
-    /**
-     *  Returns the distance (in points) between the right edge of the
-     *  text frame and the right edge of the inscribed rectangle of the shape
-     *  that contains the text.
-     *  Default value is 1/10 inch.
-     *
-     * @return the right margin
-     */
-    public float getMarginRight(){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT);
-        int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
-        return (float)val/EMU_PER_POINT;
-    }
-
-    /**
-     * Sets the right margin.
-     * @see #getMarginRight()
-     *
-     * @param margin    the right margin
-     */
-    public void setMarginRight(float margin){
-        setEscherProperty(EscherProperties.TEXT__TEXTRIGHT, (int)(margin*EMU_PER_POINT));
-    }
-
-     /**
-     *  Returns the distance (in points) between the top of the text frame
-     *  and the top of the inscribed rectangle of the shape that contains the text.
-     *  Default value is 1/20 inch.
-     *
-     * @return the top margin
-     */
-    public float getMarginTop(){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTTOP);
-        int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
-        return (float)val/EMU_PER_POINT;
-    }
-
-   /**
-     * Sets the top margin.
-     * @see #getMarginTop()
-     *
-     * @param margin    the top margin
-     */
-    public void setMarginTop(float margin){
-        setEscherProperty(EscherProperties.TEXT__TEXTTOP, (int)(margin*EMU_PER_POINT));
-    }
-
-
-    /**
-     * Returns the value indicating word wrap.
-     *
-     * @return the value indicating word wrap.
-     *  Must be one of the <code>Wrap*</code> constants defined in this class.
-     */
-    public int getWordWrap(){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT);
-        return prop == null ? WrapSquare : prop.getPropertyValue();
-    }
-
-    /**
-     *  Specifies how the text should be wrapped
-     *
-     * @param wrap  the value indicating how the text should be wrapped.
-     *  Must be one of the <code>Wrap*</code> constants defined in this class.
-     */
-    public void setWordWrap(int wrap){
-        setEscherProperty(EscherProperties.TEXT__WRAPTEXT, wrap);
-    }
-
-    /**
-     * @return id for the text.
-     */
-    public int getTextId(){
-        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
-        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTID);
-        return prop == null ? 0 : prop.getPropertyValue();
-    }
-
-    /**
-     * Sets text ID
-     *
-     * @param id of the text
-     */
-    public void setTextId(int id){
-        setEscherProperty(EscherProperties.TEXT__TEXTID, id);
-    }
-
-    /**
-      * @return the TextRun object for this text box
-      */
-     public TextRun getTextRun(){
-         if(_txtrun == null) initTextRun();
-         return _txtrun;
-     }
-
-    public void setSheet(Sheet sheet) {
-        _sheet = sheet;
-
-        // Initialize _txtrun object.
-        // (We can't do it in the constructor because the sheet
-        //  is not assigned then, it's only built once we have
-        //  all the records)
-        TextRun tx = getTextRun();
-        if (tx != null) {
-            // Supply the sheet to our child RichTextRuns
-            tx.setSheet(_sheet);
-            RichTextRun[] rt = tx.getRichTextRuns();
-            for (int i = 0; i < rt.length; i++) {
-                rt[i].supplySlideShow(_sheet.getSlideShow());
-            }
-        }
-
-    }
-
-    protected void initTextRun(){
-        EscherTextboxWrapper txtbox = getEscherTextboxWrapper();
-        Sheet sheet = getSheet();
-
-        if(sheet == null || txtbox == null) return;
-
-        OutlineTextRefAtom ota = null;
-
-        Record[] child = txtbox.getChildRecords();
-        for (int i = 0; i < child.length; i++) {
-            if (child[i] instanceof OutlineTextRefAtom) {
-                ota = (OutlineTextRefAtom)child[i];
-                break;
-            }
-        }
-
-        TextRun[] runs = _sheet.getTextRuns();
-        if (ota != null) {
-            int idx = ota.getTextIndex();
-            for (int i = 0; i < runs.length; i++) {
-                if(runs[i].getIndex() == idx){
-                    _txtrun = runs[i];
-                    break;
-                }
-            }
-            if(_txtrun == null) {
-                logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx);
-            }
-        } else {
-            int shapeId = _escherContainer.getChildById(EscherSpRecord.RECORD_ID).getShapeId();
-            if(runs != null) for (int i = 0; i < runs.length; i++) {
-                if(runs[i].getShapeId() == shapeId){
-                    _txtrun = runs[i];
-                    break;
-                }
-            }
-        }
-    }
-
-    public void draw(Graphics2D graphics){
-        AffineTransform at = graphics.getTransform();
-        ShapePainter.paint(this, graphics);
-        new TextPainter(this).paint(graphics);
-        graphics.setTransform(at);
-    }
-
-}
+
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hslf.model;
+
+import org.apache.poi.ddf.*;
+import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.usermodel.RichTextRun;
+import org.apache.poi.hslf.exceptions.HSLFException;
+import org.apache.poi.util.POILogger;
+
+import java.awt.*;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.AffineTransform;
+import java.awt.font.FontRenderContext;
+import java.awt.font.TextLayout;
+import java.io.IOException;
+import java.util.Iterator;
+
+/**
+ * A common superclass of all shapes that can hold text.
+ *
+ * @author Yegor Kozlov
+ */
+public abstract class TextShape extends SimpleShape {
+
+    /**
+     * How to anchor the text
+     */
+    public static final int AnchorTop = 0;
+    public static final int AnchorMiddle = 1;
+    public static final int AnchorBottom = 2;
+    public static final int AnchorTopCentered = 3;
+    public static final int AnchorMiddleCentered = 4;
+    public static final int AnchorBottomCentered = 5;
+    public static final int AnchorTopBaseline = 6;
+    public static final int AnchorBottomBaseline = 7;
+    public static final int AnchorTopCenteredBaseline = 8;
+    public static final int AnchorBottomCenteredBaseline = 9;
+
+    /**
+     * How to wrap the text
+     */
+    public static final int WrapSquare = 0;
+    public static final int WrapByPoints = 1;
+    public static final int WrapNone = 2;
+    public static final int WrapTopBottom = 3;
+    public static final int WrapThrough = 4;
+
+    /**
+     * How to align the text
+     */
+    public static final int AlignLeft = 0;
+    public static final int AlignCenter = 1;
+    public static final int AlignRight = 2;
+    public static final int AlignJustify = 3;
+
+    /**
+     * TextRun object which holds actual text and format data
+     */
+    protected TextRun _txtrun;
+
+    /**
+     * Escher container which holds text attributes such as
+     * TextHeaderAtom, TextBytesAtom ot TextCharsAtom, StyleTextPropAtom etc.
+     */
+    protected EscherTextboxWrapper _txtbox;
+
+    /**
+     * Used to calculate text bounds
+     */
+    protected static final FontRenderContext _frc = new FontRenderContext(null, true, true);
+
+    /**
+     * Create a TextBox object and initialize it from the supplied Record container.
+     * 
+     * @param escherRecord       <code>EscherSpContainer</code> container which holds information about this shape
+     * @param parent    the parent of the shape
+     */
+   protected TextShape(EscherContainerRecord escherRecord, Shape parent){
+        super(escherRecord, parent);
+
+    }
+
+    /**
+     * Create a new TextBox. This constructor is used when a new shape is created.
+     *
+     * @param parent    the parent of this Shape. For example, if this text box is a cell
+     * in a table then the parent is Table.
+     */
+    public TextShape(Shape parent){
+        super(null, parent);
+        _escherContainer = createSpContainer(parent instanceof ShapeGroup);
+    }
+
+    /**
+     * Create a new TextBox. This constructor is used when a new shape is created.
+     *
+     */
+    public TextShape(){
+        this(null);
+    }
+
+    public TextRun createTextRun(){
+        _txtbox = getEscherTextboxWrapper();
+        if(_txtbox == null) _txtbox = new EscherTextboxWrapper();
+
+        _txtrun = getTextRun();
+        if(_txtrun == null){
+            TextHeaderAtom tha = new TextHeaderAtom();
+            tha.setParentRecord(_txtbox);
+            _txtbox.appendChildRecord(tha);
+
+            TextCharsAtom tca = new TextCharsAtom();
+            _txtbox.appendChildRecord(tca);
+
+            StyleTextPropAtom sta = new StyleTextPropAtom(0);
+            _txtbox.appendChildRecord(sta);
+
+            _txtrun = new TextRun(tha,tca,sta);
+            _txtrun.setText("");
+
+            _escherContainer.addChildRecord(_txtbox.getEscherRecord());
+
+            setDefaultTextProperties(_txtrun);
+        }
+
+        return _txtrun;
+    }
+
+    /**
+     * Set default properties for the  TextRun.
+     * Depending on the text and shape type the defaults are different:
+     *   TextBox: align=left, valign=top
+     *   AutoShape: align=center, valign=middle
+     *
+     */
+    protected void setDefaultTextProperties(TextRun _txtrun){
+
+    }
+
+    /**
+     * Returns the text contained in this text frame.
+     *
+     * @return the text string for this textbox.
+     */
+     public String getText(){
+        TextRun tx = getTextRun();
+        return tx == null ? null : tx.getText();
+    }
+
+    /**
+     * Sets the text contained in this text frame.
+     *
+     * @param text the text string used by this object.
+     */
+    public void setText(String text){
+        TextRun tx = getTextRun();
+        if(tx == null){
+            tx = createTextRun();
+        }
+        tx.setText(text);
+        setTextId(text.hashCode());
+    }
+
+    /**
+     * When a textbox is added to  a sheet we need to tell upper-level
+     * <code>PPDrawing</code> about it.
+     *
+     * @param sh the sheet we are adding to
+     */
+    protected void afterInsert(Sheet sh){
+        super.afterInsert(sh);
+
+        EscherTextboxWrapper _txtbox = getEscherTextboxWrapper();
+        if(_txtbox != null){
+            PPDrawing ppdrawing = sh.getPPDrawing();
+            ppdrawing.addTextboxWrapper(_txtbox);
+            // Ensure the escher layer knows about the added records
+            try {
+                _txtbox.writeOut(null);
+            } catch (IOException e){
+                throw new HSLFException(e);
+            }
+            if(getAnchor().equals(new Rectangle()) && !"".equals(getText())) resizeToFitText();
+        }
+    }
+
+    protected EscherTextboxWrapper getEscherTextboxWrapper(){
+        if(_txtbox == null){
+            EscherTextboxRecord textRecord = (EscherTextboxRecord)Shape.getEscherChild(_escherContainer, EscherTextboxRecord.RECORD_ID);
+            if(textRecord != null) _txtbox = new EscherTextboxWrapper(textRecord);
+        }
+        return _txtbox;
+    }
+    /**
+     * Adjust the size of the TextShape so it encompasses the text inside it.
+     *
+     * @return a <code>Rectangle2D</code> that is the bounds of this <code>TextShape</code>.
+     */
+    public Rectangle2D resizeToFitText(){
+        String txt = getText();
+        if(txt == null || txt.length() == 0) return new Rectangle2D.Float();
+
+        RichTextRun rt = getTextRun().getRichTextRuns()[0];
+        int size = rt.getFontSize();
+        int style = 0;
+        if (rt.isBold()) style |= Font.BOLD;
+        if (rt.isItalic()) style |= Font.ITALIC;
+        String fntname = rt.getFontName();
+        Font font = new Font(fntname, style, size);
+
+        float width = 0, height = 0, leading = 0;        
+        String[] lines = txt.split("\n");        
+        for (int i = 0; i < lines.length; i++) {
+            if(lines[i].length() == 0) continue;
+            
+            TextLayout layout = new TextLayout(lines[i], font, _frc);
+            
+            leading = Math.max(leading, layout.getLeading());           
+            width = Math.max(width, layout.getAdvance());
+            height = Math.max(height, (height + (layout.getDescent() + layout.getAscent())));
+        } 	
+    	
+        // add one character to width
+        Rectangle2D charBounds = font.getMaxCharBounds(_frc);                
+        width += getMarginLeft() + getMarginRight() + charBounds.getWidth();
+        
+        // add leading to height        
+        height += getMarginTop() + getMarginBottom() + leading;
+
+        Rectangle2D anchor = getAnchor2D();
+        anchor.setRect(anchor.getX(), anchor.getY(), width, height);
+        setAnchor(anchor);
+
+        return anchor;
+    }
+
+    /**
+     * Returns the type of vertical alignment for the text.
+     * One of the <code>Anchor*</code> constants defined in this class.
+     *
+     * @return the type of alignment
+     */
+    public int getVerticalAlignment(){
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT);
+        int valign = TextShape.AnchorTop;
+        if (prop == null){
+            /**
+             * If vertical alignment was not found in the shape properties then try to
+             * fetch the master shape and search for the align property there.
+             */
+            int type = getTextRun().getRunType();
+            MasterSheet master = getSheet().getMasterSheet();
+            if(master != null){
+                TextShape masterShape = master.getPlaceholder(type);
+                if(masterShape != null) valign = masterShape.getVerticalAlignment();
+            } else {
+                //not found in the master sheet. Use the hardcoded defaults.
+                switch (type){
+                     case TextHeaderAtom.TITLE_TYPE:
+                     case TextHeaderAtom.CENTER_TITLE_TYPE:
+                         valign = TextShape.AnchorMiddle;
+                         break;
+                     default:
+                         valign = TextShape.AnchorTop;
+                         break;
+                 }
+            }
+        } else {
+            valign = prop.getPropertyValue();
+        }
+        return valign;
+    }
+
+    /**
+     * Sets the type of vertical alignment for the text.
+     * One of the <code>Anchor*</code> constants defined in this class.
+     *
+     * @param align - the type of alignment
+     */
+    public void setVerticalAlignment(int align){
+        setEscherProperty(EscherProperties.TEXT__ANCHORTEXT, align);
+    }
+
+    /**
+     * Sets the type of horizontal alignment for the text.
+     * One of the <code>Align*</code> constants defined in this class.
+     *
+     * @param align - the type of horizontal alignment
+     */
+    public void setHorizontalAlignment(int align){
+        TextRun tx = getTextRun();
+        if(tx != null) tx.getRichTextRuns()[0].setAlignment(align);
+    }
+
+    /**
+     * Gets the type of horizontal alignment for the text.
+     * One of the <code>Align*</code> constants defined in this class.
+     *
+     * @return align - the type of horizontal alignment
+     */
+    public int getHorizontalAlignment(){
+        TextRun tx = getTextRun();
+        return tx == null ? -1 : tx.getRichTextRuns()[0].getAlignment();
+    }
+
+    /**
+     * Returns the distance (in points) between the bottom of the text frame
+     * and the bottom of the inscribed rectangle of the shape that contains the text.
+     * Default value is 1/20 inch.
+     *
+     * @return the botom margin
+     */
+    public float getMarginBottom(){
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
+        int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
+        return (float)val/EMU_PER_POINT;
+    }
+
+    /**
+     * Sets the botom margin.
+     * @see #getMarginBottom()
+     *
+     * @param margin    the bottom margin
+     */
+    public void setMarginBottom(float margin){
+        setEscherProperty(EscherProperties.TEXT__TEXTBOTTOM, (int)(margin*EMU_PER_POINT));
+    }
+
+    /**
+     *  Returns the distance (in points) between the left edge of the text frame
+     *  and the left edge of the inscribed rectangle of the shape that contains
+     *  the text.
+     *  Default value is 1/10 inch.
+     *
+     * @return the left margin
+     */
+    public float getMarginLeft(){
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTLEFT);
+        int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
+        return (float)val/EMU_PER_POINT;
+    }
+
+    /**
+     * Sets the left margin.
+     * @see #getMarginLeft()
+     *
+     * @param margin    the left margin
+     */
+    public void setMarginLeft(float margin){
+        setEscherProperty(EscherProperties.TEXT__TEXTLEFT, (int)(margin*EMU_PER_POINT));
+    }
+
+    /**
+     *  Returns the distance (in points) between the right edge of the
+     *  text frame and the right edge of the inscribed rectangle of the shape
+     *  that contains the text.
+     *  Default value is 1/10 inch.
+     *
+     * @return the right margin
+     */
+    public float getMarginRight(){
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT);
+        int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
+        return (float)val/EMU_PER_POINT;
+    }
+
+    /**
+     * Sets the right margin.
+     * @see #getMarginRight()
+     *
+     * @param margin    the right margin
+     */
+    public void setMarginRight(float margin){
+        setEscherProperty(EscherProperties.TEXT__TEXTRIGHT, (int)(margin*EMU_PER_POINT));
+    }
+
+     /**
+     *  Returns the distance (in points) between the top of the text frame
+     *  and the top of the inscribed rectangle of the shape that contains the text.
+     *  Default value is 1/20 inch.
+     *
+     * @return the top margin
+     */
+    public float getMarginTop(){
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTTOP);
+        int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
+        return (float)val/EMU_PER_POINT;
+    }
+
+   /**
+     * Sets the top margin.
+     * @see #getMarginTop()
+     *
+     * @param margin    the top margin
+     */
+    public void setMarginTop(float margin){
+        setEscherProperty(EscherProperties.TEXT__TEXTTOP, (int)(margin*EMU_PER_POINT));
+    }
+
+
+    /**
+     * Returns the value indicating word wrap.
+     *
+     * @return the value indicating word wrap.
+     *  Must be one of the <code>Wrap*</code> constants defined in this class.
+     */
+    public int getWordWrap(){
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT);
+        return prop == null ? WrapSquare : prop.getPropertyValue();
+    }
+
+    /**
+     *  Specifies how the text should be wrapped
+     *
+     * @param wrap  the value indicating how the text should be wrapped.
+     *  Must be one of the <code>Wrap*</code> constants defined in this class.
+     */
+    public void setWordWrap(int wrap){
+        setEscherProperty(EscherProperties.TEXT__WRAPTEXT, wrap);
+    }
+
+    /**
+     * @return id for the text.
+     */
+    public int getTextId(){
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+        EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTID);
+        return prop == null ? 0 : prop.getPropertyValue();
+    }
+
+    /**
+     * Sets text ID
+     *
+     * @param id of the text
+     */
+    public void setTextId(int id){
+        setEscherProperty(EscherProperties.TEXT__TEXTID, id);
+    }
+
+    /**
+      * @return the TextRun object for this text box
+      */
+     public TextRun getTextRun(){
+         if(_txtrun == null) initTextRun();
+         return _txtrun;
+     }
+
+    public void setSheet(Sheet sheet) {
+        _sheet = sheet;
+
+        // Initialize _txtrun object.
+        // (We can't do it in the constructor because the sheet
+        //  is not assigned then, it's only built once we have
+        //  all the records)
+        TextRun tx = getTextRun();
+        if (tx != null) {
+            // Supply the sheet to our child RichTextRuns
+            tx.setSheet(_sheet);
+            RichTextRun[] rt = tx.getRichTextRuns();
+            for (int i = 0; i < rt.length; i++) {
+                rt[i].supplySlideShow(_sheet.getSlideShow());
+            }
+        }
+
+    }
+
+    protected void initTextRun(){
+        EscherTextboxWrapper txtbox = getEscherTextboxWrapper();
+        Sheet sheet = getSheet();
+
+        if(sheet == null || txtbox == null) return;
+
+        OutlineTextRefAtom ota = null;
+
+        Record[] child = txtbox.getChildRecords();
+        for (int i = 0; i < child.length; i++) {
+            if (child[i] instanceof OutlineTextRefAtom) {
+                ota = (OutlineTextRefAtom)child[i];
+                break;
+            }
+        }
+
+        TextRun[] runs = _sheet.getTextRuns();
+        if (ota != null) {
+            int idx = ota.getTextIndex();
+            for (int i = 0; i < runs.length; i++) {
+                if(runs[i].getIndex() == idx){
+                    _txtrun = runs[i];
+                    break;
+                }
+            }
+            if(_txtrun == null) {
+                logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx);
+            }
+        } else {
+            int shapeId = _escherContainer.getChildById(EscherSpRecord.RECORD_ID).getShapeId();
+            if(runs != null) for (int i = 0; i < runs.length; i++) {
+                if(runs[i].getShapeId() == shapeId){
+                    _txtrun = runs[i];
+                    break;
+                }
+            }
+        }
+    }
+
+    public void draw(Graphics2D graphics){
+        AffineTransform at = graphics.getTransform();
+        ShapePainter.paint(this, graphics);
+        new TextPainter(this).paint(graphics);
+        graphics.setTransform(at);
+    }
+
+    /**
+     * Return <code>OEPlaceholderAtom</code>, the atom that describes a placeholder.
+     *
+     * @return <code>OEPlaceholderAtom</code> or <code>null</code> if not found
+     */
+    public OEPlaceholderAtom getPlaceholderAtom(){
+        return (OEPlaceholderAtom)getClientDataRecord(RecordTypes.OEPlaceholderAtom.typeID);
+    }
+
+}

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java Sat Jun 21 05:03:44 2008
@@ -138,7 +138,7 @@
 				new TextProp(2, 0x4000, "spaceafter"),
 				new TextProp(2, 0x8000, "para_unknown_4"),
 				new TextProp(2, 0x10000, "para_unknown_5"),
-				new TextProp(2, 0xE0000, "para_unknown_6"),
+				new TextProp(2, 0xA0000, "para_unknown_6"),
 				new TextProp(2, 0x200000, "para_unknown_7")
 	};
 	/** All the different kinds of character properties we might handle */
@@ -167,7 +167,7 @@
 	/** 
 	 * For the Text Style Properties (StyleTextProp) Atom
 	 */
-	protected StyleTextPropAtom(byte[] source, int start, int len) {
+	public StyleTextPropAtom(byte[] source, int start, int len) {
 		// Sanity Checking - we're always at least 8+10 bytes long
 		if(len < 18) {
 			len = 18;

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java Sat Jun 21 05:03:44 2008
@@ -17,6 +17,8 @@
 package org.apache.poi.hslf.usermodel;
 
 import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.POILogger;
+import org.apache.poi.util.POILogFactory;
 import org.apache.poi.hslf.model.Picture;
 import org.apache.poi.hslf.blip.*;
 import org.apache.poi.hslf.exceptions.HSLFException;
@@ -25,6 +27,7 @@
 import java.io.IOException;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.awt.*;
 
 /**
  * A class that represents image data contained in a slide show.
@@ -33,19 +36,21 @@
  */
 public abstract class PictureData {
 
+    protected POILogger logger = POILogFactory.getLogger(this.getClass());
+
     /**
      * Size of the image checksum calculated using MD5 algorithm.
      */
     protected static final int CHECKSUM_SIZE = 16;
 
-	/**
-	* Binary data of the picture
-	*/
+    /**
+    * Binary data of the picture
+    */
     private byte[] rawdata;
-	/**
-	 * The offset to the picture in the stream
-	 */
-	protected int offset;
+    /**
+     * The offset to the picture in the stream
+     */
+    protected int offset;
 
     /**
      * Returns type of this picture.
@@ -71,6 +76,13 @@
      */
     protected abstract int getSignature();
 
+    protected static ImagePainter[] painters = new ImagePainter[8];
+    static {
+        PictureData.setImagePainter(Picture.PNG, new BitmapPainter());
+        PictureData.setImagePainter(Picture.JPEG, new BitmapPainter());
+        PictureData.setImagePainter(Picture.DIB, new BitmapPainter());
+    }
+
     /**
      * Returns the raw binary data of this Picture excluding the first 8 bytes
      * which hold image signature and size of the image data.
@@ -212,4 +224,30 @@
         return getData().length;
     }
 
+    public void draw(Graphics2D graphics, Picture parent){
+        ImagePainter painter = painters[getType()];
+        if(painter != null) painter.paint(graphics, this, parent);
+        else logger.log(POILogger.WARN, "Rendering is not supported: " + getClass().getName());
+    }
+
+    /**
+     * Register ImagePainter for the specified image type
+     *
+     * @param type  image type, must be one of the static constants defined in the <code>Picture<code> class.
+     * @param painter   
+     */
+    public static void setImagePainter(int type, ImagePainter painter){
+        painters[type] = painter;
+    }
+
+    /**
+     * Return ImagePainter for the specified image type
+     *
+     * @param type blip type, must be one of the static constants defined in the <code>Picture<code> class.
+     * @return ImagePainter for the specified image type
+     */
+    public static ImagePainter getImagePainter(int type){
+        return painters[type];
+    }
+
 }

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java Sat Jun 21 05:03:44 2008
@@ -734,7 +734,7 @@
         else if (format == Picture.WMF) bse.setBlipTypeMacOS((byte)Picture.PICT);
         else if (format == Picture.PICT) bse.setBlipTypeWin32((byte)Picture.WMF);
 
-        bse.setRef(1);
+        bse.setRef(0);
         bse.setOffset(offset);
 
         bstore.addChildRecord(bse);

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hssf/usermodel/HSSFChart.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hssf/usermodel/HSSFChart.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hssf/usermodel/HSSFChart.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hssf/usermodel/HSSFChart.java Sat Jun 21 05:03:44 2008
@@ -213,6 +213,23 @@
     		charts.toArray( new HSSFChart[charts.size()] );
     }
 
+    /** Get the X offset of the chart */
+    public int getChartX() { return chartRecord.getX(); }
+    /** Get the Y offset of the chart */
+    public int getChartY() { return chartRecord.getY(); }
+    /** Get the width of the chart. {@link ChartRecord} */
+    public int getChartWidth() { return chartRecord.getWidth(); }
+    /** Get the height of the chart. {@link ChartRecord} */
+    public int getChartHeight() { return chartRecord.getHeight(); }
+
+    /** Sets the X offset of the chart */
+    public void setChartX(int x) { chartRecord.setX(x); }
+    /** Sets the Y offset of the chart */
+    public void setChartY(int y) { chartRecord.setY(y); }
+    /** Sets the width of the chart. {@link ChartRecord} */
+    public void setChartWidth(int width) { chartRecord.setWidth(width); }
+    /** Sets the height of the chart. {@link ChartRecord} */
+    public void setChartHeight(int height) { chartRecord.setHeight(height); }
     
     /**
      * Returns the series of the chart

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java Sat Jun 21 05:03:44 2008
@@ -53,10 +53,10 @@
   protected FileInformationBlock _fib;
 
   /** main document stream buffer*/
-  private byte[] _mainStream;
+  protected byte[] _mainStream;
 
   /** table stream buffer*/
-  private byte[] _tableStream;
+  protected byte[] _tableStream;
 
   /** data stream buffer*/
   protected byte[] _dataStream;
@@ -93,6 +93,12 @@
   
   /** Holds pictures table */
   protected PicturesTable _pictures;
+  
+  /** Holds FSBA (shape) information */
+  protected FSPATable _fspa;
+  
+  /** Escher Drawing Group information */
+  protected EscherRecordHolder _dgg;
 
   protected HWPFDocument()
   {
@@ -204,9 +210,6 @@
     {
         _dataStream = new byte[0];
     }
-    
-    // read in the pictures stream
-    _pictures = new PicturesTable(this, _dataStream);
 
     // get the start of text in the main stream
     int fcMin = _fib.getFcMin();
@@ -226,6 +229,20 @@
       _cbt.adjustForDelete(0, 0, cpMin);
       _pbt.adjustForDelete(0, 0, cpMin);
     }
+    
+    // Read FSPA and Escher information
+    _fspa = new FSPATable(_tableStream, _fib.getFcPlcspaMom(), _fib.getLcbPlcspaMom(), getTextTable().getTextPieces());
+    
+    if (_fib.getFcDggInfo() != 0)
+    {
+        _dgg = new EscherRecordHolder(_tableStream, _fib.getFcDggInfo(), _fib.getLcbDggInfo());
+    } else
+    {
+        _dgg = new EscherRecordHolder();
+    }
+    
+    // read in the pictures stream
+    _pictures = new PicturesTable(this, _dataStream, _mainStream, _fspa, _dgg);
 
     _st = new SectionTable(_mainStream, _tableStream, _fib.getFcPlcfsed(), _fib.getLcbPlcfsed(), fcMin, getTextTable().getTextPieces());
     _ss = new StyleSheet(_tableStream, _fib.getFcStshf());

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java Sat Jun 21 05:03:44 2008
@@ -294,6 +294,16 @@
       _longHandler.setLong(FIBLongHandler.CBMAC, cbMac);
     }
 
+	public int getCcpText()
+	{
+	  return _longHandler.getLong(FIBLongHandler.CCPTEXT);
+	}
+
+	public void setCcpText(int ccpText)
+	{
+	  _longHandler.setLong(FIBLongHandler.CCPTEXT, ccpText);
+	}
+
     public void clearOffsetsSizes()
     {
       _fieldHandler.clearFields();
@@ -308,6 +318,26 @@
     {
       return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDMOM);
     }
+    
+    public int getFcPlcspaMom()
+    {
+        return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCSPAMOM);
+    }
+    
+    public int getLcbPlcspaMom()
+    {
+        return _fieldHandler.getFieldSize(FIBFieldHandler.PLCSPAMOM);
+    }
+    
+    public int getFcDggInfo()
+    {
+        return _fieldHandler.getFieldOffset(FIBFieldHandler.DGGINFO);
+    }
+    
+    public int getLcbDggInfo()
+    {
+        return _fieldHandler.getFieldSize(FIBFieldHandler.DGGINFO);
+    }
 
     public void writeTo (byte[] mainStream, HWPFOutputStream tableStream)
       throws IOException

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/PicturesTable.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/PicturesTable.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/PicturesTable.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/PicturesTable.java Sat Jun 21 05:03:44 2008
@@ -26,7 +26,12 @@
 
 import java.util.List;
 import java.util.ArrayList;
-
+import java.util.Iterator;
+import org.apache.poi.ddf.DefaultEscherRecordFactory;
+import org.apache.poi.ddf.EscherBSERecord;
+import org.apache.poi.ddf.EscherBlipRecord;
+import org.apache.poi.ddf.EscherRecord;
+import org.apache.poi.ddf.EscherRecordFactory;
 
 /**
  * Holds information about all pictures embedded in Word Document either via "Insert -> Picture -> From File" or via
@@ -57,6 +62,9 @@
 
   private HWPFDocument _document;
   private byte[] _dataStream;
+  private byte[] _mainStream;
+  private FSPATable _fspa;
+  private EscherRecordHolder _dgg;
 
   /** @link dependency
    * @stereotype instantiate*/
@@ -67,10 +75,13 @@
    * @param document 
    * @param _dataStream
    */
-  public PicturesTable(HWPFDocument _document, byte[] _dataStream)
+  public PicturesTable(HWPFDocument _document, byte[] _dataStream, byte[] _mainStream, FSPATable fspa, EscherRecordHolder dgg)
   {
-	this._document = _document;
+    this._document = _document;
     this._dataStream = _dataStream;
+    this._mainStream = _mainStream;
+    this._fspa = fspa;
+    this._dgg = dgg;
   }
 
   /**
@@ -83,6 +94,13 @@
     }
     return false;
   }
+  
+  public boolean hasEscherPicture(CharacterRun run) {
+    if (run.isSpecialCharacter() && !run.isObj() && !run.isOle2() && !run.isData() && run.text().startsWith("\u0008")) {
+      return true;
+    }
+    return false;
+  }
 
   /**
    * determines whether specified CharacterRun contains reference to a picture
@@ -122,6 +140,46 @@
     }
     return null;
   }
+  
+  /**
+     * Performs a recursive search for pictures in the given list of escher records.
+     *
+     * @param escherRecords the escher records.
+     * @param pictures the list to populate with the pictures.
+     */
+    private void searchForPictures(List escherRecords, List pictures)
+    {
+        Iterator recordIter = escherRecords.iterator();
+        while (recordIter.hasNext())
+        {
+            Object obj = recordIter.next();
+            if (obj instanceof EscherRecord)
+            {
+                EscherRecord escherRecord = (EscherRecord) obj;
+
+                if (escherRecord instanceof EscherBSERecord)
+                {
+                    EscherBSERecord bse = (EscherBSERecord) escherRecord;
+                    EscherBlipRecord blip = bse.getBlipRecord();
+                    if (blip != null)
+                    {
+                        pictures.add(new Picture(blip.getPicturedata()));
+                    }
+                    else if (bse.getOffset() > 0)
+                    {
+                        // Blip stored in delay stream, which in a word doc, is the main stream
+                        EscherRecordFactory recordFactory = new DefaultEscherRecordFactory();
+                        blip = (EscherBlipRecord) recordFactory.createRecord(_mainStream, bse.getOffset());
+                        blip.fillFields(_mainStream, bse.getOffset(), recordFactory);
+                        pictures.add(new Picture(blip.getPicturedata()));
+                    }
+                }
+
+                // Recursive call.
+                searchForPictures(escherRecord.getChildRecords(), pictures);
+            }
+        }
+    }
 
   /**
    * Not all documents have all the images concatenated in the data stream
@@ -136,12 +194,13 @@
     for (int i = 0; i < range.numCharacterRuns(); i++) {
     	CharacterRun run = range.getCharacterRun(i);
     	String text = run.text();
-    	int j = text.charAt(0);
     	Picture picture = extractPicture(run, false);
     	if (picture != null) {
     		pictures.add(picture);
     	}
 	}
+    
+    searchForPictures(_dgg.getEscherRecords(), pictures);
 
     return pictures;
   }

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/TextPiece.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/TextPiece.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/TextPiece.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/model/TextPiece.java Sat Jun 21 05:03:44 2008
@@ -90,12 +90,20 @@
 
    public void adjustForDelete(int start, int length)
    {
+
+	   if (usesUnicode()) {
+
+		   start /= 2;
+		   length /= 2;
+	   }
+
 	   int myStart = getStart();
 	   int myEnd = getEnd();
 	   int end = start + length;
 
 	   /* do we have to delete from this text piece? */
 	   if (start <= myEnd && end >= myStart) {
+
 		   /* find where the deleted area overlaps with this text piece */
 		   int overlapStart = Math.max(myStart, start);
 		   int overlapEnd = Math.min(myEnd, end);

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Picture.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Picture.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Picture.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Picture.java Sat Jun 21 05:03:44 2008
@@ -98,6 +98,15 @@
       fillImageContent();
     }
   }
+  
+  public Picture(byte[] _dataStream)
+  {
+      this._dataStream = _dataStream;
+      this.dataBlockStartOfsset = 0;
+      this.dataBlockSize = _dataStream.length;
+      this.pictureBytesStartOffset = 0;
+      this.size = _dataStream.length;
+  }
 
   private void fillWidthHeight()
   {
@@ -363,6 +372,7 @@
       do {
         firstByte = _dataStream[pointer];
         secondByte = _dataStream[pointer+1];
+        pointer += 2;
       } while (!(firstByte==(byte)0xFF) && pointer<endOfPicture-1);
 
       if (firstByte==((byte)0xFF) && pointer<endOfPicture-1) {

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java Sat Jun 21 05:03:44 2008
@@ -227,6 +227,25 @@
   }
 
   /**
+   * Does any <code>TextPiece</code> in this Range use unicode?
+   *
+   *	@return	true if it does and false if it doesn't
+   */
+  public boolean usesUnicode() {
+
+	initText();
+
+	for (int i = _textStart; i < _textEnd; i++)
+	{
+	  TextPiece piece = (TextPiece)_text.get(i);
+	  if (piece.usesUnicode())
+		  return true;
+	}
+
+	return false;
+  }
+
+  /**
    * Gets the text that this Range contains.
    *
    * @return The text for this range.
@@ -306,13 +325,19 @@
     // Since this is the first item in our list, it is safe to assume that
     // _start >= tp.getStart()
     int insertIndex = _start - tp.getStart();
+	if (tp.usesUnicode())
+		insertIndex /= 2;
     sb.insert(insertIndex, text);
+
     int adjustedLength = _doc.getTextTable().adjustForInsert(_textStart, text.length());
     _doc.getCharacterTable().adjustForInsert(_charStart, adjustedLength);
     _doc.getParagraphTable().adjustForInsert(_parStart, adjustedLength);
     _doc.getSectionTable().adjustForInsert(_sectionStart, adjustedLength);
     adjustForInsert(text.length());
 
+	// update the FIB.CCPText field
+	adjustFIB(text.length());
+
     return getCharacterRun(0);
   }
 
@@ -489,6 +514,7 @@
 
   public void delete()
   {
+
     initAll();
 
     int numSections = _sections.size();
@@ -519,6 +545,12 @@
     	TextPiece piece = (TextPiece)_text.get(x);
     	piece.adjustForDelete(_start, _end - _start);
     }
+
+	// update the FIB.CCPText field
+	if (usesUnicode())
+		adjustFIB(-((_end - _start) / 2));
+	else
+		adjustFIB(-(_end - _start));
   }
 
   /**
@@ -600,6 +632,47 @@
     return (ListEntry)insertAfter(props, styleIndex);
   }
 
+  /**
+   * Replace (one instance of) a piece of text with another...
+   *
+   * @param pPlaceHolder    The text to be replaced (e.g., "${organization}")
+   * @param pValue          The replacement text (e.g., "Apache Software Foundation")
+   * @param pOffset         The offset or index where the text to be replaced begins
+   *                        (relative to/within this <code>Range</code>)
+   */
+  public void replaceText(String pPlaceHolder, String pValue, int pOffset)
+  {
+	int absPlaceHolderIndex = getStartOffset() + pOffset;
+    Range subRange = new Range(
+                absPlaceHolderIndex, 
+				(absPlaceHolderIndex + pPlaceHolder.length()), getDocument()
+    );
+    if (subRange.usesUnicode()) {
+			absPlaceHolderIndex = getStartOffset() + (pOffset * 2);
+            subRange = new Range(
+                      absPlaceHolderIndex, 
+                      (absPlaceHolderIndex + (pPlaceHolder.length() * 2)), 
+					  getDocument()
+            );
+    }
+
+    subRange.insertBefore(pValue);
+
+    // re-create the sub-range so we can delete it
+    subRange = new Range(
+            (absPlaceHolderIndex + pValue.length()),
+            (absPlaceHolderIndex + pPlaceHolder.length() + pValue.length()), 
+			getDocument()
+    );
+    if (subRange.usesUnicode())
+            subRange = new Range(
+                      (absPlaceHolderIndex + (pValue.length() * 2)),
+                      (absPlaceHolderIndex + (pPlaceHolder.length() * 2) + 
+					  (pValue.length() * 2)), getDocument()
+            );
+
+    subRange.delete();
+  }
 
   /**
    * Gets the character run at index. The index is relative to this range.
@@ -828,12 +901,26 @@
   }
 
   /**
+   *	Adjust the value of <code>FIB.CCPText</code> after an insert or a delete...
+   *
+   *	@param	adjustment	The (signed) value that should be added to <code>FIB.CCPText</code>
+   */
+  protected void adjustFIB(int adjustment) {
+
+	// update the FIB.CCPText field (this should happen once per adjustment, so we don't want it in
+	// adjustForInsert() or it would get updated multiple times if the range has a parent)
+	// without this, OpenOffice.org (v. 2.2.x) does not see all the text in the document
+	_doc.getFileInformationBlock().setCcpText(_doc.getFileInformationBlock().getCcpText() + adjustment);
+  }
+
+  /**
    * adjust this range after an insert happens.
    * @param length the length to adjust for
    */
   private void adjustForInsert(int length)
   {
     _end += length;
+
     reset();
     Range parent = (Range)_parent.get();
     if (parent != null)
@@ -842,4 +929,19 @@
     }
   }
 
+
+	public int getStartOffset() {
+
+		return _start;
+	}
+
+	public int getEndOffset() {
+
+		return _end;
+	}
+
+	protected HWPFDocument getDocument() {
+
+		return _doc;
+	}
 }

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java Sat Jun 21 05:03:44 2008
@@ -23,6 +23,7 @@
 
 import java.io.*;
 import java.util.ArrayList;
+import java.util.HashMap;
 
 import org.apache.poi.hslf.usermodel.SlideShow;
 import org.apache.poi.hslf.record.TextHeaderAtom;
@@ -157,4 +158,46 @@
         assertEquals("Testing TextShape", shape1.getTextRun().getText());
     }
 
+    public void testMargins() throws IOException {
+        FileInputStream is = new FileInputStream(new File(cwd, "text-margins.ppt"));
+        SlideShow ppt = new SlideShow(is);
+        is.close();
+
+        Slide slide = ppt.getSlides()[0];
+
+        HashMap map = new HashMap();
+        Shape[] shape = slide.getShapes();
+        for (int i = 0; i < shape.length; i++) {
+            if(shape[i] instanceof TextShape){
+                TextShape tx = (TextShape)shape[i];
+                map.put(tx.getText(), tx);
+            }
+        }
+
+        TextShape tx;
+
+        tx = (TextShape)map.get("TEST1");
+        assertEquals(0.1, tx.getMarginLeft()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+        assertEquals(0.1, tx.getMarginRight()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+        assertEquals(0.39, tx.getMarginTop()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+        assertEquals(0.05, tx.getMarginBottom()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+
+        tx = (TextShape)map.get("TEST2");
+        assertEquals(0.1, tx.getMarginLeft()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+        assertEquals(0.1, tx.getMarginRight()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+        assertEquals(0.05, tx.getMarginTop()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+        assertEquals(0.39, tx.getMarginBottom()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+
+        tx = (TextShape)map.get("TEST3");
+        assertEquals(0.39, tx.getMarginLeft()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+        assertEquals(0.1, tx.getMarginRight()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+        assertEquals(0.05, tx.getMarginTop()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+        assertEquals(0.05, tx.getMarginBottom()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+
+        tx = (TextShape)map.get("TEST4");
+        assertEquals(0.1, tx.getMarginLeft()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+        assertEquals(0.39, tx.getMarginRight()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+        assertEquals(0.05, tx.getMarginTop()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+        assertEquals(0.05, tx.getMarginBottom()*Shape.EMU_PER_POINT/Shape.EMU_PER_INCH, 0.01);
+    }
 }

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hssf/usermodel/TestHSSFChart.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hssf/usermodel/TestHSSFChart.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hssf/usermodel/TestHSSFChart.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hssf/usermodel/TestHSSFChart.java Sat Jun 21 05:03:44 2008
@@ -53,6 +53,12 @@
 		assertEquals("1st Column", charts[0].getSeries()[0].getSeriesTitle());
 		assertEquals("2nd Column", charts[0].getSeries()[1].getSeriesTitle());
 		assertEquals(null, charts[0].getChartTitle());
+		
+		// Check x, y, width, height
+		assertEquals(0, charts[0].getChartX());
+		assertEquals(0, charts[0].getChartY());
+		assertEquals(26492928, charts[0].getChartWidth());
+		assertEquals(15040512, charts[0].getChartHeight());
 	}
 
 	public void testTwoCharts() throws Exception {

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hwpf/TestHWPFPictures.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hwpf/TestHWPFPictures.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hwpf/TestHWPFPictures.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/testcases/org/apache/poi/hwpf/TestHWPFPictures.java Sat Jun 21 05:03:44 2008
@@ -35,10 +35,12 @@
 	private String docAFile;
 	private String docBFile;
 	private String docCFile;
+    private String docDFile;
 	
 	private String imgAFile;
 	private String imgBFile;
 	private String imgCFile;
+    private String imgDFile;
 	
 	protected void setUp() throws Exception {
 		String dirname = System.getProperty("HWPF.testdata.path");
@@ -46,10 +48,12 @@
 		docAFile = dirname + "/testPictures.doc";
 		docBFile = dirname + "/two_images.doc";
 		docCFile = dirname + "/vector_image.doc";
+        docDFile = dirname + "/GaiaTest.doc";
 		
 		imgAFile = dirname + "/simple_image.jpg";
 		imgBFile = dirname + "/simple_image.png";
 		imgCFile = dirname + "/vector_image.emf";
+        imgDFile = dirname + "/GaiaTestImg.png";
 	}
 	
 	/**
@@ -126,7 +130,26 @@
 		assertEquals(picBytes.length, pic.getContent().length);
 		assertBytesSame(picBytes, pic.getContent());
 	}
-	
+    
+	/**
+	 * Pending the missing files being uploaded to
+	 *  bug #44937
+	 */
+    public void BROKENtestEscherDrawing() throws Exception
+    {
+        HWPFDocument docD = new HWPFDocument(new FileInputStream(docDFile));
+        List allPictures = docD.getPicturesTable().getAllPictures();
+        
+        assertEquals(1, allPictures.size());
+        
+        Picture pic = (Picture) allPictures.get(0);
+        assertNotNull(pic);
+        byte[] picD = readFile(imgDFile);
+        
+        assertEquals(picD.length, pic.getContent().length);
+        
+        assertBytesSame(picD, pic.getContent());
+    }
 	
 	private void assertBytesSame(byte[] a, byte[] b) {
 		assertEquals(a.length, b.length);

Modified: poi/tags/REL_3_1_FINAL/src/testcases/org/apache/poi/hssf/extractor/TestExcelExtractor.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/testcases/org/apache/poi/hssf/extractor/TestExcelExtractor.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/testcases/org/apache/poi/hssf/extractor/TestExcelExtractor.java (original)
+++ poi/tags/REL_3_1_FINAL/src/testcases/org/apache/poi/hssf/extractor/TestExcelExtractor.java Sat Jun 21 05:03:44 2008
@@ -165,6 +165,28 @@
 		);
 	}
 	
+	public void testWithComments() throws Exception {
+		ExcelExtractor extractor = createExtractor("SimpleWithComments.xls");
+		extractor.setIncludeSheetNames(false);
+
+		// Check without comments
+		assertEquals(
+				"1.0\tone\n" +
+				"2.0\ttwo\n" + 
+				"3.0\tthree\n", 
+				extractor.getText()
+		);
+		
+		// Now with
+		extractor.setIncludeCellComments(true);
+		assertEquals(
+				"1.0\tone Comment by Yegor Kozlov: Yegor Kozlov: first cell\n" +
+				"2.0\ttwo Comment by Yegor Kozlov: Yegor Kozlov: second cell\n" + 
+				"3.0\tthree Comment by Yegor Kozlov: Yegor Kozlov: third cell\n", 
+				extractor.getText()
+		);
+	}
+	
 	
 	/**
 	 * Embded in a non-excel file

Modified: poi/tags/REL_3_1_FINAL/src/testcases/org/apache/poi/hssf/model/AllModelTests.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/testcases/org/apache/poi/hssf/model/AllModelTests.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/testcases/org/apache/poi/hssf/model/AllModelTests.java (original)
+++ poi/tags/REL_3_1_FINAL/src/testcases/org/apache/poi/hssf/model/AllModelTests.java Sat Jun 21 05:03:44 2008
@@ -33,6 +33,9 @@
 		result.addTestSuite(TestDrawingManager2.class);
 		result.addTestSuite(TestFormulaParser.class);
 		result.addTestSuite(TestFormulaParserEval.class);
+		result.addTestSuite(TestFormulaParserIf.class);
+		result.addTestSuite(TestOperandClassTransformer.class);
+		result.addTestSuite(TestRVA.class);
 		result.addTestSuite(TestSheet.class);
 		result.addTestSuite(TestSheetAdditional.class);
 		return result;



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org