Author: yegor Date: Wed May 30 04:56:46 2007 New Revision: 542804 URL: http://svn.apache.org/viewvc?view=rev&rev=542804 Log: HSLF: readonly support for hyperlinks
Added: jakarta/poi/trunk/src/scratchpad/examples/src/org/apache/poi/hslf/examples/Hyperlinks.java jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Hyperlink.java jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/TxInteractiveInfoAtom.java jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHyperlink.java jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestTxInteractiveInfoAtom.java Modified: jakarta/poi/trunk/src/documentation/content/xdocs/hslf/how-to-shapes.xml jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/EscherTextboxWrapper.java jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/ExHyperlink.java jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/ExObjList.java jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/InteractiveInfoAtom.java jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawing.java jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestInteractiveInfo.java jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestInteractiveInfoAtom.java Modified: jakarta/poi/trunk/src/documentation/content/xdocs/hslf/how-to-shapes.xml URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/documentation/content/xdocs/hslf/how-to-shapes.xml?view=diff&rev=542804&r1=542803&r2=542804 ============================================================================== --- jakarta/poi/trunk/src/documentation/content/xdocs/hslf/how-to-shapes.xml (original) +++ jakarta/poi/trunk/src/documentation/content/xdocs/hslf/how-to-shapes.xml Wed May 30 04:56:46 2007 @@ -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> Added: jakarta/poi/trunk/src/scratchpad/examples/src/org/apache/poi/hslf/examples/Hyperlinks.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/examples/src/org/apache/poi/hslf/examples/Hyperlinks.java?view=auto&rev=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/examples/src/org/apache/poi/hslf/examples/Hyperlinks.java (added) +++ jakarta/poi/trunk/src/scratchpad/examples/src/org/apache/poi/hslf/examples/Hyperlinks.java Wed May 30 04:56:46 2007 @@ -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); + } + } + } + + } + + } +} Added: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Hyperlink.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Hyperlink.java?view=auto&rev=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Hyperlink.java (added) +++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Hyperlink.java Wed May 30 04:56:46 2007 @@ -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); + } + } + } + } +} Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java?view=diff&rev=542804&r1=542803&r2=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java (original) +++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java Wed May 30 04:56:46 2007 @@ -45,7 +45,7 @@ // 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; @@ -307,6 +307,17 @@ */ public Fill getFill(){ 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); } } Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java?view=diff&rev=542804&r1=542803&r2=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java (original) +++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java Wed May 30 04:56:46 2007 @@ -211,4 +211,13 @@ return spRecord.getOptions() >> 4; } + /** + * Returns <code>null</code> - shape groups can't have hyperlinks + * + * @return <code>null</code>. + */ + public Hyperlink getHyperlink(){ + return null; + } + } Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java?view=diff&rev=542804&r1=542803&r2=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java (original) +++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java Wed May 30 04:56:46 2007 @@ -21,6 +21,7 @@ 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 @@ 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 @@ } 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 @@ 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); Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java?view=diff&rev=542804&r1=542803&r2=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java (original) +++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java Wed May 30 04:56:46 2007 @@ -28,7 +28,6 @@ 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 @@ * @return the text string for this textbox. */ public String getText(){ - return _txtrun.getText(); + return _txtrun == null ? null : _txtrun.getText(); } /** @@ -452,56 +451,37 @@ } 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]; + if (child[i] instanceof OutlineTextRefAtom) { + ota = (OutlineTextRefAtom)child[i]; + break; + } } - // Special handling for cases where there's an OutlineTextRefAtom + Sheet sheet = getSheet(); + TextRun[] runs = sheet.getTextRuns(); 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(idx < runs.length) _txtrun = runs[idx]; + if(_txtrun == null) { + logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx); } - } - - // 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); } 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); + } } + } } Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java?view=diff&rev=542804&r1=542803&r2=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java (original) +++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java Wed May 30 04:56:46 2007 @@ -49,6 +49,12 @@ 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 @@ -516,5 +522,29 @@ 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); } } Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/EscherTextboxWrapper.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/EscherTextboxWrapper.java?view=diff&rev=542804&r1=542803&r2=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/EscherTextboxWrapper.java (original) +++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/EscherTextboxWrapper.java Wed May 30 04:56:46 2007 @@ -39,6 +39,7 @@ { private EscherTextboxRecord _escherRecord; private long _type; + private int shapeId; /** * Returns the underlying DDF Escher Record @@ -93,4 +94,18 @@ // 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; + } } Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/ExHyperlink.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/ExHyperlink.java?view=diff&rev=542804&r1=542803&r2=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/ExHyperlink.java (original) +++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/ExHyperlink.java Wed May 30 04:56:46 2007 @@ -42,13 +42,22 @@ /** * 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 @@ * 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(); } /** Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/ExObjList.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/ExObjList.java?view=diff&rev=542804&r1=542803&r2=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/ExObjList.java (original) +++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/ExObjList.java Wed May 30 04:56:46 2007 @@ -109,4 +109,21 @@ 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; + } } Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/InteractiveInfoAtom.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/InteractiveInfoAtom.java?view=diff&rev=542804&r1=542803&r2=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/InteractiveInfoAtom.java (original) +++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/InteractiveInfoAtom.java Wed May 30 04:56:46 2007 @@ -30,10 +30,37 @@ * (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 @@ * 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 byte getAction() { + return _data[8]; + } + + /** + * Hyperlink Action + * <p> + * see <code>ACTION_*</code> constants for the list of actions + * </p> + * + * @param val hyperlink action. + */ + public void setAction(byte val) { + _data[8] = 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 int _getNumber3() { - return LittleEndian.getInt(_data,8); + public byte getJump() { + return _data[10]; } - protected void _setNumber3(int val) { - LittleEndian.putInt(_data, 8, val); + + /** + * Jump + * <p> + * see <code>JUMP_*</code> constants for the list of actions + * </p> + * + * @param val jump + */ + public void setJump(byte val) { + _data[10] = val; } /** - * Get the fourth number - meaning unknown + * 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 int _getNumber4() { - return LittleEndian.getInt(_data,12); + public byte getFlags() { + return _data[11]; } - protected void _setNumber4(int val) { - LittleEndian.putInt(_data, 12, 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 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; } /** Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawing.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawing.java?view=diff&rev=542804&r1=542803&r2=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawing.java (original) +++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawing.java Wed May 30 04:56:46 2007 @@ -147,6 +147,13 @@ 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()) { Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java?view=diff&rev=542804&r1=542803&r2=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java (original) +++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java Wed May 30 04:56:46 2007 @@ -112,7 +112,7 @@ 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); Added: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/TxInteractiveInfoAtom.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/TxInteractiveInfoAtom.java?view=auto&rev=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/TxInteractiveInfoAtom.java (added) +++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/TxInteractiveInfoAtom.java Wed May 30 04:56:46 2007 @@ -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); + } +} Added: jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHyperlink.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHyperlink.java?view=auto&rev=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHyperlink.java (added) +++ jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHyperlink.java Wed May 30 04:56:46 2007 @@ -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)); + + } + } + + } + +} Modified: jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java?view=diff&rev=542804&r1=542803&r2=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java (original) +++ jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java Wed May 30 04:56:46 2007 @@ -161,7 +161,8 @@ 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]; Modified: jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestInteractiveInfo.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestInteractiveInfo.java?view=diff&rev=542804&r1=542803&r2=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestInteractiveInfo.java (original) +++ jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestInteractiveInfo.java Wed May 30 04:56:46 2007 @@ -48,7 +48,7 @@ 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 @@ 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(); Modified: jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestInteractiveInfoAtom.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestInteractiveInfoAtom.java?view=diff&rev=542804&r1=542803&r2=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestInteractiveInfoAtom.java (original) +++ jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestInteractiveInfoAtom.java Wed May 30 04:56:46 2007 @@ -53,22 +53,22 @@ 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 @@ 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 @@ 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(); Added: jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestTxInteractiveInfoAtom.java URL: http://svn.apache.org/viewvc/jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestTxInteractiveInfoAtom.java?view=auto&rev=542804 ============================================================================== --- jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestTxInteractiveInfoAtom.java (added) +++ jakarta/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestTxInteractiveInfoAtom.java Wed May 30 04:56:46 2007 @@ -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]); + } + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] Mailing List: http://jakarta.apache.org/site/mail2.html#poi The Apache Jakarta POI Project: http://jakarta.apache.org/poi/