aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/scratchpad/src/org/apache/poi/hpbf/dev/PLCDumper.java15
-rw-r--r--src/scratchpad/src/org/apache/poi/hpbf/model/QuillContents.java3
-rw-r--r--src/scratchpad/src/org/apache/poi/hpbf/model/qcbits/QCPLCBit.java175
-rw-r--r--src/scratchpad/testcases/org/apache/poi/hpbf/model/TestQuillContents.java63
4 files changed, 245 insertions, 11 deletions
diff --git a/src/scratchpad/src/org/apache/poi/hpbf/dev/PLCDumper.java b/src/scratchpad/src/org/apache/poi/hpbf/dev/PLCDumper.java
index 368755efc0..cdec78c8cf 100644
--- a/src/scratchpad/src/org/apache/poi/hpbf/dev/PLCDumper.java
+++ b/src/scratchpad/src/org/apache/poi/hpbf/dev/PLCDumper.java
@@ -20,17 +20,11 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import org.apache.poi.ddf.DefaultEscherRecordFactory;
-import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.hpbf.HPBFDocument;
import org.apache.poi.hpbf.model.QuillContents;
import org.apache.poi.hpbf.model.qcbits.QCBit;
-import org.apache.poi.poifs.filesystem.DirectoryNode;
-import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.HexDump;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.StringUtil;
/**
* For dumping out the PLC contents of QC Bits of a
@@ -41,8 +35,8 @@ public class PLCDumper {
private HPBFDocument doc;
private QuillContents qc;
- public PLCDumper(HPBFDocument doc) {
- this.doc = doc;
+ public PLCDumper(HPBFDocument hpbfDoc) {
+ doc = hpbfDoc;
qc = doc.getQuillContents();
}
public PLCDumper(POIFSFileSystem fs) throws IOException {
@@ -67,7 +61,6 @@ public class PLCDumper {
}
private void dumpPLC() {
- QuillContents qc = doc.getQuillContents();
QCBit[] bits = qc.getBits();
for(int i=0; i<bits.length; i++) {
@@ -82,8 +75,8 @@ public class PLCDumper {
System.out.println("");
System.out.println("Dumping " + bit.getBitType() + " bit at " + index);
System.out.println(" Is a " + bit.getThingType() + ", number is " + bit.getOptA());
- System.out.println(" Starts at " + bit.getDataOffset() + " (" + Integer.toHexString(bit.getDataOffset()) + ")");
- System.out.println(" Runs for " + bit.getLength() + " (" + Integer.toHexString(bit.getLength()) + ")");
+ System.out.println(" Starts at " + bit.getDataOffset() + " (0x" + Integer.toHexString(bit.getDataOffset()) + ")");
+ System.out.println(" Runs for " + bit.getLength() + " (0x" + Integer.toHexString(bit.getLength()) + ")");
System.out.println(HexDump.dump(bit.getData(), 0, 0));
}
diff --git a/src/scratchpad/src/org/apache/poi/hpbf/model/QuillContents.java b/src/scratchpad/src/org/apache/poi/hpbf/model/QuillContents.java
index b8d4ad298a..56f7bfcc9c 100644
--- a/src/scratchpad/src/org/apache/poi/hpbf/model/QuillContents.java
+++ b/src/scratchpad/src/org/apache/poi/hpbf/model/QuillContents.java
@@ -19,6 +19,7 @@ package org.apache.poi.hpbf.model;
import java.io.IOException;
import org.apache.poi.hpbf.model.qcbits.QCBit;
+import org.apache.poi.hpbf.model.qcbits.QCPLCBit;
import org.apache.poi.hpbf.model.qcbits.QCTextBit;
import org.apache.poi.hpbf.model.qcbits.UnknownQCBit;
import org.apache.poi.poifs.filesystem.DirectoryNode;
@@ -64,6 +65,8 @@ public final class QuillContents extends HPBFPart {
// Create
if(bitType.equals("TEXT")) {
bits[i] = new QCTextBit(thingType, bitType, bitData);
+ } else if(bitType.equals("PLC ")) {
+ bits[i] = QCPLCBit.createQCPLCBit(thingType, bitType, bitData);
} else {
bits[i] = new UnknownQCBit(thingType, bitType, bitData);
}
diff --git a/src/scratchpad/src/org/apache/poi/hpbf/model/qcbits/QCPLCBit.java b/src/scratchpad/src/org/apache/poi/hpbf/model/qcbits/QCPLCBit.java
new file mode 100644
index 0000000000..92e936528a
--- /dev/null
+++ b/src/scratchpad/src/org/apache/poi/hpbf/model/qcbits/QCPLCBit.java
@@ -0,0 +1,175 @@
+/* ====================================================================
+ 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.hpbf.model.qcbits;
+
+import org.apache.poi.util.LittleEndian;
+
+
+/**
+ * A "PLC " (PLC) based bit of Quill Contents. The exact
+ * format is determined by the type of the PLCs.
+ */
+public class QCPLCBit extends QCBit {
+ protected int numberOfPLCs;
+ protected int typeOfPLCS;
+ /**
+ * The data which goes before the main PLC entries.
+ * This is apparently always made up of 2 byte
+ * un-signed ints..
+ */
+ protected int[] preData;
+ /** The first value of each PLC, normally 4 bytes */
+ protected long[] plcValA;
+ /** The second value of each PLC, normally 4 bytes */
+ protected long[] plcValB;
+
+
+ private QCPLCBit(String thingType, String bitType, byte[] data) {
+ super(thingType, bitType, data);
+
+ // First four bytes are the number
+ numberOfPLCs = (int)LittleEndian.getUInt(data, 0);
+
+ // Next four bytes are the type
+ typeOfPLCS = (int)LittleEndian.getUInt(data, 4);
+
+ // Init the arrays that we can
+ plcValA = new long[numberOfPLCs];
+ plcValB = new long[numberOfPLCs];
+ }
+
+
+
+ public int getNumberOfPLCs() {
+ return numberOfPLCs;
+ }
+ public int getTypeOfPLCS() {
+ return typeOfPLCS;
+ }
+
+ public int[] getPreData() {
+ return preData;
+ }
+
+ public long[] getPlcValA() {
+ return plcValA;
+ }
+ public long[] getPlcValB() {
+ return plcValB;
+ }
+
+
+
+ public static QCPLCBit createQCPLCBit(String thingType, String bitType, byte[] data) {
+ // Grab the type
+ int type = (int)LittleEndian.getUInt(data, 4);
+ switch(type) {
+ case 0:
+ return new Type0(thingType, bitType, data);
+ case 4:
+ return new Type4(thingType, bitType, data);
+ case 8:
+ return new Type8(thingType, bitType, data);
+ case 12: // 0xc
+ return new Type12(thingType, bitType, data);
+ default:
+ throw new IllegalArgumentException("Sorry, I don't know how to deal with PLCs of type " + type);
+ }
+ }
+
+
+ /**
+ * Type 0 seem to be somewhat rare. They have 8 bytes of pre-data,
+ * then 2x 2 byte values.
+ */
+ public static class Type0 extends QCPLCBit {
+ private Type0(String thingType, String bitType, byte[] data) {
+ super(thingType, bitType, data);
+
+ // Grab our 4x pre-data
+ preData = new int[4];
+ preData[0] = LittleEndian.getUShort(data, 8+0);
+ preData[1] = LittleEndian.getUShort(data, 8+2);
+ preData[2] = LittleEndian.getUShort(data, 8+4);
+ preData[3] = LittleEndian.getUShort(data, 8+6);
+
+ // And grab the 2 byte values
+ for(int i=0; i<numberOfPLCs; i++) {
+ plcValA[i] = LittleEndian.getUShort(data, 16+(4*i));
+ plcValB[i] = LittleEndian.getUShort(data, 16+(4*i)+2);
+ }
+ }
+ }
+
+ /**
+ * Type 4 is quite common. They have 8 bytes of pre-data,
+ * then 2x 4 byte values.
+ */
+ public static class Type4 extends QCPLCBit {
+ private Type4(String thingType, String bitType, byte[] data) {
+ super(thingType, bitType, data);
+
+ // Grab our 4x pre-data
+ preData = new int[4];
+ preData[0] = LittleEndian.getUShort(data, 8+0);
+ preData[1] = LittleEndian.getUShort(data, 8+2);
+ preData[2] = LittleEndian.getUShort(data, 8+4);
+ preData[3] = LittleEndian.getUShort(data, 8+6);
+
+ // And grab the 4 byte values
+ for(int i=0; i<numberOfPLCs; i++) {
+ plcValA[i] = LittleEndian.getUInt(data, 16+(8*i));
+ plcValB[i] = LittleEndian.getUInt(data, 16+(8*i)+4);
+ }
+ }
+ }
+
+ /**
+ * Type 8 is quite common. They have 14 bytes of pre-data,
+ * then 2x 4 byte values.
+ */
+ public static class Type8 extends QCPLCBit {
+ private Type8(String thingType, String bitType, byte[] data) {
+ super(thingType, bitType, data);
+
+ // Grab our 7x pre-data
+ preData = new int[7];
+ preData[0] = LittleEndian.getUShort(data, 8+0);
+ preData[1] = LittleEndian.getUShort(data, 8+2);
+ preData[2] = LittleEndian.getUShort(data, 8+4);
+ preData[3] = LittleEndian.getUShort(data, 8+6);
+ preData[4] = LittleEndian.getUShort(data, 8+8);
+ preData[5] = LittleEndian.getUShort(data, 8+10);
+ preData[6] = LittleEndian.getUShort(data, 8+12);
+
+ // And grab the 4 byte values
+ for(int i=0; i<numberOfPLCs; i++) {
+ plcValA[i] = LittleEndian.getUInt(data, 22+(8*i));
+ plcValB[i] = LittleEndian.getUInt(data, 22+(8*i)+4);
+ }
+ }
+ }
+
+ /**
+ * Type 12 holds hyperlinks, and is very complex.
+ */
+ public static class Type12 extends QCPLCBit {
+ private Type12(String thingType, String bitType, byte[] data) {
+ super(thingType, bitType, data);
+ }
+ }
+}
diff --git a/src/scratchpad/testcases/org/apache/poi/hpbf/model/TestQuillContents.java b/src/scratchpad/testcases/org/apache/poi/hpbf/model/TestQuillContents.java
index ce6ddf83ef..ecbc226098 100644
--- a/src/scratchpad/testcases/org/apache/poi/hpbf/model/TestQuillContents.java
+++ b/src/scratchpad/testcases/org/apache/poi/hpbf/model/TestQuillContents.java
@@ -21,6 +21,8 @@ import java.io.FileInputStream;
import org.apache.poi.hpbf.HPBFDocument;
import org.apache.poi.hpbf.model.qcbits.QCTextBit;
+import org.apache.poi.hpbf.model.qcbits.QCPLCBit.Type4;
+import org.apache.poi.hpbf.model.qcbits.QCPLCBit.Type8;
import junit.framework.TestCase;
@@ -77,4 +79,65 @@ public class TestQuillContents extends TestCase {
assertTrue(t.startsWith("This is some text on the first page"));
assertTrue(t.endsWith("Within doc to page 1\r"));
}
+
+ public void testPLC() throws Exception {
+ File f = new File(dir, "Simple.pub");
+ HPBFDocument doc = new HPBFDocument(
+ new FileInputStream(f)
+ );
+
+ QuillContents qc = doc.getQuillContents();
+ assertEquals(20, qc.getBits().length);
+
+ assertTrue(qc.getBits()[9] instanceof Type4);
+ assertTrue(qc.getBits()[10] instanceof Type4);
+ assertTrue(qc.getBits()[12] instanceof Type8);
+
+ Type4 plc9 = (Type4)qc.getBits()[9];
+ Type4 plc10 = (Type4)qc.getBits()[10];
+ Type8 plc12 = (Type8)qc.getBits()[12];
+
+
+ assertEquals(1, plc9.getNumberOfPLCs());
+ assertEquals(4, plc9.getPreData().length);
+ assertEquals(1, plc9.getPlcValA().length);
+ assertEquals(1, plc9.getPlcValB().length);
+
+ assertEquals(0, plc9.getPreData()[0]);
+ assertEquals(0, plc9.getPreData()[1]);
+ assertEquals(0, plc9.getPreData()[2]);
+ assertEquals(0, plc9.getPreData()[3]);
+ assertEquals(0x356, plc9.getPlcValA()[0]);
+ assertEquals(0x600, plc9.getPlcValB()[0]);
+
+
+ assertEquals(1, plc10.getNumberOfPLCs());
+ assertEquals(4, plc10.getPreData().length);
+ assertEquals(1, plc10.getPlcValA().length);
+ assertEquals(1, plc10.getPlcValB().length);
+
+ assertEquals(0, plc10.getPreData()[0]);
+ assertEquals(0, plc10.getPreData()[1]);
+ assertEquals(0, plc10.getPreData()[2]);
+ assertEquals(0, plc10.getPreData()[3]);
+ assertEquals(0x356, plc10.getPlcValA()[0]);
+ assertEquals(0x800, plc10.getPlcValB()[0]);
+
+ assertEquals(2, plc12.getNumberOfPLCs());
+ assertEquals(7, plc12.getPreData().length);
+ assertEquals(2, plc12.getPlcValA().length);
+ assertEquals(2, plc12.getPlcValB().length);
+
+ assertEquals(0xff, plc12.getPreData()[0]);
+ assertEquals(0, plc12.getPreData()[1]);
+ assertEquals(0x3d, plc12.getPreData()[2]);
+ assertEquals(0, plc12.getPreData()[3]);
+ assertEquals(0x6e, plc12.getPreData()[4]);
+ assertEquals(0, plc12.getPreData()[5]);
+ assertEquals(0, plc12.getPreData()[6]);
+ assertEquals(0xa0000, plc12.getPlcValA()[0]);
+ assertEquals(0x22000000, plc12.getPlcValB()[0]);
+ assertEquals(0x05, plc12.getPlcValA()[1]);
+ assertEquals(0x04, plc12.getPlcValB()[1]);
+ }
}