git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1148303 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_8_BETA4
@@ -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 ); | |||
} |
@@ -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; | |||
@@ -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 |
@@ -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) { |
@@ -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; |
@@ -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; | |||
} | |||
} |
@@ -39,24 +39,15 @@ import org.apache.poi.hwpf.model.io.HWPFOutputStream; | |||
*/ | |||
public class FieldsTables | |||
{ | |||
private static final class GenericPropertyNodeComparator implements | |||
Comparator<GenericPropertyNode> | |||
{ | |||
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 <T> int binarySearch( GenericPropertyNode[] array, | |||
int startIndex, int endIndex, int requiredStartOffset ) | |||
{ | |||
checkIndexForBinarySearch( array.length, startIndex, endIndex ); | |||
private Map<DocumentPart, PlexOfCps> _tables; | |||
private Map<DocumentPart, Map<Integer, Field>> _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<PlexOfField> toArrayList( PlexOfCps plexOfCps ) | |||
{ | |||
if ( plexOfCps == null ) | |||
return new ArrayList<PlexOfField>(); | |||
ArrayList<PlexOfField> fields = new ArrayList<PlexOfField>(); | |||
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<FieldsDocumentPart, Map<Integer, Field>> _fieldsByOffset; | |||
private Map<FieldsDocumentPart, PlexOfCps> _tables; | |||
private GenericPropertyNodeComparator comparator = new GenericPropertyNodeComparator(); | |||
public FieldsTables( byte[] tableStream, FileInformationBlock fib ) | |||
{ | |||
_tables = new HashMap<DocumentPart, PlexOfCps>( | |||
DocumentPart.values().length ); | |||
_fieldsByOffset = new HashMap<DocumentPart, Map<Integer, Field>>( | |||
DocumentPart.values().length ); | |||
_tables = new HashMap<FieldsDocumentPart, PlexOfCps>( | |||
FieldsDocumentPart.values().length ); | |||
_fieldsByOffset = new HashMap<FieldsDocumentPart, Map<Integer, Field>>( | |||
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<Field> getFields( FieldsDocumentPart part ) | |||
{ | |||
Map<Integer, Field> map = _fieldsByOffset.get( part ); | |||
if ( map == null || map.isEmpty() ) | |||
return Collections.emptySet(); | |||
return Collections.unmodifiableCollection( map.values() ); | |||
} | |||
public ArrayList<PlexOfField> getFieldsPLCF( FieldsDocumentPart part ) | |||
{ | |||
return toArrayList( _tables.get( part ) ); | |||
} | |||
@Deprecated | |||
public ArrayList<PlexOfField> getFieldsPLCF( int partIndex ) | |||
{ | |||
return getFieldsPLCF( FieldsDocumentPart.values()[partIndex] ); | |||
} | |||
public Field lookupFieldByStartOffset( FieldsDocumentPart documentPart, | |||
int offset ) | |||
{ | |||
Map<Integer, Field> map = _fieldsByOffset.get( documentPart ); | |||
if ( map == null || map.isEmpty() ) | |||
return null; | |||
return map.get( Integer.valueOf( offset ) ); | |||
} | |||
private Map<Integer, Field> parseFieldStructure( PlexOfCps plexOfCps ) | |||
{ | |||
if (plexOfCps == null) | |||
if ( plexOfCps == null ) | |||
return new HashMap<Integer, Field>(); | |||
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 <T> 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<Integer, Field> 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<Field> getFields( DocumentPart part ) | |||
{ | |||
Map<Integer, Field> map = _fieldsByOffset.get( part ); | |||
if ( map == null || map.isEmpty() ) | |||
return Collections.emptySet(); | |||
return Collections.unmodifiableCollection( map.values() ); | |||
} | |||
@Deprecated | |||
public ArrayList<PlexOfField> getFieldsPLCF( int partIndex ) | |||
{ | |||
return getFieldsPLCF( DocumentPart.values()[partIndex] ); | |||
} | |||
public ArrayList<PlexOfField> getFieldsPLCF( DocumentPart documentPart ) | |||
{ | |||
return toArrayList( _tables.get( documentPart ) ); | |||
} | |||
private static ArrayList<PlexOfField> toArrayList( PlexOfCps plexOfCps ) | |||
{ | |||
if ( plexOfCps == null ) | |||
return new ArrayList<PlexOfField>(); | |||
ArrayList<PlexOfField> fields = new ArrayList<PlexOfField>(); | |||
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<GenericPropertyNode> | |||
{ | |||
public int compare( GenericPropertyNode o1, GenericPropertyNode o2 ) | |||
{ | |||
int thisVal = o1.getStart(); | |||
int anotherVal = o2.getStart(); | |||
return thisVal < anotherVal ? -1 : thisVal == anotherVal ? 0 : 1; | |||
} | |||
} | |||
} |
@@ -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 ); |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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 | |||
* <code>FIB.CCPText</code> 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 | |||
* <code>FIB.CCPText</code> 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. |
@@ -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<PlexOfField> fieldsPlexes = fieldsTables | |||
.getFieldsPLCF( part ); |
@@ -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<PlexOfField> expectedFields = doc1.getFieldsTables() | |||
.getFieldsPLCF( DocumentPart.MAIN ); | |||
.getFieldsPLCF( FieldsDocumentPart.MAIN ); | |||
List<PlexOfField> actualFields = doc2.getFieldsTables() | |||
.getFieldsPLCF( DocumentPart.MAIN ); | |||
.getFieldsPLCF( FieldsDocumentPart.MAIN ); | |||
assertEquals( expectedFields.size(), actualFields.size() ); | |||
assertTableStructures( doc1.getRange(), doc2.getRange() ); |