HWPF Bookmarks tables are correctly updated on text updates. Add HWPF API to update range text and delete bookmarks.
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1170437 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
95d61faec0
commit
b12828a65e
@ -34,6 +34,8 @@
|
|||||||
|
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.8-beta5" date="2011-??-??">
|
<release version="3.8-beta5" date="2011-??-??">
|
||||||
|
<action dev="poi-developers" type="add">Add HWPF API to update range text and delete bookmarks</action>
|
||||||
|
<action dev="poi-developers" type="add">HWPF Bookmarks tables are correctly updated on text updates</action>
|
||||||
<action dev="poi-developers" type="add">51670 - avoid LeftoverDataException when reading .xls files with invalid LabelRecords</action>
|
<action dev="poi-developers" type="add">51670 - avoid LeftoverDataException when reading .xls files with invalid LabelRecords</action>
|
||||||
<action dev="poi-developers" type="add">51196 - prevent NPE in XWPFPicture.getPictureData() </action>
|
<action dev="poi-developers" type="add">51196 - prevent NPE in XWPFPicture.getPictureData() </action>
|
||||||
<action dev="poi-developers" type="add">51771 - prevent NPE when getting object data from OLEShape in HSLF</action>
|
<action dev="poi-developers" type="add">51771 - prevent NPE when getting object data from OLEShape in HSLF</action>
|
||||||
|
@ -17,7 +17,13 @@
|
|||||||
package org.apache.poi.hwpf.model;
|
package org.apache.poi.hwpf.model;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.poi.util.POILogFactory;
|
||||||
|
|
||||||
|
import org.apache.poi.util.POILogger;
|
||||||
|
|
||||||
import org.apache.poi.hwpf.model.io.HWPFOutputStream;
|
import org.apache.poi.hwpf.model.io.HWPFOutputStream;
|
||||||
import org.apache.poi.util.Internal;
|
import org.apache.poi.util.Internal;
|
||||||
@ -25,17 +31,45 @@ import org.apache.poi.util.Internal;
|
|||||||
@Internal
|
@Internal
|
||||||
public class BookmarksTables
|
public class BookmarksTables
|
||||||
{
|
{
|
||||||
|
private static final POILogger logger = POILogFactory
|
||||||
|
.getLogger( BookmarksTables.class );
|
||||||
|
|
||||||
private PlexOfCps descriptorsFirst = new PlexOfCps( 4 );
|
private PlexOfCps descriptorsFirst = new PlexOfCps( 4 );
|
||||||
|
|
||||||
private PlexOfCps descriptorsLim = new PlexOfCps( 0 );
|
private PlexOfCps descriptorsLim = new PlexOfCps( 0 );
|
||||||
|
|
||||||
private String[] names = new String[0];
|
private List<String> names = new ArrayList<String>( 0 );
|
||||||
|
|
||||||
public BookmarksTables( byte[] tableStream, FileInformationBlock fib )
|
public BookmarksTables( byte[] tableStream, FileInformationBlock fib )
|
||||||
{
|
{
|
||||||
read( tableStream, fib );
|
read( tableStream, fib );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void afterDelete( int startCp, int length )
|
||||||
|
{
|
||||||
|
descriptorsFirst.adjust( startCp, -length );
|
||||||
|
descriptorsLim.adjust( startCp, -length );
|
||||||
|
for ( int i = 0; i < descriptorsFirst.length(); i++ )
|
||||||
|
{
|
||||||
|
GenericPropertyNode startNode = descriptorsFirst.getProperty( i );
|
||||||
|
GenericPropertyNode endNode = descriptorsLim.getProperty( i );
|
||||||
|
if ( startNode.getStart() == endNode.getStart() )
|
||||||
|
{
|
||||||
|
logger.log( POILogger.DEBUG, "Removing bookmark #",
|
||||||
|
Integer.valueOf( i ), "..." );
|
||||||
|
remove( i );
|
||||||
|
i--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void afterInsert( int startCp, int length )
|
||||||
|
{
|
||||||
|
descriptorsFirst.adjust( startCp, length );
|
||||||
|
descriptorsLim.adjust( startCp - 1, length );
|
||||||
|
}
|
||||||
|
|
||||||
public int getBookmarksCount()
|
public int getBookmarksCount()
|
||||||
{
|
{
|
||||||
return descriptorsFirst.length();
|
return descriptorsFirst.length();
|
||||||
@ -70,14 +104,14 @@ public class BookmarksTables
|
|||||||
return descriptorsLim.length();
|
return descriptorsLim.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName( int index ) throws ArrayIndexOutOfBoundsException
|
public String getName( int index )
|
||||||
{
|
{
|
||||||
return names[index];
|
return names.get( index );
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNamesCount()
|
public int getNamesCount()
|
||||||
{
|
{
|
||||||
return names.length;
|
return names.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void read( byte[] tableStream, FileInformationBlock fib )
|
private void read( byte[] tableStream, FileInformationBlock fib )
|
||||||
@ -86,7 +120,8 @@ public class BookmarksTables
|
|||||||
int namesLength = fib.getLcbSttbfbkmk();
|
int namesLength = fib.getLcbSttbfbkmk();
|
||||||
|
|
||||||
if ( namesStart != 0 && namesLength != 0 )
|
if ( namesStart != 0 && namesLength != 0 )
|
||||||
this.names = SttbfUtils.read( tableStream, namesStart );
|
this.names = new ArrayList<String>( Arrays.asList( SttbfUtils.read(
|
||||||
|
tableStream, namesStart ) ) );
|
||||||
|
|
||||||
int firstDescriptorsStart = fib.getFcPlcfbkf();
|
int firstDescriptorsStart = fib.getFcPlcfbkf();
|
||||||
int firstDescriptorsLength = fib.getLcbPlcfbkf();
|
int firstDescriptorsLength = fib.getLcbPlcfbkf();
|
||||||
@ -102,15 +137,16 @@ public class BookmarksTables
|
|||||||
limDescriptorsLength, 0 );
|
limDescriptorsLength, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void remove( int index )
|
||||||
|
{
|
||||||
|
descriptorsFirst.remove( index );
|
||||||
|
descriptorsLim.remove( index );
|
||||||
|
names.remove( index );
|
||||||
|
}
|
||||||
|
|
||||||
public void setName( int index, String name )
|
public void setName( int index, String name )
|
||||||
{
|
{
|
||||||
if ( index < names.length )
|
names.set( index, name );
|
||||||
{
|
|
||||||
String[] newNames = new String[index + 1];
|
|
||||||
System.arraycopy( names, 0, newNames, 0, names.length );
|
|
||||||
names = newNames;
|
|
||||||
}
|
|
||||||
names[index] = name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writePlcfBkmkf( FileInformationBlock fib,
|
public void writePlcfBkmkf( FileInformationBlock fib,
|
||||||
@ -152,7 +188,7 @@ public class BookmarksTables
|
|||||||
public void writeSttbfBkmk( FileInformationBlock fib,
|
public void writeSttbfBkmk( FileInformationBlock fib,
|
||||||
HWPFOutputStream tableStream ) throws IOException
|
HWPFOutputStream tableStream ) throws IOException
|
||||||
{
|
{
|
||||||
if ( names == null || names.length == 0 )
|
if ( names == null || names.isEmpty() )
|
||||||
{
|
{
|
||||||
fib.setFcSttbfbkmk( 0 );
|
fib.setFcSttbfbkmk( 0 );
|
||||||
fib.setLcbSttbfbkmk( 0 );
|
fib.setLcbSttbfbkmk( 0 );
|
||||||
@ -160,7 +196,8 @@ public class BookmarksTables
|
|||||||
}
|
}
|
||||||
|
|
||||||
int start = tableStream.getOffset();
|
int start = tableStream.getOffset();
|
||||||
SttbfUtils.write( tableStream, names );
|
SttbfUtils
|
||||||
|
.write( tableStream, names.toArray( new String[names.size()] ) );
|
||||||
int end = tableStream.getOffset();
|
int end = tableStream.getOffset();
|
||||||
|
|
||||||
fib.setFcSttbfbkmk( start );
|
fib.setFcSttbfbkmk( start );
|
||||||
|
@ -19,6 +19,7 @@ package org.apache.poi.hwpf.model;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.apache.poi.util.Internal;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,6 +67,36 @@ public final class PlexOfCps
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
void adjust( int startCp, int shift )
|
||||||
|
{
|
||||||
|
for ( GenericPropertyNode node : _props )
|
||||||
|
{
|
||||||
|
if ( node.getStart() > startCp )
|
||||||
|
{
|
||||||
|
if ( node.getStart() + shift < startCp )
|
||||||
|
{
|
||||||
|
node.setStart( startCp );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node.setStart( node.getStart() + shift );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( node.getEnd() >= startCp )
|
||||||
|
{
|
||||||
|
if ( node.getEnd() + shift < startCp )
|
||||||
|
{
|
||||||
|
node.setEnd( startCp );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node.setEnd( node.getEnd() + shift );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public GenericPropertyNode getProperty( int index )
|
public GenericPropertyNode getProperty( int index )
|
||||||
{
|
{
|
||||||
return _props.get( index );
|
return _props.get( index );
|
||||||
@ -74,6 +105,13 @@ public final class PlexOfCps
|
|||||||
public void addProperty( GenericPropertyNode node )
|
public void addProperty( GenericPropertyNode node )
|
||||||
{
|
{
|
||||||
_props.add( node );
|
_props.add( node );
|
||||||
|
_iMac++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove( int index )
|
||||||
|
{
|
||||||
|
_props.remove( index );
|
||||||
|
_iMac--;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] toByteArray()
|
public byte[] toByteArray()
|
||||||
|
@ -47,4 +47,12 @@ public interface Bookmarks
|
|||||||
*/
|
*/
|
||||||
Map<Integer, List<Bookmark>> getBookmarksStartedBetween(
|
Map<Integer, List<Bookmark>> getBookmarksStartedBetween(
|
||||||
int startInclusive, int endExclusive );
|
int startInclusive, int endExclusive );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove bookmark from document (but not the bookmark text)
|
||||||
|
*
|
||||||
|
* @param index
|
||||||
|
* bookmark document index to be removed
|
||||||
|
*/
|
||||||
|
void remove( int index );
|
||||||
}
|
}
|
||||||
|
@ -37,119 +37,6 @@ import org.apache.poi.hwpf.model.PropertyNode;
|
|||||||
public class BookmarksImpl implements Bookmarks
|
public class BookmarksImpl implements Bookmarks
|
||||||
{
|
{
|
||||||
|
|
||||||
private final BookmarksTables bookmarksTables;
|
|
||||||
|
|
||||||
private Map<Integer, List<GenericPropertyNode>> sortedDescriptors = null;
|
|
||||||
|
|
||||||
private int[] sortedStartPositions = null;
|
|
||||||
|
|
||||||
public BookmarksImpl( BookmarksTables bookmarksTables )
|
|
||||||
{
|
|
||||||
this.bookmarksTables = bookmarksTables;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Bookmark getBookmark( final GenericPropertyNode first )
|
|
||||||
{
|
|
||||||
return new BookmarkImpl( first );
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bookmark getBookmark( int index )
|
|
||||||
{
|
|
||||||
final GenericPropertyNode first = bookmarksTables
|
|
||||||
.getDescriptorFirst( index );
|
|
||||||
return getBookmark( first );
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Bookmark> getBookmarksAt( int startCp )
|
|
||||||
{
|
|
||||||
updateSortedDescriptors();
|
|
||||||
|
|
||||||
List<GenericPropertyNode> nodes = sortedDescriptors.get( Integer
|
|
||||||
.valueOf( startCp ) );
|
|
||||||
if ( nodes == null || nodes.isEmpty() )
|
|
||||||
return Collections.emptyList();
|
|
||||||
|
|
||||||
List<Bookmark> result = new ArrayList<Bookmark>( nodes.size() );
|
|
||||||
for ( GenericPropertyNode node : nodes )
|
|
||||||
{
|
|
||||||
result.add( getBookmark( node ) );
|
|
||||||
}
|
|
||||||
return Collections.unmodifiableList( result );
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getBookmarksCount()
|
|
||||||
{
|
|
||||||
return bookmarksTables.getDescriptorsFirstCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<Integer, List<Bookmark>> getBookmarksStartedBetween(
|
|
||||||
int startInclusive, int endExclusive )
|
|
||||||
{
|
|
||||||
updateSortedDescriptors();
|
|
||||||
|
|
||||||
int startLookupIndex = Arrays.binarySearch( this.sortedStartPositions,
|
|
||||||
startInclusive );
|
|
||||||
if ( startLookupIndex < 0 )
|
|
||||||
startLookupIndex = -( startLookupIndex + 1 );
|
|
||||||
int endLookupIndex = Arrays.binarySearch( this.sortedStartPositions,
|
|
||||||
endExclusive );
|
|
||||||
if ( endLookupIndex < 0 )
|
|
||||||
endLookupIndex = -( endLookupIndex + 1 );
|
|
||||||
|
|
||||||
Map<Integer, List<Bookmark>> result = new LinkedHashMap<Integer, List<Bookmark>>();
|
|
||||||
for ( int lookupIndex = startLookupIndex; lookupIndex < endLookupIndex; lookupIndex++ )
|
|
||||||
{
|
|
||||||
int s = sortedStartPositions[lookupIndex];
|
|
||||||
if ( s < startInclusive )
|
|
||||||
continue;
|
|
||||||
if ( s >= endExclusive )
|
|
||||||
break;
|
|
||||||
|
|
||||||
List<Bookmark> startedAt = getBookmarksAt( s );
|
|
||||||
if ( startedAt != null )
|
|
||||||
result.put( Integer.valueOf( s ), startedAt );
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.unmodifiableMap( result );
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateSortedDescriptors()
|
|
||||||
{
|
|
||||||
if ( sortedDescriptors != null )
|
|
||||||
return;
|
|
||||||
|
|
||||||
Map<Integer, List<GenericPropertyNode>> result = new HashMap<Integer, List<GenericPropertyNode>>();
|
|
||||||
for ( int b = 0; b < bookmarksTables.getDescriptorsFirstCount(); b++ )
|
|
||||||
{
|
|
||||||
GenericPropertyNode property = bookmarksTables
|
|
||||||
.getDescriptorFirst( b );
|
|
||||||
Integer positionKey = Integer.valueOf( property.getStart() );
|
|
||||||
List<GenericPropertyNode> atPositionList = result.get( positionKey );
|
|
||||||
if ( atPositionList == null )
|
|
||||||
{
|
|
||||||
atPositionList = new LinkedList<GenericPropertyNode>();
|
|
||||||
result.put( positionKey, atPositionList );
|
|
||||||
}
|
|
||||||
atPositionList.add( property );
|
|
||||||
}
|
|
||||||
|
|
||||||
int counter = 0;
|
|
||||||
int[] indices = new int[result.size()];
|
|
||||||
for ( Map.Entry<Integer, List<GenericPropertyNode>> entry : result
|
|
||||||
.entrySet() )
|
|
||||||
{
|
|
||||||
indices[counter++] = entry.getKey().intValue();
|
|
||||||
List<GenericPropertyNode> updated = new ArrayList<GenericPropertyNode>(
|
|
||||||
entry.getValue() );
|
|
||||||
Collections.sort( updated, PropertyNode.EndComparator.instance );
|
|
||||||
entry.setValue( updated );
|
|
||||||
}
|
|
||||||
Arrays.sort( indices );
|
|
||||||
|
|
||||||
this.sortedDescriptors = result;
|
|
||||||
this.sortedStartPositions = indices;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class BookmarkImpl implements Bookmark
|
private final class BookmarkImpl implements Bookmark
|
||||||
{
|
{
|
||||||
private final GenericPropertyNode first;
|
private final GenericPropertyNode first;
|
||||||
@ -232,4 +119,141 @@ public class BookmarksImpl implements Bookmarks
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final BookmarksTables bookmarksTables;
|
||||||
|
|
||||||
|
private Map<Integer, List<GenericPropertyNode>> sortedDescriptors = null;
|
||||||
|
|
||||||
|
private int[] sortedStartPositions = null;
|
||||||
|
|
||||||
|
public BookmarksImpl( BookmarksTables bookmarksTables )
|
||||||
|
{
|
||||||
|
this.bookmarksTables = bookmarksTables;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void afterDelete( int startCp, int length )
|
||||||
|
{
|
||||||
|
bookmarksTables.afterDelete( startCp, length );
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void afterInsert( int startCp, int length )
|
||||||
|
{
|
||||||
|
bookmarksTables.afterInsert( startCp, length );
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bookmark getBookmark( final GenericPropertyNode first )
|
||||||
|
{
|
||||||
|
return new BookmarkImpl( first );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bookmark getBookmark( int index )
|
||||||
|
{
|
||||||
|
final GenericPropertyNode first = bookmarksTables
|
||||||
|
.getDescriptorFirst( index );
|
||||||
|
return getBookmark( first );
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Bookmark> getBookmarksAt( int startCp )
|
||||||
|
{
|
||||||
|
updateSortedDescriptors();
|
||||||
|
|
||||||
|
List<GenericPropertyNode> nodes = sortedDescriptors.get( Integer
|
||||||
|
.valueOf( startCp ) );
|
||||||
|
if ( nodes == null || nodes.isEmpty() )
|
||||||
|
return Collections.emptyList();
|
||||||
|
|
||||||
|
List<Bookmark> result = new ArrayList<Bookmark>( nodes.size() );
|
||||||
|
for ( GenericPropertyNode node : nodes )
|
||||||
|
{
|
||||||
|
result.add( getBookmark( node ) );
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableList( result );
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBookmarksCount()
|
||||||
|
{
|
||||||
|
return bookmarksTables.getDescriptorsFirstCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Integer, List<Bookmark>> getBookmarksStartedBetween(
|
||||||
|
int startInclusive, int endExclusive )
|
||||||
|
{
|
||||||
|
updateSortedDescriptors();
|
||||||
|
|
||||||
|
int startLookupIndex = Arrays.binarySearch( this.sortedStartPositions,
|
||||||
|
startInclusive );
|
||||||
|
if ( startLookupIndex < 0 )
|
||||||
|
startLookupIndex = -( startLookupIndex + 1 );
|
||||||
|
int endLookupIndex = Arrays.binarySearch( this.sortedStartPositions,
|
||||||
|
endExclusive );
|
||||||
|
if ( endLookupIndex < 0 )
|
||||||
|
endLookupIndex = -( endLookupIndex + 1 );
|
||||||
|
|
||||||
|
Map<Integer, List<Bookmark>> result = new LinkedHashMap<Integer, List<Bookmark>>();
|
||||||
|
for ( int lookupIndex = startLookupIndex; lookupIndex < endLookupIndex; lookupIndex++ )
|
||||||
|
{
|
||||||
|
int s = sortedStartPositions[lookupIndex];
|
||||||
|
if ( s < startInclusive )
|
||||||
|
continue;
|
||||||
|
if ( s >= endExclusive )
|
||||||
|
break;
|
||||||
|
|
||||||
|
List<Bookmark> startedAt = getBookmarksAt( s );
|
||||||
|
if ( startedAt != null )
|
||||||
|
result.put( Integer.valueOf( s ), startedAt );
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableMap( result );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove( int index )
|
||||||
|
{
|
||||||
|
bookmarksTables.remove( index );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reset()
|
||||||
|
{
|
||||||
|
sortedDescriptors = null;
|
||||||
|
sortedStartPositions = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateSortedDescriptors()
|
||||||
|
{
|
||||||
|
if ( sortedDescriptors != null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Map<Integer, List<GenericPropertyNode>> result = new HashMap<Integer, List<GenericPropertyNode>>();
|
||||||
|
for ( int b = 0; b < bookmarksTables.getDescriptorsFirstCount(); b++ )
|
||||||
|
{
|
||||||
|
GenericPropertyNode property = bookmarksTables
|
||||||
|
.getDescriptorFirst( b );
|
||||||
|
Integer positionKey = Integer.valueOf( property.getStart() );
|
||||||
|
List<GenericPropertyNode> atPositionList = result.get( positionKey );
|
||||||
|
if ( atPositionList == null )
|
||||||
|
{
|
||||||
|
atPositionList = new LinkedList<GenericPropertyNode>();
|
||||||
|
result.put( positionKey, atPositionList );
|
||||||
|
}
|
||||||
|
atPositionList.add( property );
|
||||||
|
}
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
int[] indices = new int[result.size()];
|
||||||
|
for ( Map.Entry<Integer, List<GenericPropertyNode>> entry : result
|
||||||
|
.entrySet() )
|
||||||
|
{
|
||||||
|
indices[counter++] = entry.getKey().intValue();
|
||||||
|
List<GenericPropertyNode> updated = new ArrayList<GenericPropertyNode>(
|
||||||
|
entry.getValue() );
|
||||||
|
Collections.sort( updated, PropertyNode.EndComparator.instance );
|
||||||
|
entry.setValue( updated );
|
||||||
|
}
|
||||||
|
Arrays.sort( indices );
|
||||||
|
|
||||||
|
this.sortedDescriptors = result;
|
||||||
|
this.sortedStartPositions = indices;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,8 @@ import java.lang.ref.WeakReference;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import org.apache.poi.util.Internal;
|
||||||
|
|
||||||
import org.apache.poi.hwpf.model.BytePropertyNode;
|
import org.apache.poi.hwpf.model.BytePropertyNode;
|
||||||
|
|
||||||
import org.apache.poi.hwpf.HWPFDocument;
|
import org.apache.poi.hwpf.HWPFDocument;
|
||||||
@ -330,6 +332,11 @@ public class Range { // TODO -instantiable superclass
|
|||||||
_doc.getCharacterTable().adjustForInsert( _charStart, text.length() );
|
_doc.getCharacterTable().adjustForInsert( _charStart, text.length() );
|
||||||
_doc.getParagraphTable().adjustForInsert( _parStart, text.length() );
|
_doc.getParagraphTable().adjustForInsert( _parStart, text.length() );
|
||||||
_doc.getSectionTable().adjustForInsert( _sectionStart, text.length() );
|
_doc.getSectionTable().adjustForInsert( _sectionStart, text.length() );
|
||||||
|
if ( _doc instanceof HWPFDocument )
|
||||||
|
{
|
||||||
|
( (BookmarksImpl) ( (HWPFDocument) _doc ).getBookmarks() )
|
||||||
|
.afterInsert( _start, text.length() );
|
||||||
|
}
|
||||||
adjustForInsert( text.length() );
|
adjustForInsert( text.length() );
|
||||||
|
|
||||||
// update the FIB.CCPText + friends fields
|
// update the FIB.CCPText + friends fields
|
||||||
@ -356,6 +363,11 @@ public class Range { // TODO -instantiable superclass
|
|||||||
_doc.getCharacterTable().adjustForInsert( _charEnd - 1, text.length() );
|
_doc.getCharacterTable().adjustForInsert( _charEnd - 1, text.length() );
|
||||||
_doc.getParagraphTable().adjustForInsert( _parEnd - 1, text.length() );
|
_doc.getParagraphTable().adjustForInsert( _parEnd - 1, text.length() );
|
||||||
_doc.getSectionTable().adjustForInsert( _sectionEnd - 1, text.length() );
|
_doc.getSectionTable().adjustForInsert( _sectionEnd - 1, text.length() );
|
||||||
|
if ( _doc instanceof HWPFDocument )
|
||||||
|
{
|
||||||
|
( (BookmarksImpl) ( (HWPFDocument) _doc ).getBookmarks() )
|
||||||
|
.afterInsert( _end, text.length() );
|
||||||
|
}
|
||||||
adjustForInsert( text.length() );
|
adjustForInsert( text.length() );
|
||||||
|
|
||||||
assert sanityCheck();
|
assert sanityCheck();
|
||||||
@ -558,6 +570,12 @@ public class Range { // TODO -instantiable superclass
|
|||||||
// + " -> " + sepx.getEnd());
|
// + " -> " + sepx.getEnd());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( _doc instanceof HWPFDocument )
|
||||||
|
{
|
||||||
|
( (BookmarksImpl) ( (HWPFDocument) _doc ).getBookmarks() )
|
||||||
|
.afterDelete( _start, ( _end - _start ) );
|
||||||
|
}
|
||||||
|
|
||||||
_text.delete( _start, _end );
|
_text.delete( _start, _end );
|
||||||
Range parent = _parent.get();
|
Range parent = _parent.get();
|
||||||
if ( parent != null )
|
if ( parent != null )
|
||||||
@ -703,6 +721,35 @@ public class Range { // TODO -instantiable superclass
|
|||||||
return (ListEntry) insertAfter(props, styleIndex);
|
return (ListEntry) insertAfter(props, styleIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace range text with new one, adding it to the range and deleting
|
||||||
|
* original text from document
|
||||||
|
*
|
||||||
|
* @param newText
|
||||||
|
* The text to be replaced with
|
||||||
|
* @param addAfter
|
||||||
|
* if <tt>true</tt> the text will be added at the end of current
|
||||||
|
* range, otherwise to the beginning
|
||||||
|
*/
|
||||||
|
public void replaceText( String newText, boolean addAfter )
|
||||||
|
{
|
||||||
|
if ( addAfter )
|
||||||
|
{
|
||||||
|
int originalEnd = getEndOffset();
|
||||||
|
insertAfter( newText );
|
||||||
|
new Range( getStartOffset(), originalEnd, this ).delete();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int originalStart = getStartOffset();
|
||||||
|
int originalEnd = getEndOffset();
|
||||||
|
|
||||||
|
insertBefore( newText );
|
||||||
|
new Range( originalStart + newText.length(), originalEnd
|
||||||
|
+ newText.length(), this ).delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace (one instance of) a piece of text with another...
|
* Replace (one instance of) a piece of text with another...
|
||||||
*
|
*
|
||||||
@ -714,6 +761,7 @@ public class Range { // TODO -instantiable superclass
|
|||||||
* The offset or index where the text to be replaced begins
|
* The offset or index where the text to be replaced begins
|
||||||
* (relative to/within this <code>Range</code>)
|
* (relative to/within this <code>Range</code>)
|
||||||
*/
|
*/
|
||||||
|
@Internal
|
||||||
public void replaceText(String pPlaceHolder, String pValue, int pOffset) {
|
public void replaceText(String pPlaceHolder, String pValue, int pOffset) {
|
||||||
int absPlaceHolderIndex = getStartOffset() + pOffset;
|
int absPlaceHolderIndex = getStartOffset() + pOffset;
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
==================================================================== */
|
==================================================================== */
|
||||||
package org.apache.poi.hwpf.model;
|
package org.apache.poi.hwpf.model;
|
||||||
|
|
||||||
|
import org.apache.poi.hwpf.usermodel.Range;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.apache.poi.hwpf.HWPFDocument;
|
import org.apache.poi.hwpf.HWPFDocument;
|
||||||
@ -43,4 +45,52 @@ public class TestBookmarksTables extends TestCase
|
|||||||
assertEquals( 27, bookmark.getStart() );
|
assertEquals( 27, bookmark.getStart() );
|
||||||
assertEquals( 38, bookmark.getEnd() );
|
assertEquals( 38, bookmark.getEnd() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testDeleteRange()
|
||||||
|
{
|
||||||
|
HWPFDocument doc = HWPFTestDataSamples.openSampleFile( "pageref.doc" );
|
||||||
|
Range range = new Range( 27, 41, doc );
|
||||||
|
range.delete();
|
||||||
|
|
||||||
|
assertEquals( 0, doc.getBookmarks().getBookmarksCount() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReplaceTextAfter()
|
||||||
|
{
|
||||||
|
HWPFDocument doc = HWPFTestDataSamples.openSampleFile( "pageref.doc" );
|
||||||
|
Bookmark bookmark = doc.getBookmarks().getBookmark( 0 );
|
||||||
|
Range range = new Range( bookmark.getStart(), bookmark.getEnd(), doc );
|
||||||
|
range.replaceText( "1destin2ation3", true );
|
||||||
|
|
||||||
|
bookmark = doc.getBookmarks().getBookmark( 0 );
|
||||||
|
assertEquals( "userref", bookmark.getName() );
|
||||||
|
assertEquals( 27, bookmark.getStart() );
|
||||||
|
assertEquals( 41, bookmark.getEnd() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReplaceTextBefore()
|
||||||
|
{
|
||||||
|
HWPFDocument doc = HWPFTestDataSamples.openSampleFile( "pageref.doc" );
|
||||||
|
Bookmark bookmark = doc.getBookmarks().getBookmark( 0 );
|
||||||
|
Range range = new Range( bookmark.getStart(), bookmark.getEnd(), doc );
|
||||||
|
range.replaceText( "1destin2ation3", false );
|
||||||
|
|
||||||
|
bookmark = doc.getBookmarks().getBookmark( 0 );
|
||||||
|
assertEquals( "userref", bookmark.getName() );
|
||||||
|
assertEquals( 27, bookmark.getStart() );
|
||||||
|
assertEquals( 41, bookmark.getEnd() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUpdateText()
|
||||||
|
{
|
||||||
|
HWPFDocument doc = HWPFTestDataSamples.openSampleFile( "pageref.doc" );
|
||||||
|
Bookmark bookmark = doc.getBookmarks().getBookmark( 0 );
|
||||||
|
Range range = new Range( bookmark.getStart(), bookmark.getEnd(), doc );
|
||||||
|
range.replaceText( "destination", "1destin2ation3" );
|
||||||
|
|
||||||
|
bookmark = doc.getBookmarks().getBookmark( 0 );
|
||||||
|
assertEquals( "userref", bookmark.getName() );
|
||||||
|
assertEquals( 27, bookmark.getStart() );
|
||||||
|
assertEquals( 41, bookmark.getEnd() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user