summaryrefslogtreecommitdiffstats
path: root/src/scratchpad
diff options
context:
space:
mode:
authorYegor Kozlov <yegor@apache.org>2008-01-04 14:19:14 +0000
committerYegor Kozlov <yegor@apache.org>2008-01-04 14:19:14 +0000
commitce32b7c036323c2b722ee129ac8a428abd4fe5ce (patch)
tree9f1274454491f23d795137e6e6afcd7887f98f6e /src/scratchpad
parent329d1ae3307d1beccb50410dc960badd42ca5df0 (diff)
downloadpoi-REL_3_0_2_BETA2.tar.gz
poi-REL_3_0_2_BETA2.zip
merged TRUNK changes r608809 into REL_3_0_2_BETA2REL_3_0_2_BETA2
git-svn-id: https://svn.apache.org/repos/asf/poi/tags/REL_3_0_2_BETA2@608846 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/scratchpad')
-rwxr-xr-xsrc/scratchpad/examples/src/org/apache/poi/hslf/examples/TableDemo.java127
-rw-r--r--src/scratchpad/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java2
-rw-r--r--src/scratchpad/src/org/apache/poi/hslf/model/Fill.java2
-rw-r--r--src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java5
-rw-r--r--src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java12
-rwxr-xr-xsrc/scratchpad/src/org/apache/poi/hslf/model/Table.java291
-rwxr-xr-xsrc/scratchpad/src/org/apache/poi/hslf/model/TableCell.java155
-rw-r--r--src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java19
-rw-r--r--src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java15
-rw-r--r--src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java6
-rw-r--r--src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java23
-rw-r--r--src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java1
-rw-r--r--src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Date.java2
-rw-r--r--src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Day.java2
-rw-r--r--src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Mid.java76
-rw-r--r--src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Month.java2
-rw-r--r--src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Replace.java89
-rw-r--r--src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Substitute.java94
-rw-r--r--src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Trim.java60
-rw-r--r--src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Year.java2
-rw-r--r--src/scratchpad/src/org/apache/poi/hwpf/model/ListTables.java12
-rw-r--r--src/scratchpad/src/org/apache/poi/hwpf/sprm/TableSprmUncompressor.java6
-rw-r--r--src/scratchpad/src/org/apache/poi/hwpf/usermodel/ListEntry.java21
-rwxr-xr-xsrc/scratchpad/testcases/org/apache/poi/hslf/data/43781.pptbin0 -> 39424 bytes
-rw-r--r--src/scratchpad/testcases/org/apache/poi/hslf/data/sample.pptxbin0 -> 47215 bytes
-rw-r--r--src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java32
-rw-r--r--src/scratchpad/testcases/org/apache/poi/hsmf/model/TestBlankFileRead.java15
-rw-r--r--src/scratchpad/testcases/org/apache/poi/hsmf/model/TestSimpleFileRead.java12
-rw-r--r--src/scratchpad/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xlsbin125952 -> 130048 bytes
-rw-r--r--src/scratchpad/testcases/org/apache/poi/hssf/record/formula/eval/TestEverything.java40
-rw-r--r--src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestEverything.java9
-rw-r--r--src/scratchpad/testcases/org/apache/poi/hwpf/data/AIOOB-Tap.docbin0 -> 57856 bytes
-rw-r--r--src/scratchpad/testcases/org/apache/poi/hwpf/data/IllustrativeCases.docxbin0 -> 22858 bytes
-rw-r--r--src/scratchpad/testcases/org/apache/poi/hwpf/data/ListEntryNoListTable.docbin0 -> 19456 bytes
-rw-r--r--src/scratchpad/testcases/org/apache/poi/hwpf/data/sample.docxbin0 -> 14860 bytes
-rw-r--r--src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestProblems.java77
36 files changed, 1152 insertions, 57 deletions
diff --git a/src/scratchpad/examples/src/org/apache/poi/hslf/examples/TableDemo.java b/src/scratchpad/examples/src/org/apache/poi/hslf/examples/TableDemo.java
new file mode 100755
index 0000000000..25ff9ad017
--- /dev/null
+++ b/src/scratchpad/examples/src/org/apache/poi/hslf/examples/TableDemo.java
@@ -0,0 +1,127 @@
+
+/* ====================================================================
+ 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.examples;
+
+import org.apache.poi.hslf.usermodel.SlideShow;
+import org.apache.poi.hslf.usermodel.RichTextRun;
+import org.apache.poi.hslf.model.*;
+
+import java.awt.*;
+import java.io.FileOutputStream;
+
+/**
+ * Demonstrates how to create tables
+ *
+ * @author Yegor Kozlov
+ */
+public class TableDemo {
+
+ public static void main(String[] args) throws Exception {
+
+ //test data for the first taable
+ String[][] txt1 = {
+ {"INPUT FILE", "NUMBER OF RECORDS"},
+ {"Item File", "11,559"},
+ {"Vendor File", "502"},
+ {"Purchase History File - # of PO\u2019s\r(12/01/04 - 05/31/06)", "12,852"},
+ {"Purchase History File - # of PO Lines\r(12/01/04 - 05/31/06)", "53,523" },
+ {"Total PO History Spend", "$10,172,038"}
+ };
+
+ SlideShow ppt = new SlideShow();
+
+ Slide slide = ppt.createSlide();
+
+ //six rows, two columns
+ Table table1 = new Table(6, 2);
+ for (int i = 0; i < txt1.length; i++) {
+ for (int j = 0; j < txt1[i].length; j++) {
+ TableCell cell = table1.getCell(i, j);
+ cell.setText(txt1[i][j]);
+ RichTextRun rt = cell.getTextRun().getRichTextRuns()[0];
+ rt.setFontName("Arial");
+ rt.setFontSize(10);
+ if(i == 0){
+ cell.getFill().setForegroundColor(new Color(227, 227, 227));
+ } else {
+ rt.setBold(true);
+ }
+ cell.setVerticalAlignment(TextBox.AnchorMiddle);
+ cell.setHorizontalAlignment(TextBox.AlignCenter);
+ }
+ }
+
+ Line border1 = table1.createBorder();
+ border1.setLineColor(Color.black);
+ border1.setLineWidth(1.0);
+ table1.setAllBorders(border1);
+
+ table1.setColumnWidth(0, 300);
+ table1.setColumnWidth(1, 150);
+
+ slide.addShape(table1);
+ int pgWidth = ppt.getPageSize().width;
+ table1.moveTo((pgWidth - table1.getAnchor().width)/2, 100);
+
+ //test data for the second taable
+ String[][] txt2 = {
+ {"Data Source"},
+ {"CAS Internal Metrics - Item Master Summary\r" +
+ "CAS Internal Metrics - Vendor Summary\r" +
+ "CAS Internal Metrics - PO History Summary"}
+ };
+
+ //two rows, one column
+ Table table2 = new Table(2, 1);
+ for (int i = 0; i < txt2.length; i++) {
+ for (int j = 0; j < txt2[i].length; j++) {
+ TableCell cell = table2.getCell(i, j);
+ cell.setText(txt2[i][j]);
+ RichTextRun rt = cell.getTextRun().getRichTextRuns()[0];
+ rt.setFontSize(10);
+ rt.setFontName("Arial");
+ if(i == 0){
+ cell.getFill().setForegroundColor(new Color(0, 51, 102));
+ rt.setFontColor(Color.white);
+ rt.setBold(true);
+ rt.setFontSize(14);
+ cell.setHorizontalAlignment(TextBox.AlignCenter);
+ } else {
+ rt.setBullet(true);
+ rt.setFontSize(12);
+ cell.setHorizontalAlignment(TextBox.AlignLeft);
+ }
+ cell.setVerticalAlignment(TextBox.AnchorMiddle);
+ }
+ }
+ table2.setColumnWidth(0, 300);
+ table2.setRowHeight(0, 30);
+ table2.setRowHeight(1, 70);
+
+ Line border2 = table2.createBorder();
+ table2.setOutsideBorders(border2);
+
+ slide.addShape(table2);
+ table2.moveTo(200, 400);
+
+ FileOutputStream out = new FileOutputStream("hslf-table.ppt");
+ ppt.write(out);
+ out.close();
+
+ }
+}
diff --git a/src/scratchpad/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java b/src/scratchpad/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java
index 5f7392739f..1c8d994bfe 100644
--- a/src/scratchpad/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java
+++ b/src/scratchpad/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java
@@ -283,7 +283,7 @@ public class XLS2CSVmra implements HSSFListener {
format = format.replaceAll("\\\\-","-");
// Format as a date
- Date d = HSSFDateUtil.getJavaDate(value);
+ Date d = HSSFDateUtil.getJavaDate(value, false);
DateFormat df = new SimpleDateFormat(format);
return df.format(d);
} else {
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Fill.java b/src/scratchpad/src/org/apache/poi/hslf/model/Fill.java
index f0d85400be..7eae4edc4c 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/Fill.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/Fill.java
@@ -150,10 +150,12 @@ public class Fill {
EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID);
if (color == null) {
Shape.setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, -1);
+ Shape.setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150010);
}
else {
int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB();
Shape.setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, rgb);
+ Shape.setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150011);
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java b/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java
index b1761b2d9a..d8ddc7d2f2 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java
@@ -153,7 +153,7 @@ public abstract class Sheet {
*/
protected static void findTextRuns(Record[] records, Vector found) {
// Look for a TextHeaderAtom
- for (int i = 0; i < (records.length - 1); i++) {
+ for (int i = 0, slwtIndex=0; i < (records.length - 1); i++) {
if (records[i] instanceof TextHeaderAtom) {
TextRun trun = null;
TextHeaderAtom tha = (TextHeaderAtom) records[i];
@@ -179,7 +179,6 @@ public abstract class Sheet {
// TextSpecInfoAtom - Safe to ignore
} else {
System.err.println("Found a TextHeaderAtom not followed by a TextBytesAtom or TextCharsAtom: Followed by " + records[i + 1].getRecordType());
- continue;
}
if (trun != null) {
@@ -191,12 +190,14 @@ public abstract class Sheet {
Record[] recs = new Record[lst.size()];
lst.toArray(recs);
trun._records = recs;
+ trun.setIndex(slwtIndex);
found.add(trun);
i++;
} else {
// Not a valid one, so skip on to next and look again
}
+ slwtIndex++;
}
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java
index 2f634ccd17..1074916004 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java
@@ -124,8 +124,10 @@ public class SimpleShape extends Shape {
int rgb = p1.getPropertyValue();
if (rgb >= 0x8000000) {
int idx = rgb % 0x8000000;
- ColorSchemeAtom ca = getSheet().getColorScheme();
- if(idx >= 0 && idx <= 7) rgb = ca.getColor(idx);
+ if(getSheet() != null) {
+ ColorSchemeAtom ca = getSheet().getColorScheme();
+ if(idx >= 0 && idx <= 7) rgb = ca.getColor(idx);
+ }
}
Color tmp = new Color(rgb, true);
clr = new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed());
@@ -192,8 +194,10 @@ public class SimpleShape extends Shape {
int rgb = p1.getPropertyValue();
if (rgb >= 0x8000000) {
int idx = rgb % 0x8000000;
- ColorSchemeAtom ca = getSheet().getColorScheme();
- rgb = ca.getColor(idx);
+ if(getSheet() != null) {
+ ColorSchemeAtom ca = getSheet().getColorScheme();
+ rgb = ca.getColor(idx);
+ }
}
Color tmp = new Color(rgb, true);
clr = new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed());
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Table.java b/src/scratchpad/src/org/apache/poi/hslf/model/Table.java
new file mode 100755
index 0000000000..a9f21b54f3
--- /dev/null
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/Table.java
@@ -0,0 +1,291 @@
+
+/* ====================================================================
+ 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.util.LittleEndian;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Iterator;
+import java.awt.*;
+
+/**
+ * Represents a table in a PowerPoint presentation
+ *
+ * @author Yegor Kozlov
+ */
+public class Table extends ShapeGroup {
+
+ protected static final int BORDER_TOP = 1;
+ protected static final int BORDER_RIGHT = 2;
+ protected static final int BORDER_BOTTOM = 3;
+ protected static final int BORDER_LEFT = 4;
+
+ protected static final int BORDERS_ALL = 5;
+ protected static final int BORDERS_OUTSIDE = 6;
+ protected static final int BORDERS_INSIDE = 7;
+ protected static final int BORDERS_NONE = 8;
+
+
+ protected TableCell[][] cells;
+
+ /**
+ * Create a new Table of the given number of rows and columns
+ *
+ * @param numrows the number of rows
+ * @param numcols the number of columns
+ */
+ public Table(int numrows, int numcols) {
+ super();
+
+ int x=0, y=0, tblWidth=0, tblHeight=0;
+ cells = new TableCell[numrows][numcols];
+ for (int i = 0; i < cells.length; i++) {
+ x = 0;
+ for (int j = 0; j < cells[i].length; j++) {
+ cells[i][j] = new TableCell(this);
+ Rectangle anchor = new Rectangle(x, y, TableCell.DEFAULT_WIDTH, TableCell.DEFAULT_HEIGHT);
+ cells[i][j].setAnchor(anchor);
+ x += TableCell.DEFAULT_WIDTH;
+ }
+ y += TableCell.DEFAULT_HEIGHT;
+ }
+ tblWidth = x;
+ tblHeight = y;
+ setAnchor(new Rectangle(0, 0, tblWidth, tblHeight));
+
+ EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);
+ List lst = spCont.getChildRecords();
+ EscherOptRecord opt = new EscherOptRecord();
+ opt.setRecordId((short)0xF122);
+ opt.addEscherProperty(new EscherSimpleProperty((short)0x39F, 1));
+ EscherArrayProperty p = new EscherArrayProperty((short)0x43A0, false, null);
+ p.setSizeOfElements(0x0004);
+ p.setNumberOfElementsInArray(numrows);
+ p.setNumberOfElementsInMemory(numrows);
+ opt.addEscherProperty(p);
+ lst.add(lst.size()-1, opt);
+
+ }
+
+ /**
+ * Create a Table object and initilize 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 Table(EscherContainerRecord escherRecord, Shape parent) {
+ super(escherRecord, parent);
+ }
+
+ /**
+ * Gets a cell
+ *
+ * @param row the row index (0-based)
+ * @param col the column index (0-based)
+ * @return the cell
+ */
+ public TableCell getCell(int row, int col) {
+ return cells[row][col];
+ }
+
+ public int getNumberOfColumns() {
+ return cells[0].length;
+ }
+ public int getNumberOfRows() {
+ return cells.length;
+ }
+
+ protected void afterInsert(Sheet sh){
+ EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);
+ List lst = spCont.getChildRecords();
+ EscherOptRecord opt = (EscherOptRecord)lst.get(lst.size()-2);
+ EscherArrayProperty p = (EscherArrayProperty)opt.getEscherProperty(1);
+ for (int i = 0; i < cells.length; i++) {
+ TableCell cell = cells[i][0];
+ int rowHeight = cell.getAnchor().height*MASTER_DPI/POINT_DPI;
+ byte[] val = new byte[4];
+ LittleEndian.putInt(val, rowHeight);
+ p.setElement(i, val);
+ for (int j = 0; j < cells[i].length; j++) {
+ TableCell c = cells[i][j];
+ addShape(c);
+
+ Line bt = c.getBorderTop();
+ if(bt != null) addShape(bt);
+
+ Line br = c.getBorderRight();
+ if(br != null) addShape(br);
+
+ Line bb = c.getBorderBottom();
+ if(bb != null) addShape(bb);
+
+ Line bl = c.getBorderLeft();
+ if(bl != null) addShape(bl);
+
+ }
+ }
+
+ }
+
+ /**
+ * Sets the row height.
+ *
+ * @param row the row index (0-based)
+ * @param height the height to set (in pixels)
+ */
+ public void setRowHeight(int row, int height){
+ int currentHeight = cells[row][0].getAnchor().height;
+ int dy = height - currentHeight;
+
+ for (int i = row; i < cells.length; i++) {
+ for (int j = 0; j < cells[i].length; j++) {
+ Rectangle anchor = cells[i][j].getAnchor();
+ if(i == row) anchor.height = height;
+ else anchor.y += dy;
+ cells[i][j].setAnchor(anchor);
+ }
+ }
+ Rectangle tblanchor = getAnchor();
+ tblanchor.height += dy;
+ setAnchor(tblanchor);
+
+ }
+
+ /**
+ * Sets the column width.
+ *
+ * @param col the column index (0-based)
+ * @param width the width to set (in pixels)
+ */
+ public void setColumnWidth(int col, int width){
+ int currentWidth = cells[0][col].getAnchor().width;
+ int dx = width - currentWidth;
+ for (int i = 0; i < cells.length; i++) {
+ Rectangle anchor = cells[i][col].getAnchor();
+ anchor.width = width;
+ cells[i][col].setAnchor(anchor);
+
+ if(col < cells[i].length - 1) for (int j = col+1; j < cells[i].length; j++) {
+ anchor = cells[i][j].getAnchor();
+ anchor.x += dx;
+ cells[i][j].setAnchor(anchor);
+ }
+ }
+ Rectangle tblanchor = getAnchor();
+ tblanchor.width += dx;
+ setAnchor(tblanchor);
+ }
+
+ /**
+ * Format the table and apply the specified Line to all cell boundaries,
+ * both outside and inside
+ *
+ * @param line the border line
+ */
+ public void setAllBorders(Line line){
+ for (int i = 0; i < cells.length; i++) {
+ for (int j = 0; j < cells[i].length; j++) {
+ TableCell cell = cells[i][j];
+ cell.setBorderTop(cloneBorder(line));
+ cell.setBorderLeft(cloneBorder(line));
+ if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line));
+ if(i == cells.length - 1) cell.setBorderBottom(cloneBorder(line));
+ }
+ }
+ }
+
+ /**
+ * Format the outside border using the specified Line object
+ *
+ * @param line the border line
+ */
+ public void setOutsideBorders(Line line){
+ for (int i = 0; i < cells.length; i++) {
+ for (int j = 0; j < cells[i].length; j++) {
+ TableCell cell = cells[i][j];
+
+ if(j == 0) cell.setBorderLeft(cloneBorder(line));
+ if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line));
+ else {
+ cell.setBorderLeft(null);
+ cell.setBorderLeft(null);
+ }
+
+ if(i == 0) cell.setBorderTop(cloneBorder(line));
+ else if(i == cells.length - 1) cell.setBorderBottom(cloneBorder(line));
+ else {
+ cell.setBorderTop(null);
+ cell.setBorderBottom(null);
+ }
+ }
+ }
+ }
+
+ /**
+ * Format the inside border using the specified Line object
+ *
+ * @param line the border line
+ */
+ public void setInsideBorders(Line line){
+ for (int i = 0; i < cells.length; i++) {
+ for (int j = 0; j < cells[i].length; j++) {
+ TableCell cell = cells[i][j];
+
+ if(j != cells[i].length - 1)
+ cell.setBorderRight(cloneBorder(line));
+ else {
+ cell.setBorderLeft(null);
+ cell.setBorderLeft(null);
+ }
+ if(i != cells.length - 1) cell.setBorderBottom(cloneBorder(line));
+ else {
+ cell.setBorderTop(null);
+ cell.setBorderBottom(null);
+ }
+ }
+ }
+ }
+
+ private Line cloneBorder(Line line){
+ Line border = createBorder();
+ border.setLineWidth(line.getLineWidth());
+ border.setLineStyle(line.getLineStyle());
+ border.setLineDashing(line.getLineDashing());
+ border.setLineColor(line.getLineColor());
+ return border;
+ }
+
+ /**
+ * Create a border to format this table
+ *
+ * @return the created border
+ */
+ public Line createBorder(){
+ Line line = new Line(this);
+
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(line.getSpContainer(), EscherOptRecord.RECORD_ID);
+ setEscherProperty(opt, EscherProperties.GEOMETRY__SHAPEPATH, -1);
+ setEscherProperty(opt, EscherProperties.GEOMETRY__FILLOK, -1);
+ setEscherProperty(opt, EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000);
+ setEscherProperty(opt, EscherProperties.THREED__LIGHTFACE, 0x80000);
+
+ return line;
+ }
+}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java b/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java
new file mode 100755
index 0000000000..bb93e06b71
--- /dev/null
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java
@@ -0,0 +1,155 @@
+
+/* ====================================================================
+ 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.EscherTextboxWrapper;
+import org.apache.poi.hslf.record.TextHeaderAtom;
+import org.apache.poi.hslf.usermodel.RichTextRun;
+
+import java.awt.*;
+
+/**
+ * Represents a cell in a ppt table
+ *
+ * @author Yegor Kozlov
+ */
+public class TableCell extends TextBox {
+ protected static final int DEFAULT_WIDTH = 100;
+ protected static final int DEFAULT_HEIGHT = 40;
+
+ private Line borderLeft;
+ private Line borderRight;
+ private Line borderTop;
+ private Line borderBottom;
+
+ /**
+ * Create a TableCell 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 TableCell(EscherContainerRecord escherRecord, Shape parent){
+ super(escherRecord, parent);
+ }
+
+ /**
+ * Create a new TableCell. 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 TableCell(Shape parent){
+ super(parent);
+
+ setShapeType(ShapeTypes.Rectangle);
+ _txtrun.setRunType(TextHeaderAtom.HALF_BODY_TYPE);
+ _txtrun.getRichTextRuns()[0].setFlag(false, 0, false);
+ }
+
+ protected EscherContainerRecord createSpContainer(boolean isChild){
+ EscherContainerRecord spContainer = super.createSpContainer(isChild);
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(spContainer, EscherOptRecord.RECORD_ID);
+ setEscherProperty(opt, EscherProperties.TEXT__TEXTID, 0);
+ setEscherProperty(opt, EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x20000);
+ setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150001);
+ setEscherProperty(opt, EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000);
+ setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x40000);
+
+ return spContainer;
+ }
+
+ protected void anchorBorder(int type, Line line){
+ Rectangle cellAnchor = getAnchor();
+ Rectangle lineAnchor = new Rectangle();
+ switch(type){
+ case Table.BORDER_TOP:
+ lineAnchor.x = cellAnchor.x;
+ lineAnchor.y = cellAnchor.y;
+ lineAnchor.width = cellAnchor.width;
+ lineAnchor.height = 0;
+ break;
+ case Table.BORDER_RIGHT:
+ lineAnchor.x = cellAnchor.x + cellAnchor.width;
+ lineAnchor.y = cellAnchor.y;
+ lineAnchor.width = 0;
+ lineAnchor.height = cellAnchor.height;
+ break;
+ case Table.BORDER_BOTTOM:
+ lineAnchor.x = cellAnchor.x;
+ lineAnchor.y = cellAnchor.y + cellAnchor.height;
+ lineAnchor.width = cellAnchor.width;
+ lineAnchor.height = 0;
+ break;
+ case Table.BORDER_LEFT:
+ lineAnchor.x = cellAnchor.x;
+ lineAnchor.y = cellAnchor.y;
+ lineAnchor.width = 0;
+ lineAnchor.height = cellAnchor.height;
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown border type: " + type);
+ }
+ line.setAnchor(lineAnchor);
+ }
+
+ public Line getBorderLeft() {
+ return borderLeft;
+ }
+
+ public void setBorderLeft(Line line) {
+ if(line != null) anchorBorder(Table.BORDER_LEFT, line);
+ this.borderLeft = line;
+ }
+
+ public Line getBorderRight() {
+ return borderRight;
+ }
+
+ public void setBorderRight(Line line) {
+ if(line != null) anchorBorder(Table.BORDER_RIGHT, line);
+ this.borderRight = line;
+ }
+
+ public Line getBorderTop() {
+ return borderTop;
+ }
+
+ public void setBorderTop(Line line) {
+ if(line != null) anchorBorder(Table.BORDER_TOP, line);
+ this.borderTop = line;
+ }
+
+ public Line getBorderBottom() {
+ return borderBottom;
+ }
+
+ public void setBorderBottom(Line line) {
+ if(line != null) anchorBorder(Table.BORDER_BOTTOM, line);
+ this.borderBottom = line;
+ }
+
+ public void setAnchor(Rectangle anchor){
+ super.setAnchor(anchor);
+
+ if(borderTop != null) anchorBorder(Table.BORDER_TOP, borderTop);
+ if(borderRight != null) anchorBorder(Table.BORDER_RIGHT, borderRight);
+ if(borderBottom != null) anchorBorder(Table.BORDER_BOTTOM, borderBottom);
+ if(borderLeft != null) anchorBorder(Table.BORDER_LEFT, borderLeft);
+ }
+}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java b/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java
index 2d5c866f77..1f9a489a78 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java
@@ -196,7 +196,7 @@ public class TextBox extends SimpleShape {
} catch (IOException e){
throw new HSLFException(e);
}
- if(getAnchor().equals(new java.awt.Rectangle())) resizeToFitText();
+ if(getAnchor().equals(new java.awt.Rectangle()) && !"".equals(getText())) resizeToFitText();
}
/**
@@ -264,6 +264,14 @@ public class TextBox extends SimpleShape {
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
setEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT, align);
}
+
+ public void setHorizontalAlignment(int align){
+ _txtrun.getRichTextRuns()[0].setAlignment(align);
+ }
+ public int getHorizontalAlignment(){
+ return _txtrun.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.
@@ -466,7 +474,11 @@ public class TextBox extends SimpleShape {
TextRun[] runs = sheet.getTextRuns();
if (ota != null) {
int idx = ota.getTextIndex();
- if(idx < runs.length) _txtrun = runs[idx];
+ for (int i = 0; i < runs.length; i++) {
+ if(runs[i].getIndex() == idx){
+ _txtrun = runs[i];
+ }
+ }
if(_txtrun == null) {
logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx);
}
@@ -478,9 +490,6 @@ public class TextBox extends SimpleShape {
break;
}
}
- if(_txtrun == null) {
- logger.log(POILogger.WARN, "text run not found for shapeId=" + shapeId);
- }
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java b/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java
index 4999df7581..ca6e02d69b 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java
@@ -50,6 +50,7 @@ public class TextRun
private SlideShow slideShow;
private Sheet sheet;
private int shapeId;
+ private int slwtIndex; //position in the owning SlideListWithText
/**
* all text run records that follow TextHeaderAtom.
* (there can be misc InteractiveInfo, TxInteractiveInfo and other records)
@@ -538,6 +539,20 @@ public class TextRun
}
/**
+ * @return 0-based index of the text run in the SLWT container
+ */
+ protected int getIndex(){
+ return slwtIndex;
+ }
+
+ /**
+ * @param id 0-based index of the text run in the SLWT container
+ */
+ protected void setIndex(int id){
+ slwtIndex = id;
+ }
+
+ /**
* Returns the array of all hyperlinks in this text run
*
* @return the array of all hyperlinks in this text run
diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java
index 0ee01b9a96..d16bf7bc02 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java
@@ -198,7 +198,7 @@ public class RichTextRun
setFlag(true, index, value);
}
- private void setFlag(boolean isCharacter, int index, boolean value) {
+ public void setFlag(boolean isCharacter, int index, boolean value) {
TextPropCollection props;
String propname;
if (isCharacter){
@@ -282,7 +282,7 @@ public class RichTextRun
* @param propName The name of the Character TextProp
* @param val The value to set for the TextProp
*/
- private void setParaTextPropVal(String propName, int val) {
+ public void setParaTextPropVal(String propName, int val) {
// Ensure we have the StyleTextProp atom we're going to need
if(paragraphStyle == null) {
parentRun.ensureStyleAtomPresent();
@@ -297,7 +297,7 @@ public class RichTextRun
* @param propName The name of the Paragraph TextProp
* @param val The value to set for the TextProp
*/
- private void setCharTextPropVal(String propName, int val) {
+ public void setCharTextPropVal(String propName, int val) {
// Ensure we have the StyleTextProp atom we're going to need
if(characterStyle == null) {
parentRun.ensureStyleAtomPresent();
diff --git a/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java b/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java
index ed215f6382..eb915160b3 100644
--- a/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java
+++ b/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java
@@ -48,15 +48,24 @@ public class MAPIMessage {
/**
- * Constructor for reading MSG Files.
+ * Constructor for reading MSG Files from the file system.
* @param filename
* @throws IOException
*/
public MAPIMessage(String filename) throws IOException {
- InputStream in = new FileInputStream(new File(filename));
+ this(new FileInputStream(new File(filename)));
+ }
+
+ /**
+ * Constructor for reading MSG Files from an input stream.
+ * @param in
+ * @throws IOException
+ */
+ public MAPIMessage(InputStream in) throws IOException {
this.fs = new POIFSFileSystem(in);
chunkParser = new POIFSChunkParser(this.fs);
}
+
/**
* Gets a string value based on the passed chunk.
@@ -102,6 +111,16 @@ public class MAPIMessage {
}
/**
+ * Gets the display value of the "FROM" line of the outlook message
+ * This is not the actual address that was sent from but the formated display of the user name.
+ * @return
+ * @throws ChunkNotFoundException
+ */
+ public String getDisplayFrom() throws ChunkNotFoundException {
+ return getStringFromChunk(Chunks.getInstance().displayFromChunk);
+ }
+
+ /**
* Gets the display value of the "TO" line of the outlook message
* This is not the actual list of addresses/values that will be sent to if you click Reply in the email.
* @return
diff --git a/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java
index 309efeac9d..6a3936d964 100644
--- a/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java
+++ b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java
@@ -29,6 +29,7 @@ public class Chunks {
public StringChunk textBodyChunk = new StringChunk(0x1000); //BODY Chunk, for plain/text messages
public StringChunk subjectChunk = new StringChunk(0x0037); //Subject link chunk, in plain/text
public StringChunk displayToChunk = new StringChunk(0x0E04); //Value that is in the TO field (not actually the addresses as they are stored in recip directory nodes
+ public StringChunk displayFromChunk = new StringChunk(0x0C1A); //Value that is in the FROM field
public StringChunk displayCCChunk = new StringChunk(0x0E03); //value that shows in the CC field
public StringChunk displayBCCChunk = new StringChunk(0x0E02); //Value that shows in the BCC field
public StringChunk conversationTopic = new StringChunk(0x0070); //Sort of like the subject line, but without the RE: and FWD: parts.
diff --git a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Date.java b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Date.java
index 34dcc7cdae..6861a02524 100644
--- a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Date.java
+++ b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Date.java
@@ -70,7 +70,7 @@ public class Date extends NumericFunction {
c.set(year, month, day, 0, 0, 0);
c.set(Calendar.MILLISECOND, 0);
- return new NumberEval(HSSFDateUtil.getExcelDate(c.getTime()));
+ return new NumberEval(HSSFDateUtil.getExcelDate(c.getTime(), false)); // XXX fix 1900/1904 problem
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Day.java b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Day.java
index 283633442e..0ae5694767 100644
--- a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Day.java
+++ b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Day.java
@@ -46,7 +46,7 @@ srcCellRow, srcCellCol);
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
if (HSSFDateUtil.isValidExcelDate(ne.getNumberValue())) {
- java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue());
+ java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue(), false); // XXX fix 1900/1904 problem
java.util.Calendar c = java.util.Calendar.getInstance();
c.setTime(d);
retval = new NumberEval(c.get(java.util.Calendar.DAY_OF_MONTH));
diff --git a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Mid.java b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Mid.java
index 30593142e8..d6c4399ae3 100644
--- a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Mid.java
+++ b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Mid.java
@@ -20,6 +20,80 @@
*/
package org.apache.poi.hssf.record.formula.functions;
-public class Mid extends NotImplementedFunction {
+import org.apache.poi.hssf.record.formula.eval.BlankEval;
+import org.apache.poi.hssf.record.formula.eval.ErrorEval;
+import org.apache.poi.hssf.record.formula.eval.Eval;
+import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
+import org.apache.poi.hssf.record.formula.eval.StringEval;
+import org.apache.poi.hssf.record.formula.eval.StringValueEval;
+import org.apache.poi.hssf.record.formula.eval.ValueEval;
+
+/**
+ * An implementation of the MID function:
+ * Returns a specific number of characters from a text string,
+ * starting at the position you specify, based on the number
+ * of characters you specify.
+ * @author Manda Wilson &lt; wilson at c bio dot msk cc dot org &gt;
+ */
+public class Mid extends TextFunction {
+ /**
+ * Returns a specific number of characters from a text string,
+ * starting at the position you specify, based on the number
+ * of characters you specify.
+ *
+ * @see org.apache.poi.hssf.record.formula.eval.Eval
+ */
+ public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
+ Eval retval = null;
+ String str = null;
+ int startNum = 0;
+ int numChars = 0;
+
+ switch (operands.length) {
+ default:
+ retval = ErrorEval.VALUE_INVALID;
+ case 3:
+ // first operand is text string containing characters to extract
+ // second operand is position of first character to extract
+ // third operand is the number of characters to return
+ ValueEval firstveval = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
+ ValueEval secondveval = singleOperandEvaluate(operands[1], srcCellRow, srcCellCol);
+ ValueEval thirdveval = singleOperandEvaluate(operands[2], srcCellRow, srcCellCol);
+ if (firstveval instanceof StringValueEval
+ && secondveval instanceof NumericValueEval
+ && thirdveval instanceof NumericValueEval) {
+
+ StringValueEval strEval = (StringValueEval) firstveval;
+ str = strEval.getStringValue();
+
+ NumericValueEval startNumEval = (NumericValueEval) secondveval;
+ // NOTE: it is safe to cast to int here
+ // because in Excel =MID("test", 1, 1.7) returns t
+ // so 1.7 must be truncated to 1
+ // and =MID("test", 1.9, 2) returns te
+ // so 1.9 must be truncated to 1
+ startNum = (int) startNumEval.getNumberValue();
+
+ NumericValueEval numCharsEval = (NumericValueEval) thirdveval;
+ numChars = (int) numCharsEval.getNumberValue();
+
+ } else {
+ retval = ErrorEval.VALUE_INVALID;
+ }
+ }
+
+ if (retval == null) {
+ if (startNum < 1 || numChars < 0) {
+ retval = ErrorEval.VALUE_INVALID;
+ } else if (startNum > str.length() || numChars == 0) {
+ retval = BlankEval.INSTANCE;
+ } else if (startNum + numChars > str.length()) {
+ retval = new StringEval(str.substring(startNum - 1));
+ } else {
+ retval = new StringEval(str.substring(startNum - 1, numChars));
+ }
+ }
+ return retval;
+ }
}
diff --git a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Month.java b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Month.java
index 065c565d14..d5178b22df 100644
--- a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Month.java
+++ b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Month.java
@@ -50,7 +50,7 @@ public class Month extends NumericFunction {
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
if (HSSFDateUtil.isValidExcelDate(ne.getNumberValue())) {
- java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue());
+ java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue(), false); // XXX fix 1900/1904 problem
retval = new NumberEval(d.getMonth()+1);
} else {
retval = ErrorEval.NUM_ERROR;
diff --git a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Replace.java b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Replace.java
index 3ba7a2b2ce..95413f0823 100644
--- a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Replace.java
+++ b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Replace.java
@@ -20,6 +20,93 @@
*/
package org.apache.poi.hssf.record.formula.functions;
-public class Replace extends NotImplementedFunction {
+import org.apache.poi.hssf.record.formula.eval.ErrorEval;
+import org.apache.poi.hssf.record.formula.eval.Eval;
+import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
+import org.apache.poi.hssf.record.formula.eval.StringEval;
+import org.apache.poi.hssf.record.formula.eval.StringValueEval;
+import org.apache.poi.hssf.record.formula.eval.ValueEval;
+
+/**
+ * An implementation of the REPLACE function:
+ * Replaces part of a text string based on the number of characters
+ * you specify, with another text string.
+ * @author Manda Wilson &lt; wilson at c bio dot msk cc dot org &gt;
+ */
+public class Replace extends TextFunction {
+
+ /**
+ * Replaces part of a text string based on the number of characters
+ * you specify, with another text string.
+ *
+ * @see org.apache.poi.hssf.record.formula.eval.Eval
+ */
+ public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
+ Eval retval = null;
+ String oldStr = null;
+ String newStr = null;
+ int startNum = 0;
+ int numChars = 0;
+
+ switch (operands.length) {
+ default:
+ retval = ErrorEval.VALUE_INVALID;
+ case 4:
+ // first operand is text string containing characters to replace
+ // second operand is position of first character to replace
+ // third operand is the number of characters in the old string
+ // you want to replace with new string
+ // fourth operand is the new string
+ ValueEval firstveval = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
+ ValueEval secondveval = singleOperandEvaluate(operands[1], srcCellRow, srcCellCol);
+ ValueEval thirdveval = singleOperandEvaluate(operands[2], srcCellRow, srcCellCol);
+ ValueEval fourthveval = singleOperandEvaluate(operands[3], srcCellRow, srcCellCol);
+ if (firstveval instanceof StringValueEval
+ && secondveval instanceof NumericValueEval
+ && thirdveval instanceof NumericValueEval
+ && fourthveval instanceof StringValueEval) {
+
+ StringValueEval oldStrEval = (StringValueEval) firstveval;
+ oldStr = oldStrEval.getStringValue();
+
+ NumericValueEval startNumEval = (NumericValueEval) secondveval;
+ // NOTE: it is safe to cast to int here
+ // because in Excel =REPLACE("task", 2.7, 3, "est")
+ // returns test
+ // so 2.7 must be truncated to 2
+ // and =REPLACE("task", 1, 1.9, "") returns ask
+ // so 1.9 must be truncated to 1
+ startNum = (int) startNumEval.getNumberValue();
+
+ NumericValueEval numCharsEval = (NumericValueEval) thirdveval;
+ numChars = (int) numCharsEval.getNumberValue();
+
+ StringValueEval newStrEval = (StringValueEval) fourthveval;
+ newStr = newStrEval.getStringValue();
+ } else {
+ retval = ErrorEval.VALUE_INVALID;
+ }
+ }
+
+ if (retval == null) {
+ if (startNum < 1 || numChars < 0) {
+ retval = ErrorEval.VALUE_INVALID;
+ } else {
+ StringBuffer strBuff = new StringBuffer(oldStr);
+ // remove any characters that should be replaced
+ if (startNum <= oldStr.length() && numChars != 0) {
+ strBuff.delete(startNum - 1, startNum - 1 + numChars);
+ }
+ // now insert (or append) newStr
+ if (startNum > strBuff.length()) {
+ strBuff.append(newStr);
+ } else {
+ strBuff.insert(startNum - 1, newStr);
+ }
+ retval = new StringEval(strBuff.toString());
+ }
+ }
+ return retval;
+ }
}
diff --git a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Substitute.java b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Substitute.java
index 8a975c569e..9d2e9ce361 100644
--- a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Substitute.java
+++ b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Substitute.java
@@ -20,6 +20,98 @@
*/
package org.apache.poi.hssf.record.formula.functions;
-public class Substitute extends NotImplementedFunction {
+import org.apache.poi.hssf.record.formula.eval.ErrorEval;
+import org.apache.poi.hssf.record.formula.eval.Eval;
+import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
+import org.apache.poi.hssf.record.formula.eval.StringEval;
+import org.apache.poi.hssf.record.formula.eval.StringValueEval;
+import org.apache.poi.hssf.record.formula.eval.ValueEval;
+/**
+ * An implementation of the SUBSTITUTE function:
+ * Substitutes text in a text string with new text, some number of times.
+ * @author Manda Wilson &lt; wilson at c bio dot msk cc dot org &gt;
+ */
+public class Substitute extends TextFunction {
+ private static final int REPLACE_ALL = -1;
+
+ /**
+ *Substitutes text in a text string with new text, some number of times.
+ *
+ * @see org.apache.poi.hssf.record.formula.eval.Eval
+ */
+ public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
+ Eval retval = null;
+ String oldStr = null;
+ String searchStr = null;
+ String newStr = null;
+ int numToReplace = REPLACE_ALL;
+
+ switch (operands.length) {
+ default:
+ retval = ErrorEval.VALUE_INVALID;
+ case 4:
+ ValueEval fourthveval = singleOperandEvaluate(operands[3], srcCellRow, srcCellCol);
+ if (fourthveval instanceof NumericValueEval) {
+ NumericValueEval numToReplaceEval = (NumericValueEval) fourthveval;
+ // NOTE: it is safe to cast to int here
+ // because in Excel =SUBSTITUTE("teststr","t","T",1.9)
+ // returns Teststr
+ // so 1.9 must be truncated to 1
+ numToReplace = (int) numToReplaceEval.getNumberValue();
+ } else {
+ retval = ErrorEval.VALUE_INVALID;
+ }
+ case 3:
+ // first operand is text string containing characters to replace
+ // second operand is text to find
+ // third operand is replacement text
+ ValueEval firstveval = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
+ ValueEval secondveval = singleOperandEvaluate(operands[1], srcCellRow, srcCellCol);
+ ValueEval thirdveval = singleOperandEvaluate(operands[2], srcCellRow, srcCellCol);
+ if (firstveval instanceof StringValueEval
+ && secondveval instanceof StringValueEval
+ && thirdveval instanceof StringValueEval) {
+
+ StringValueEval oldStrEval = (StringValueEval) firstveval;
+ oldStr = oldStrEval.getStringValue();
+
+ StringValueEval searchStrEval = (StringValueEval) secondveval;
+ searchStr = searchStrEval.getStringValue();
+
+ StringValueEval newStrEval = (StringValueEval) thirdveval;
+ newStr = newStrEval.getStringValue();
+ } else {
+ retval = ErrorEval.VALUE_INVALID;
+ }
+ }
+
+ if (retval == null) {
+ if (numToReplace != REPLACE_ALL && numToReplace < 1) {
+ retval = ErrorEval.VALUE_INVALID;
+ } else if (searchStr.length() == 0) {
+ retval = new StringEval(oldStr);
+ } else {
+ StringBuffer strBuff = new StringBuffer();
+ int startIndex = 0;
+ int nextMatch = -1;
+ for (int leftToReplace = numToReplace;
+ (leftToReplace > 0 || numToReplace == REPLACE_ALL)
+ && (nextMatch = oldStr.indexOf(searchStr, startIndex)) != -1;
+ leftToReplace--) {
+ // store everything from end of last match to start of this match
+ strBuff.append(oldStr.substring(startIndex, nextMatch));
+ strBuff.append(newStr);
+ startIndex = nextMatch + searchStr.length();
+ }
+ // store everything from end of last match to end of string
+ if (startIndex < oldStr.length()) {
+ strBuff.append(oldStr.substring(startIndex));
+ }
+ retval = new StringEval(strBuff.toString());
+ }
+ }
+ return retval;
+ }
+
}
diff --git a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Trim.java b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Trim.java
index 69b3ce6f55..5e9d91c7cc 100644
--- a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Trim.java
+++ b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Trim.java
@@ -14,12 +14,62 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/*
- * Created on May 15, 2005
- *
- */
package org.apache.poi.hssf.record.formula.functions;
-public class Trim extends NotImplementedFunction {
+import org.apache.poi.hssf.record.formula.eval.BlankEval;
+import org.apache.poi.hssf.record.formula.eval.ErrorEval;
+import org.apache.poi.hssf.record.formula.eval.Eval;
+import org.apache.poi.hssf.record.formula.eval.NumberEval;
+import org.apache.poi.hssf.record.formula.eval.StringEval;
+import org.apache.poi.hssf.record.formula.eval.StringValueEval;
+import org.apache.poi.hssf.record.formula.eval.ValueEval;
+
+/**
+ * An implementation of the TRIM function:
+ * Removes leading and trailing spaces from value if evaluated operand
+ * value is string.
+ * @author Manda Wilson &lt; wilson at c bio dot msk cc dot org &gt;
+ */
+public class Trim extends TextFunction {
+ /**
+ * Removes leading and trailing spaces from value if evaluated
+ * operand value is string.
+ * Returns StringEval only if evaluated operand is of type string
+ * (and is not blank or null) or number. If evaluated operand is
+ * of type string and is blank or null, or if evaluated operand is
+ * of type blank, returns BlankEval. Otherwise returns ErrorEval.
+ *
+ * @see org.apache.poi.hssf.record.formula.eval.Eval
+ */
+ public Eval evaluate(Eval[] operands, int srcCellRow, short srcCellCol) {
+ Eval retval = ErrorEval.VALUE_INVALID;
+ String str = null;
+
+ switch (operands.length) {
+ default:
+ break;
+ case 1:
+ ValueEval veval = singleOperandEvaluate(operands[0], srcCellRow, srcCellCol);
+ if (veval instanceof StringValueEval) {
+ StringValueEval sve = (StringValueEval) veval;
+ str = sve.getStringValue();
+ if (str == null || str.trim().equals("")) {
+ return BlankEval.INSTANCE;
+ }
+ }
+ else if (veval instanceof NumberEval) {
+ NumberEval neval = (NumberEval) veval;
+ str = neval.getStringValue();
+ }
+ else if (veval instanceof BlankEval) {
+ return BlankEval.INSTANCE;
+ }
+ }
+
+ if (str != null) {
+ retval = new StringEval(str.trim());
+ }
+ return retval;
+ }
}
diff --git a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Year.java b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Year.java
index 76ea617cc6..b461a09668 100644
--- a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Year.java
+++ b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/Year.java
@@ -51,7 +51,7 @@ public class Year extends NumericFunction {
if (ve instanceof NumericValueEval) {
NumericValueEval ne = (NumericValueEval) ve;
if (HSSFDateUtil.isValidExcelDate(ne.getNumberValue())) {
- java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue());
+ java.util.Date d = HSSFDateUtil.getJavaDate(ne.getNumberValue(), false); // XXX fix 1900/1904 problem
retval = new NumberEval(d.getYear()+1900);
} else {
retval = ErrorEval.NUM_ERROR;
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/ListTables.java b/src/scratchpad/src/org/apache/poi/hwpf/model/ListTables.java
index cec20c91e6..4196566d9a 100644
--- a/src/scratchpad/src/org/apache/poi/hwpf/model/ListTables.java
+++ b/src/scratchpad/src/org/apache/poi/hwpf/model/ListTables.java
@@ -19,6 +19,8 @@
package org.apache.poi.hwpf.model;
import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
import org.apache.poi.hwpf.model.io.*;
@@ -37,6 +39,7 @@ public class ListTables
{
private static final int LIST_DATA_SIZE = 28;
private static final int LIST_FORMAT_OVERRIDE_SIZE = 16;
+ private static POILogger log = POILogFactory.getLogger(ListTables.class);
HashMap _listMap = new HashMap();
ArrayList _overrideList = new ArrayList();
@@ -189,8 +192,13 @@ public class ListTables
public ListLevel getLevel(int listID, int level)
{
ListData lst = (ListData)_listMap.get(new Integer(listID));
- ListLevel lvl = lst.getLevels()[level];
- return lvl;
+ if(level < lst.numLevels()) {
+ ListLevel lvl = lst.getLevels()[level];
+ return lvl;
+ } else {
+ log.log(POILogger.WARN, "Requested level " + level + " which was greater than the maximum defined (" + lst.numLevels() + ")");
+ return null;
+ }
}
public ListData getListData(int listID)
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/sprm/TableSprmUncompressor.java b/src/scratchpad/src/org/apache/poi/hwpf/sprm/TableSprmUncompressor.java
index 87547565f2..f8fc91f123 100644
--- a/src/scratchpad/src/org/apache/poi/hwpf/sprm/TableSprmUncompressor.java
+++ b/src/scratchpad/src/org/apache/poi/hwpf/sprm/TableSprmUncompressor.java
@@ -148,8 +148,10 @@ public class TableSprmUncompressor
for (int x = 0; x < itcMac; x++)
{
- if(hasTCs) rgtc[x] = TableCellDescriptor.convertBytesToTC(grpprl,
- offset + (1 + ( (itcMac + 1) * 2) + (x * 20)));
+ // Sometimes, the grpprl does not contain data at every offset. I have no idea why this happens.
+ if(hasTCs && offset + (1 + ( (itcMac + 1) * 2) + (x * 20)) < grpprl.length)
+ rgtc[x] = TableCellDescriptor.convertBytesToTC(grpprl,
+ offset + (1 + ( (itcMac + 1) * 2) + (x * 20)));
else
rgtc[x] = new TableCellDescriptor();
}
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/ListEntry.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/ListEntry.java
index 1b0ba626c2..9bafce7927 100644
--- a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/ListEntry.java
+++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/ListEntry.java
@@ -23,21 +23,28 @@ import org.apache.poi.hwpf.model.ListFormatOverrideLevel;
import org.apache.poi.hwpf.model.ListLevel;
import org.apache.poi.hwpf.model.ListTables;
import org.apache.poi.hwpf.model.PAPX;
-
-import org.apache.poi.hwpf.sprm.SprmBuffer;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
public class ListEntry
extends Paragraph
{
- ListLevel _level;
- ListFormatOverrideLevel _overrideLevel;
+ private static POILogger log = POILogFactory.getLogger(ListEntry.class);
+
+ ListLevel _level;
+ ListFormatOverrideLevel _overrideLevel;
ListEntry(PAPX papx, Range parent, ListTables tables)
{
super(papx, parent);
- ListFormatOverride override = tables.getOverride(_props.getIlfo());
- _overrideLevel = override.getOverrideLevel(_props.getIlvl());
- _level = tables.getLevel(override.getLsid(), _props.getIlvl());
+
+ if(tables != null) {
+ ListFormatOverride override = tables.getOverride(_props.getIlfo());
+ _overrideLevel = override.getOverrideLevel(_props.getIlvl());
+ _level = tables.getLevel(override.getLsid(), _props.getIlvl());
+ } else {
+ log.log(POILogger.WARN, "No ListTables found for ListEntry - document probably partly corrupt, and you may experience problems");
+ }
}
public int type()
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/data/43781.ppt b/src/scratchpad/testcases/org/apache/poi/hslf/data/43781.ppt
new file mode 100755
index 0000000000..ddea91fe89
--- /dev/null
+++ b/src/scratchpad/testcases/org/apache/poi/hslf/data/43781.ppt
Binary files differ
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/data/sample.pptx b/src/scratchpad/testcases/org/apache/poi/hslf/data/sample.pptx
new file mode 100644
index 0000000000..fbd540c1e0
--- /dev/null
+++ b/src/scratchpad/testcases/org/apache/poi/hslf/data/sample.pptx
Binary files differ
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java
index 933aa176b7..996a733ac9 100644
--- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java
+++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java
@@ -25,6 +25,7 @@ import org.apache.poi.hslf.model.Shape;
import java.io.*;
import java.util.HashSet;
import java.util.HashMap;
+import java.util.ArrayList;
import java.awt.*;
/**
@@ -298,4 +299,35 @@ public class TestBugs extends TestCase {
}
+ /**
+ * Bug 38256: RuntimeException: Couldn't instantiate the class for type with id 0.
+ * ( also fixed followup: getTextRuns() returns no text )
+ */
+ public void test43781 () throws Exception {
+ FileInputStream is = new FileInputStream(new File(cwd, "43781.ppt"));
+ SlideShow ppt = new SlideShow(is);
+ is.close();
+
+ assertTrue("No Exceptions while reading file", true);
+
+ Slide slide = ppt.getSlides()[0];
+ TextRun[] tr1 = slide.getTextRuns();
+
+ ArrayList lst = new ArrayList();
+ Shape[] shape = slide.getShapes();
+ for (int i = 0; i < shape.length; i++) {
+ if( shape[i] instanceof TextBox){
+ TextRun textRun = ((TextBox)shape[i]).getTextRun();
+ if(textRun != null) lst.add(textRun);
+ }
+
+ }
+ TextRun[] tr2 = new TextRun[lst.size()];
+ lst.toArray(tr2);
+
+ assertEquals(tr1.length, tr2.length);
+ for (int i = 0; i < tr1.length; i++) {
+ assertEquals(tr1[i].getText(), tr2[i].getText());
+ }
+ }
}
diff --git a/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestBlankFileRead.java b/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestBlankFileRead.java
index 05735870b4..314cc506c4 100644
--- a/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestBlankFileRead.java
+++ b/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestBlankFileRead.java
@@ -84,6 +84,21 @@ public class TestBlankFileRead extends TestCase {
}
/**
+ * Test to see if we can read the FROM Chunk.
+ * @throws ChunkNotFoundException
+ *
+ */
+ public void testReadDisplayFrom() throws ChunkNotFoundException {
+ try {
+ mapiMessage.getDisplayFrom();
+ } catch(ChunkNotFoundException exp) {
+ return;
+ }
+
+ TestCase.fail("Should have thrown a ChunkNotFoundException but didn't");
+ }
+
+ /**
* Test to see if we can read the CC Chunk.
* @throws ChunkNotFoundException
*
diff --git a/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestSimpleFileRead.java b/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestSimpleFileRead.java
index 0ede68965a..925685218d 100644
--- a/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestSimpleFileRead.java
+++ b/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestSimpleFileRead.java
@@ -67,6 +67,18 @@ private MAPIMessage mapiMessage;
}
/**
+ * Test to see if we can read the From Chunk.
+ * @throws ChunkNotFoundException
+ *
+ */
+ public void testReadDisplayFrom() throws ChunkNotFoundException {
+ String obtained = mapiMessage.getDisplayFrom();
+ String expected = "Travis Ferguson";
+
+ TestCase.assertEquals(obtained, expected);
+ }
+
+ /**
* Test to see if we can read the CC Chunk.
* @throws ChunkNotFoundException
*
diff --git a/src/scratchpad/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls b/src/scratchpad/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls
index b2388f1d03..cf4b6fa501 100644
--- a/src/scratchpad/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls
+++ b/src/scratchpad/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls
Binary files differ
diff --git a/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/eval/TestEverything.java b/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/eval/TestEverything.java
index d1ab0c7076..ac3ca2eb29 100644
--- a/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/eval/TestEverything.java
+++ b/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/eval/TestEverything.java
@@ -23,27 +23,37 @@ package org.apache.poi.hssf.record.formula.eval;
import junit.framework.TestSuite;
/**
- * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
+ * This is a test of all the Eval functions we have implemented.
+ * Add newly implemented Eval functions in here to have them
+ * tested.
+ * For newly implemented functions,
+ * @see org.apache.poi.hssf.record.formula.functions.TestEverything
*
+ * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*/
public class TestEverything extends TestSuite {
public static TestSuite suite() throws Exception {
TestSuite suite = new TestSuite("Tests for OperationEval concrete implementation classes.");
- suite.addTest(new GenericFormulaTestCase("D23"));
- suite.addTest(new GenericFormulaTestCase("D27"));
- suite.addTest(new GenericFormulaTestCase("D31"));
- suite.addTest(new GenericFormulaTestCase("D35"));
- suite.addTest(new GenericFormulaTestCase("D39"));
- suite.addTest(new GenericFormulaTestCase("D43"));
- suite.addTest(new GenericFormulaTestCase("D47"));
- suite.addTest(new GenericFormulaTestCase("D51"));
- suite.addTest(new GenericFormulaTestCase("D55"));
- suite.addTest(new GenericFormulaTestCase("D59"));
- suite.addTest(new GenericFormulaTestCase("D63"));
- suite.addTest(new GenericFormulaTestCase("D67"));
- suite.addTest(new GenericFormulaTestCase("D71"));
- suite.addTest(new GenericFormulaTestCase("D75"));
+ suite.addTest(new GenericFormulaTestCase("D23")); // Add
+ suite.addTest(new GenericFormulaTestCase("D27")); // ConcatEval
+ suite.addTest(new GenericFormulaTestCase("D31")); // DivideEval
+ suite.addTest(new GenericFormulaTestCase("D35")); // EqualEval
+ suite.addTest(new GenericFormulaTestCase("D39")); // GreaterEqualEval
+ suite.addTest(new GenericFormulaTestCase("D43")); // GreaterThanEval
+ suite.addTest(new GenericFormulaTestCase("D47")); // LessEqualEval
+ suite.addTest(new GenericFormulaTestCase("D51")); // LessThanEval
+ suite.addTest(new GenericFormulaTestCase("D55")); // MultiplyEval
+ suite.addTest(new GenericFormulaTestCase("D59")); // NotEqualEval
+ suite.addTest(new GenericFormulaTestCase("D63")); // PowerEval
+ suite.addTest(new GenericFormulaTestCase("D67")); // SubtractEval
+ suite.addTest(new GenericFormulaTestCase("D71")); // UnaryMinusEval
+ suite.addTest(new GenericFormulaTestCase("D75")); // UnaryPlusEval
+
+ // Add newly implemented Eval functions here
+ // (Formula functions go in
+ // @see org.apache.poi.hssf.record.formula.functions.TestEverything )
+
return suite;
}
}
diff --git a/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestEverything.java b/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestEverything.java
index ad93996339..8337810216 100644
--- a/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestEverything.java
+++ b/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestEverything.java
@@ -25,11 +25,16 @@ import org.apache.poi.hssf.record.formula.eval.GenericFormulaTestCase;
import junit.framework.TestSuite;
/**
- * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
+ * This is a test of all the normal formula functions we have implemented.
+ * It should pick up newly implemented functions which are correctly added
+ * to the test formula excel file, but tweak the rows below if you
+ * add any past the end of what's currently checked.
+ * For newly implemented eval functions,
+ * @see org.apache.poi.hssf.record.formula.eval.TestEverything
*
+ * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*/
public class TestEverything extends TestSuite {
-
public static TestSuite suite() throws Exception {
TestSuite suite = new TestSuite("Tests for individual function classes");
String s;
diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/data/AIOOB-Tap.doc b/src/scratchpad/testcases/org/apache/poi/hwpf/data/AIOOB-Tap.doc
new file mode 100644
index 0000000000..bfd5906caa
--- /dev/null
+++ b/src/scratchpad/testcases/org/apache/poi/hwpf/data/AIOOB-Tap.doc
Binary files differ
diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/data/IllustrativeCases.docx b/src/scratchpad/testcases/org/apache/poi/hwpf/data/IllustrativeCases.docx
new file mode 100644
index 0000000000..29dacb652e
--- /dev/null
+++ b/src/scratchpad/testcases/org/apache/poi/hwpf/data/IllustrativeCases.docx
Binary files differ
diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/data/ListEntryNoListTable.doc b/src/scratchpad/testcases/org/apache/poi/hwpf/data/ListEntryNoListTable.doc
new file mode 100644
index 0000000000..939f5a4a9e
--- /dev/null
+++ b/src/scratchpad/testcases/org/apache/poi/hwpf/data/ListEntryNoListTable.doc
Binary files differ
diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/data/sample.docx b/src/scratchpad/testcases/org/apache/poi/hwpf/data/sample.docx
new file mode 100644
index 0000000000..8dd04bcdb8
--- /dev/null
+++ b/src/scratchpad/testcases/org/apache/poi/hwpf/data/sample.docx
Binary files differ
diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestProblems.java b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestProblems.java
new file mode 100644
index 0000000000..8e7f47ed96
--- /dev/null
+++ b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestProblems.java
@@ -0,0 +1,77 @@
+/*
+* 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.hwpf.usermodel;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.poi.hwpf.HWPFDocument;
+import org.apache.poi.hwpf.model.StyleSheet;
+import org.apache.poi.hwpf.model.TextPiece;
+import org.apache.poi.hwpf.usermodel.Paragraph;
+import org.apache.poi.hwpf.usermodel.Range;
+import org.apache.poi.util.LittleEndian;
+
+import junit.framework.TestCase;
+
+/**
+ * Test various problem documents
+ *
+ * @author Nick Burch (nick at torchbox dot com)
+ */
+public class TestProblems extends TestCase {
+ private String dirname = System.getProperty("HWPF.testdata.path");
+
+ protected void setUp() throws Exception {
+ }
+
+ /**
+ * ListEntry passed no ListTable
+ */
+ public void testListEntryNoListTable() throws Exception {
+ HWPFDocument doc = new HWPFDocument(new FileInputStream(dirname + "/ListEntryNoListTable.doc"));
+
+ Range r = doc.getRange();
+ StyleSheet styleSheet = doc.getStyleSheet();
+ for (int x = 0; x < r.numSections(); x++) {
+ Section s = r.getSection(x);
+ for (int y = 0; y < s.numParagraphs(); y++) {
+ Paragraph paragraph = s.getParagraph(y);
+ //System.out.println(paragraph.getCharacterRun(0).text());
+ }
+ }
+ }
+
+ /**
+ * AIOOB for TableSprmUncompressor.unCompressTAPOperation
+ */
+ public void testSprmAIOOB() throws Exception {
+ HWPFDocument doc = new HWPFDocument(new FileInputStream(dirname + "/AIOOB-Tap.doc"));
+
+ Range r = doc.getRange();
+ StyleSheet styleSheet = doc.getStyleSheet();
+ for (int x = 0; x < r.numSections(); x++) {
+ Section s = r.getSection(x);
+ for (int y = 0; y < s.numParagraphs(); y++) {
+ Paragraph paragraph = s.getParagraph(y);
+ //System.out.println(paragraph.getCharacterRun(0).text());
+ }
+ }
+ }
+}