From 3c200abd02eb595f0c597dd7f54ef7bfc50d652e Mon Sep 17 00:00:00 2001 From: Sergey Vladimirov Date: Sun, 23 Sep 2012 12:56:32 +0000 Subject: [PATCH] refactor list format override structures (was marked with @Internal annotation) git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1389038 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hwpf/converter/AbstractWordUtils.java | 49 ++-- .../poi/hwpf/model/FIBFieldHandler.java | 4 +- .../poi/hwpf/model/FileInformationBlock.java | 61 +++- .../src/org/apache/poi/hwpf/model/LFO.java | 2 +- .../poi/hwpf/model/ListFormatOverride.java | 97 ------- .../poi/hwpf/model/types/LFOAbstractType.java | 147 +++++----- .../apache/poi/hwpf/usermodel/HWPFList.java | 262 +++++++++++++----- 7 files changed, 356 insertions(+), 266 deletions(-) delete mode 100644 src/scratchpad/src/org/apache/poi/hwpf/model/ListFormatOverride.java diff --git a/src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordUtils.java b/src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordUtils.java index 710ca2453..83fe7987a 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordUtils.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordUtils.java @@ -20,6 +20,8 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; import java.util.Set; import java.util.TreeSet; @@ -27,10 +29,8 @@ import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.HWPFDocumentCore; import org.apache.poi.hwpf.HWPFOldDocument; import org.apache.poi.hwpf.OldWordFileFormatException; -import org.apache.poi.hwpf.model.ListLevel; -import org.apache.poi.hwpf.model.ListTables; import org.apache.poi.hwpf.usermodel.BorderCode; -import org.apache.poi.hwpf.usermodel.Paragraph; +import org.apache.poi.hwpf.usermodel.HWPFList; import org.apache.poi.hwpf.usermodel.Table; import org.apache.poi.hwpf.usermodel.TableCell; import org.apache.poi.hwpf.usermodel.TableRow; @@ -226,32 +226,39 @@ public class AbstractWordUtils return stringBuilder.toString(); } - public static String getBulletText( ListTables listTables, - Paragraph paragraph, int listId ) + public static class NumberingState { + + private final Map levels = new HashMap(); + + } + + public static String getBulletText(NumberingState numberingState, HWPFList list, char level ) { - final ListLevel listLevel = listTables.getLevel( listId, - paragraph.getIlvl() ); - - if ( listLevel==null || listLevel.getNumberText() == null ) - return EMPTY; - StringBuffer bulletBuffer = new StringBuffer(); - char[] xst = listLevel.getNumberText().toCharArray(); + char[] xst = list.getNumberText( level ).toCharArray(); for ( char element : xst ) { if ( element < 9 ) { - ListLevel numLevel = listTables.getLevel( listId, element ); - - int num = numLevel.getStartAt(); - bulletBuffer.append( NumberFormatter.getNumber( num, - listLevel.getNumberFormat() ) ); - - if ( numLevel == listLevel ) + final String key = list.getLsid() + "#" + ( (int) element ); + int num; + if ( numberingState.levels.containsKey( key ) ) { - numLevel.setStartAt( numLevel.getStartAt() + 1 ); + num = numberingState.levels.get( key ).intValue(); + } + else + { + num = list.getStartAt( level ); + numberingState.levels.put( key, Integer.valueOf( num ) ); } + bulletBuffer.append( NumberFormatter.getNumber( num, + list.getNumberFormat( level ) ) ); + + if ( level == element ) + { + numberingState.levels.put( key, Integer.valueOf( num + 1 ) ); + } } else { @@ -259,7 +266,7 @@ public class AbstractWordUtils } } - byte follow = listLevel.getTypeOfCharFollowingTheNumber(); + byte follow = list.getTypeOfCharFollowingTheNumber(level); switch ( follow ) { case 0: diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/FIBFieldHandler.java b/src/scratchpad/src/org/apache/poi/hwpf/model/FIBFieldHandler.java index 1ef29fdd6..9d61d8abb 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/FIBFieldHandler.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/FIBFieldHandler.java @@ -120,7 +120,9 @@ public final class FIBFieldHandler public static final int ROUTESLIP = 70; public static final int STTBSAVEDBY = 71; public static final int STTBFNM = 72; - public static final int PLCFLST = 73; + public static final int PLFLST = 73; + @Deprecated + public static final int PLCFLST = PLFLST; public static final int PLFLFO = 74; public static final int PLCFTXBXBKD = 75;//validated public static final int PLCFTXBXHDRBKD = 76; 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 d09a2db0e..89161055d 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java @@ -229,7 +229,7 @@ public final class FileInformationBlock implements Cloneable knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLCFBTECHPX ) ); knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLCFBTEPAPX ) ); knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLCFSED ) ); - knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLCFLST ) ); + knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLFLST ) ); knownFieldSet.add( Integer.valueOf( FIBFieldHandler.PLFLFO ) ); // field info @@ -457,29 +457,78 @@ public final class FileInformationBlock implements Cloneable _fieldHandler.setFieldSize(FIBFieldHandler.PLCFSED, lcbPlcfSed); } + @Deprecated public int getFcPlcfLst() { return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCFLST); } + /** + * An unsigned integer that specifies an offset in the Table Stream. A + * PlfLst that contains list formatting information begins at this offset. + * An array of LVLs is appended to the PlfLst. lcbPlfLst does not account + * for the array of LVLs. The size of the array of LVLs is specified by the + * LSTFs in PlfLst. For each LSTF whose fSimpleList is set to 0x1, there is + * one LVL in the array of LVLs that specifies the level formatting of the + * single level in the list which corresponds to the LSTF. And, for each + * LSTF whose fSimpleList is set to 0x0, there are 9 LVLs in the array of + * LVLs that specify the level formatting of the respective levels in the + * list which corresponds to the LSTF. This array of LVLs is in the same + * respective order as the LSTFs in PlfLst. If lcbPlfLst is 0, fcPlfLst is + * undefined and MUST be ignored. + *

+ * Quote from + * "[MS-DOC] -- v20110315, Word (.doc) Binary File Format; page 76 / 621" + */ + public int getFcPlfLst() + { + return _fieldHandler.getFieldOffset( FIBFieldHandler.PLFLST ); + } + + @Deprecated public int getLcbPlcfLst() { return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFLST); } - public void setFcPlcfLst(int fcPlcfLst) + public int getLcbPlfLst() { - _fieldHandler.setFieldOffset(FIBFieldHandler.PLCFLST, fcPlcfLst); + return _fieldHandler.getFieldSize( FIBFieldHandler.PLFLST ); } - public void setLcbPlcfLst(int lcbPlcfLst) + @Deprecated + public void setFcPlcfLst( int fcPlcfLst ) { - _fieldHandler.setFieldSize(FIBFieldHandler.PLCFLST, lcbPlcfLst); + _fieldHandler.setFieldOffset( FIBFieldHandler.PLCFLST, fcPlcfLst ); } + public void setFcPlfLst( int fcPlfLst ) + { + _fieldHandler.setFieldOffset( FIBFieldHandler.PLFLST, fcPlfLst ); + } + + @Deprecated + public void setLcbPlcfLst( int lcbPlcfLst ) + { + _fieldHandler.setFieldSize( FIBFieldHandler.PLCFLST, lcbPlcfLst ); + } + + public void setLcbPlfLst( int lcbPlfLst ) + { + _fieldHandler.setFieldSize( FIBFieldHandler.PLFLST, lcbPlfLst ); + } + + /** + * An unsigned integer that specifies an offset in the Table Stream. A + * PlfLfo that contains list formatting override information begins at this + * offset. If lcbPlfLfo is zero, fcPlfLfo is undefined and MUST be ignored. + *

+ * Quote from + * "[MS-DOC] -- v20110315, Word (.doc) Binary File Format; page 76 / 621" + */ public int getFcPlfLfo() { - return _fieldHandler.getFieldOffset(FIBFieldHandler.PLFLFO); + return _fieldHandler.getFieldOffset( FIBFieldHandler.PLFLFO ); } public int getLcbPlfLfo() diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/LFO.java b/src/scratchpad/src/org/apache/poi/hwpf/model/LFO.java index 4d8d09960..edc069964 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/LFO.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/LFO.java @@ -29,7 +29,7 @@ import org.apache.poi.hwpf.model.types.LFOAbstractType; * @author Sergey Vladimirov (vlsergey {at} gmail {dot} com) */ @Internal -class LFO extends LFOAbstractType +public class LFO extends LFOAbstractType { public LFO() { diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/ListFormatOverride.java b/src/scratchpad/src/org/apache/poi/hwpf/model/ListFormatOverride.java deleted file mode 100644 index c9ab49e14..000000000 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/ListFormatOverride.java +++ /dev/null @@ -1,97 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hwpf.model; - -import org.apache.poi.util.Internal; - -@Internal -public final class ListFormatOverride -{ - private LFO _lfo; - - private LFOData _lfoData; - - public ListFormatOverride( byte[] buf, int offset ) - { - _lfo = new LFO( buf, offset ); - } - - public ListFormatOverride( int lsid ) - { - _lfo = new LFO(); - _lfo.setLsid( lsid ); - } - - public ListFormatOverrideLevel[] getLevelOverrides() - { - return _lfoData.getRgLfoLvl(); - } - - LFO getLfo() - { - return _lfo; - } - - LFOData getLfoData() - { - return _lfoData; - } - - public int getLsid() - { - return _lfo.getLsid(); - } - - public ListFormatOverrideLevel getOverrideLevel( int level ) - { - ListFormatOverrideLevel retLevel = null; - for ( int x = 0; x < getLevelOverrides().length; x++ ) - { - if ( getLevelOverrides()[x].getLevelNum() == level ) - { - retLevel = getLevelOverrides()[x]; - } - } - return retLevel; - } - - public int numOverrides() - { - return _lfo.getClfolvl(); - } - - void setLfoData( LFOData _lfoData ) - { - this._lfoData = _lfoData; - } - - public void setLsid( int lsid ) - { - _lfo.setLsid( lsid ); - } - - public void setOverride( int index, ListFormatOverrideLevel lfolvl ) - { - getLevelOverrides()[index] = lfolvl; - } - - public byte[] toByteArray() - { - return _lfo.serialize(); - } -} diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/LFOAbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/LFOAbstractType.java index f747435e9..e36017e65 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/types/LFOAbstractType.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/types/LFOAbstractType.java @@ -21,31 +21,32 @@ import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; /** - * List Format Override (LFO).

Class and fields descriptions are quoted from - Microsoft Office Word 97-2007 Binary File Format - + * List Format Override (LFO). *

- * NOTE: This source is automatically generated please do not modify this file. Either subclass or - * remove the record in src/types/definitions. + * Class and fields descriptions are quoted from [MS-DOC] --v20110315; Word + * (.doc) Binary File Format + * *

- * This class is internal. It content or properties may change without notice + * NOTE: This source is automatically generated please do not modify this file. + * Either subclass or remove the record in src/types/definitions. + *

+ * This class is internal. It content or properties may change without notice * due to changes in our knowledge of internal Microsoft Word binary structures. - - * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary File Format - Specification [*.doc] - + * + * @author Sergey Vladimirov; according to [MS-DOC] --v20110315; Word (.doc) + * Binary File Format; Copyright (c) Microsoft Corporation */ @Internal public abstract class LFOAbstractType { protected int field_1_lsid; - protected int field_2_reserved1; - protected int field_3_reserved2; + protected int field_2_unused1; + protected int field_3_unused2; protected byte field_4_clfolvl; protected byte field_5_ibstFltAutoNum; protected Grfhic field_6_grfhic; - protected byte field_7_reserved3; + protected byte field_7_unused3; protected LFOAbstractType() { @@ -54,29 +55,29 @@ public abstract class LFOAbstractType protected void fillFields( byte[] data, int offset ) { - field_1_lsid = LittleEndian.getInt( data, 0x0 + offset ); - field_2_reserved1 = LittleEndian.getInt( data, 0x4 + offset ); - field_3_reserved2 = LittleEndian.getInt( data, 0x8 + offset ); - field_4_clfolvl = data[ 0xc + offset ]; - field_5_ibstFltAutoNum = data[ 0xd + offset ]; - field_6_grfhic = new Grfhic( data, 0xe + offset ); - field_7_reserved3 = data[ 0xf + offset ]; + field_1_lsid = LittleEndian.getInt( data, 0x0 + offset ); + field_2_unused1 = LittleEndian.getInt( data, 0x4 + offset ); + field_3_unused2 = LittleEndian.getInt( data, 0x8 + offset ); + field_4_clfolvl = data[0xc + offset]; + field_5_ibstFltAutoNum = data[0xd + offset]; + field_6_grfhic = new Grfhic( data, 0xe + offset ); + field_7_unused3 = data[0xf + offset]; } public void serialize( byte[] data, int offset ) { LittleEndian.putInt( data, 0x0 + offset, field_1_lsid ); - LittleEndian.putInt( data, 0x4 + offset, field_2_reserved1 ); - LittleEndian.putInt( data, 0x8 + offset, field_3_reserved2 ); - data[ 0xc + offset ] = field_4_clfolvl; - data[ 0xd + offset ] = field_5_ibstFltAutoNum; + LittleEndian.putInt( data, 0x4 + offset, field_2_unused1 ); + LittleEndian.putInt( data, 0x8 + offset, field_3_unused2 ); + data[0xc + offset] = field_4_clfolvl; + data[0xd + offset] = field_5_ibstFltAutoNum; field_6_grfhic.serialize( data, 0xe + offset ); - data[ 0xf + offset ] = field_7_reserved3; + data[0xf + offset] = field_7_unused3; } public byte[] serialize() { - final byte[] result = new byte[ getSize() ]; + final byte[] result = new byte[getSize()]; serialize( result, 0 ); return result; } @@ -101,9 +102,9 @@ public abstract class LFOAbstractType LFOAbstractType other = (LFOAbstractType) obj; if ( field_1_lsid != other.field_1_lsid ) return false; - if ( field_2_reserved1 != other.field_2_reserved1 ) + if ( field_2_unused1 != other.field_2_unused1 ) return false; - if ( field_3_reserved2 != other.field_3_reserved2 ) + if ( field_3_unused2 != other.field_3_unused2 ) return false; if ( field_4_clfolvl != other.field_4_clfolvl ) return false; @@ -116,7 +117,7 @@ public abstract class LFOAbstractType } else if ( !field_6_grfhic.equals( other.field_6_grfhic ) ) return false; - if ( field_7_reserved3 != other.field_7_reserved3 ) + if ( field_7_unused3 != other.field_7_unused3 ) return false; return true; } @@ -127,40 +128,42 @@ public abstract class LFOAbstractType final int prime = 31; int result = 1; result = prime * result + field_1_lsid; - result = prime * result + field_2_reserved1; - result = prime * result + field_3_reserved2; + result = prime * result + field_2_unused1; + result = prime * result + field_3_unused2; result = prime * result + field_4_clfolvl; result = prime * result + field_5_ibstFltAutoNum; result = prime * result + field_6_grfhic.hashCode(); - result = prime * result + field_7_reserved3; + result = prime * result + field_7_unused3; return result; } public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("[LFO]\n"); - builder.append(" .lsid = "); - builder.append(" (").append(getLsid()).append(" )\n"); - builder.append(" .reserved1 = "); - builder.append(" (").append(getReserved1()).append(" )\n"); - builder.append(" .reserved2 = "); - builder.append(" (").append(getReserved2()).append(" )\n"); - builder.append(" .clfolvl = "); - builder.append(" (").append(getClfolvl()).append(" )\n"); - builder.append(" .ibstFltAutoNum = "); - builder.append(" (").append(getIbstFltAutoNum()).append(" )\n"); - builder.append(" .grfhic = "); - builder.append(" (").append(getGrfhic()).append(" )\n"); - builder.append(" .reserved3 = "); - builder.append(" (").append(getReserved3()).append(" )\n"); + builder.append( "[LFO]\n" ); + builder.append( " .lsid = " ); + builder.append( " (" ).append( getLsid() ).append( " )\n" ); + builder.append( " .unused1 = " ); + builder.append( " (" ).append( getUnused1() ).append( " )\n" ); + builder.append( " .unused2 = " ); + builder.append( " (" ).append( getUnused2() ).append( " )\n" ); + builder.append( " .clfolvl = " ); + builder.append( " (" ).append( getClfolvl() ).append( " )\n" ); + builder.append( " .ibstFltAutoNum = " ); + builder.append( " (" ).append( getIbstFltAutoNum() ).append( " )\n" ); + builder.append( " .grfhic = " ); + builder.append( " (" ).append( getGrfhic() ).append( " )\n" ); + builder.append( " .unused3 = " ); + builder.append( " (" ).append( getUnused3() ).append( " )\n" ); - builder.append("[/LFO]\n"); + builder.append( "[/LFO]\n" ); return builder.toString(); } /** - * List ID of corresponding LSTF (see LSTF). + * A signed integer that specifies the list identifier of an LSTF. This LFO + * corresponds to the LSTF in PlfLst.rgLstf that has an lsid whose value is + * equal to this value.. */ @Internal public int getLsid() @@ -169,7 +172,9 @@ public abstract class LFOAbstractType } /** - * List ID of corresponding LSTF (see LSTF). + * A signed integer that specifies the list identifier of an LSTF. This LFO + * corresponds to the LSTF in PlfLst.rgLstf that has an lsid whose value is + * equal to this value.. */ @Internal public void setLsid( int field_1_lsid ) @@ -178,43 +183,43 @@ public abstract class LFOAbstractType } /** - * Reserved. + * This field MUST be ignored. */ @Internal - public int getReserved1() + public int getUnused1() { - return field_2_reserved1; + return field_2_unused1; } /** - * Reserved. + * This field MUST be ignored. */ @Internal - public void setReserved1( int field_2_reserved1 ) + public void setUnused1( int field_2_unused1 ) { - this.field_2_reserved1 = field_2_reserved1; + this.field_2_unused1 = field_2_unused1; } /** - * Reserved. + * This field MUST be ignored. */ @Internal - public int getReserved2() + public int getUnused2() { - return field_3_reserved2; + return field_3_unused2; } /** - * Reserved. + * This field MUST be ignored. */ @Internal - public void setReserved2( int field_3_reserved2 ) + public void setUnused2( int field_3_unused2 ) { - this.field_3_reserved2 = field_3_reserved2; + this.field_3_unused2 = field_3_unused2; } /** - * Count of levels whose format is overridden (see LFOLVL). + * An unsigned integer that specifies the field that this LFO represents.. */ @Internal public byte getClfolvl() @@ -223,7 +228,7 @@ public abstract class LFOAbstractType } /** - * Count of levels whose format is overridden (see LFOLVL). + * An unsigned integer that specifies the field that this LFO represents.. */ @Internal public void setClfolvl( byte field_4_clfolvl ) @@ -268,21 +273,21 @@ public abstract class LFOAbstractType } /** - * Reserved. + * This field MUST be ignored. */ @Internal - public byte getReserved3() + public byte getUnused3() { - return field_7_reserved3; + return field_7_unused3; } /** - * Reserved. + * This field MUST be ignored. */ @Internal - public void setReserved3( byte field_7_reserved3 ) + public void setUnused3( byte field_7_unused3 ) { - this.field_7_reserved3 = field_7_reserved3; + this.field_7_unused3 = field_7_unused3; } -} // END OF CLASS +} // END OF CLASS diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/HWPFList.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/HWPFList.java index 8a4c3fa00..06e8ed2e7 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/HWPFList.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/HWPFList.java @@ -17,94 +17,218 @@ package org.apache.poi.hwpf.usermodel; -import org.apache.poi.hwpf.model.ListLevel; -import org.apache.poi.hwpf.model.ListData; -import org.apache.poi.hwpf.model.ListFormatOverride; -import org.apache.poi.hwpf.model.StyleSheet; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +import org.apache.poi.hwpf.model.ListTables; + +import org.apache.poi.util.Internal; + +import org.apache.poi.hwpf.model.LFO; +import org.apache.poi.hwpf.model.LFOData; +import org.apache.poi.hwpf.model.ListData; +import org.apache.poi.hwpf.model.ListLevel; +import org.apache.poi.hwpf.model.StyleSheet; import org.apache.poi.hwpf.sprm.CharacterSprmCompressor; import org.apache.poi.hwpf.sprm.ParagraphSprmCompressor; /** * This class is used to create a list in a Word document. It is used in - * conjunction with {@link - * org.apache.poi.hwpf.HWPFDocument#registerList(HWPFList) registerList} in - * {@link org.apache.poi.hwpf.HWPFDocument HWPFDocument}. - * - * In Word, lists are not ranged entities, meaning you can't actually add one - * to the document. Lists only act as properties for list entries. Once you + * conjunction with + * {@link org.apache.poi.hwpf.HWPFDocument#registerList(HWPFList) registerList} + * in {@link org.apache.poi.hwpf.HWPFDocument HWPFDocument}. + * + * In Word, lists are not ranged entities, meaning you can't actually add one to + * the document. Lists only act as properties for list entries. Once you * register a list, you can add list entries to a document that are a part of * the list. - * + * * The only benefit of this that I see, is that you can add a list entry * anywhere in the document and continue numbering from the previous list. - * + * * @author Ryan Ackley */ -public final class HWPFList { - private ListData _listData; - private ListFormatOverride _override; - private boolean _registered; - private StyleSheet _styleSheet; +public final class HWPFList +{ + private static POILogger log = POILogFactory.getLogger( HWPFList.class ); - /** - * - * @param numbered true if the list should be numbered; false if it should be - * bulleted. - * @param styleSheet The document's stylesheet. - */ - public HWPFList(boolean numbered, StyleSheet styleSheet) - { - _listData = new ListData((int)(Math.random() * System.currentTimeMillis()), numbered); - _override = new ListFormatOverride(_listData.getLsid()); - _styleSheet = styleSheet; - } + private boolean _ignoreLogicalLeftIdentation = false; + private LFO _lfo; + private LFOData _lfoData; + private ListData _listData; + private ListTables _listTables; + private boolean _registered; + private StyleSheet _styleSheet; - /** - * Sets the character properties of the list numbers. - * - * @param level the level number that the properties should apply to. - * @param chp The character properties. - */ - public void setLevelNumberProperties(int level, CharacterProperties chp) - { - ListLevel listLevel = _listData.getLevel(level); - int styleIndex = _listData.getLevelStyle(level); - CharacterProperties base = _styleSheet.getCharacterStyle(styleIndex); + /** + * + * @param numbered + * true if the list should be numbered; false if it should be + * bulleted. + * @param styleSheet + * The document's stylesheet. + */ + public HWPFList( boolean numbered, StyleSheet styleSheet ) + { + _listData = new ListData( + (int) ( Math.random() * System.currentTimeMillis() ), numbered ); + _lfo = new LFO(); + _lfo.setLsid( _listData.getLsid() ); + _lfoData = new LFOData(); + _styleSheet = styleSheet; + } - byte[] grpprl = CharacterSprmCompressor.compressCharacterProperty(chp, base); - listLevel.setNumberProperties(grpprl); - } + public HWPFList( StyleSheet styleSheet, ListTables listTables, int ilfo ) + { + _listTables = listTables; + _styleSheet = styleSheet; + _registered = true; - /** - * Sets the paragraph properties for a particular level of the list. - * - * @param level The level number. - * @param pap The paragraph properties - */ - public void setLevelParagraphProperties(int level, ParagraphProperties pap) - { - ListLevel listLevel = _listData.getLevel(level); - int styleIndex = _listData.getLevelStyle(level); - ParagraphProperties base = _styleSheet.getParagraphStyle(styleIndex); + /* See documentation for sprmPIlfo (0x460B) */ + if ( ilfo == 0 || ilfo == 0xF801 ) + { + throw new IllegalArgumentException( "Paragraph not in list" ); + } + else if ( 0x0001 <= ilfo && ilfo <= 0x07FE ) + { + _lfo = listTables.getLfo( ilfo ); + _lfoData = listTables.getLfoData( ilfo ); + } + else if ( 0xF802 <= ilfo && ilfo <= 0xFFFF ) + { + int nilfo = ilfo ^ 0xFFFF; + _lfo = listTables.getLfo( nilfo ); + _lfoData = listTables.getLfoData( nilfo ); + _ignoreLogicalLeftIdentation = true; + } + else + { + throw new IllegalArgumentException( "Incorrect ilfo: " + ilfo ); + } - byte[] grpprl = ParagraphSprmCompressor.compressParagraphProperty(pap, base); - listLevel.setLevelProperties(grpprl); - } + _listData = listTables.getListData( _lfo.getLsid() ); + } - public void setLevelStyle(int level, int styleIndex) - { - _listData.setLevelStyle(level, styleIndex); - } + @Internal + public LFO getLFO() + { + return _lfo; + } - public ListData getListData() - { - return _listData; - } + @Internal + public LFOData getLFOData() + { + return _lfoData; + } - public ListFormatOverride getOverride() - { - return _override; - } + @Internal + public ListData getListData() + { + return _listData; + } + public int getLsid() + { + return _lfo.getLsid(); + } + + @Internal + ListLevel getLVL( char level ) + { + if ( level >= _listData.numLevels() ) + { + throw new IllegalArgumentException( "Required level " + + ( (int) level ) + + " is more than number of level for list (" + + _listData.numLevels() + ")" ); + } + ListLevel lvl = _listData.getLevels()[level]; + return lvl; + } + + /** + * An MSONFC, as specified in [MS-OSHARED] section 2.2.1.3, that specifies + * the format of the level numbers that replace the placeholders for this + * level in the xst fields of the LVLs in this list. This value MUST not be + * equal to 0x08, 0x09, 0x0F, or 0x13. If this is equal to 0xFF or 0x17, + * this level does not have a number sequence and therefore has no number + * formatting. If this is equal to 0x17, the level uses bullets. + */ + public int getNumberFormat( char level ) + { + return getLVL( level ).getNumberFormat(); + } + + public String getNumberText( char level ) + { + return getLVL( level ).getNumberText(); + } + + public int getStartAt( char level ) + { + return getLVL( level ).getStartAt(); + } + + /** + * "The type of character following the number text for the paragraph: 0 == tab, 1 == space, 2 == nothing." + */ + public byte getTypeOfCharFollowingTheNumber( char level ) + { + return getLVL( level ).getTypeOfCharFollowingTheNumber(); + } + + public boolean isIgnoreLogicalLeftIdentation() + { + return _ignoreLogicalLeftIdentation; + } + + public void setIgnoreLogicalLeftIdentation( + boolean ignoreLogicalLeftIdentation ) + { + this._ignoreLogicalLeftIdentation = ignoreLogicalLeftIdentation; + } + + /** + * Sets the character properties of the list numbers. + * + * @param level + * the level number that the properties should apply to. + * @param chp + * The character properties. + */ + public void setLevelNumberProperties( int level, CharacterProperties chp ) + { + ListLevel listLevel = _listData.getLevel( level ); + int styleIndex = _listData.getLevelStyle( level ); + CharacterProperties base = _styleSheet.getCharacterStyle( styleIndex ); + + byte[] grpprl = CharacterSprmCompressor.compressCharacterProperty( chp, + base ); + listLevel.setNumberProperties( grpprl ); + } + + /** + * Sets the paragraph properties for a particular level of the list. + * + * @param level + * The level number. + * @param pap + * The paragraph properties + */ + public void setLevelParagraphProperties( int level, ParagraphProperties pap ) + { + ListLevel listLevel = _listData.getLevel( level ); + int styleIndex = _listData.getLevelStyle( level ); + ParagraphProperties base = _styleSheet.getParagraphStyle( styleIndex ); + + byte[] grpprl = ParagraphSprmCompressor.compressParagraphProperty( pap, + base ); + listLevel.setLevelProperties( grpprl ); + } + + public void setLevelStyle( int level, int styleIndex ) + { + _listData.setLevelStyle( level, styleIndex ); + } }