package org.apache.poi.hpbf.model.qcbits;
import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.StringUtil;
/**
* Type 12 holds hyperlinks, and is very complex.
*/
public static class Type12 extends QCPLCBit {
+ private String[] hyperlinks;
+
+ private static final int oneStartsAt = 0x4c;
+ private static final int twoStartsAt = 0x68;
+ private static final int threePlusIncrement = 22;
+
private Type12(String thingType, String bitType, byte[] data) {
super(thingType, bitType, data);
+
+ // How many hyperlinks do we really have?
+ // (zero hyperlinks gets numberOfPLCs=1)
+ if(data.length == 0x34) {
+ hyperlinks = new String[0];
+ } else {
+ hyperlinks = new String[numberOfPLCs];
+ }
+
+ // We have 4 bytes, then the start point of each
+ // hyperlink, then the end point of the text.
+ preData = new int[1+numberOfPLCs+1];
+ for(int i=0; i<preData.length; i++) {
+ preData[i] = (int)LittleEndian.getUInt(data, 8+(i*4));
+ }
+
+ // Then we have a whole bunch of stuff, which grows
+ // with the number of hyperlinks
+ // For now, we think these are shorts
+ int at = 8+4+(numberOfPLCs*4)+4;
+ int until = 0x34;
+ if(numberOfPLCs == 1 && hyperlinks.length == 1) {
+ until = oneStartsAt;
+ } else if(numberOfPLCs >= 2) {
+ until = twoStartsAt + (numberOfPLCs-2)*threePlusIncrement;
+ }
+
+ plcValA = new long[(until-at)/2];
+ plcValB = new long[0];
+ for(int i=0; i<plcValA.length; i++) {
+ plcValA[i] = LittleEndian.getUShort(data, at+(i*2));
+ }
+
+ // Finally, we have a series of lengths + hyperlinks
+ at = until;
+ for(int i=0; i<hyperlinks.length; i++) {
+ int len = LittleEndian.getUShort(data, at);
+ int first = LittleEndian.getUShort(data, at+2);
+ if(first == 0) {
+ // Crazy special case
+ // Length is in bytes, from the start
+ // Hyperlink appears to be empty
+ hyperlinks[i] = "";
+ at += len;
+ } else {
+ // Normal case. Length is in characters
+ hyperlinks[i] = StringUtil.getFromUnicodeLE(data, at+2, len);
+ at += 2 + (2*len);
+ }
+ }
+ }
+
+ /**
+ * Returns the number of hyperlinks, which should
+ * either be zero, or the number of PLC bits
+ */
+ public int getNumberOfHyperlinks() {
+ return hyperlinks.length;
+ }
+
+ /**
+ * Returns the URL of the hyperlink at the
+ * given index.
+ * @param number The hyperlink number, zero based
+ */
+ public String getHyperlink(int number) {
+ return hyperlinks[number];
+ }
+ /**
+ * Returns where in the text (in characters) the
+ * hyperlink at the given index starts
+ * applying to.
+ * @param number The hyperlink number, zero based
+ */
+ public int getTextStartAt(int number) {
+ return preData[1+number];
+ }
+ /**
+ * Returns where in the text that this block
+ * of hyperlinks stops applying to. Normally,
+ * but not always the end of the text.
+ */
+ public int getAllTextEndAt() {
+ return preData[numberOfPLCs+1];
}
}
}
assertEquals(0x000004, plc16.getPlcValA()[5]);
assertEquals(0x000004, plc16.getPlcValB()[5]);
}
+
+ public void testNoHyperlinks() throws Exception {
+ File f = new File(dir, "SampleNewsletter.pub");
+ HPBFDocument doc = new HPBFDocument(
+ new FileInputStream(f)
+ );
+
+ QuillContents qc = doc.getQuillContents();
+ assertEquals(20, qc.getBits().length);
+
+ Type12 plc18 = (Type12)qc.getBits()[18];
+
+ assertEquals(1, plc18.getNumberOfPLCs());
+ assertEquals(0, plc18.getNumberOfHyperlinks());
+ assertEquals(0, plc18.getTextStartAt(0));
+ assertEquals(601, plc18.getAllTextEndAt());
+ }
+
+ public void testSimpleHyperlink() throws Exception {
+ File f;
+ HPBFDocument doc;
+ QuillContents qc;
+ Type12 hlBit;
+
+ // Link at 10
+ f = new File(dir, "LinkAt10.pub");
+ doc = new HPBFDocument(
+ new FileInputStream(f)
+ );
+ qc = doc.getQuillContents();
+
+ hlBit = (Type12)qc.getBits()[12];
+ assertEquals(1, hlBit.getNumberOfPLCs());
+ assertEquals(1, hlBit.getNumberOfHyperlinks());
+
+ assertEquals(10, hlBit.getTextStartAt(0));
+ assertEquals(15, hlBit.getAllTextEndAt());
+ assertEquals("http://poi.apache.org/", hlBit.getHyperlink(0));
+
+ // Longer link at 10
+ f = new File(dir, "LinkAt10Longer.pub");
+ doc = new HPBFDocument(
+ new FileInputStream(f)
+ );
+ qc = doc.getQuillContents();
+
+ hlBit = (Type12)qc.getBits()[12];
+ assertEquals(1, hlBit.getNumberOfPLCs());
+ assertEquals(1, hlBit.getNumberOfHyperlinks());
+
+ assertEquals(10, hlBit.getTextStartAt(0));
+ assertEquals(15, hlBit.getAllTextEndAt());
+ assertEquals("http://poi.apache.org/hpbf/", hlBit.getHyperlink(0));
+
+ // Link at 20
+ f = new File(dir, "LinkAt20.pub");
+ doc = new HPBFDocument(
+ new FileInputStream(f)
+ );
+ qc = doc.getQuillContents();
+
+ hlBit = (Type12)qc.getBits()[12];
+ assertEquals(1, hlBit.getNumberOfPLCs());
+ assertEquals(1, hlBit.getNumberOfHyperlinks());
+
+ assertEquals(20, hlBit.getTextStartAt(0));
+ assertEquals(25, hlBit.getAllTextEndAt());
+ assertEquals("http://poi.apache.org/", hlBit.getHyperlink(0));
+ }
+
+ public void testManyHyperlinks() throws Exception {
+ File f;
+ HPBFDocument doc;
+ QuillContents qc;
+ Type12 hlBit;
+
+ // Link at 10
+ f = new File(dir, "LinkAt10.pub");
+ doc = new HPBFDocument(
+ new FileInputStream(f)
+ );
+ qc = doc.getQuillContents();
+
+ hlBit = (Type12)qc.getBits()[12];
+ assertEquals(1, hlBit.getNumberOfPLCs());
+ assertEquals(1, hlBit.getNumberOfHyperlinks());
+
+ assertEquals(10, hlBit.getTextStartAt(0));
+ assertEquals(15, hlBit.getAllTextEndAt());
+ assertEquals("http://poi.apache.org/", hlBit.getHyperlink(0));
+
+ }
+
+ public void testHyperlinkDifferentVersions() throws Exception {
+ File f;
+ HPBFDocument doc;
+ QuillContents qc;
+ Type12 hlBitA;
+ Type12 hlBitB;
+
+ // Latest version
+ f = new File(dir, "Sample.pub");
+ doc = new HPBFDocument(
+ new FileInputStream(f)
+ );
+ qc = doc.getQuillContents();
+
+ hlBitA = (Type12)qc.getBits()[14];
+ assertEquals(2, hlBitA.getNumberOfPLCs());
+ assertEquals(2, hlBitA.getNumberOfHyperlinks());
+
+ assertEquals(25, hlBitA.getTextStartAt(0));
+ assertEquals(72, hlBitA.getTextStartAt(1));
+ assertEquals(87, hlBitA.getAllTextEndAt());
+ assertEquals("http://poi.apache.org/", hlBitA.getHyperlink(0));
+ assertEquals("C:\\Documents and Settings\\Nick\\My Documents\\Booleans.xlsx", hlBitA.getHyperlink(1));
+
+ hlBitB = (Type12)qc.getBits()[15];
+ assertEquals(3, hlBitB.getNumberOfPLCs());
+ assertEquals(3, hlBitB.getNumberOfHyperlinks());
+
+ assertEquals(27, hlBitB.getTextStartAt(0));
+ assertEquals(37, hlBitB.getTextStartAt(1));
+ assertEquals(54, hlBitB.getTextStartAt(2));
+ assertEquals(75, hlBitB.getAllTextEndAt());
+ assertEquals("", hlBitB.getHyperlink(0));
+ assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(1));
+ assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(2));
+
+ // 2000 version
+ f = new File(dir, "Sample2000.pub");
+ doc = new HPBFDocument(
+ new FileInputStream(f)
+ );
+ qc = doc.getQuillContents();
+
+ hlBitA = (Type12)qc.getBits()[13];
+ assertEquals(2, hlBitA.getNumberOfPLCs());
+ assertEquals(2, hlBitA.getNumberOfHyperlinks());
+
+ assertEquals(25, hlBitA.getTextStartAt(0));
+ assertEquals(72, hlBitA.getTextStartAt(1));
+ assertEquals(87, hlBitA.getAllTextEndAt());
+ assertEquals("http://poi.apache.org/", hlBitA.getHyperlink(0));
+ assertEquals("C:\\Documents and Settings\\Nick\\My Documents\\Booleans.xlsx", hlBitA.getHyperlink(1));
+
+ hlBitB = (Type12)qc.getBits()[14];
+ assertEquals(3, hlBitB.getNumberOfPLCs());
+ assertEquals(3, hlBitB.getNumberOfHyperlinks());
+
+ assertEquals(27, hlBitB.getTextStartAt(0));
+ assertEquals(37, hlBitB.getTextStartAt(1));
+ assertEquals(54, hlBitB.getTextStartAt(2));
+ assertEquals(75, hlBitB.getAllTextEndAt());
+ assertEquals("", hlBitB.getHyperlink(0));
+ assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(1));
+ assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(2));
+
+ // 98 version
+ f = new File(dir, "Sample98.pub");
+ doc = new HPBFDocument(
+ new FileInputStream(f)
+ );
+ qc = doc.getQuillContents();
+
+ hlBitA = (Type12)qc.getBits()[13];
+ assertEquals(2, hlBitA.getNumberOfPLCs());
+ assertEquals(2, hlBitA.getNumberOfHyperlinks());
+
+ assertEquals(25, hlBitA.getTextStartAt(0));
+ assertEquals(72, hlBitA.getTextStartAt(1));
+ assertEquals(87, hlBitA.getAllTextEndAt());
+ assertEquals("http://poi.apache.org/", hlBitA.getHyperlink(0));
+ assertEquals("C:\\Documents and Settings\\Nick\\My Documents\\Booleans.xlsx", hlBitA.getHyperlink(1));
+
+ hlBitB = (Type12)qc.getBits()[14];
+ assertEquals(3, hlBitB.getNumberOfPLCs());
+ assertEquals(3, hlBitB.getNumberOfHyperlinks());
+
+ assertEquals(27, hlBitB.getTextStartAt(0));
+ assertEquals(37, hlBitB.getTextStartAt(1));
+ assertEquals(54, hlBitB.getTextStartAt(2));
+ assertEquals(75, hlBitB.getAllTextEndAt());
+ assertEquals("", hlBitB.getHyperlink(0));
+ assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(1));
+ assertEquals("mailto:dev@poi.apache.org?subject=HPBF", hlBitB.getHyperlink(2));
+ }
}