HSLF: readonly support for hyperlinks
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@542804 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d9c17a60ad
commit
49a0737b06
@ -38,6 +38,7 @@
|
||||
<li><link href="#SlideTitle">How to set slide title</link></li>
|
||||
<li><link href="#Fill">How to work with slide/shape background</link></li>
|
||||
<li><link href="#Bullets">How to create bulleted lists</link></li>
|
||||
<li><link href="#Hyperlinks">Hyperlinks</link></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section><title>Features</title>
|
||||
@ -323,31 +324,68 @@
|
||||
<anchor id="Bullets"/>
|
||||
<section><title>How to create bulleted lists</title>
|
||||
<source>
|
||||
SlideShow ppt = new SlideShow();
|
||||
SlideShow ppt = new SlideShow();
|
||||
|
||||
Slide slide = ppt.createSlide();
|
||||
Slide slide = ppt.createSlide();
|
||||
|
||||
TextBox shape = new TextBox();
|
||||
RichTextRun rt = shape.getTextRun().getRichTextRuns()[0];
|
||||
shape.setText(
|
||||
"January\r" +
|
||||
"February\r" +
|
||||
"March\r" +
|
||||
"April");
|
||||
rt.setFontSize(42);
|
||||
rt.setBullet(true);
|
||||
rt.setBulletOffset(0); //bullet offset
|
||||
rt.setTextOffset(50); //text offset (should be greater than bullet offset)
|
||||
rt.setBulletChar('\u263A'); //bullet character
|
||||
slide.addShape(shape);
|
||||
TextBox shape = new TextBox();
|
||||
RichTextRun rt = shape.getTextRun().getRichTextRuns()[0];
|
||||
shape.setText(
|
||||
"January\r" +
|
||||
"February\r" +
|
||||
"March\r" +
|
||||
"April");
|
||||
rt.setFontSize(42);
|
||||
rt.setBullet(true);
|
||||
rt.setBulletOffset(0); //bullet offset
|
||||
rt.setTextOffset(50); //text offset (should be greater than bullet offset)
|
||||
rt.setBulletChar('\u263A'); //bullet character
|
||||
slide.addShape(shape);
|
||||
|
||||
shape.setAnchor(new java.awt.Rectangle(50, 50, 500, 300)); //position of the text box in the slide
|
||||
slide.addShape(shape);
|
||||
shape.setAnchor(new java.awt.Rectangle(50, 50, 500, 300)); //position of the text box in the slide
|
||||
slide.addShape(shape);
|
||||
|
||||
FileOutputStream out = new FileOutputStream("bullets.ppt");
|
||||
ppt.write(out);
|
||||
out.close();
|
||||
</source>
|
||||
FileOutputStream out = new FileOutputStream("bullets.ppt");
|
||||
ppt.write(out);
|
||||
out.close();
|
||||
</source>
|
||||
</section>
|
||||
<anchor id="Hyperlinks"/>
|
||||
<section><title>How to read hyperlinks from a slide show</title>
|
||||
<source>
|
||||
FileInputStream is = new FileInputStream("slideshow.ppt");
|
||||
SlideShow ppt = new SlideShow(is);
|
||||
is.close();
|
||||
|
||||
Slide[] slide = ppt.getSlides();
|
||||
for (int j = 0; j < slide.length; j++) {
|
||||
|
||||
//read hyperlinks from the text runs
|
||||
TextRun[] txt = slide[j].getTextRuns();
|
||||
for (int k = 0; k < txt.length; k++) {
|
||||
String text = txt[k].getText();
|
||||
Hyperlink[] links = txt[k].getHyperlinks();
|
||||
if(links != null) for (int l = 0; l < links.length; l++) {
|
||||
Hyperlink link = links[l];
|
||||
String title = link.getTitle();
|
||||
String address = link.getAddress();
|
||||
String substring = text.substring(link.getStartIndex(), link.getEndIndex()-1); //in ppt end index is inclusive
|
||||
}
|
||||
}
|
||||
|
||||
//in PowerPoint you can assign a hyperlink to a shape without text,
|
||||
//for example to a Line object. The code below demonstrates how to
|
||||
//read such hyperlinks
|
||||
Shape[] sh = slide[j].getShapes();
|
||||
for (int k = 0; k < sh.length; k++) {
|
||||
Hyperlink link = sh[k].getHyperlink();
|
||||
if(link != null) {
|
||||
String title = link.getTitle();
|
||||
String address = link.getAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
</source>
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
@ -0,0 +1,80 @@
|
||||
/* ====================================================================
|
||||
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.model.Slide;
|
||||
import org.apache.poi.hslf.model.TextRun;
|
||||
import org.apache.poi.hslf.model.Hyperlink;
|
||||
import org.apache.poi.hslf.model.Shape;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
|
||||
/**
|
||||
* Demonstrates how to read hyperlinks from a presentation
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class Hyperlinks {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
FileInputStream is = new FileInputStream(args[i]);
|
||||
SlideShow ppt = new SlideShow(is);
|
||||
is.close();
|
||||
|
||||
Slide[] slide = ppt.getSlides();
|
||||
for (int j = 0; j < slide.length; j++) {
|
||||
System.out.println("slide " + slide[j].getSlideNumber());
|
||||
|
||||
//read hyperlinks from the slide's text runs
|
||||
System.out.println("reading hyperlinks from the text runs");
|
||||
TextRun[] txt = slide[j].getTextRuns();
|
||||
for (int k = 0; k < txt.length; k++) {
|
||||
String text = txt[k].getText();
|
||||
Hyperlink[] links = txt[k].getHyperlinks();
|
||||
if(links != null) for (int l = 0; l < links.length; l++) {
|
||||
Hyperlink link = links[l];
|
||||
String title = link.getTitle();
|
||||
String address = link.getAddress();
|
||||
System.out.println(" " + title);
|
||||
System.out.println(" " + address);
|
||||
String substring = text.substring(link.getStartIndex(), link.getEndIndex()-1);//in ppt end index is inclusive
|
||||
System.out.println(" " + substring);
|
||||
}
|
||||
}
|
||||
|
||||
//in PowerPoint you can assign a hyperlink to a shape without text,
|
||||
//for example to a Line object. The code below demonstrates how to
|
||||
//read such hyperlinks
|
||||
System.out.println(" reading hyperlinks from the slide's shapes");
|
||||
Shape[] sh = slide[j].getShapes();
|
||||
for (int k = 0; k < sh.length; k++) {
|
||||
Hyperlink link = sh[k].getHyperlink();
|
||||
if(link != null) {
|
||||
String title = link.getTitle();
|
||||
String address = link.getAddress();
|
||||
System.out.println(" " + title);
|
||||
System.out.println(" " + address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
168
src/scratchpad/src/org/apache/poi/hslf/model/Hyperlink.java
Normal file
168
src/scratchpad/src/org/apache/poi/hslf/model/Hyperlink.java
Normal file
@ -0,0 +1,168 @@
|
||||
|
||||
/* ====================================================================
|
||||
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.hslf.record.*;
|
||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
import org.apache.poi.ddf.EscherContainerRecord;
|
||||
import org.apache.poi.ddf.EscherRecord;
|
||||
import org.apache.poi.ddf.EscherClientDataRecord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Represents a hyperlink in a PowerPoint document
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class Hyperlink {
|
||||
|
||||
private int type;
|
||||
private String address;
|
||||
private String title;
|
||||
private int startIndex, endIndex;
|
||||
|
||||
/**
|
||||
* Gets the type of the hyperlink action.
|
||||
* Must be a <code>ACTION_*</code> constant defined in <code>InteractiveInfoAtom</code>
|
||||
*
|
||||
* @return the hyperlink URL
|
||||
* @see InteractiveInfoAtom
|
||||
*/
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hyperlink URL
|
||||
*
|
||||
* @return the hyperlink URL
|
||||
*/
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hyperlink user-friendly title (if different from URL)
|
||||
*
|
||||
* @return the hyperlink user-friendly title
|
||||
*/
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the beginning character position
|
||||
*
|
||||
* @return the beginning character position
|
||||
*/
|
||||
public int getStartIndex() {
|
||||
return startIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ending character position
|
||||
*
|
||||
* @return the ending character position
|
||||
*/
|
||||
public int getEndIndex() {
|
||||
return endIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find hyperlinks in a text run
|
||||
*
|
||||
* @param run <code>TextRun</code> to lookup hyperlinks in
|
||||
* @return found hyperlinks or <code>null</code> if not found
|
||||
*/
|
||||
protected static Hyperlink[] find(TextRun run){
|
||||
ArrayList lst = new ArrayList();
|
||||
SlideShow ppt = run.getSheet().getSlideShow();
|
||||
//document-level container which stores info about all links in a presentation
|
||||
ExObjList exobj = ppt.getDocumentRecord().getExObjList();
|
||||
if (exobj == null) {
|
||||
return null;
|
||||
}
|
||||
Record[] records = run._records;
|
||||
if(records != null) find(records, exobj, lst);
|
||||
|
||||
Hyperlink[] links = null;
|
||||
if (lst.size() > 0){
|
||||
links = new Hyperlink[lst.size()];
|
||||
lst.toArray(links);
|
||||
}
|
||||
return links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find hyperlink assigned to the supplied shape
|
||||
*
|
||||
* @param shape <code>Shape</code> to lookup hyperlink in
|
||||
* @return found hyperlink or <code>null</code>
|
||||
*/
|
||||
protected static Hyperlink find(Shape shape){
|
||||
ArrayList lst = new ArrayList();
|
||||
SlideShow ppt = shape.getSheet().getSlideShow();
|
||||
//document-level container which stores info about all links in a presentation
|
||||
ExObjList exobj = ppt.getDocumentRecord().getExObjList();
|
||||
if (exobj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
EscherContainerRecord spContainer = shape.getSpContainer();
|
||||
List spchild = spContainer.getChildRecords();
|
||||
for (Iterator it = spchild.iterator(); it.hasNext(); ) {
|
||||
EscherRecord obj = (EscherRecord)it.next();
|
||||
if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID){
|
||||
byte[] data = ((EscherContainerRecord)obj).serialize();
|
||||
Record[] records = Record.findChildRecords(data, 8, data.length-8);
|
||||
if(records != null) find(records, exobj, lst);
|
||||
}
|
||||
}
|
||||
|
||||
return lst.size() == 1 ? (Hyperlink)lst.get(0) : null;
|
||||
}
|
||||
|
||||
private static void find(Record[] records, ExObjList exobj, List out){
|
||||
for (int i = 0; i < records.length; i++) {
|
||||
//see if we have InteractiveInfo in the textrun's records
|
||||
if( records[i] instanceof InteractiveInfo){
|
||||
InteractiveInfo hldr = (InteractiveInfo)records[i];
|
||||
InteractiveInfoAtom info = hldr.getInteractiveInfoAtom();
|
||||
int id = info.getHyperlinkID();
|
||||
ExHyperlink linkRecord = exobj.get(id);
|
||||
if (linkRecord != null){
|
||||
Hyperlink link = new Hyperlink();
|
||||
link.title = linkRecord.getLinkTitle();
|
||||
link.address = linkRecord.getLinkURL();
|
||||
link.type = info.getAction();
|
||||
|
||||
if (++i < records.length && records[i] instanceof TxInteractiveInfoAtom){
|
||||
TxInteractiveInfoAtom txinfo = (TxInteractiveInfoAtom)records[i];
|
||||
link.startIndex = txinfo.getStartIndex();
|
||||
link.endIndex = txinfo.getEndIndex();
|
||||
}
|
||||
out.add(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -45,7 +45,7 @@ public abstract class Shape {
|
||||
|
||||
// For logging
|
||||
protected POILogger logger = POILogFactory.getLogger(this.getClass());
|
||||
|
||||
|
||||
/**
|
||||
* In Escher absolute distances are specified in
|
||||
* English Metric Units (EMUs), occasionally referred to as A units;
|
||||
@ -309,4 +309,15 @@ public abstract class Shape {
|
||||
return new Fill(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the hyperlink assigned to this shape
|
||||
*
|
||||
* @return the hyperlink assigned to this shape
|
||||
* or <code>null</code> if not found.
|
||||
*/
|
||||
public Hyperlink getHyperlink(){
|
||||
return Hyperlink.find(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -211,4 +211,13 @@ public class ShapeGroup extends Shape{
|
||||
return spRecord.getOptions() >> 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>null</code> - shape groups can't have hyperlinks
|
||||
*
|
||||
* @return <code>null</code>.
|
||||
*/
|
||||
public Hyperlink getHyperlink(){
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ package org.apache.poi.hslf.model;
|
||||
import org.apache.poi.ddf.EscherContainerRecord;
|
||||
import org.apache.poi.ddf.EscherDgRecord;
|
||||
import org.apache.poi.ddf.EscherRecord;
|
||||
import org.apache.poi.ddf.EscherSpRecord;
|
||||
import org.apache.poi.hslf.record.*;
|
||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
|
||||
@ -127,7 +128,13 @@ public abstract class Sheet {
|
||||
Vector runsV = new Vector();
|
||||
EscherTextboxWrapper[] wrappers = ppdrawing.getTextboxWrappers();
|
||||
for (int i = 0; i < wrappers.length; i++) {
|
||||
int s1 = runsV.size();
|
||||
findTextRuns(wrappers[i].getChildRecords(), runsV);
|
||||
int s2 = runsV.size();
|
||||
if (s2 != s1){
|
||||
TextRun t = (TextRun) runsV.get(runsV.size()-1);
|
||||
t.setShapeId(wrappers[i].getShapeId());
|
||||
}
|
||||
}
|
||||
TextRun[] runs = new TextRun[runsV.size()];
|
||||
for (int i = 0; i < runs.length; i++) {
|
||||
@ -176,6 +183,15 @@ public abstract class Sheet {
|
||||
}
|
||||
|
||||
if (trun != null) {
|
||||
ArrayList lst = new ArrayList();
|
||||
for (int j = i; j < records.length; j++) {
|
||||
if(j > i && records[j] instanceof TextHeaderAtom) break;
|
||||
lst.add(records[j]);
|
||||
}
|
||||
Record[] recs = new Record[lst.size()];
|
||||
lst.toArray(recs);
|
||||
trun._records = recs;
|
||||
|
||||
found.add(trun);
|
||||
i++;
|
||||
} else {
|
||||
@ -232,6 +248,11 @@ public abstract class Sheet {
|
||||
EscherDgRecord dg = (EscherDgRecord) Shape.getEscherChild(dgContainer, EscherDgRecord.RECORD_ID);
|
||||
dg.setNumShapes(dg.getNumShapes() + 1);
|
||||
|
||||
int shapeId = dg.getLastMSOSPID()+1;
|
||||
dg.setLastMSOSPID(shapeId);
|
||||
|
||||
EscherSpRecord sp = shape.getSpContainer().getChildById(EscherSpRecord.RECORD_ID);
|
||||
if(sp != null) sp.setShapeId(shapeId);
|
||||
shape.setSheet(this);
|
||||
shape.afterInsert(this);
|
||||
|
||||
|
@ -28,7 +28,6 @@ import java.awt.*;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.TextLayout;
|
||||
import java.io.IOException;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* Represents a TextFrame shape in PowerPoint.
|
||||
@ -170,7 +169,7 @@ public class TextBox extends SimpleShape {
|
||||
* @return the text string for this textbox.
|
||||
*/
|
||||
public String getText(){
|
||||
return _txtrun.getText();
|
||||
return _txtrun == null ? null : _txtrun.getText();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -452,56 +451,37 @@ public class TextBox extends SimpleShape {
|
||||
}
|
||||
|
||||
private void initTextRun(){
|
||||
TextHeaderAtom tha = null;
|
||||
TextCharsAtom tca = null;
|
||||
TextBytesAtom tba = null;
|
||||
StyleTextPropAtom sta = null;
|
||||
OutlineTextRefAtom ota = null;
|
||||
|
||||
// Find the interesting child records
|
||||
Record[] child = _txtbox.getChildRecords();
|
||||
for (int i = 0; i < child.length; i++) {
|
||||
if (child[i] instanceof TextHeaderAtom) tha = (TextHeaderAtom)child[i];
|
||||
else if (child[i] instanceof TextBytesAtom) tba = (TextBytesAtom)child[i];
|
||||
else if (child[i] instanceof StyleTextPropAtom) sta = (StyleTextPropAtom)child[i];
|
||||
else if (child[i] instanceof OutlineTextRefAtom) ota = (OutlineTextRefAtom)child[i];
|
||||
else if (child[i] instanceof TextCharsAtom) tca = (TextCharsAtom)child[i];
|
||||
}
|
||||
|
||||
// Special handling for cases where there's an OutlineTextRefAtom
|
||||
if (ota != null) {
|
||||
// TextHeaderAtom, TextBytesAtom and StyleTextPropAtom are
|
||||
// stored outside of EscherContainerRecord
|
||||
int idx = ota.getTextIndex();
|
||||
Slide sl = (Slide)getSheet();
|
||||
Record[] rec = sl.getSlideAtomsSet().getSlideRecords();
|
||||
for (int i = 0, j = 0; i < rec.length; i++) {
|
||||
if(rec[i].getRecordType() == RecordTypes.TextHeaderAtom.typeID){
|
||||
if(j++ == idx) { //we found j-th TextHeaderAtom, read the text data
|
||||
for (int k = i; k < rec.length; k++) {
|
||||
if (rec[k] instanceof TextHeaderAtom) {
|
||||
if (tha != null) break;
|
||||
else tha = (TextHeaderAtom)rec[k];
|
||||
}
|
||||
else if (rec[k] instanceof TextBytesAtom) tba = (TextBytesAtom)rec[k];
|
||||
else if (rec[k] instanceof TextCharsAtom) tca = (TextCharsAtom)rec[k];
|
||||
else if (rec[k] instanceof StyleTextPropAtom) sta = (StyleTextPropAtom)rec[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (child[i] instanceof OutlineTextRefAtom) {
|
||||
ota = (OutlineTextRefAtom)child[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we found the records we needed, create a TextRun
|
||||
if(tba != null) {
|
||||
// Bytes based Text Run
|
||||
_txtrun = new TextRun(tha,tba,sta);
|
||||
} else if (tca != null) {
|
||||
// Characters (unicode) based Text Run
|
||||
_txtrun = new TextRun(tha,tca,sta);
|
||||
|
||||
Sheet sheet = getSheet();
|
||||
TextRun[] runs = sheet.getTextRuns();
|
||||
if (ota != null) {
|
||||
int idx = ota.getTextIndex();
|
||||
if(idx < runs.length) _txtrun = runs[idx];
|
||||
if(_txtrun == null) {
|
||||
logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx);
|
||||
}
|
||||
} else {
|
||||
// Empty text box
|
||||
logger.log(POILogger.WARN, "no text records found for TextBox");
|
||||
int shapeId = _escherContainer.getChildById(EscherSpRecord.RECORD_ID).getShapeId();
|
||||
if(runs != null) for (int i = 0; i < runs.length; i++) {
|
||||
if(runs[i].getShapeId() == shapeId){
|
||||
_txtrun = runs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(_txtrun == null) {
|
||||
logger.log(POILogger.WARN, "text run not found for shapeId=" + shapeId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,12 @@ public class TextRun
|
||||
protected RichTextRun[] _rtRuns;
|
||||
private SlideShow slideShow;
|
||||
private Sheet sheet;
|
||||
private int shapeId;
|
||||
/**
|
||||
* all text run records that follow TextHeaderAtom.
|
||||
* (there can be misc InteractiveInfo, TxInteractiveInfo and other records)
|
||||
*/
|
||||
protected Record[] _records;
|
||||
|
||||
/**
|
||||
* Constructs a Text Run from a Unicode text block
|
||||
@ -517,4 +523,28 @@ public class TextRun
|
||||
public Sheet getSheet(){
|
||||
return this.sheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Shape ID
|
||||
*/
|
||||
protected int getShapeId(){
|
||||
return shapeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id Shape ID
|
||||
*/
|
||||
protected void setShapeId(int id){
|
||||
shapeId = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the array of all hyperlinks in this text run
|
||||
*
|
||||
* @return the array of all hyperlinks in this text run
|
||||
* or <code>null</code> if not found.
|
||||
*/
|
||||
public Hyperlink[] getHyperlinks(){
|
||||
return Hyperlink.find(this);
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ public class EscherTextboxWrapper extends RecordContainer
|
||||
{
|
||||
private EscherTextboxRecord _escherRecord;
|
||||
private long _type;
|
||||
private int shapeId;
|
||||
|
||||
/**
|
||||
* Returns the underlying DDF Escher Record
|
||||
@ -93,4 +94,18 @@ public class EscherTextboxWrapper extends RecordContainer
|
||||
// Save in the escher layer
|
||||
_escherRecord.setData(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Shape ID
|
||||
*/
|
||||
public int getShapeId(){
|
||||
return shapeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id Shape ID
|
||||
*/
|
||||
public void setShapeId(int id){
|
||||
shapeId = id;
|
||||
}
|
||||
}
|
||||
|
@ -42,13 +42,22 @@ public class ExHyperlink extends RecordContainer {
|
||||
|
||||
/**
|
||||
* Returns the URL of the link.
|
||||
* TODO: Figure out which of detailsA or detailsB is the
|
||||
* one that always holds it
|
||||
*
|
||||
* @return the URL of the link
|
||||
*/
|
||||
public String getLinkURL() {
|
||||
return linkDetailsA.getText();
|
||||
return linkDetailsB == null ? null : linkDetailsB.getText();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the hyperlink's user-readable name
|
||||
*
|
||||
* @return the hyperlink's user-readable name
|
||||
*/
|
||||
public String getLinkTitle() {
|
||||
return linkDetailsA == null ? null : linkDetailsA.getText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the URL of the link
|
||||
* TODO: Figure out if we should always set both
|
||||
@ -66,13 +75,13 @@ public class ExHyperlink extends RecordContainer {
|
||||
* Get the link details (field A)
|
||||
*/
|
||||
public String _getDetailsA() {
|
||||
return linkDetailsA.getText();
|
||||
return linkDetailsA == null ? null : linkDetailsA.getText();
|
||||
}
|
||||
/**
|
||||
* Get the link details (field B)
|
||||
*/
|
||||
public String _getDetailsB() {
|
||||
return linkDetailsB.getText();
|
||||
return linkDetailsB == null ? null : linkDetailsB.getText();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,4 +109,21 @@ public class ExObjList extends RecordContainer {
|
||||
writeOut(_header[0],_header[1],_type,_children,out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a hyperlink by its unique id
|
||||
*
|
||||
* @param id hyperlink id
|
||||
* @return found <code>ExHyperlink</code> or <code>null</code>
|
||||
*/
|
||||
public ExHyperlink get(int id){
|
||||
for(int i=0; i<_children.length; i++) {
|
||||
if(_children[i] instanceof ExHyperlink) {
|
||||
ExHyperlink rec = (ExHyperlink)_children[i];
|
||||
if (rec.getExHyperlinkAtom().getNumber() == id){
|
||||
return rec;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -30,10 +30,37 @@ import org.apache.poi.util.LittleEndian;
|
||||
* (The actual link is held Document.ExObjList.ExHyperlink)
|
||||
*
|
||||
* @author Nick Burch
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
|
||||
public class InteractiveInfoAtom extends RecordAtom
|
||||
{
|
||||
|
||||
/**
|
||||
* Action Table
|
||||
*/
|
||||
public static final int ACTION_NONE = 0;
|
||||
public static final int ACTION_MACRO = 1;
|
||||
public static final int ACTION_RUNPROGRAM = 2;
|
||||
public static final int ACTION_JUMP = 3;
|
||||
public static final int ACTION_HYPERLINK = 4;
|
||||
public static final int ACTION_OLE = 5;
|
||||
public static final int ACTION_MEDIA = 6;
|
||||
public static final int ACTION_CUSTOMSHOW = 7;
|
||||
|
||||
/**
|
||||
* Jump Table
|
||||
*/
|
||||
public static final int JUMP_NONE = 0;
|
||||
public static final int JUMP_NEXTSLIDE = 1;
|
||||
public static final int JUMP_PREVIOUSSLIDE = 2;
|
||||
public static final int JUMP_FIRSTSLIDE = 3;
|
||||
public static final int JUMP_LASTSLIDE = 4;
|
||||
public static final int JUMP_LASTSLIDEVIEWED = 5;
|
||||
public static final int JUMP_ENDSHOW = 6;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Record header.
|
||||
*/
|
||||
@ -90,46 +117,138 @@ public class InteractiveInfoAtom extends RecordAtom
|
||||
* ExHyperlink with this number to get the details.
|
||||
* @return the link number
|
||||
*/
|
||||
public int getNumber() {
|
||||
public int getHyperlinkID() {
|
||||
return LittleEndian.getInt(_data,4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the link number
|
||||
* @param number the link number.
|
||||
* Sets the persistent unique identifier of the link
|
||||
*
|
||||
* @param number the persistent unique identifier of the link
|
||||
*/
|
||||
public void setNumber(int number) {
|
||||
public void setHyperlinkID(int number) {
|
||||
LittleEndian.putInt(_data,4,number);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first number - meaning unknown
|
||||
* a reference to a sound in the sound collection.
|
||||
*/
|
||||
public int _getNumber1() {
|
||||
public int getSoundRef() {
|
||||
return LittleEndian.getInt(_data,0);
|
||||
}
|
||||
protected void _setNumber1(int val) {
|
||||
/**
|
||||
* a reference to a sound in the sound collection.
|
||||
*
|
||||
* @param val a reference to a sound in the sound collection
|
||||
*/
|
||||
public void setSoundRef(int val) {
|
||||
LittleEndian.putInt(_data, 0, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the third number - meaning unknown
|
||||
* Hyperlink Action.
|
||||
* <p>
|
||||
* see <code>ACTION_*</code> constants for the list of actions
|
||||
* </p>
|
||||
*
|
||||
* @return hyperlink action.
|
||||
*/
|
||||
public int _getNumber3() {
|
||||
return LittleEndian.getInt(_data,8);
|
||||
}
|
||||
protected void _setNumber3(int val) {
|
||||
LittleEndian.putInt(_data, 8, val);
|
||||
public byte getAction() {
|
||||
return _data[8];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fourth number - meaning unknown
|
||||
* Hyperlink Action
|
||||
* <p>
|
||||
* see <code>ACTION_*</code> constants for the list of actions
|
||||
* </p>
|
||||
*
|
||||
* @param val hyperlink action.
|
||||
*/
|
||||
public int _getNumber4() {
|
||||
return LittleEndian.getInt(_data,12);
|
||||
public void setAction(byte val) {
|
||||
_data[8] = val;
|
||||
}
|
||||
protected void _setNumber4(int val) {
|
||||
LittleEndian.putInt(_data, 12, val);
|
||||
|
||||
/**
|
||||
* Only valid when action == OLEAction. OLE verb to use, 0 = first verb, 1 = second verb, etc.
|
||||
*/
|
||||
public byte getOleVerb() {
|
||||
return _data[9];
|
||||
}
|
||||
|
||||
/**
|
||||
* Only valid when action == OLEAction. OLE verb to use, 0 = first verb, 1 = second verb, etc.
|
||||
*/
|
||||
public void setOleVerb(byte val) {
|
||||
_data[9] = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Jump
|
||||
* <p>
|
||||
* see <code>JUMP_*</code> constants for the list of actions
|
||||
* </p>
|
||||
*
|
||||
* @return jump
|
||||
*/
|
||||
public byte getJump() {
|
||||
return _data[10];
|
||||
}
|
||||
|
||||
/**
|
||||
* Jump
|
||||
* <p>
|
||||
* see <code>JUMP_*</code> constants for the list of actions
|
||||
* </p>
|
||||
*
|
||||
* @param val jump
|
||||
*/
|
||||
public void setJump(byte val) {
|
||||
_data[10] = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flags
|
||||
* <p>
|
||||
* <li> Bit 1: Animated. If 1, then button is animated
|
||||
* <li> Bit 2: Stop sound. If 1, then stop current sound when button is pressed.
|
||||
* <li> Bit 3: CustomShowReturn. If 1, and this is a jump to custom show,
|
||||
* then return to this slide after custom show.
|
||||
* </p>
|
||||
*/
|
||||
public byte getFlags() {
|
||||
return _data[11];
|
||||
}
|
||||
|
||||
/**
|
||||
* Flags
|
||||
* <p>
|
||||
* <li> Bit 1: Animated. If 1, then button is animated
|
||||
* <li> Bit 2: Stop sound. If 1, then stop current sound when button is pressed.
|
||||
* <li> Bit 3: CustomShowReturn. If 1, and this is a jump to custom show,
|
||||
* then return to this slide after custom show.
|
||||
* </p>
|
||||
*/
|
||||
public void setFlags(byte val) {
|
||||
_data[11] = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* hyperlink type
|
||||
*
|
||||
* @return hyperlink type
|
||||
*/
|
||||
public byte getHyperlinkType() {
|
||||
return _data[12];
|
||||
}
|
||||
|
||||
/**
|
||||
* hyperlink type
|
||||
*
|
||||
* @param val hyperlink type
|
||||
*/
|
||||
public void setHyperlinkType(byte val) {
|
||||
_data[12] = val;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,6 +147,13 @@ public class PPDrawing extends RecordAtom
|
||||
EscherTextboxRecord tbr = (EscherTextboxRecord)toSearch[i];
|
||||
EscherTextboxWrapper w = new EscherTextboxWrapper(tbr);
|
||||
found.add(w);
|
||||
for (int j = i; j >= 0; j--) {
|
||||
if(toSearch[j] instanceof EscherSpRecord){
|
||||
EscherSpRecord sp = (EscherSpRecord)toSearch[j];
|
||||
w.setShapeId(sp.getShapeId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If it has children, walk them
|
||||
if(toSearch[i].isContainerRecord()) {
|
||||
|
@ -112,7 +112,7 @@ public class RecordTypes {
|
||||
public static final Type SlideNumberMCAtom = new Type(4056,null);
|
||||
public static final Type HeadersFooters = new Type(4057,null);
|
||||
public static final Type HeadersFootersAtom = new Type(4058,null);
|
||||
public static final Type TxInteractiveInfoAtom = new Type(4063,null);
|
||||
public static final Type TxInteractiveInfoAtom = new Type(4063,TxInteractiveInfoAtom.class);
|
||||
public static final Type CharFormatAtom = new Type(4066,null);
|
||||
public static final Type ParaFormatAtom = new Type(4067,null);
|
||||
public static final Type RecolorInfoAtom = new Type(4071,null);
|
||||
|
@ -0,0 +1,122 @@
|
||||
/* ====================================================================
|
||||
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.record;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Tne atom that holds starting and ending character positions of a hyperlink
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class TxInteractiveInfoAtom extends RecordAtom {
|
||||
/**
|
||||
* Record header.
|
||||
*/
|
||||
private byte[] _header;
|
||||
|
||||
/**
|
||||
* Record data.
|
||||
*/
|
||||
private byte[] _data;
|
||||
|
||||
/**
|
||||
* Constructs a brand new link related atom record.
|
||||
*/
|
||||
protected TxInteractiveInfoAtom() {
|
||||
_header = new byte[8];
|
||||
_data = new byte[8];
|
||||
|
||||
LittleEndian.putShort(_header, 2, (short)getRecordType());
|
||||
LittleEndian.putInt(_header, 4, _data.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the link related atom record from its
|
||||
* source data.
|
||||
*
|
||||
* @param source the source data as a byte array.
|
||||
* @param start the start offset into the byte array.
|
||||
* @param len the length of the slice in the byte array.
|
||||
*/
|
||||
protected TxInteractiveInfoAtom(byte[] source, int start, int len) {
|
||||
// Get the header.
|
||||
_header = new byte[8];
|
||||
System.arraycopy(source,start,_header,0,8);
|
||||
|
||||
// Get the record data.
|
||||
_data = new byte[len-8];
|
||||
System.arraycopy(source,start+8,_data,0,len-8);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the beginning character position
|
||||
*
|
||||
* @return the beginning character position
|
||||
*/
|
||||
public int getStartIndex() {
|
||||
return LittleEndian.getInt(_data, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the beginning character position
|
||||
* @param idx the beginning character position
|
||||
*/
|
||||
public void setStartIndex(int idx) {
|
||||
LittleEndian.putInt(_data, 0, idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ending character position
|
||||
*
|
||||
* @return the ending character position
|
||||
*/
|
||||
public int getEndIndex() {
|
||||
return LittleEndian.getInt(_data, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ending character position
|
||||
*
|
||||
* @param idx the ending character position
|
||||
*/
|
||||
public void setEndIndex(int idx) {
|
||||
LittleEndian.putInt(_data, 4, idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the record type.
|
||||
* @return the record type.
|
||||
*/
|
||||
public long getRecordType() { return RecordTypes.TxInteractiveInfoAtom.typeID; }
|
||||
|
||||
/**
|
||||
* Write the contents of the record back, so it can be written
|
||||
* to disk
|
||||
*
|
||||
* @param out the output stream to write to.
|
||||
* @throws java.io.IOException if an error occurs.
|
||||
*/
|
||||
public void writeOut(OutputStream out) throws IOException {
|
||||
out.write(_header);
|
||||
out.write(_data);
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/* ====================================================================
|
||||
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 junit.framework.TestCase;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
|
||||
/**
|
||||
* Test Hyperlink.
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class TestHyperlink extends TestCase {
|
||||
protected String cwd = System.getProperty("HSLF.testdata.path");
|
||||
|
||||
public void testTextRunHyperlinks() throws Exception {
|
||||
FileInputStream is = new FileInputStream(new File(cwd, "WithLinks.ppt"));
|
||||
SlideShow ppt = new SlideShow(is);
|
||||
is.close();
|
||||
|
||||
TextRun[] run;
|
||||
Slide slide;
|
||||
slide = ppt.getSlides()[0];
|
||||
run = slide.getTextRuns();
|
||||
for (int i = 0; i < run.length; i++) {
|
||||
String text = run[i].getText();
|
||||
if (text.equals(
|
||||
"This page has two links:\n" +
|
||||
"http://jakarta.apache.org/poi/\n" +
|
||||
"\n" +
|
||||
"http://slashdot.org/\n" +
|
||||
"\n" +
|
||||
"In addition, its notes has one link")){
|
||||
|
||||
Hyperlink[] links = run[i].getHyperlinks();
|
||||
assertNotNull(links);
|
||||
assertEquals(2, links.length);
|
||||
|
||||
assertEquals("http://jakarta.apache.org/poi/", links[0].getTitle());
|
||||
assertEquals("http://jakarta.apache.org/poi/", links[0].getAddress());
|
||||
assertEquals("http://jakarta.apache.org/poi/", text.substring(links[0].getStartIndex(), links[0].getEndIndex()-1));
|
||||
|
||||
assertEquals("http://slashdot.org/", links[1].getTitle());
|
||||
assertEquals("http://slashdot.org/", links[1].getAddress());
|
||||
assertEquals("http://slashdot.org/", text.substring(links[1].getStartIndex(), links[1].getEndIndex()-1));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
slide = ppt.getSlides()[1];
|
||||
run = slide.getTextRuns();
|
||||
for (int i = 0; i < run.length; i++) {
|
||||
String text = run[i].getText();
|
||||
if (text.equals(
|
||||
"I have the one link:\n" +
|
||||
"Jakarta HSSF")){
|
||||
|
||||
Hyperlink[] links = run[i].getHyperlinks();
|
||||
assertNotNull(links);
|
||||
assertEquals(1, links.length);
|
||||
|
||||
assertEquals("http://jakarta.apache.org/poi/hssf/", links[0].getTitle());
|
||||
assertEquals("http://jakarta.apache.org/poi/hssf/", links[0].getAddress());
|
||||
assertEquals("Jakarta HSSF", text.substring(links[0].getStartIndex(), links[0].getEndIndex()-1));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -161,7 +161,8 @@ public class TestShapes extends TestCase {
|
||||
out.close();
|
||||
|
||||
ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())));
|
||||
|
||||
sl = ppt.getSlides()[0];
|
||||
|
||||
txtbox = (TextBox)sl.getShapes()[0];
|
||||
rt = txtbox.getTextRun().getRichTextRuns()[0];
|
||||
|
||||
|
@ -48,7 +48,7 @@ public class TestInteractiveInfo extends TestCase {
|
||||
InteractiveInfo ii = new InteractiveInfo(data_a, 0, data_a.length);
|
||||
InteractiveInfoAtom ia = ii.getInteractiveInfoAtom();
|
||||
|
||||
assertEquals(1, ia.getNumber());
|
||||
assertEquals(1, ia.getHyperlinkID());
|
||||
}
|
||||
|
||||
public void testWrite() throws Exception {
|
||||
@ -69,10 +69,10 @@ public class TestInteractiveInfo extends TestCase {
|
||||
InteractiveInfoAtom ia = ii.getInteractiveInfoAtom();
|
||||
|
||||
// Set values
|
||||
ia.setNumber(1);
|
||||
ia._setNumber1(0);
|
||||
ia._setNumber3(4);
|
||||
ia._setNumber4(8);
|
||||
ia.setHyperlinkID(1);
|
||||
ia.setSoundRef(0);
|
||||
ia.setAction((byte)4);
|
||||
ia.setHyperlinkType((byte)8);
|
||||
|
||||
// Check it's now the same as a
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
@ -53,22 +53,22 @@ public class TestInteractiveInfoAtom extends TestCase {
|
||||
InteractiveInfoAtom ia = new InteractiveInfoAtom(data_a, 0, data_a.length);
|
||||
InteractiveInfoAtom ib = new InteractiveInfoAtom(data_b, 0, data_b.length);
|
||||
|
||||
assertEquals(1, ia.getNumber());
|
||||
assertEquals(4, ib.getNumber());
|
||||
assertEquals(1, ia.getHyperlinkID());
|
||||
assertEquals(4, ib.getHyperlinkID());
|
||||
}
|
||||
|
||||
public void testGetRest() throws Exception {
|
||||
InteractiveInfoAtom ia = new InteractiveInfoAtom(data_a, 0, data_a.length);
|
||||
InteractiveInfoAtom ib = new InteractiveInfoAtom(data_b, 0, data_b.length);
|
||||
|
||||
assertEquals(0, ia._getNumber1());
|
||||
assertEquals(0, ib._getNumber1());
|
||||
assertEquals(0, ia.getSoundRef());
|
||||
assertEquals(0, ib.getSoundRef());
|
||||
|
||||
assertEquals(4, ia._getNumber3());
|
||||
assertEquals(4, ib._getNumber3());
|
||||
assertEquals(4, ia.getAction());
|
||||
assertEquals(4, ib.getAction());
|
||||
|
||||
assertEquals(8, ia._getNumber4());
|
||||
assertEquals(8, ib._getNumber4());
|
||||
assertEquals(8, ia.getHyperlinkType());
|
||||
assertEquals(8, ib.getHyperlinkType());
|
||||
}
|
||||
|
||||
public void testWrite() throws Exception {
|
||||
@ -88,10 +88,10 @@ public class TestInteractiveInfoAtom extends TestCase {
|
||||
InteractiveInfoAtom ia = new InteractiveInfoAtom();
|
||||
|
||||
// Set values
|
||||
ia.setNumber(1);
|
||||
ia._setNumber1(0);
|
||||
ia._setNumber3(4);
|
||||
ia._setNumber4(8);
|
||||
ia.setHyperlinkID(1);
|
||||
ia.setSoundRef(0);
|
||||
ia.setAction((byte)4);
|
||||
ia.setHyperlinkType((byte)8);
|
||||
|
||||
// Check it's now the same as a
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
@ -109,7 +109,7 @@ public class TestInteractiveInfoAtom extends TestCase {
|
||||
InteractiveInfoAtom ia = new InteractiveInfoAtom(data_a, 0, data_a.length);
|
||||
|
||||
// Change the number
|
||||
ia.setNumber(4);
|
||||
ia.setHyperlinkID(4);
|
||||
|
||||
// Check bytes are now the same
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
@ -0,0 +1,110 @@
|
||||
|
||||
/* ====================================================================
|
||||
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.record;
|
||||
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Tests that TxInteractiveInfoAtom works properly.
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class TestTxInteractiveInfoAtom extends TestCase {
|
||||
// From WithLinks.ppt
|
||||
private byte[] data_a = new byte[] {
|
||||
00, 00, (byte)0xDF, 0x0F, 0x08, 00, 00, 00,
|
||||
0x19, 00, 00, 00, 0x38, 00, 00, 00
|
||||
};
|
||||
|
||||
private byte[] data_b = new byte[] {
|
||||
00, 00, (byte)0xDF, 0x0F, 0x08, 00, 00, 00,
|
||||
0x39, 00, 00, 00, 0x4E, 00, 00, 00
|
||||
};
|
||||
|
||||
public void testRead() throws Exception {
|
||||
TxInteractiveInfoAtom ia1 = new TxInteractiveInfoAtom(data_a, 0, data_a.length);
|
||||
|
||||
assertEquals(4063, ia1.getRecordType());
|
||||
assertEquals(25, ia1.getStartIndex());
|
||||
assertEquals(56, ia1.getEndIndex());
|
||||
|
||||
TxInteractiveInfoAtom ia2 = new TxInteractiveInfoAtom(data_b, 0, data_b.length);
|
||||
|
||||
assertEquals(4063, ia2.getRecordType());
|
||||
assertEquals(57, ia2.getStartIndex());
|
||||
assertEquals(78, ia2.getEndIndex());
|
||||
}
|
||||
|
||||
public void testWrite() throws Exception {
|
||||
TxInteractiveInfoAtom atom = new TxInteractiveInfoAtom(data_a, 0, data_a.length);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
atom.writeOut(baos);
|
||||
byte[] b = baos.toByteArray();
|
||||
|
||||
assertEquals(data_a.length, b.length);
|
||||
for(int i=0; i<data_a.length; i++) {
|
||||
assertEquals(data_a[i],b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Create A from scratch
|
||||
public void testCreate() throws Exception {
|
||||
TxInteractiveInfoAtom ia = new TxInteractiveInfoAtom();
|
||||
|
||||
// Set values
|
||||
ia.setStartIndex(25);
|
||||
ia.setEndIndex(56);
|
||||
|
||||
// Check it's now the same as a
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ia.writeOut(baos);
|
||||
byte[] b = baos.toByteArray();
|
||||
|
||||
assertEquals(data_a.length, b.length);
|
||||
for(int i=0; i<data_a.length; i++) {
|
||||
assertEquals(data_a[i],b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Try to turn a into b
|
||||
public void testChange() throws Exception {
|
||||
TxInteractiveInfoAtom ia = new TxInteractiveInfoAtom(data_a, 0, data_a.length);
|
||||
|
||||
// Change the number
|
||||
ia.setStartIndex(57);
|
||||
ia.setEndIndex(78);
|
||||
|
||||
// Check bytes are now the same
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ia.writeOut(baos);
|
||||
byte[] b = baos.toByteArray();
|
||||
|
||||
// Should now be the same
|
||||
assertEquals(data_b.length, b.length);
|
||||
for(int i=0; i<data_b.length; i++) {
|
||||
assertEquals(data_b[i],b[i]);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user