--- src/scratchpad/src/org/apache/poi/hwpf/usermodel/ListEntry.java (revision 1005818) +++ src/scratchpad/src/org/apache/poi/hwpf/usermodel/ListEntry.java (working copy) @@ -22,6 +22,8 @@ import org.apache.poi.hwpf.model.ListLevel; import org.apache.poi.hwpf.model.ListTables; import org.apache.poi.hwpf.model.PAPX; +import org.apache.poi.hwpf.sprm.CharacterSprmUncompressor; +import org.apache.poi.hwpf.sprm.ParagraphSprmUncompressor; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -32,15 +34,36 @@ ListLevel _level; ListFormatOverrideLevel _overrideLevel; - + + CharacterProperties _numberProps; + ListEntry(PAPX papx, Range parent, ListTables tables) { super(papx, parent); - + if(tables != null) { ListFormatOverride override = tables.getOverride(_props.getIlfo()); _overrideLevel = override.getOverrideLevel(_props.getIlvl()); - _level = tables.getLevel(override.getLsid(), _props.getIlvl()); + if (_overrideLevel != null && _overrideLevel.isFormatting()) + _level = _overrideLevel.getLevel(); + else + _level = tables.getLevel(override.getLsid(), _props.getIlvl()); + + // first process SPRMs from the level, then from papx + _props = ParagraphSprmUncompressor.uncompressPAP(_doc.getStyleSheet().getParagraphStyle(papx.getIstd()), _level.getLevelProperties(), 0); + _props = ParagraphSprmUncompressor.uncompressPAP(_props, papx.getGrpprl(), 2); + + // FIXME Base character properties are taken from the first CharacterRun in the paragraph. This is not fully correct, but + // I don't know a better way. If whole paragraph is formatted some way, the number gets formatted as well, but the SPRM + // is not stored in _level.getNumberProperties(), but is somehow taken from the paragraph. If we base it on StyleSheet, + // we do not take this formatting. But if only the first word is formatted (i.e. the first CharacterRun), we format the number + // incorrectly. + CharacterProperties baseCharacterProperties; + if (numCharacterRuns() > 0) + baseCharacterProperties = getCharacterRun(0).cloneProperties(); + else + baseCharacterProperties = _doc.getStyleSheet().getCharacterStyle(getStyleIndex()); + _numberProps = CharacterSprmUncompressor.uncompressCHP(baseCharacterProperties, _level.getNumberProperties(), 0); } else { log.log(POILogger.WARN, "No ListTables found for ListEntry - document probably partly corrupt, and you may experience problems"); } @@ -50,4 +73,9 @@ { return TYPE_LISTENTRY; } + + public CharacterProperties getNumberProperties() { + return _numberProps; + } + } --- src/scratchpad/src/org/apache/poi/hwpf/model/ListLevel.java (revision 1005818) +++ src/scratchpad/src/org/apache/poi/hwpf/model/ListLevel.java (working copy) @@ -91,7 +91,7 @@ System.arraycopy(buf, offset, _rgbxchNums, 0, RGBXCH_NUMS_SIZE); offset += RGBXCH_NUMS_SIZE; - _ixchFollow = buf[offset++]; + _ixchFollow = buf[offset++]; _dxaSpace = LittleEndian.getInt(buf, offset); offset += LittleEndian.INT_SIZE; _dxaIndent = LittleEndian.getInt(buf, offset); @@ -129,6 +129,71 @@ return _iStartAt; } + /** + * From specification: + * + *
nfc value | Numbering scheme |
---|---|
0 | Arabic (1, 2, 3) |
1 | Uppercase Roman numeral (I, II, III) |
2 | Lowercase Roman numeral (i, ii, iii) |
3 | Uppercase letter (A, B, C) |
4 | Lowercase letter (a, b, c) |
5 | Ordinal number (1st, 2nd, 3rd) |
6 | Cardinal text number (One, Two Three) |
7 | Ordinal text number (First, Second, Third) |
10 | Kanji numbering without the digit character (dbnum1). |
11 | Kanji numbering with the digit character (dbnum2). |
12 | 46 phonetic Katakana characters in "aiueo" order (aiueo). |
13 | 46 phonetic katakana characters in "iroha" order (iroha). |
14 | Double Byte character |
15 | Single Byte character |
16 | Kanji numbering 3 (dbnum3). |
17 | Kanji numbering 4 (dbnum4). |
18 | Circle numbering (circlenum). |
19 | Double-byte Arabic numbering |
20 | 46 phonetic double-byte Katakana characters (*aiueo*dbchar). |
21 | 46 phonetic double-byte katakana characters (*iroha*dbchar). |
22 | Arabic with leading zero (01, 02, 03, ..., 10, 11) |
23 | Bullet (no number at all) |
24 | Korean numbering 2 (ganada). |
25 | Korean numbering 1 (chosung). |
26 | Chinese numbering 1 (gb1). |
27 | Chinese numbering 2 (gb2). |
28 | Chinese numbering 3 (gb3). |
29 | Chinese numbering 4 (gb4). |
30 | Chinese Zodiac numbering 1 |
31 | Chinese Zodiac numbering 2 |
32 | Chinese Zodiac numbering 3 |
33 | Taiwanese double-byte numbering 1 |
34 | Taiwanese double-byte numbering 2 |
35 | Taiwanese double-byte numbering 3 |
36 | Taiwanese double-byte numbering 4 |
37 | Chinese double-byte numbering 1 |
38 | Chinese double-byte numbering 2 |
39 | Chinese double-byte numbering 3 |
40 | Chinese double-byte numbering 4 |
41 | Korean double-byte numbering 1 |
42 | Korean double-byte numbering 2 |
43 | Korean double-byte numbering 3 |
44 | Korean double-byte numbering 4 |
45 | Hebrew non-standard decimal |
46 | Arabic Alif Ba Tah |
47 | Hebrew Biblical standard |
48 | Arabic Abjad style |
49 | Hindi vowels |
50 | Hindi consonants |
51 | Hindi numbers |
52 | Hindi descriptive (cardinals) |
53 | Thai letters |
54 | Thai numbers |
55 | Thai descriptive (cardinals |
56 | Vietnamese descriptive (cardinals) |
57 | Page Number format - # - |
58 | Lower case Russian alphabet |
59 | Upper case Russian alphabet |