From fbdcb0329d7a9b4958befaa8d840ab9304d7de35 Mon Sep 17 00:00:00 2001 From: Sergey Vladimirov Date: Tue, 19 Jul 2011 12:51:11 +0000 Subject: [PATCH] introduce SubdocumentPart and simplify CP start/end FIB API git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1148303 13f79535-47bb-0310-9956-ffa450edef68 --- .../src/org/apache/poi/hwpf/HWPFDocument.java | 7 +- .../hwpf/converter/AbstractWordConverter.java | 6 +- .../org/apache/poi/hwpf/dev/HWPFLister.java | 5 +- .../poi/hwpf/model/CPSplitCalculator.java | 1 + .../apache/poi/hwpf/model/FIBLongHandler.java | 22 +- ...umentPart.java => FieldsDocumentPart.java} | 18 +- .../apache/poi/hwpf/model/FieldsTables.java | 271 +++++++++--------- .../poi/hwpf/model/FileInformationBlock.java | 133 ++++++++- .../poi/hwpf/model/SubdocumentType.java | 45 +++ .../poi/hwpf/usermodel/HeaderStories.java | 13 +- .../org/apache/poi/hwpf/usermodel/Range.java | 108 ++++--- .../org/apache/poi/hwpf/TestFieldsTables.java | 6 +- .../poi/hwpf/usermodel/TestProblems.java | 6 +- 13 files changed, 423 insertions(+), 218 deletions(-) rename src/scratchpad/src/org/apache/poi/hwpf/model/{DocumentPart.java => FieldsDocumentPart.java} (72%) create mode 100644 src/scratchpad/src/org/apache/poi/hwpf/model/SubdocumentType.java diff --git a/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java b/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java index e317b24fc8..7bcfd98328 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java @@ -42,6 +42,7 @@ import org.apache.poi.hwpf.model.SavedByTable; import org.apache.poi.hwpf.model.SectionTable; import org.apache.poi.hwpf.model.ShapesTable; import org.apache.poi.hwpf.model.StyleSheet; +import org.apache.poi.hwpf.model.SubdocumentType; import org.apache.poi.hwpf.model.TextPiece; import org.apache.poi.hwpf.model.TextPieceTable; import org.apache.poi.hwpf.model.io.HWPFFileSystem; @@ -64,6 +65,7 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem; public final class HWPFDocument extends HWPFDocumentCore { /** And for making sense of CP lengths in the FIB */ + @Deprecated protected CPSplitCalculator _cpSplit; /** table stream buffer*/ @@ -268,6 +270,7 @@ public final class HWPFDocument extends HWPFDocumentCore return _cft.getTextPieceTable(); } + @Deprecated public CPSplitCalculator getCPSplitCalculator() { return _cpSplit; @@ -319,7 +322,9 @@ public final class HWPFDocument extends HWPFDocumentCore int bytesStart = getFileInformationBlock().getFcMin(); int charsStart = getTextTable().getCharIndex( bytesStart ); - int charsEnd = charsStart + getFileInformationBlock().getCcpText(); + int charsEnd = charsStart + + getFileInformationBlock().getSubdocumentTextStreamLength( + SubdocumentType.MAIN ); return new Range( charsStart, charsEnd, this ); } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordConverter.java b/src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordConverter.java index 236ac67ebd..61daedff82 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordConverter.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordConverter.java @@ -23,7 +23,7 @@ import org.apache.poi.hpsf.SummaryInformation; import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.HWPFDocumentCore; import org.apache.poi.hwpf.converter.FontReplacer.Triplet; -import org.apache.poi.hwpf.model.DocumentPart; +import org.apache.poi.hwpf.model.FieldsDocumentPart; import org.apache.poi.hwpf.model.Field; import org.apache.poi.hwpf.model.ListFormatOverride; import org.apache.poi.hwpf.model.ListTables; @@ -111,7 +111,7 @@ public abstract class AbstractWordConverter { Field aliveField = ( (HWPFDocument) hwpfDocument ) .getFieldsTables().lookupFieldByStartOffset( - DocumentPart.MAIN, + FieldsDocumentPart.MAIN, characterRun.getStartOffset() ); if ( aliveField != null ) { @@ -309,7 +309,7 @@ public abstract class AbstractWordConverter HWPFDocument hwpfDocument = (HWPFDocument) wordDocument; Field field = hwpfDocument.getFieldsTables().lookupFieldByStartOffset( - DocumentPart.MAIN, startOffset ); + FieldsDocumentPart.MAIN, startOffset ); if ( field == null ) return null; diff --git a/src/scratchpad/src/org/apache/poi/hwpf/dev/HWPFLister.java b/src/scratchpad/src/org/apache/poi/hwpf/dev/HWPFLister.java index 1c25535427..2622449fbe 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/dev/HWPFLister.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/dev/HWPFLister.java @@ -36,7 +36,7 @@ import org.apache.poi.hwpf.HWPFDocumentCore; import org.apache.poi.hwpf.HWPFOldDocument; import org.apache.poi.hwpf.OldWordFileFormatException; import org.apache.poi.hwpf.model.CHPX; -import org.apache.poi.hwpf.model.DocumentPart; +import org.apache.poi.hwpf.model.FieldsDocumentPart; import org.apache.poi.hwpf.model.FileInformationBlock; import org.apache.poi.hwpf.model.GenericPropertyNode; import org.apache.poi.hwpf.model.PAPFormattedDiskPage; @@ -315,6 +315,7 @@ public final class HWPFLister { FileInformationBlock fib = _doc.getFileInformationBlock(); System.out.println( fib ); + } private void dumpFields() @@ -327,7 +328,7 @@ public final class HWPFLister HWPFDocument document = (HWPFDocument) _doc; - for ( DocumentPart part : DocumentPart.values() ) + for ( FieldsDocumentPart part : FieldsDocumentPart.values() ) { System.out.println( "=== Document part: " + part + " ===" ); for ( org.apache.poi.hwpf.model.Field field : document diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/CPSplitCalculator.java b/src/scratchpad/src/org/apache/poi/hwpf/model/CPSplitCalculator.java index 225fc1c333..3ad722cb71 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/CPSplitCalculator.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/CPSplitCalculator.java @@ -24,6 +24,7 @@ import org.apache.poi.hwpf.HWPFDocument; * where different kinds of text can be found within the * overall CP splurge. */ +@Deprecated public final class CPSplitCalculator { private FileInformationBlock fib; public CPSplitCalculator(FileInformationBlock fib) { diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/FIBLongHandler.java b/src/scratchpad/src/org/apache/poi/hwpf/model/FIBLongHandler.java index ef51961c86..1578bb8eef 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/FIBLongHandler.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/FIBLongHandler.java @@ -29,34 +29,54 @@ public final class FIBLongHandler { public static final int PRODUCTREVISED = 2; /** * Pointer to length of main document text stream 1 + * + * @since Word 97 */ public static final int CCPTEXT = 3; /** * Pointer to length of footnote subdocument text stream + * + * @since Word 97 */ public static final int CCPFTN = 4; /** * Pointer to length of header subdocument text stream + * + * @since Word 97 */ public static final int CCPHDD = 5; /** * Pointer to length of macro subdocument text stream, which should now * always be 0 + * + * @since Word 97 */ public static final int CCPMCR = 6; /** * Pointer to length of annotation subdocument text stream + * + * @since Word 97 */ public static final int CCPATN = 7; /** * Pointer to length of endnote subdocument text stream + * + * @since Word 97 */ public static final int CCPEDN = 8; /** * Pointer to length of textbox subdocument text stream + * + * @since Word 97 */ public static final int CCPTXBX = 9; - public static final int CCPHDRTXBX = 10; + + /** + * Length of header textbox subdocument text stream + * + * @since Word 97 + */ + public static final int CCPHDRTXBX = 10; public static final int PNFBPCHPFIRST = 11; public static final int PNCHPFIRST = 12; public static final int CPNBTECHP = 13; diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/DocumentPart.java b/src/scratchpad/src/org/apache/poi/hwpf/model/FieldsDocumentPart.java similarity index 72% rename from src/scratchpad/src/org/apache/poi/hwpf/model/DocumentPart.java rename to src/scratchpad/src/org/apache/poi/hwpf/model/FieldsDocumentPart.java index 90bfa1b1f5..f2e654cf76 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/DocumentPart.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/FieldsDocumentPart.java @@ -1,46 +1,52 @@ package org.apache.poi.hwpf.model; -public enum DocumentPart { +public enum FieldsDocumentPart { /** * annotation subdocument */ ANNOTATIONS( FIBFieldHandler.PLCFFLDATN ), + /** * endnote subdocument */ ENDNOTES( FIBFieldHandler.PLCFFLDEDN ), + /** * footnote subdocument */ FOOTNOTES( FIBFieldHandler.PLCFFLDFTN ), + /** * header subdocument */ HEADER( FIBFieldHandler.PLCFFLDHDR ), + /** * header textbox subdoc */ HEADER_TEXTBOX( FIBFieldHandler.PLCFFLDHDRTXBX ), + /** * main document */ MAIN( FIBFieldHandler.PLCFFLDMOM ), + /** * textbox subdoc */ TEXTBOX( FIBFieldHandler.PLCFFLDTXBX ); - private final int fibHandlerFieldsField; + private final int fibFieldsField; - private DocumentPart( final int fibHandlerField ) + private FieldsDocumentPart( final int fibHandlerField ) { - this.fibHandlerFieldsField = fibHandlerField; + this.fibFieldsField = fibHandlerField; } - public int getFibHandlerFieldsPosition() + public int getFibFieldsField() { - return fibHandlerFieldsField; + return fibFieldsField; } } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/FieldsTables.java b/src/scratchpad/src/org/apache/poi/hwpf/model/FieldsTables.java index 74f394ea2c..2c2b766a03 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/FieldsTables.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/FieldsTables.java @@ -39,24 +39,15 @@ import org.apache.poi.hwpf.model.io.HWPFOutputStream; */ public class FieldsTables { - private static final class GenericPropertyNodeComparator implements - Comparator - { - public int compare( GenericPropertyNode o1, GenericPropertyNode o2 ) - { - int thisVal = o1.getStart(); - int anotherVal = o2.getStart(); - return thisVal < anotherVal ? -1 : thisVal == anotherVal ? 0 : 1; - } - } - - private GenericPropertyNodeComparator comparator = new GenericPropertyNodeComparator(); + // The size in bytes of the FLD data structure + private static final int FLD_SIZE = 2; /** * annotation subdocument */ @Deprecated public static final int PLCFFLDATN = 0; + /** * endnote subdocument */ @@ -88,33 +79,135 @@ public class FieldsTables @Deprecated public static final int PLCFFLDTXBX = 6; - // The size in bytes of the FLD data structure - private static final int FLD_SIZE = 2; + /** + * This is port and adaptation of Arrays.binarySearch from Java 6 (Apache + * Harmony). + */ + private static int binarySearch( GenericPropertyNode[] array, + int startIndex, int endIndex, int requiredStartOffset ) + { + checkIndexForBinarySearch( array.length, startIndex, endIndex ); - private Map _tables; - private Map> _fieldsByOffset; + int low = startIndex, mid = -1, high = endIndex - 1, result = 0; + while ( low <= high ) + { + mid = ( low + high ) >>> 1; + int midStart = array[mid].getStart(); + + if ( midStart == requiredStartOffset ) + { + return mid; + } + else if ( midStart < requiredStartOffset ) + { + low = mid + 1; + } + else + { + high = mid - 1; + } + } + if ( mid < 0 ) + { + int insertPoint = endIndex; + for ( int index = startIndex; index < endIndex; index++ ) + { + if ( requiredStartOffset < array[index].getStart() ) + { + insertPoint = index; + } + } + return -insertPoint - 1; + } + return -mid - ( result >= 0 ? 1 : 2 ); + } + + private static void checkIndexForBinarySearch( int length, int start, + int end ) + { + if ( start > end ) + { + throw new IllegalArgumentException(); + } + if ( length < end || 0 > start ) + { + throw new ArrayIndexOutOfBoundsException(); + } + } + + private static ArrayList toArrayList( PlexOfCps plexOfCps ) + { + if ( plexOfCps == null ) + return new ArrayList(); + + ArrayList fields = new ArrayList(); + fields.ensureCapacity( plexOfCps.length() ); + + for ( int i = 0; i < plexOfCps.length(); i++ ) + { + GenericPropertyNode propNode = plexOfCps.getProperty( i ); + PlexOfField plex = new PlexOfField( propNode ); + fields.add( plex ); + } + + return fields; + } + + private Map> _fieldsByOffset; + + private Map _tables; + + private GenericPropertyNodeComparator comparator = new GenericPropertyNodeComparator(); public FieldsTables( byte[] tableStream, FileInformationBlock fib ) { - _tables = new HashMap( - DocumentPart.values().length ); - _fieldsByOffset = new HashMap>( - DocumentPart.values().length ); + _tables = new HashMap( + FieldsDocumentPart.values().length ); + _fieldsByOffset = new HashMap>( + FieldsDocumentPart.values().length ); - for ( DocumentPart documentPart : DocumentPart.values() ) + for ( FieldsDocumentPart part : FieldsDocumentPart.values() ) { - final PlexOfCps plexOfCps = readPLCF( tableStream, fib, - documentPart ); + final PlexOfCps plexOfCps = readPLCF( tableStream, fib, part ); - _fieldsByOffset - .put( documentPart, parseFieldStructure( plexOfCps ) ); - _tables.put( documentPart, plexOfCps ); + _fieldsByOffset.put( part, parseFieldStructure( plexOfCps ) ); + _tables.put( part, plexOfCps ); } } + public Collection getFields( FieldsDocumentPart part ) + { + Map map = _fieldsByOffset.get( part ); + if ( map == null || map.isEmpty() ) + return Collections.emptySet(); + + return Collections.unmodifiableCollection( map.values() ); + } + + public ArrayList getFieldsPLCF( FieldsDocumentPart part ) + { + return toArrayList( _tables.get( part ) ); + } + + @Deprecated + public ArrayList getFieldsPLCF( int partIndex ) + { + return getFieldsPLCF( FieldsDocumentPart.values()[partIndex] ); + } + + public Field lookupFieldByStartOffset( FieldsDocumentPart documentPart, + int offset ) + { + Map map = _fieldsByOffset.get( documentPart ); + if ( map == null || map.isEmpty() ) + return null; + + return map.get( Integer.valueOf( offset ) ); + } + private Map parseFieldStructure( PlexOfCps plexOfCps ) { - if (plexOfCps == null) + if ( plexOfCps == null ) return new HashMap(); GenericPropertyNode[] nodes = plexOfCps.toPropertiesArray(); @@ -242,73 +335,8 @@ public class FieldsTables } } - /** - * This is port and adaptation of Arrays.binarySearch from Java 6 (Apache - * Harmony). - */ - private static int binarySearch( GenericPropertyNode[] array, - int startIndex, int endIndex, int requiredStartOffset ) - { - checkIndexForBinarySearch( array.length, startIndex, endIndex ); - - int low = startIndex, mid = -1, high = endIndex - 1, result = 0; - while ( low <= high ) - { - mid = ( low + high ) >>> 1; - int midStart = array[mid].getStart(); - - if ( midStart == requiredStartOffset ) - { - return mid; - } - else if ( midStart < requiredStartOffset ) - { - low = mid + 1; - } - else - { - high = mid - 1; - } - } - if ( mid < 0 ) - { - int insertPoint = endIndex; - for ( int index = startIndex; index < endIndex; index++ ) - { - if ( requiredStartOffset < array[index].getStart() ) - { - insertPoint = index; - } - } - return -insertPoint - 1; - } - return -mid - ( result >= 0 ? 1 : 2 ); - } - - private static void checkIndexForBinarySearch( int length, int start, - int end ) - { - if ( start > end ) - { - throw new IllegalArgumentException(); - } - if ( length < end || 0 > start ) - { - throw new ArrayIndexOutOfBoundsException(); - } - } - - public Field lookupFieldByStartOffset( DocumentPart documentPart, int offset ) - { - Map map = _fieldsByOffset.get( documentPart); - if ( map == null || map.isEmpty() ) - return null; - - return map.get( Integer.valueOf( offset ) ); - } - private PlexOfCps readPLCF( byte[] tableStream, FileInformationBlock fib, - DocumentPart documentPart ) + FieldsDocumentPart documentPart ) { int start = fib.getFieldsPlcfOffset( documentPart ); int length = fib.getFieldsPlcfLength( documentPart ); @@ -319,45 +347,7 @@ public class FieldsTables return new PlexOfCps( tableStream, start, length, FLD_SIZE ); } - public Collection getFields( DocumentPart part ) - { - Map map = _fieldsByOffset.get( part ); - if ( map == null || map.isEmpty() ) - return Collections.emptySet(); - - return Collections.unmodifiableCollection( map.values() ); - } - - @Deprecated - public ArrayList getFieldsPLCF( int partIndex ) - { - return getFieldsPLCF( DocumentPart.values()[partIndex] ); - } - - public ArrayList getFieldsPLCF( DocumentPart documentPart ) - { - return toArrayList( _tables.get( documentPart ) ); - } - - private static ArrayList toArrayList( PlexOfCps plexOfCps ) - { - if ( plexOfCps == null ) - return new ArrayList(); - - ArrayList fields = new ArrayList(); - fields.ensureCapacity( plexOfCps.length() ); - - for ( int i = 0; i < plexOfCps.length(); i++ ) - { - GenericPropertyNode propNode = plexOfCps.getProperty( i ); - PlexOfField plex = new PlexOfField( propNode ); - fields.add( plex ); - } - - return fields; - } - - private int savePlex( FileInformationBlock fib, DocumentPart documentPart, + private int savePlex( FileInformationBlock fib, FieldsDocumentPart part, PlexOfCps plexOfCps, HWPFOutputStream outputStream ) throws IOException { @@ -371,8 +361,8 @@ public class FieldsTables outputStream.write( data ); - fib.setFieldsPlcfOffset( documentPart, start ); - fib.setFieldsPlcfLength( documentPart, length ); + fib.setFieldsPlcfOffset( part, start ); + fib.setFieldsPlcfLength( part, length ); return length; } @@ -380,10 +370,21 @@ public class FieldsTables public void write( FileInformationBlock fib, HWPFOutputStream tableStream ) throws IOException { - for ( DocumentPart part : DocumentPart.values() ) + for ( FieldsDocumentPart part : FieldsDocumentPart.values() ) { PlexOfCps plexOfCps = _tables.get( part ); savePlex( fib, part, plexOfCps, tableStream ); } } + + private static final class GenericPropertyNodeComparator implements + Comparator + { + public int compare( GenericPropertyNode o1, GenericPropertyNode o2 ) + { + int thisVal = o1.getStart(); + int anotherVal = o2.getStart(); + return thisVal < anotherVal ? -1 : thisVal == anotherVal ? 0 : 1; + } + } } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java b/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java index 10254158a2..d5d9c5046d 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java @@ -18,6 +18,8 @@ package org.apache.poi.hwpf.model; import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.HashSet; import org.apache.poi.hwpf.model.io.HWPFOutputStream; @@ -84,6 +86,56 @@ public final class FileInformationBlock extends FIBAbstractType tableStream, fieldSet, true); } + @Override + public String toString() + { + StringBuilder stringBuilder = new StringBuilder( super.toString() ); + stringBuilder.append( "[FIB2]\n" ); + stringBuilder.append( "\tSubdocuments info:\n" ); + for ( SubdocumentType type : SubdocumentType.values() ) + { + stringBuilder.append( "\t\t" ); + stringBuilder.append( type ); + stringBuilder.append( " has length of " ); + stringBuilder.append( getSubdocumentTextStreamLength( type ) ); + stringBuilder.append( " char(s)\n" ); + } + stringBuilder.append( "\tFields PLCF info:\n" ); + for ( FieldsDocumentPart part : FieldsDocumentPart.values() ) + { + stringBuilder.append( "\t\t" ); + stringBuilder.append( part ); + stringBuilder.append( ": PLCF starts at " ); + stringBuilder.append( getFieldsPlcfOffset( part ) ); + stringBuilder.append( " and have length of " ); + stringBuilder.append( getFieldsPlcfLength( part ) ); + stringBuilder.append( "\n" ); + } + try + { + stringBuilder.append( "\tJava reflection info:\n" ); + for ( Method method : FileInformationBlock.class.getMethods() ) + { + if ( !method.getName().startsWith( "get" ) + || !Modifier.isPublic( method.getModifiers() ) + || Modifier.isStatic( method.getModifiers() ) + || method.getParameterTypes().length > 0 ) + continue; + stringBuilder.append( "\t\t" ); + stringBuilder.append( method.getName() ); + stringBuilder.append( " => " ); + stringBuilder.append( method.invoke( this ) ); + stringBuilder.append( "\n" ); + } + } + catch ( Exception exc ) + { + stringBuilder.append( "(exc: " + exc.getMessage() + ")" ); + } + stringBuilder.append( "[/FIB2]\n" ); + return stringBuilder.toString(); + } + public int getFcDop() { return _fieldHandler.getFieldOffset(FIBFieldHandler.DOP); @@ -344,14 +396,14 @@ public final class FileInformationBlock extends FIBAbstractType { _fieldHandler.setFieldSize(FIBFieldHandler.PLFLFO, modifiedHigh); } - - + /** * How many bytes of the main stream contain real data. */ public int getCbMac() { return _longHandler.getLong(FIBLongHandler.CBMAC); } + /** * Updates the count of the number of bytes in the * main stream which contain real data @@ -360,15 +412,30 @@ public final class FileInformationBlock extends FIBAbstractType _longHandler.setLong(FIBLongHandler.CBMAC, cbMac); } + /** + * @return length of specified subdocument text stream in characters + */ + public int getSubdocumentTextStreamLength( SubdocumentType type ) + { + return _longHandler.getLong( type.getFibLongFieldIndex() ); + } + + public void setSubdocumentTextStreamLength( SubdocumentType type, int length ) + { + _longHandler.setLong( type.getFibLongFieldIndex(), length ); + } + /** * The count of CPs in the main document */ + @Deprecated public int getCcpText() { return _longHandler.getLong(FIBLongHandler.CCPTEXT); } /** * Updates the count of CPs in the main document */ + @Deprecated public void setCcpText(int ccpText) { _longHandler.setLong(FIBLongHandler.CCPTEXT, ccpText); } @@ -376,12 +443,14 @@ public final class FileInformationBlock extends FIBAbstractType /** * The count of CPs in the footnote subdocument */ + @Deprecated public int getCcpFtn() { return _longHandler.getLong(FIBLongHandler.CCPFTN); } /** * Updates the count of CPs in the footnote subdocument */ + @Deprecated public void setCcpFtn(int ccpFtn) { _longHandler.setLong(FIBLongHandler.CCPFTN, ccpFtn); } @@ -389,12 +458,14 @@ public final class FileInformationBlock extends FIBAbstractType /** * The count of CPs in the header story subdocument */ + @Deprecated public int getCcpHdd() { return _longHandler.getLong(FIBLongHandler.CCPHDD); } /** * Updates the count of CPs in the header story subdocument */ + @Deprecated public void setCcpHdd(int ccpHdd) { _longHandler.setLong(FIBLongHandler.CCPHDD, ccpHdd); } @@ -402,15 +473,19 @@ public final class FileInformationBlock extends FIBAbstractType /** * The count of CPs in the comments (atn) subdocument */ + @Deprecated public int getCcpAtn() { return _longHandler.getLong(FIBLongHandler.CCPATN); } + + @Deprecated public int getCcpCommentAtn() { return getCcpAtn(); } /** * Updates the count of CPs in the comments (atn) story subdocument */ + @Deprecated public void setCcpAtn(int ccpAtn) { _longHandler.setLong(FIBLongHandler.CCPATN, ccpAtn); } @@ -418,12 +493,14 @@ public final class FileInformationBlock extends FIBAbstractType /** * The count of CPs in the end note subdocument */ + @Deprecated public int getCcpEdn() { return _longHandler.getLong(FIBLongHandler.CCPEDN); } /** * Updates the count of CPs in the end note subdocument */ + @Deprecated public void setCcpEdn(int ccpEdn) { _longHandler.setLong(FIBLongHandler.CCPEDN, ccpEdn); } @@ -431,12 +508,14 @@ public final class FileInformationBlock extends FIBAbstractType /** * The count of CPs in the main document textboxes */ + @Deprecated public int getCcpTxtBx() { return _longHandler.getLong(FIBLongHandler.CCPTXBX); } /** * Updates the count of CPs in the main document textboxes */ + @Deprecated public void setCcpTxtBx(int ccpTxtBx) { _longHandler.setLong(FIBLongHandler.CCPTXBX, ccpTxtBx); } @@ -444,12 +523,14 @@ public final class FileInformationBlock extends FIBAbstractType /** * The count of CPs in the header textboxes */ + @Deprecated public int getCcpHdrTxtBx() { return _longHandler.getLong(FIBLongHandler.CCPHDRTXBX); } /** * Updates the count of CPs in the header textboxes */ + @Deprecated public void setCcpHdrTxtBx(int ccpTxtBx) { _longHandler.setLong(FIBLongHandler.CCPHDRTXBX, ccpTxtBx); } @@ -460,165 +541,189 @@ public final class FileInformationBlock extends FIBAbstractType _fieldHandler.clearFields(); } - public int getFieldsPlcfOffset( DocumentPart documentPart ) + public int getFieldsPlcfOffset( FieldsDocumentPart part ) { - return _fieldHandler.getFieldOffset( documentPart - .getFibHandlerFieldsPosition() ); + return _fieldHandler.getFieldOffset( part.getFibFieldsField() ); } - public int getFieldsPlcfLength( DocumentPart documentPart ) + public int getFieldsPlcfLength( FieldsDocumentPart part ) { - return _fieldHandler.getFieldSize( documentPart - .getFibHandlerFieldsPosition() ); + return _fieldHandler.getFieldSize( part.getFibFieldsField() ); } - public void setFieldsPlcfOffset( DocumentPart documentPart, int offset ) + public void setFieldsPlcfOffset( FieldsDocumentPart part, int offset ) { - _fieldHandler.setFieldOffset( - documentPart.getFibHandlerFieldsPosition(), offset ); + _fieldHandler.setFieldOffset( part.getFibFieldsField(), offset ); } - public void setFieldsPlcfLength( DocumentPart documentPart, int length ) + public void setFieldsPlcfLength( FieldsDocumentPart part, int length ) { - _fieldHandler.setFieldSize( documentPart.getFibHandlerFieldsPosition(), - length ); + _fieldHandler.setFieldSize( part.getFibFieldsField(), length ); } + @Deprecated public int getFcPlcffldAtn() { return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDATN); } + @Deprecated public int getLcbPlcffldAtn() { return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDATN); } + @Deprecated public void setFcPlcffldAtn( int offset ) { _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDATN, offset ); } + @Deprecated public void setLcbPlcffldAtn( int size ) { _fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDATN, size ); } + @Deprecated public int getFcPlcffldEdn() { return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDEDN); } + @Deprecated public int getLcbPlcffldEdn() { return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDEDN); } + @Deprecated public void setFcPlcffldEdn( int offset ) { _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDEDN, offset ); } + @Deprecated public void setLcbPlcffldEdn( int size ) { _fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDEDN, size ); } + @Deprecated public int getFcPlcffldFtn() { return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDFTN); } + @Deprecated public int getLcbPlcffldFtn() { return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDFTN); } + @Deprecated public void setFcPlcffldFtn( int offset ) { _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDFTN, offset ); } + @Deprecated public void setLcbPlcffldFtn( int size ) { _fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDFTN, size ); } + @Deprecated public int getFcPlcffldHdr() { return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDHDR); } + @Deprecated public int getLcbPlcffldHdr() { return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDHDR); } + @Deprecated public void setFcPlcffldHdr( int offset ) { _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDHDR, offset ); } + @Deprecated public void setLcbPlcffldHdr( int size ) { _fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDHDR, size ); } + @Deprecated public int getFcPlcffldHdrtxbx() { return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDHDRTXBX); } + @Deprecated public int getLcbPlcffldHdrtxbx() { return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDHDRTXBX); } + @Deprecated public void setFcPlcffldHdrtxbx( int offset ) { _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDHDRTXBX, offset ); } + @Deprecated public void setLcbPlcffldHdrtxbx( int size ) { _fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDHDRTXBX, size ); } + @Deprecated public int getFcPlcffldMom() { return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDMOM); } + @Deprecated public int getLcbPlcffldMom() { return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDMOM); } + @Deprecated public void setFcPlcffldMom( int offset ) { _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDMOM, offset ); } + @Deprecated public void setLcbPlcffldMom( int size ) { _fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDMOM, size ); } + @Deprecated public int getFcPlcffldTxbx() { return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFFLDTXBX); } + @Deprecated public int getLcbPlcffldTxbx() { return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDTXBX); } + @Deprecated public void setFcPlcffldTxbx( int offset ) { _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFFLDTXBX, offset ); } + @Deprecated public void setLcbPlcffldTxbx( int size ) { _fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDTXBX, size ); diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/SubdocumentType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/SubdocumentType.java new file mode 100644 index 0000000000..1090814892 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/SubdocumentType.java @@ -0,0 +1,45 @@ +package org.apache.poi.hwpf.model; + +/** + * Document text parts that can have text pieces (CPs) + * + * @author Sergey Vladimirov (vlsergey {at} gmail {dot} com) + */ +public enum SubdocumentType { + MAIN( FIBLongHandler.CCPTEXT ), + + FOOTNOTE( FIBLongHandler.CCPFTN ), + + HEADER( FIBLongHandler.CCPHDD ), + + MACRO( FIBLongHandler.CCPMCR ), + + ANNOTATION( FIBLongHandler.CCPATN ), + + ENDNOTE( FIBLongHandler.CCPEDN ), + + TEXTBOX( FIBLongHandler.CCPTXBX ), + + HEADER_TEXTBOX( FIBLongHandler.CCPHDRTXBX ); + + /** + * Array of {@link SubdocumentType}s ordered by document position and FIB + * field order + */ + public static final SubdocumentType[] ORDERED = new SubdocumentType[] { + MAIN, FOOTNOTE, HEADER, MACRO, ANNOTATION, ENDNOTE, TEXTBOX, + HEADER_TEXTBOX }; + + private final int fibLongFieldIndex; + + private SubdocumentType( int fibLongFieldIndex ) + { + this.fibLongFieldIndex = fibLongFieldIndex; + } + + public int getFibLongFieldIndex() + { + return fibLongFieldIndex; + } + +} diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/HeaderStories.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/HeaderStories.java index 9a979164ff..fed191c7d4 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/HeaderStories.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/HeaderStories.java @@ -21,6 +21,7 @@ import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.model.FileInformationBlock; import org.apache.poi.hwpf.model.GenericPropertyNode; import org.apache.poi.hwpf.model.PlexOfCps; +import org.apache.poi.hwpf.model.SubdocumentType; /** * A HeaderStory is a Header, a Footer, or footnote/endnote @@ -42,10 +43,14 @@ public final class HeaderStories { this.headerStories = doc.getHeaderStoryRange(); FileInformationBlock fib = doc.getFileInformationBlock(); - // If there's no PlcfHdd, nothing to do - if(fib.getCcpHdd() == 0) { - return; - } +// // If there's no PlcfHdd, nothing to do +// if(fib.getCcpHdd() == 0) { +// return; +// } + + if (fib.getSubdocumentTextStreamLength( SubdocumentType.HEADER ) == 0) + return; + if(fib.getPlcfHddSize() == 0) { return; } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java index 9b3144e2b4..f2cc1eae77 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java @@ -24,13 +24,13 @@ import java.util.NoSuchElementException; import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.HWPFDocumentCore; import org.apache.poi.hwpf.model.CHPX; -import org.apache.poi.hwpf.model.CPSplitCalculator; import org.apache.poi.hwpf.model.FileInformationBlock; import org.apache.poi.hwpf.model.ListTables; import org.apache.poi.hwpf.model.PAPX; import org.apache.poi.hwpf.model.PropertyNode; import org.apache.poi.hwpf.model.SEPX; import org.apache.poi.hwpf.model.StyleSheet; +import org.apache.poi.hwpf.model.SubdocumentType; import org.apache.poi.hwpf.model.TextPiece; import org.apache.poi.hwpf.sprm.CharacterSprmCompressor; import org.apache.poi.hwpf.sprm.ParagraphSprmCompressor; @@ -1044,52 +1044,68 @@ public class Range { // TODO -instantiable superclass _sectionRangeFound = false; } - /** - * Adjust the value of the various FIB character count fields, eg - * FIB.CCPText after an insert or a delete... - * - * Works on all CCP fields from this range onwards - * - * @param adjustment - * The (signed) value that should be added to the FIB CCP fields - */ - protected void adjustFIB(int adjustment) { - assert (_doc instanceof HWPFDocument); - - // update the FIB.CCPText field (this should happen once per adjustment, - // so we don't want it in - // adjustForInsert() or it would get updated multiple times if the range - // has a parent) - // without this, OpenOffice.org (v. 2.2.x) does not see all the text in - // the document - - CPSplitCalculator cpS = ((HWPFDocument)_doc).getCPSplitCalculator(); - FileInformationBlock fib = _doc.getFileInformationBlock(); - - // Do for each affected part - if (_start < cpS.getMainDocumentEnd()) { - fib.setCcpText(fib.getCcpText() + adjustment); - } + /** + * Adjust the value of the various FIB character count fields, eg + * FIB.CCPText after an insert or a delete... + * + * Works on all CCP fields from this range onwards + * + * @param adjustment + * The (signed) value that should be added to the FIB CCP fields + */ + protected void adjustFIB( int adjustment ) + { + assert ( _doc instanceof HWPFDocument ); + + // update the FIB.CCPText field (this should happen once per adjustment, + // so we don't want it in + // adjustForInsert() or it would get updated multiple times if the range + // has a parent) + // without this, OpenOffice.org (v. 2.2.x) does not see all the text in + // the document + + FileInformationBlock fib = _doc.getFileInformationBlock(); + + // // Do for each affected part + // if (_start < cpS.getMainDocumentEnd()) { + // fib.setCcpText(fib.getCcpText() + adjustment); + // } + // + // if (_start < cpS.getCommentsEnd()) { + // fib.setCcpAtn(fib.getCcpAtn() + adjustment); + // } + // if (_start < cpS.getEndNoteEnd()) { + // fib.setCcpEdn(fib.getCcpEdn() + adjustment); + // } + // if (_start < cpS.getFootnoteEnd()) { + // fib.setCcpFtn(fib.getCcpFtn() + adjustment); + // } + // if (_start < cpS.getHeaderStoryEnd()) { + // fib.setCcpHdd(fib.getCcpHdd() + adjustment); + // } + // if (_start < cpS.getHeaderTextboxEnd()) { + // fib.setCcpHdrTxtBx(fib.getCcpHdrTxtBx() + adjustment); + // } + // if (_start < cpS.getMainTextboxEnd()) { + // fib.setCcpTxtBx(fib.getCcpTxtBx() + adjustment); + // } + + // much simple implementation base on SubdocumentType --sergey + + int currentEnd = 0; + for ( SubdocumentType type : SubdocumentType.ORDERED ) + { + int currentLength = fib.getSubdocumentTextStreamLength( type ); + currentEnd += currentLength; - if (_start < cpS.getCommentsEnd()) { - fib.setCcpAtn(fib.getCcpAtn() + adjustment); - } - if (_start < cpS.getEndNoteEnd()) { - fib.setCcpEdn(fib.getCcpEdn() + adjustment); - } - if (_start < cpS.getFootnoteEnd()) { - fib.setCcpFtn(fib.getCcpFtn() + adjustment); - } - if (_start < cpS.getHeaderStoryEnd()) { - fib.setCcpHdd(fib.getCcpHdd() + adjustment); - } - if (_start < cpS.getHeaderTextboxEnd()) { - fib.setCcpHdrTxtBx(fib.getCcpHdrTxtBx() + adjustment); - } - if (_start < cpS.getMainTextboxEnd()) { - fib.setCcpTxtBx(fib.getCcpTxtBx() + adjustment); - } - } + // do we need to shift this part? + if ( _start < currentEnd ) + { + fib.setSubdocumentTextStreamLength( type, currentLength + + adjustment ); + } + } + } /** * adjust this range after an insert happens. diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/TestFieldsTables.java b/src/scratchpad/testcases/org/apache/poi/hwpf/TestFieldsTables.java index 40b7169b60..a0c71f81f5 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/TestFieldsTables.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/TestFieldsTables.java @@ -21,7 +21,7 @@ package org.apache.poi.hwpf; import java.util.ArrayList; -import org.apache.poi.hwpf.model.DocumentPart; +import org.apache.poi.hwpf.model.FieldsDocumentPart; import org.apache.poi.hwpf.model.FieldsTables; import org.apache.poi.hwpf.model.FileInformationBlock; import org.apache.poi.hwpf.model.PlexOfField; @@ -80,9 +80,9 @@ public class TestFieldsTables extends HWPFTestCase FieldsTables fieldsTables = new FieldsTables( tableStream, fib ); - for ( int i = 0; i < DocumentPart.values().length; i++ ) + for ( int i = 0; i < FieldsDocumentPart.values().length; i++ ) { - DocumentPart part = DocumentPart.values()[i]; + FieldsDocumentPart part = FieldsDocumentPart.values()[i]; ArrayList fieldsPlexes = fieldsTables .getFieldsPLCF( part ); diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestProblems.java b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestProblems.java index a3f1bd31c0..0dbe2cf2d7 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestProblems.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestProblems.java @@ -32,7 +32,7 @@ import org.apache.poi.hwpf.HWPFTestCase; import org.apache.poi.hwpf.HWPFTestDataSamples; import org.apache.poi.hwpf.extractor.Word6Extractor; import org.apache.poi.hwpf.extractor.WordExtractor; -import org.apache.poi.hwpf.model.DocumentPart; +import org.apache.poi.hwpf.model.FieldsDocumentPart; import org.apache.poi.hwpf.model.PlexOfField; import org.apache.poi.hwpf.model.StyleSheet; import org.apache.poi.util.IOUtils; @@ -554,9 +554,9 @@ public final class TestProblems extends HWPFTestCase { .getCharacterTable().getTextRuns().size() ); List expectedFields = doc1.getFieldsTables() - .getFieldsPLCF( DocumentPart.MAIN ); + .getFieldsPLCF( FieldsDocumentPart.MAIN ); List actualFields = doc2.getFieldsTables() - .getFieldsPLCF( DocumentPart.MAIN ); + .getFieldsPLCF( FieldsDocumentPart.MAIN ); assertEquals( expectedFields.size(), actualFields.size() ); assertTableStructures( doc1.getRange(), doc2.getRange() ); -- 2.39.5