import java.io.FileNotFoundException;
import java.io.IOException;
+import org.apache.poi.hpbf.model.qcbits.QCBit;
+import org.apache.poi.hpbf.model.qcbits.QCTextBit;
+import org.apache.poi.hpbf.model.qcbits.UnknownQCBit;
import org.apache.poi.poifs.filesystem.DirectoryNode;
+import org.apache.poi.util.LittleEndian;
/**
* Quill -> QuillSub -> CONTENTS
*/
public class QuillContents extends HPBFPart {
+ private QCBit[] bits;
+
public QuillContents(DirectoryNode baseDir)
throws FileNotFoundException, IOException {
super(baseDir);
// Now parse the first 512 bytes, and produce
// all our bits
+
+ // Check first 8 bytes
+ String f8 = new String(data, 0, 8);
+ if(! f8.equals("CHNKINK ")) {
+ throw new IllegalArgumentException("Expecting 'CHNKINK ' but was '"+f8+"'");
+ }
+ // Ignore the next 24, for now at least
+
+ // Now, parse all our QC Bits
+ bits = new QCBit[20];
+ for(int i=0; i<20; i++) {
+ int offset = 0x20 + i*24;
+ if(data[offset] == 0x18 && data[offset+1] == 0x00) {
+ // Has some data
+ String thingType = new String(data, offset+2, 4);
+ int optA = LittleEndian.getUShort(data, offset+6);
+ int optB = LittleEndian.getUShort(data, offset+8);
+ int optC = LittleEndian.getUShort(data, offset+10);
+ String bitType = new String(data, offset+12, 4);
+ int from = (int)LittleEndian.getUInt(data, offset+16);
+ int len = (int)LittleEndian.getUInt(data, offset+20);
+
+ byte[] bitData = new byte[len];
+ System.arraycopy(data, from, bitData, 0, len);
+
+ // Create
+ if(bitType.equals("TEXT")) {
+ bits[i] = new QCTextBit(thingType, bitType, bitData);
+ } else {
+ bits[i] = new UnknownQCBit(thingType, bitType, bitData);
+ }
+ bits[i].setOptA(optA);
+ bits[i].setOptB(optB);
+ bits[i].setOptC(optC);
+ } else {
+ // Doesn't have data
+ }
+ }
+ }
+
+ public QCBit[] getBits() {
+ return bits;
}
protected void generateData() {
--- /dev/null
+/* ====================================================================
+ 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;
+
+/**
+ * Parent of all Quill CONTENTS bits
+ */
+public abstract class QCBit {
+ protected String thingType;
+ protected String bitType;
+ protected byte[] data;
+
+ protected int optA;
+ protected int optB;
+ protected int optC;
+
+ public QCBit(String thingType, String bitType, byte[] data) {
+ this.thingType = thingType;
+ this.bitType = bitType;
+ this.data = data;
+ }
+
+ /**
+ * Returns the type of the thing, eg TEXT, FONT
+ * or TOKN
+ */
+ public String getThingType() { return thingType; }
+ /**
+ * Returns the type of the bit data, eg TEXT
+ * or PLC
+ */
+ public String getBitType() { return bitType; }
+ public byte[] getData() { return data; }
+
+ public int getOptA() {
+ return optA;
+ }
+ public void setOptA(int optA) {
+ this.optA = optA;
+ }
+
+ public int getOptB() {
+ return optB;
+ }
+ public void setOptB(int optB) {
+ this.optB = optB;
+ }
+
+ public int getOptC() {
+ return optC;
+ }
+ public void setOptC(int optC) {
+ this.optC = optC;
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.StringUtil;
+
+/**
+ * A Text based bit of Quill Contents
+ */
+public class QCTextBit extends QCBit {
+ public QCTextBit(String thingType, String bitType, byte[] data) {
+ super(thingType, bitType, data);
+ }
+
+ public String getText() {
+ return StringUtil.getFromUnicodeLE(
+ data, 0, data.length/2
+ );
+ }
+
+ public void setText(String text) {
+ data = new byte[text.length()*2];
+ StringUtil.putUnicodeLE(text, data, 0);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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;
+
+/**
+ * Any Quill Contents bits we don't know
+ * how to handle explicitly
+ */
+public class UnknownQCBit extends QCBit {
+ public UnknownQCBit(String thingType, String bitType, byte[] data) {
+ super(thingType, bitType, data);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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;
+
+import java.io.File;
+import java.io.FileInputStream;
+
+import org.apache.poi.hpbf.HPBFDocument;
+import org.apache.poi.hpbf.model.qcbits.QCTextBit;
+
+import junit.framework.TestCase;
+
+public class TestQuillContents extends TestCase {
+ private String dir;
+
+ protected void setUp() throws Exception {
+ dir = System.getProperty("HPBF.testdata.path");
+ }
+
+ public void testBasics() throws Exception {
+ File f = new File(dir, "Sample.pub");
+ HPBFDocument doc = new HPBFDocument(
+ new FileInputStream(f)
+ );
+
+ QuillContents qc = doc.getQuillContents();
+ assertEquals(20, qc.getBits().length);
+ for(int i=0; i<19; i++) {
+ assertNotNull(qc.getBits()[i]);
+ }
+ // Last one is blank
+ assertNull(qc.getBits()[19]);
+
+ // Should be text, then three STSHs
+ assertEquals("TEXT", qc.getBits()[0].getThingType());
+ assertEquals("TEXT", qc.getBits()[0].getBitType());
+ assertEquals(0, qc.getBits()[0].getOptA());
+
+ assertEquals("STSH", qc.getBits()[1].getThingType());
+ assertEquals("STSH", qc.getBits()[1].getBitType());
+ assertEquals(0, qc.getBits()[1].getOptA());
+
+ assertEquals("STSH", qc.getBits()[2].getThingType());
+ assertEquals("STSH", qc.getBits()[2].getBitType());
+ assertEquals(1, qc.getBits()[2].getOptA());
+
+ assertEquals("STSH", qc.getBits()[3].getThingType());
+ assertEquals("STSH", qc.getBits()[3].getBitType());
+ assertEquals(2, qc.getBits()[3].getOptA());
+ }
+
+ public void testText() throws Exception {
+ File f = new File(dir, "Sample.pub");
+ HPBFDocument doc = new HPBFDocument(
+ new FileInputStream(f)
+ );
+
+ QuillContents qc = doc.getQuillContents();
+ assertEquals(20, qc.getBits().length);
+
+ QCTextBit text = (QCTextBit)qc.getBits()[0];
+ String t = text.getText();
+ assertTrue(t.startsWith("This is some text on the first page"));
+ assertTrue(t.endsWith("Within doc to page 1\r"));
+ }
+}