]> source.dussan.org Git - poi.git/commitdiff
initial support for endnotes and footnotes in HWPF
authorSergey Vladimirov <sergey@apache.org>
Wed, 20 Jul 2011 22:31:59 +0000 (22:31 +0000)
committerSergey Vladimirov <sergey@apache.org>
Wed, 20 Jul 2011 22:31:59 +0000 (22:31 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1148959 13f79535-47bb-0310-9956-ffa450edef68

14 files changed:
src/documentation/content/xdocs/status.xml
src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java
src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java
src/scratchpad/src/org/apache/poi/hwpf/model/FootnoteReferenceDescriptor.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hwpf/model/NoteType.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hwpf/model/NotesTables.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hwpf/model/types/FRDAbstractType.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hwpf/usermodel/Notes.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hwpf/usermodel/NotesImpl.java [new file with mode: 0644]
src/scratchpad/testcases/org/apache/poi/hwpf/AllHWPFTests.java
src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToHtmlConverter.java
src/scratchpad/testcases/org/apache/poi/hwpf/model/TestNotesTables.java [new file with mode: 0644]
src/types/definitions/frd_type.xml [new file with mode: 0644]
test-data/document/endingnote.doc [new file with mode: 0644]

index 82000db2998d37a89af6fd0ebf40e249778b5549..b4b5101a306415dfe647f233ce7e6cbd8ffd7fa7 100644 (file)
 
     <changes>
         <release version="3.8-beta4" date="2011-??-??">
+           <action dev="poi-developers" type="add">Initial support for endnotes and footnotes in HWPF</action>
            <action dev="poi-developers" type="fix">51470 - avoid exception when cloning XSSF sheets with background images</action>
            <action dev="poi-developers" type="fix">51481 - Fixed autofilters in HSSF to avoid warnings in Excel 2007</action>
            <action dev="poi-developers" type="fix">51533 - Avoid exception when changing name of a sheet containing shared formulas</action>
            <action dev="poi-developers" type="add">Support for appending images to existing drawings in HSSF</action>
-           <action dev="poi-developers" type="fix">Added initial support for bookmarks in HWPF</action>
+           <action dev="poi-developers" type="add">Initial support for bookmarks in HWPF</action>
            <action dev="poi-developers" type="fix">46250 - Fixed cloning worksheets with images</action>
            <action dev="poi-developers" type="fix">51524 - PapBinTable constructor is slow (regression)</action>
            <action dev="poi-developers" type="fix">51514 - allow HSSFObjectData to work with both POIFS and NPOIFS</action>
index fd2fccfc8f3328f763df4426e318f57e706cb63b..852e895506d1aa448b624a9d1bd71caef02ea27e 100644 (file)
@@ -36,6 +36,8 @@ import org.apache.poi.hwpf.model.FSPATable;
 import org.apache.poi.hwpf.model.FieldsTables;
 import org.apache.poi.hwpf.model.FontTable;
 import org.apache.poi.hwpf.model.ListTables;
+import org.apache.poi.hwpf.model.NoteType;
+import org.apache.poi.hwpf.model.NotesTables;
 import org.apache.poi.hwpf.model.PAPBinTable;
 import org.apache.poi.hwpf.model.PicturesTable;
 import org.apache.poi.hwpf.model.RevisionMarkAuthorTable;
@@ -51,6 +53,8 @@ import org.apache.poi.hwpf.model.io.HWPFOutputStream;
 import org.apache.poi.hwpf.usermodel.Bookmarks;
 import org.apache.poi.hwpf.usermodel.BookmarksImpl;
 import org.apache.poi.hwpf.usermodel.HWPFList;
+import org.apache.poi.hwpf.usermodel.Notes;
+import org.apache.poi.hwpf.usermodel.NotesImpl;
 import org.apache.poi.hwpf.usermodel.Range;
 import org.apache.poi.poifs.common.POIFSConstants;
 import org.apache.poi.poifs.filesystem.DirectoryNode;
@@ -110,6 +114,18 @@ public final class HWPFDocument extends HWPFDocumentCore
   /** Holds the bookmarks */
   protected Bookmarks _bookmarks;
 
+  /** Holds the ending notes tables */
+  protected NotesTables _endnotesTables = new NotesTables( NoteType.ENDNOTE );
+
+  /** Holds the footnotes */
+  protected Notes _endnotes = new NotesImpl( _endnotesTables );
+
+  /** Holds the footnotes tables */
+  protected NotesTables _footnotesTables = new NotesTables( NoteType.FOOTNOTE );
+
+  /** Holds the footnotes */
+  protected Notes _footnotes = new NotesImpl( _footnotesTables );
+
   /** Holds the fields PLCFs */
   protected FieldsTables _fieldsTables;
 
@@ -273,6 +289,12 @@ public final class HWPFDocument extends HWPFDocumentCore
 
     _bookmarksTables = new BookmarksTables( _tableStream, _fib );
     _bookmarks = new BookmarksImpl( _bookmarksTables );
+
+    _endnotesTables = new NotesTables( NoteType.ENDNOTE, _tableStream, _fib );
+    _endnotes = new NotesImpl( _endnotesTables );
+    _footnotesTables = new NotesTables( NoteType.FOOTNOTE, _tableStream, _fib );
+    _footnotes = new NotesImpl( _footnotesTables );
+
     _fieldsTables = new FieldsTables(_tableStream, _fib);
   }
 
@@ -470,6 +492,22 @@ public final class HWPFDocument extends HWPFDocumentCore
         return _bookmarks;
     }
 
+    /**
+     * @return user-friendly interface to access document endnotes
+     */
+    public Notes getEndnotes()
+    {
+        return _endnotes;
+    }
+
+    /**
+     * @return user-friendly interface to access document footnotes
+     */
+    public Notes getFootnotes()
+    {
+        return _footnotes;
+    }
+
   /**
    * @return FieldsTables object, that is able to extract fields descriptors from this document
    */
@@ -589,17 +627,75 @@ public final class HWPFDocument extends HWPFDocumentCore
     _fib.setLcbPlcfbtePapx(tableStream.getOffset() - tableOffset);
     tableOffset = tableStream.getOffset();
 
+        /*
+         * plcfendRef (endnote reference position table) Written immediately
+         * after the previously recorded table if the document contains endnotes
+         * 
+         * plcfendTxt (endnote text position table) Written immediately after
+         * the plcfendRef if the document contains endnotes
+         * 
+         * Microsoft Office Word 97-2007 Binary File Format (.doc)
+         * Specification; Page 24 of 210
+         */
+        _endnotesTables.writeRef( _fib, tableStream );
+        _endnotesTables.writeTxt( _fib, tableStream );
+        tableOffset = tableStream.getOffset();
+
+    /*
+     * plcffld*** (table of field positions and statuses for annotation
+     * subdocument) Written immediately after the previously recorded table,
+     * if the ******* subdocument contains fields.
+     * 
+     * Microsoft Office Word 97-2007 Binary File Format (.doc)
+     * Specification; Page 24 of 210
+     */
+
+    if ( _fieldsTables != null )
+    {
+        _fieldsTables.write( _fib, tableStream );
+        tableOffset = tableStream.getOffset();
+    }
+
+        /*
+         * plcffndRef (footnote reference position table) Written immediately
+         * after the stsh if the document contains footnotes
+         * 
+         * plcffndTxt (footnote text position table) Written immediately after
+         * the plcffndRef if the document contains footnotes
+         * 
+         * Microsoft Office Word 97-2007 Binary File Format (.doc)
+         * Specification; Page 24 of 210
+         */
+        _footnotesTables.writeRef( _fib, tableStream );
+        _footnotesTables.writeTxt( _fib, tableStream );
+        tableOffset = tableStream.getOffset();
+
+        /*
+         * plcfsed (section table) Written immediately after the previously
+         * recorded table. Recorded in all Word documents
+         * 
+         * Microsoft Office Word 97-2007 Binary File Format (.doc)
+         * Specification; Page 25 of 210
+         */
+
     // write out the SectionTable.
     _fib.setFcPlcfsed(tableOffset);
     _st.writeTo(docSys, fcMin);
     _fib.setLcbPlcfsed(tableStream.getOffset() - tableOffset);
     tableOffset = tableStream.getOffset();
 
-        if ( _fieldsTables != null )
-        {
-            _fieldsTables.write( _fib, tableStream );
-            tableOffset = tableStream.getOffset();
-        }
+        /*
+         * plcflst (list formats) Written immediately after the end of the
+         * previously recorded, if there are any lists defined in the document.
+         * This begins with a short count of LSTF structures followed by those
+         * LSTF structures. This is immediately followed by the allocated data
+         * hanging off the LSTFs. This data consists of the array of LVLs for
+         * each LSTF. (Each LVL consists of an LVLF followed by two grpprls and
+         * an XST.)
+         * 
+         * Microsoft Office Word 97-2007 Binary File Format (.doc)
+         * Specification; Page 25 of 210
+         */
 
     // write out the list tables
     if (_lt != null)
@@ -607,7 +703,22 @@ public final class HWPFDocument extends HWPFDocumentCore
       _fib.setFcPlcfLst(tableOffset);
       _lt.writeListDataTo(tableStream);
       _fib.setLcbPlcfLst(tableStream.getOffset() - tableOffset);
+    }
+
+    /*
+     * plflfo (more list formats) Written immediately after the end of the
+     * plcflst and its accompanying data, if there are any lists defined in
+     * the document. This consists first of a PL of LFO records, followed by
+     * the allocated data (if any) hanging off the LFOs. The allocated data
+     * consists of the array of LFOLVLFs for each LFO (and each LFOLVLF is
+     * immediately followed by some LVLs).
+     * 
+     * Microsoft Office Word 97-2007 Binary File Format (.doc)
+     * Specification; Page 26 of 210
+     */
 
+    if (_lt != null)
+    {
       _fib.setFcPlfLfo(tableStream.getOffset());
       _lt.writeListOverridesTo(tableStream);
       _fib.setLcbPlfLfo(tableStream.getOffset() - tableOffset);
index a15847d6efbdc70b4bc45187b4b2bbdd19a4c572..f574d0939b105371d87fdfda4756218b370feced 100644 (file)
@@ -85,6 +85,15 @@ public final class FileInformationBlock extends FIBAbstractType
         knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLCFBKL ) );
         knownFieldSet.add( Integer.valueOf( FIBFieldHandler.STTBFBKMK ) );
 
+        // notes
+        for ( NoteType noteType : NoteType.values() )
+        {
+            knownFieldSet.add( Integer.valueOf( noteType
+                    .getFibDescriptorsFieldIndex() ) );
+            knownFieldSet.add( Integer.valueOf( noteType
+                    .getFibTextPositionsFieldIndex() ) );
+        }
+
         knownFieldSet.add( Integer.valueOf( FIBFieldHandler.STTBFFFN ) );
         knownFieldSet.add( Integer.valueOf( FIBFieldHandler.STTBFRMARK ) );
         knownFieldSet.add( Integer.valueOf( FIBFieldHandler.STTBSAVEDBY ) );
@@ -121,6 +130,24 @@ public final class FileInformationBlock extends FIBAbstractType
             stringBuilder.append( getFieldsPlcfLength( part ) );
             stringBuilder.append( "\n" );
         }
+        stringBuilder.append( "\tNotes PLCF info:\n" );
+        for ( NoteType noteType : NoteType.values() )
+        {
+            stringBuilder.append( "\t\t" );
+            stringBuilder.append( noteType );
+            stringBuilder.append( ": descriptions starts " );
+            stringBuilder.append( getNotesDescriptorsOffset( noteType ) );
+            stringBuilder.append( " and have length of " );
+            stringBuilder.append( getNotesDescriptorsSize( noteType ) );
+            stringBuilder.append( " bytes\n" );
+            stringBuilder.append( "\t\t" );
+            stringBuilder.append( noteType );
+            stringBuilder.append( ": text positions starts " );
+            stringBuilder.append( getNotesTextPositionsOffset( noteType ) );
+            stringBuilder.append( " and have length of " );
+            stringBuilder.append( getNotesTextPositionsSize( noteType ) );
+            stringBuilder.append( " bytes\n" );
+        }
         try
         {
             stringBuilder.append( "\tJava reflection info:\n" );
@@ -842,7 +869,55 @@ public final class FileInformationBlock extends FIBAbstractType
         return _fieldHandler.getFieldSize(FIBFieldHandler.DGGINFO);
     }
 
-    public void writeTo (byte[] mainStream, HWPFOutputStream tableStream)
+    public int getNotesDescriptorsOffset( NoteType noteType )
+    {
+        return _fieldHandler.getFieldOffset( noteType
+                .getFibDescriptorsFieldIndex() );
+    }
+
+    public void setNotesDescriptorsOffset( NoteType noteType, int offset )
+    {
+        _fieldHandler.setFieldOffset( noteType.getFibDescriptorsFieldIndex(),
+                offset );
+    }
+
+    public int getNotesDescriptorsSize( NoteType noteType )
+    {
+        return _fieldHandler.getFieldSize( noteType
+                .getFibDescriptorsFieldIndex() );
+    }
+
+    public void setNotesDescriptorsSize( NoteType noteType, int offset )
+    {
+        _fieldHandler.setFieldSize( noteType.getFibDescriptorsFieldIndex(),
+                offset );
+    }
+
+    public int getNotesTextPositionsOffset( NoteType noteType )
+    {
+        return _fieldHandler.getFieldOffset( noteType
+                .getFibTextPositionsFieldIndex() );
+    }
+
+    public void setNotesTextPositionsOffset( NoteType noteType, int offset )
+    {
+        _fieldHandler.setFieldOffset( noteType.getFibTextPositionsFieldIndex(),
+                offset );
+    }
+
+    public int getNotesTextPositionsSize( NoteType noteType )
+    {
+        return _fieldHandler.getFieldSize( noteType
+                .getFibTextPositionsFieldIndex() );
+    }
+
+    public void setNotesTextPositionsSize( NoteType noteType, int offset )
+    {
+        _fieldHandler.setFieldSize( noteType.getFibTextPositionsFieldIndex(),
+                offset );
+    }
+
+    public void writeTo( byte[] mainStream, HWPFOutputStream tableStream)
       throws IOException
     {
       //HWPFOutputStream mainDocument = sys.getStream("WordDocument");
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/FootnoteReferenceDescriptor.java b/src/scratchpad/src/org/apache/poi/hwpf/model/FootnoteReferenceDescriptor.java
new file mode 100644 (file)
index 0000000..73f6103
--- /dev/null
@@ -0,0 +1,83 @@
+/* ====================================================================
+   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.hwpf.model;
+
+import org.apache.poi.hwpf.model.types.FRDAbstractType;
+
+public final class FootnoteReferenceDescriptor extends FRDAbstractType
+        implements Cloneable
+{
+    public FootnoteReferenceDescriptor()
+    {
+    }
+
+    public FootnoteReferenceDescriptor( byte[] data, int offset )
+    {
+        fillFields( data, offset );
+    }
+
+    @Override
+    protected FootnoteReferenceDescriptor clone()
+    {
+        try
+        {
+            return (FootnoteReferenceDescriptor) super.clone();
+        }
+        catch ( CloneNotSupportedException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        if ( this == obj )
+            return true;
+        if ( obj == null )
+            return false;
+        if ( getClass() != obj.getClass() )
+            return false;
+        FootnoteReferenceDescriptor other = (FootnoteReferenceDescriptor) obj;
+        if ( field_1_nAuto != other.field_1_nAuto )
+            return false;
+        return true;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + field_1_nAuto;
+        return result;
+    }
+
+    public boolean isEmpty()
+    {
+        return field_1_nAuto == 0;
+    }
+
+    @Override
+    public String toString()
+    {
+        if ( isEmpty() )
+            return "[FRD] EMPTY";
+
+        return super.toString();
+    }
+}
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/NoteType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/NoteType.java
new file mode 100644 (file)
index 0000000..2c43337
--- /dev/null
@@ -0,0 +1,51 @@
+/* ====================================================================
+   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.
+==================================================================== */
+
+/**
+ * Word document notes types (and their FIB field indices)
+ * 
+ * @author Sergey Vladimirov (vlsergey {at} gmail {doc} com)
+ */
+package org.apache.poi.hwpf.model;
+
+public enum NoteType {
+    /** Ending note */
+    ENDNOTE( FIBFieldHandler.PLCFENDREF, FIBFieldHandler.PLCFENDTXT ),
+
+    /** Footnote */
+    FOOTNOTE( FIBFieldHandler.PLCFFNDREF, FIBFieldHandler.PLCFFNDTXT );
+
+    private final int fibDescriptorsFieldIndex;
+    private final int fibTextPositionsFieldIndex;
+
+    private NoteType( int fibDescriptorsFieldIndex,
+            int fibTextPositionsFieldIndex )
+    {
+        this.fibDescriptorsFieldIndex = fibDescriptorsFieldIndex;
+        this.fibTextPositionsFieldIndex = fibTextPositionsFieldIndex;
+    }
+
+    public int getFibDescriptorsFieldIndex()
+    {
+        return fibDescriptorsFieldIndex;
+    }
+
+    public int getFibTextPositionsFieldIndex()
+    {
+        return fibTextPositionsFieldIndex;
+    }
+}
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/NotesTables.java b/src/scratchpad/src/org/apache/poi/hwpf/model/NotesTables.java
new file mode 100644 (file)
index 0000000..21f5ba3
--- /dev/null
@@ -0,0 +1,118 @@
+/* ====================================================================
+   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.hwpf.model;
+
+import java.io.IOException;
+
+import org.apache.poi.hwpf.model.io.HWPFOutputStream;
+
+/**
+ * Holds information about document notes (footnotes or ending notes)
+ * 
+ * @author Sergey Vladimirov (vlsergey {at} gmail {doc} com)
+ */
+public class NotesTables
+{
+    private PlexOfCps descriptors = new PlexOfCps(
+            FootnoteReferenceDescriptor.getSize() );
+
+    private final NoteType noteType;
+
+    private PlexOfCps textPositions = new PlexOfCps( 0 );
+
+    public NotesTables( final NoteType noteType )
+    {
+        this.noteType = noteType;
+        textPositions
+                .addProperty( new GenericPropertyNode( 0, 1, new byte[0] ) );
+    }
+
+    public NotesTables( final NoteType noteType, byte[] tableStream,
+            FileInformationBlock fib )
+    {
+        this.noteType = noteType;
+        read( tableStream, fib );
+    }
+
+    public GenericPropertyNode getDescriptor( int index )
+    {
+        return descriptors.getProperty( index );
+    }
+
+    public int getDescriptorsCount()
+    {
+        return descriptors.length();
+    }
+
+    public GenericPropertyNode getTextPosition( int index )
+    {
+        return textPositions.getProperty( index );
+    }
+
+    private void read( byte[] tableStream, FileInformationBlock fib )
+    {
+        int referencesStart = fib.getNotesDescriptorsOffset( noteType );
+        int referencesLength = fib.getNotesDescriptorsSize( noteType );
+
+        if ( referencesStart != 0 && referencesLength != 0 )
+            this.descriptors = new PlexOfCps( tableStream, referencesStart,
+                    referencesLength, FootnoteReferenceDescriptor.getSize() );
+
+        int textPositionsStart = fib.getNotesTextPositionsOffset( noteType );
+        int textPositionsLength = fib.getNotesTextPositionsSize( noteType );
+
+        if ( textPositionsStart != 0 && textPositionsLength != 0 )
+            this.textPositions = new PlexOfCps( tableStream,
+                    textPositionsStart, textPositionsLength, 0 );
+    }
+
+    public void writeRef( FileInformationBlock fib, HWPFOutputStream tableStream )
+            throws IOException
+    {
+        if ( descriptors == null || descriptors.length() == 0 )
+        {
+            fib.setNotesDescriptorsOffset( noteType, 0 );
+            fib.setNotesDescriptorsSize( noteType, 0 );
+            return;
+        }
+
+        int start = tableStream.getOffset();
+        tableStream.write( descriptors.toByteArray() );
+        int end = tableStream.getOffset();
+
+        fib.setNotesDescriptorsOffset( noteType, start );
+        fib.setNotesDescriptorsSize( noteType, end - start );
+    }
+
+    public void writeTxt( FileInformationBlock fib, HWPFOutputStream tableStream )
+            throws IOException
+    {
+        if ( textPositions == null || textPositions.length() == 0 )
+        {
+            fib.setNotesTextPositionsOffset( noteType, 0 );
+            fib.setNotesTextPositionsSize( noteType, 0 );
+            return;
+        }
+
+        int start = tableStream.getOffset();
+        tableStream.write( textPositions.toByteArray() );
+        int end = tableStream.getOffset();
+
+        fib.setNotesTextPositionsOffset( noteType, start );
+        fib.setNotesTextPositionsSize( noteType, end - start );
+    }
+}
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/FRDAbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/FRDAbstractType.java
new file mode 100644 (file)
index 0000000..8ee32e7
--- /dev/null
@@ -0,0 +1,89 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
+package org.apache.poi.hwpf.model.types;\r
+\r
+import org.apache.poi.util.LittleEndian;\r
+\r
+/**\r
+ * Footnote Reference Descriptor (FRD).\r
+ * <p>\r
+ * Class and fields descriptions are quoted from Microsoft Office Word 97-2007\r
+ * Binary File Format (.doc) Specification\r
+ * \r
+ * NOTE: This source is automatically generated please do not modify this file.\r
+ * Either subclass or remove the record in src/types/definitions.\r
+ * \r
+ * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary\r
+ *         File Format (.doc) Specification\r
+ */\r
+public abstract class FRDAbstractType\r
+{\r
+\r
+    protected short field_1_nAuto;\r
+\r
+    protected FRDAbstractType()\r
+    {\r
+    }\r
+\r
+    protected void fillFields( byte[] data, int offset )\r
+    {\r
+        field_1_nAuto = LittleEndian.getShort( data, 0x0 + offset );\r
+    }\r
+\r
+    public void serialize( byte[] data, int offset )\r
+    {\r
+        LittleEndian.putShort( data, 0x0 + offset, field_1_nAuto );\r
+    }\r
+\r
+    /**\r
+     * Size of record\r
+     */\r
+    public static int getSize()\r
+    {\r
+        return 0 + 2;\r
+    }\r
+\r
+    public String toString()\r
+    {\r
+        StringBuilder builder = new StringBuilder();\r
+        builder.append( "[FRD]\n" );\r
+        builder.append( "    .nAuto                = " );\r
+        builder.append( " (" ).append( getNAuto() ).append( " )\n" );\r
+\r
+        builder.append( "[/FRD]\n" );\r
+        return builder.toString();\r
+    }\r
+\r
+    /**\r
+     * If > 0, the note is an automatically numbered note, otherwise it has a\r
+     * custom mark.\r
+     */\r
+    public short getNAuto()\r
+    {\r
+        return field_1_nAuto;\r
+    }\r
+\r
+    /**\r
+     * If > 0, the note is an automatically numbered note, otherwise it has a\r
+     * custom mark.\r
+     */\r
+    public void setNAuto( short field_1_nAuto )\r
+    {\r
+        this.field_1_nAuto = field_1_nAuto;\r
+    }\r
+\r
+} // END OF CLASS\r
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Notes.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Notes.java
new file mode 100644 (file)
index 0000000..68ffd02
--- /dev/null
@@ -0,0 +1,47 @@
+/* ====================================================================
+   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.hwpf.usermodel;
+
+/**
+ * User-friendly interface to access document notes information
+ * 
+ * @author Sergey Vladimirov (vlsergey {at} gmail {doc} com)
+ */
+public interface Notes
+{
+    /**
+     * Returns the location of note anchor in main textspace
+     */
+    int getNoteAnchorPosition( int index );
+
+    /**
+     * Returns count of notes in document
+     */
+    int getNotesCount();
+
+    /**
+     * Returns the end offset of the text corresponding to the reference within
+     * the footnote text address space
+     */
+    int getNoteTextEndOffset( int index );
+
+    /**
+     * Returns the start offset of the text corresponding to the reference
+     * within the footnote text address space
+     */
+    int getNoteTextStartOffset( int index );
+}
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/NotesImpl.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/NotesImpl.java
new file mode 100644 (file)
index 0000000..a5710e2
--- /dev/null
@@ -0,0 +1,54 @@
+/* ====================================================================
+   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.hwpf.usermodel;
+
+import org.apache.poi.hwpf.model.NotesTables;
+
+/**
+ * Default implementation of {@link Notes} interface
+ * 
+ * @author Sergey Vladimirov (vlsergey {at} gmail {doc} com)
+ */
+public class NotesImpl implements Notes
+{
+    private final NotesTables notesTables;
+
+    public NotesImpl( NotesTables notesTables )
+    {
+        this.notesTables = notesTables;
+    }
+
+    public int getNoteAnchorPosition( int index )
+    {
+        return notesTables.getDescriptor( index ).getStart();
+    }
+
+    public int getNotesCount()
+    {
+        return notesTables.getDescriptorsCount();
+    }
+
+    public int getNoteTextEndOffset( int index )
+    {
+        return notesTables.getTextPosition( index ).getEnd();
+    }
+
+    public int getNoteTextStartOffset( int index )
+    {
+        return notesTables.getTextPosition( index ).getStart();
+    }
+}
index 0a72d7603136fcc0d4136d3789c4324191d18406..a488fe3391714ed7902d99cd07202b833ca7ccbb 100644 (file)
@@ -31,6 +31,7 @@ import org.apache.poi.hwpf.model.TestDocumentProperties;
 import org.apache.poi.hwpf.model.TestFileInformationBlock;
 import org.apache.poi.hwpf.model.TestFontTable;
 import org.apache.poi.hwpf.model.TestListTables;
+import org.apache.poi.hwpf.model.TestNotesTables;
 import org.apache.poi.hwpf.model.TestPAPBinTable;
 import org.apache.poi.hwpf.model.TestPlexOfCps;
 import org.apache.poi.hwpf.model.TestRevisionMarkAuthorTable;
@@ -86,6 +87,7 @@ public final class AllHWPFTests
         suite.addTestSuite( TestFileInformationBlock.class );
         suite.addTestSuite( TestFontTable.class );
         suite.addTestSuite( TestListTables.class );
+        suite.addTestSuite( TestNotesTables.class );
         suite.addTestSuite( TestPAPBinTable.class );
         suite.addTestSuite( TestPlexOfCps.class );
         suite.addTestSuite( TestRevisionMarkAuthorTable.class );
index 175be9058e071f84cae33e83b9c94538d42ffb61..7c557affcdaed640b85577eea3520b0ca93549a5 100644 (file)
@@ -141,6 +141,15 @@ public class TestWordToHtmlConverter extends TestCase
         assertContains( result, substring );
     }
 
+    public void testEndnote() throws Exception
+    {
+        String result = getHtmlText( "endingnote.doc" );
+
+        assertContains( result, "<a href=\"#userref\">" );
+        assertContains( result, "<a name=\"userref\">" );
+        assertContains( result, "1" );
+    }
+
     public void testEquation() throws Exception
     {
         String result = getHtmlText( "equation.doc" );
diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/model/TestNotesTables.java b/src/scratchpad/testcases/org/apache/poi/hwpf/model/TestNotesTables.java
new file mode 100644 (file)
index 0000000..4679d24
--- /dev/null
@@ -0,0 +1,45 @@
+/* ====================================================================
+   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.hwpf.model;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.hwpf.HWPFDocument;
+import org.apache.poi.hwpf.HWPFTestDataSamples;
+import org.apache.poi.hwpf.usermodel.Notes;
+
+/**
+ * Test cases for {@link NotesTables} and default implementation of
+ * {@link Notes}
+ * 
+ * @author Sergey Vladimirov (vlsergey {at} gmail {dot} com)
+ */
+public class TestNotesTables extends TestCase
+{
+    public void test()
+    {
+        HWPFDocument doc = HWPFTestDataSamples
+                .openSampleFile( "endingnote.doc" );
+        Notes notes = doc.getEndnotes();
+
+        assertEquals( 1, notes.getNotesCount() );
+
+        assertEquals( 10, notes.getNoteAnchorPosition( 0 ) );
+        assertEquals( 0, notes.getNoteTextStartOffset( 0 ) );
+        assertEquals( 19, notes.getNoteTextEndOffset( 0 ) );
+    }
+}
diff --git a/src/types/definitions/frd_type.xml b/src/types/definitions/frd_type.xml
new file mode 100644 (file)
index 0000000..a447413
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<!--
+    ====================================================================
+    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.
+    ====================================================================
+-->
+<record fromfile="true" name="FRD" package="org.apache.poi.hwpf.model.types">
+    <suffix>AbstractType</suffix>
+    <extends>HDFType</extends>
+    <description>Footnote Reference Descriptor (FRD). &lt;p&gt;Class and fields descriptions are
+        quoted from Microsoft Office Word 97-2007 Binary File Format (.doc) Specification
+    </description>
+    <author>Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary File Format (.doc)
+        Specification
+    </author>
+    <fields>
+        <field type="short" size="2" name="nAuto"
+            description="If > 0, the note is an automatically numbered note, otherwise it has a custom mark"/>
+    </fields>
+</record>
diff --git a/test-data/document/endingnote.doc b/test-data/document/endingnote.doc
new file mode 100644 (file)
index 0000000..92c6780
Binary files /dev/null and b/test-data/document/endingnote.doc differ