fix stylesheet saving

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1156629 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Sergey Vladimirov 2011-08-11 14:29:29 +00:00
parent 3cbe7923e5
commit f7b888743f

View File

@ -32,7 +32,10 @@ import org.apache.poi.util.LittleEndian;
* compressed styles that are based on styles contained in the stylesheet. This * compressed styles that are based on styles contained in the stylesheet. This
* class also contains static utility functions to uncompress different * class also contains static utility functions to uncompress different
* formatting properties. * formatting properties.
* * <p>
* Fields documentation is quotes from Microsoft Office Word 97-2007 Binary File
* Format (.doc) Specification, page 36 of 210
*
* @author Ryan Ackley * @author Ryan Ackley
*/ */
@Internal @Internal
@ -48,13 +51,74 @@ public final class StyleSheet implements HDFType {
private final static ParagraphProperties NIL_PAP = new ParagraphProperties(); private final static ParagraphProperties NIL_PAP = new ParagraphProperties();
private final static CharacterProperties NIL_CHP = new CharacterProperties(); private final static CharacterProperties NIL_CHP = new CharacterProperties();
private int _stshiLength; /**
private int _baseLength; * Size of the STSHI structure
private int _flags; */
private int _maxIndex; private int _cbStshi;
private int _maxFixedIndex;
private int _stylenameVersion; /**
private int[] _rgftc; * Length of STD Base as stored in a file
* <p>
* "The STD structure (see below) is divided into a fixed-length "base", and
* a variable length part. The stshi.cbSTDBaseInFile indicates the size in
* bytes of the fixed-length base of the STD as it was written in this file.
* If the STD base is grown in a future version, the file format doesn't
* change, because the style sheet reader can discard parts it doesn't know
* about, or use defaults if the file's STD is not as large as it was
* expecting. (Currently, stshi.cbSTDBaseInFile is 8.)"
*/
private int _cbSTDBaseInFile;
/**
* First bit - Are built-in stylenames stored?
* <p>
* "Previous versions of Word did not store the style name if the style was
* a built-in style; Word 6.0 stores the style name for compatibility with
* future versions. Note: the built-in style names may need to be
* "regenerated" if the file is opened in a different language or if
* stshi.nVerBuiltInNamesWhenSaved doesn't match the expected value."
* <p>
* other - Spare flags
*/
private int _flags;
/**
* Max sti known when this file was written
* <p>
* "This indicates the last built-in style known to the version of Word that
* saved this file."
*/
private int _stiMaxWhenSaved;
/**
* How many fixed-index istds are there?
* <p>
* "Each array of styles has some fixed-index styles at the beginning. This
* indicates the number of fixed-index positions reserved in the style sheet
* when it was saved."
*/
private int _istdMaxFixedWhenSaved;
/**
* Current version of built-in stylenames
* <p>
* "Since built-in style names are saved with the document, this provides a
* way to see if the saved names are the same "version" as the names in the
* version of Word that is loading the file. If not, the built-in style
* names need to be "regenerated", i.e. the old names need to be replaced
* with the new."
*/
private int nVerBuiltInNamesWhenSaved;
/**
* rgftc used by StandardChpStsh for document
* <p>
* "This is a list of the default fonts for this style sheet. The first is
* for ASCII characters (0-127), the second is for East Asian characters,
* and the third is the default font for non-East Asian, non-ASCII text. See
* notes on sprmCRgftcX for details."
*/
private int[] _rgftcStandardChpStsh;
StyleDescription[] _styleDescriptions; StyleDescription[] _styleDescriptions;
@ -67,33 +131,48 @@ public final class StyleSheet implements HDFType {
*/ */
public StyleSheet(byte[] tableStream, int offset) public StyleSheet(byte[] tableStream, int offset)
{ {
int startOffset = offset; int startOffset = offset;
_stshiLength = LittleEndian.getShort(tableStream, offset); _cbStshi = LittleEndian.getShort( tableStream, offset );
offset += LittleEndian.SHORT_SIZE; offset += LittleEndian.SHORT_SIZE;
int stdCount = LittleEndian.getShort(tableStream, offset);
offset += LittleEndian.SHORT_SIZE;
_baseLength = LittleEndian.getShort(tableStream, offset);
offset += LittleEndian.SHORT_SIZE;
_flags = LittleEndian.getShort(tableStream, offset);
offset += LittleEndian.SHORT_SIZE;
_maxIndex = LittleEndian.getShort(tableStream, offset);
offset += LittleEndian.SHORT_SIZE;
_maxFixedIndex = LittleEndian.getShort(tableStream, offset);
offset += LittleEndian.SHORT_SIZE;
_stylenameVersion = LittleEndian.getShort(tableStream, offset);
offset += LittleEndian.SHORT_SIZE;
_rgftc = new int[3]; /*
_rgftc[0] = LittleEndian.getShort(tableStream, offset); * Count of styles in stylesheet
offset += LittleEndian.SHORT_SIZE; *
_rgftc[1] = LittleEndian.getShort(tableStream, offset); * The number of styles in this style sheet. There will be stshi.cstd
offset += LittleEndian.SHORT_SIZE; * (cbSTD, STD) pairs in the file following the STSHI. Note: styles can
_rgftc[2] = LittleEndian.getShort(tableStream, offset); * be empty, i.e. cbSTD==0.
offset += LittleEndian.SHORT_SIZE; */
int cstd = LittleEndian.getUShort( tableStream, offset );
offset += LittleEndian.SHORT_SIZE;
offset = startOffset + LittleEndian.SHORT_SIZE + _stshiLength; _cbSTDBaseInFile = LittleEndian.getUShort( tableStream, offset );
_styleDescriptions = new StyleDescription[stdCount]; offset += LittleEndian.SHORT_SIZE;
for(int x = 0; x < stdCount; x++)
_flags = LittleEndian.getShort( tableStream, offset );
offset += LittleEndian.SHORT_SIZE;
_stiMaxWhenSaved = LittleEndian.getUShort( tableStream, offset );
offset += LittleEndian.SHORT_SIZE;
_istdMaxFixedWhenSaved = LittleEndian.getUShort( tableStream, offset );
offset += LittleEndian.SHORT_SIZE;
nVerBuiltInNamesWhenSaved = LittleEndian.getUShort( tableStream, offset );
offset += LittleEndian.SHORT_SIZE;
_rgftcStandardChpStsh = new int[3];
_rgftcStandardChpStsh[0] = LittleEndian.getShort( tableStream, offset );
offset += LittleEndian.SHORT_SIZE;
_rgftcStandardChpStsh[1] = LittleEndian.getShort( tableStream, offset );
offset += LittleEndian.SHORT_SIZE;
_rgftcStandardChpStsh[2] = LittleEndian.getShort( tableStream, offset );
offset += LittleEndian.SHORT_SIZE;
// shall we discard cbLSD and mpstilsd?
offset = startOffset + LittleEndian.SHORT_SIZE + _cbStshi;
_styleDescriptions = new StyleDescription[cstd];
for(int x = 0; x < cstd; x++)
{ {
int stdSize = LittleEndian.getShort(tableStream, offset); int stdSize = LittleEndian.getShort(tableStream, offset);
//get past the size //get past the size
@ -103,7 +182,7 @@ public final class StyleSheet implements HDFType {
//byte[] std = new byte[stdSize]; //byte[] std = new byte[stdSize];
StyleDescription aStyle = new StyleDescription(tableStream, StyleDescription aStyle = new StyleDescription(tableStream,
_baseLength, offset, true); _cbSTDBaseInFile, offset, true);
_styleDescriptions[x] = aStyle; _styleDescriptions[x] = aStyle;
} }
@ -124,29 +203,39 @@ public final class StyleSheet implements HDFType {
public void writeTo(HWPFOutputStream out) public void writeTo(HWPFOutputStream out)
throws IOException throws IOException
{ {
int offset = 0; int offset = 0;
/*
* we don't support 2003 Word extensions in STSHI (but may be we should
* at least not delete them, shouldn't we?), so our structure is always
* 18 bytes in length -- sergey
*/
this._cbStshi = 18;
// add two bytes so we can prepend the stylesheet w/ its size // add two bytes so we can prepend the stylesheet w/ its size
byte[] buf = new byte[_stshiLength + 2]; byte[] buf = new byte[_cbStshi + 2];
LittleEndian.putShort(buf, offset, (short)_stshiLength);
LittleEndian.putUShort(buf, offset, (short)_cbStshi);
offset += LittleEndian.SHORT_SIZE; offset += LittleEndian.SHORT_SIZE;
LittleEndian.putShort(buf, offset, (short)_styleDescriptions.length); LittleEndian.putUShort(buf, offset, (short)_styleDescriptions.length);
offset += LittleEndian.SHORT_SIZE; offset += LittleEndian.SHORT_SIZE;
LittleEndian.putShort(buf, offset, (short)_baseLength); LittleEndian.putUShort(buf, offset, (short)_cbSTDBaseInFile);
offset += LittleEndian.SHORT_SIZE; offset += LittleEndian.SHORT_SIZE;
LittleEndian.putShort(buf, offset, (short)_flags); LittleEndian.putShort(buf, offset, (short)_flags);
offset += LittleEndian.SHORT_SIZE; offset += LittleEndian.SHORT_SIZE;
LittleEndian.putShort(buf, offset, (short)_maxIndex); LittleEndian.putUShort(buf, offset, (short)_stiMaxWhenSaved);
offset += LittleEndian.SHORT_SIZE; offset += LittleEndian.SHORT_SIZE;
LittleEndian.putShort(buf, offset, (short)_maxFixedIndex); LittleEndian.putUShort(buf, offset, (short)_istdMaxFixedWhenSaved);
offset += LittleEndian.SHORT_SIZE; offset += LittleEndian.SHORT_SIZE;
LittleEndian.putShort(buf, offset, (short)_stylenameVersion); LittleEndian.putUShort(buf, offset, (short)nVerBuiltInNamesWhenSaved);
offset += LittleEndian.SHORT_SIZE; offset += LittleEndian.SHORT_SIZE;
LittleEndian.putShort(buf, offset, (short)_rgftc[0]); LittleEndian.putShort(buf, offset, (short)_rgftcStandardChpStsh[0]);
offset += LittleEndian.SHORT_SIZE; offset += LittleEndian.SHORT_SIZE;
LittleEndian.putShort(buf, offset, (short)_rgftc[1]); LittleEndian.putShort(buf, offset, (short)_rgftcStandardChpStsh[1]);
offset += LittleEndian.SHORT_SIZE; offset += LittleEndian.SHORT_SIZE;
LittleEndian.putShort(buf, offset, (short)_rgftc[2]); LittleEndian.putShort(buf, offset, (short)_rgftcStandardChpStsh[2]);
out.write(buf); out.write(buf);
@ -180,11 +269,11 @@ public final class StyleSheet implements HDFType {
{ {
StyleSheet ss = (StyleSheet)o; StyleSheet ss = (StyleSheet)o;
if (ss._baseLength == _baseLength && ss._flags == _flags && if (ss._cbSTDBaseInFile == _cbSTDBaseInFile && ss._flags == _flags &&
ss._maxFixedIndex ==_maxFixedIndex && ss._maxIndex == _maxIndex && ss._istdMaxFixedWhenSaved ==_istdMaxFixedWhenSaved && ss._stiMaxWhenSaved == _stiMaxWhenSaved &&
ss._rgftc[0] == _rgftc[0] && ss._rgftc[1] == _rgftc[1] && ss._rgftcStandardChpStsh[0] == _rgftcStandardChpStsh[0] && ss._rgftcStandardChpStsh[1] == _rgftcStandardChpStsh[1] &&
ss._rgftc[2] == _rgftc[2] && ss._stshiLength == _stshiLength && ss._rgftcStandardChpStsh[2] == _rgftcStandardChpStsh[2] && ss._cbStshi == _cbStshi &&
ss._stylenameVersion == _stylenameVersion) ss.nVerBuiltInNamesWhenSaved == nVerBuiltInNamesWhenSaved)
{ {
if (ss._styleDescriptions.length == _styleDescriptions.length) if (ss._styleDescriptions.length == _styleDescriptions.length)
{ {