View | Details | Raw Unified | Return to bug 53979
Collapse All | Expand All

(-)src/scratchpad/src/org/apache/poi/hslf/record/TextAutoNumberSchemeEnum.java (+109 lines)
Line 0 Link Here
1
package org.apache.poi.hslf.record;
2
3
public enum TextAutoNumberSchemeEnum {
4
	//Name Value Meaning
5
	ANM_AlphaLcPeriod 			((short) 0x0000), // "Lowercase Latin character followed by a period. Example: a., b., c., ..."),
6
	ANM_AlphaUcPeriod 			((short) 0x0001), // "Uppercase Latin character followed by a period. Example: A., B., C., ..."),
7
	ANM_ArabicParenRight		((short) 0x0002), // "Arabic numeral followed by a closing parenthesis. Example: 1), 2), 3), ..."),
8
	ANM_ArabicPeriod			((short) 0x0003), // "Arabic numeral followed by a period. Example: 1., 2., 3., ..."),
9
	ANM_RomanLcParenBoth		((short) 0x0004), // "Lowercase Roman numeral enclosed in parentheses. Example: (i), (ii), (iii), ..."),            
10
	ANM_RomanLcParenRight		((short) 0x0005), // "Lowercase Roman numeral followed by a closing parenthesis. Example: i), ii), iii), ..."),     
11
	ANM_RomanLcPeriod			((short) 0x0006), // "Lowercase Roman numeral followed by a period. Example: i., ii., iii., ..."), 
12
	ANM_RomanUcPeriod			((short) 0x0007), // "Uppercase Roman numeral followed by a period. Example: I., II., III., ..."),
13
	ANM_AlphaLcParenBoth		((short) 0x0008), // "Lowercase alphabetic character enclosed in parentheses. Example: (a), (b), (c), ..."),
14
	ANM_AlphaLcParenRight		((short) 0x0009), // "Lowercase alphabetic character followed by a closing parenthesis. Example: a), b), c), ..."),
15
	ANM_AlphaUcParenBoth		((short) 0x000A), // "Uppercase alphabetic character enclosed in parentheses. Example: (A), (B), (C), ..."),
16
	ANM_AlphaUcParenRight		((short) 0x000B), // "Uppercase alphabetic character followed by a closing parenthesis. Example: A), B), C), ..."), 
17
	ANM_ArabicParenBoth			((short) 0x000C), // "Arabic numeral enclosed in parentheses. Example: (1), (2), (3), ..."),
18
	ANM_ArabicPlain				((short) 0x000D), // "Arabic numeral. Example: 1, 2, 3, ..."),
19
	ANM_RomanUcParenBoth		((short) 0x000E), // "Uppercase Roman numeral enclosed in parentheses. Example: (I), (II), (III), ..."),
20
	ANM_RomanUcParenRight		((short) 0x000F), // "Uppercase Roman numeral followed by a closing parenthesis. Example: I), II), III), ..."),
21
	ANM_ChsPlain				((short) 0x0010), // "Simplified Chinese."),
22
	ANM_ChsPeriod				((short) 0x0011), // "Simplified Chinese with single-byte period."),
23
	ANM_CircleNumDBPlain		((short) 0x0012), // "Double byte circle numbers."),
24
	ANM_CircleNumWDBWhitePlain	((short) 0x0013), // "Wingdings white circle numbers."),
25
	ANM_CircleNumWDBBlackPlain	((short) 0x0014), // "Wingdings black circle numbers."),
26
	ANM_ChtPlain				((short) 0x0015), // "Traditional Chinese."),
27
	ANM_ChtPeriod				((short) 0x0016), // "Traditional Chinese with single-byte period."),
28
	ANM_Arabic1Minus			((short) 0x0017), // "Bidi Arabic 1 (AraAlpha) with ANSI minus symbol."),
29
	ANM_Arabic2Minus			((short) 0x0018), // "Bidi Arabic 2 (AraAbjad) with ANSI minus symbol."),
30
	ANM_Hebrew2Minus			((short) 0x0019), // "Bidi Hebrew 2 with ANSI minus symbol."),
31
	ANM_JpnKorPlain				((short) 0x001A), // "Japanese/Korean."),
32
	ANM_JpnKorPeriod			((short) 0x001B), // "Japanese/Korean with single-byte period."),
33
	ANM_ArabicDbPlain			((short) 0x001C), // "Double-byte Arabic numbers."),
34
	ANM_ArabicDbPeriod			((short) 0x001D), // "Double-byte Arabic numbers with double-byte period."),
35
	ANM_ThaiAlphaPeriod			((short) 0x001E), // "Thai alphabetic character followed by a period."),
36
	ANM_ThaiAlphaParenRight		((short) 0x001F), // "Thai alphabetic character followed by a closing parenthesis."),
37
	ANM_ThaiAlphaParenBoth		((short) 0x0020), // "Thai alphabetic character enclosed by parentheses."),
38
	ANM_ThaiNumPeriod			((short) 0x0021), // "Thai numeral followed by a period."),
39
	ANM_ThaiNumParenRight		((short) 0x0022), // "Thai numeral followed by a closing parenthesis."),
40
	ANM_ThaiNumParenBoth		((short) 0x0023), // "Thai numeral enclosed in parentheses."),
41
	ANM_HindiAlphaPeriod		((short) 0x0024), // "Hindi alphabetic character followed by a period."),
42
	ANM_HindiNumPeriod			((short) 0x0025), // "Hindi numeric character followed by a period."),
43
	ANM_JpnChsDBPeriod			((short) 0x0026), // "Japanese with double-byte period."),
44
	ANM_HindiNumParenRight		((short) 0x0027), // "Hindi numeric character followed by a closing parenthesis."),
45
	ANM_HindiAlpha1Period		((short) 0x0028); // "Hindi alphabetic character followed by a period.");
46
47
	private final short value;
48
	private TextAutoNumberSchemeEnum(final short code) {
49
		this.value = code;
50
	}
51
	private short getValue() { return value; }
52
	public String getDescription() {
53
		return TextAutoNumberSchemeEnum.getDescription(this);
54
	}
55
	public static String getDescription(final TextAutoNumberSchemeEnum code) {
56
		switch (code) {
57
		case ANM_AlphaLcPeriod			: return "Lowercase Latin character followed by a period. Example: a., b., c., ...";
58
		case ANM_AlphaUcPeriod 			: return "Uppercase Latin character followed by a period. Example: A., B., C., ...";
59
		case ANM_ArabicParenRight		: return "Arabic numeral followed by a closing parenthesis. Example: 1), 2), 3), ...";
60
		case ANM_ArabicPeriod			: return "Arabic numeral followed by a period. Example: 1., 2., 3., ...";
61
		case ANM_RomanLcParenBoth		: return "Lowercase Roman numeral enclosed in parentheses. Example: (i), (ii), (iii), ...";            
62
		case ANM_RomanLcParenRight		: return "Lowercase Roman numeral followed by a closing parenthesis. Example: i), ii), iii), ...";     
63
		case ANM_RomanLcPeriod			: return "Lowercase Roman numeral followed by a period. Example: i., ii., iii., ...";
64
		case ANM_RomanUcPeriod			: return "Uppercase Roman numeral followed by a period. Example: I., II., III., ...";
65
		case ANM_AlphaLcParenBoth		: return "Lowercase alphabetic character enclosed in parentheses. Example: (a), (b), (c), ...";
66
		case ANM_AlphaLcParenRight		: return "Lowercase alphabetic character followed by a closing parenthesis. Example: a), b), c), ...";
67
		case ANM_AlphaUcParenBoth		: return "Uppercase alphabetic character enclosed in parentheses. Example: (A), (B), (C), ...";
68
		case ANM_AlphaUcParenRight		: return "Uppercase alphabetic character followed by a closing parenthesis. Example: A), B), C), ..."; 
69
		case ANM_ArabicParenBoth		: return "Arabic numeral enclosed in parentheses. Example: (1), (2), (3), ...";
70
		case ANM_ArabicPlain			: return "Arabic numeral. Example: 1, 2, 3, ...";
71
		case ANM_RomanUcParenBoth		: return "Uppercase Roman numeral enclosed in parentheses. Example: (I), (II), (III), ...";
72
		case ANM_RomanUcParenRight		: return "Uppercase Roman numeral followed by a closing parenthesis. Example: I), II), III), ...";
73
		case ANM_ChsPlain				: return "Simplified Chinese.";
74
		case ANM_ChsPeriod				: return "Simplified Chinese with single-byte period.";
75
		case ANM_CircleNumDBPlain		: return "Double byte circle numbers.";
76
		case ANM_CircleNumWDBWhitePlain	: return "Wingdings white circle numbers.";
77
		case ANM_CircleNumWDBBlackPlain	: return "Wingdings black circle numbers.";
78
		case ANM_ChtPlain				: return "Traditional Chinese.";
79
		case ANM_ChtPeriod				: return "Traditional Chinese with single-byte period.";
80
		case ANM_Arabic1Minus			: return "Bidi Arabic 1 (AraAlpha) with ANSI minus symbol.";
81
		case ANM_Arabic2Minus			: return "Bidi Arabic 2 (AraAbjad) with ANSI minus symbol.";
82
		case ANM_Hebrew2Minus			: return "Bidi Hebrew 2 with ANSI minus symbol.";
83
		case ANM_JpnKorPlain			: return "Japanese/Korean.";
84
		case ANM_JpnKorPeriod			: return "Japanese/Korean with single-byte period.";
85
		case ANM_ArabicDbPlain			: return "Double-byte Arabic numbers.";
86
		case ANM_ArabicDbPeriod			: return "Double-byte Arabic numbers with double-byte period.";
87
		case ANM_ThaiAlphaPeriod		: return "Thai alphabetic character followed by a period.";
88
		case ANM_ThaiAlphaParenRight	: return "Thai alphabetic character followed by a closing parenthesis.";
89
		case ANM_ThaiAlphaParenBoth		: return "Thai alphabetic character enclosed by parentheses.";
90
		case ANM_ThaiNumPeriod			: return "Thai numeral followed by a period.";
91
		case ANM_ThaiNumParenRight		: return "Thai numeral followed by a closing parenthesis.";
92
		case ANM_ThaiNumParenBoth		: return "Thai numeral enclosed in parentheses.";
93
		case ANM_HindiAlphaPeriod		: return "Hindi alphabetic character followed by a period.";
94
		case ANM_HindiNumPeriod			: return "Hindi numeric character followed by a period.";
95
		case ANM_JpnChsDBPeriod			: return "Japanese with double-byte period.";
96
		case ANM_HindiNumParenRight		: return "Hindi numeric character followed by a closing parenthesis.";
97
		case ANM_HindiAlpha1Period		: return "Hindi alphabetic character followed by a period.";
98
		default							: return "Unknown Numbered Scheme";
99
		}
100
	}
101
	public static TextAutoNumberSchemeEnum valueOf(short autoNumberScheme) {
102
		for (TextAutoNumberSchemeEnum item: TextAutoNumberSchemeEnum.values()) {
103
			if (autoNumberScheme == item.getValue()) {
104
				return item;
105
			}
106
		}
107
		return null;
108
	}
109
}
(-)src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java (-2 / +2 lines)
Lines 169-175 Link Here
169
                    TextBytesAtom tba = (TextBytesAtom) records[i + 1];
169
                    TextBytesAtom tba = (TextBytesAtom) records[i + 1];
170
                    trun = new TextRun(tha, tba, stpa);
170
                    trun = new TextRun(tha, tba, stpa);
171
                } else if (records[i + 1].getRecordType() == 4001l) {
171
                } else if (records[i + 1].getRecordType() == 4001l) {
172
                    // StyleTextPropAtom - Safe to ignore
172
                	stpa = (StyleTextPropAtom) records[i + 1];
173
                } else if (records[i + 1].getRecordType() == 4010l) {
173
                } else if (records[i + 1].getRecordType() == 4010l) {
174
                    // TextSpecInfoAtom - Safe to ignore
174
                    // TextSpecInfoAtom - Safe to ignore
175
                } else {
175
                } else {
Lines 177-183 Link Here
177
                }
177
                }
178
178
179
                if (trun != null) {
179
                if (trun != null) {
180
                    ArrayList lst = new ArrayList();
180
                    List<Record> lst = new ArrayList<Record>();
181
                    for (int j = i; j < records.length; j++) {
181
                    for (int j = i; j < records.length; j++) {
182
                        if(j > i && records[j] instanceof TextHeaderAtom) break;
182
                        if(j > i && records[j] instanceof TextHeaderAtom) break;
183
                        lst.add(records[j]);
183
                        lst.add(records[j]);
(-)src/scratchpad/src/org/apache/poi/hslf/record/StyleTextProp9Atom.java (+146 lines)
Line 0 Link Here
1
/* ====================================================================
2
   Licensed to the Apache Software Foundation (ASF) under one or more
3
   contributor license agreements.  See the NOTICE file distributed with
4
   this work for additional information regarding copyright ownership.
5
   The ASF licenses this file to You under the Apache License, Version 2.0
6
   (the "License"); you may not use this file except in compliance with
7
   the License.  You may obtain a copy of the License at
8
9
       http://www.apache.org/licenses/LICENSE-2.0
10
11
   Unless required by applicable law or agreed to in writing, software
12
   distributed under the License is distributed on an "AS IS" BASIS,
13
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
   See the License for the specific language governing permissions and
15
   limitations under the License.
16
==================================================================== */
17
18
package org.apache.poi.hslf.record;
19
20
import java.io.IOException;
21
import java.io.OutputStream;
22
import java.util.LinkedList;
23
import java.util.List;
24
25
import org.apache.poi.util.LittleEndian;
26
27
/**
28
 * The atom record that specifies additional text formatting.
29
 *
30
 * @author Alex Nikiforov [mailto:anikif@gmail.com]
31
 */
32
public final class StyleTextProp9Atom extends RecordAtom {
33
	private final static byte[] MARKER = {0, 0, (byte)0x80, 3, (byte)255, (byte)255, 1, 0};
34
	private TextAutoNumberSchemeEnum[] autoNumberSchemes;
35
	private Short[] startNumbers;
36
    /** Record header. */
37
    private byte[] header;
38
    /** Record data. */
39
    private byte[] data;
40
    private short version;
41
    private short recordId;
42
    private int length;
43
44
    /**
45
     * Constructs the link related atom record from its
46
     *  source data.
47
     *
48
     * @param source the source data as a byte array.
49
     * @param start the start offset into the byte array.
50
     * @param len the length of the slice in the byte array.
51
     */
52
    protected StyleTextProp9Atom(byte[] source, int start, int len) {
53
        // Get the header.
54
    	List<Short> startNumberList = new LinkedList<Short>();
55
    	List<TextAutoNumberSchemeEnum> schemes = new LinkedList<TextAutoNumberSchemeEnum>();
56
        header = new byte[8];
57
        System.arraycopy(source,start, header,0,8);
58
        this.version  = LittleEndian.getShort(header, 0);
59
        this.recordId = LittleEndian.getShort(header, 2);
60
        this.length   = LittleEndian.getInt(header, 4);
61
        
62
        // Get the record data.
63
        data = new byte[len-8];
64
        System.arraycopy(source, start+8, data, 0, len-8);
65
        boolean markerFound = false;
66
        for (int i = 0; i < data.length; i++) {
67
        	markerFound = true;
68
        	for (int j = 0; j < MARKER.length; j++) {
69
        		if (i + j >= data.length || MARKER[j] != data[i + j]) {
70
        			markerFound = false;
71
        			break; 
72
        		}
73
        	}
74
        	if (markerFound) {
75
        		i += MARKER.length;
76
        		schemes.add(TextAutoNumberSchemeEnum.valueOf(LittleEndian.getShort(data, i )));
77
        		i += 2;
78
        		startNumberList.add(LittleEndian.getShort(data, i ));
79
        		i += 2;
80
        	}
81
        	if (i >= data.length) {
82
        		break;
83
        	}
84
        }
85
        this.autoNumberSchemes = (TextAutoNumberSchemeEnum[]) schemes.toArray(new TextAutoNumberSchemeEnum[schemes.size()]);
86
        this.startNumbers = (Short[]) startNumberList.toArray(new Short[startNumberList.size()]);
87
    }
88
89
	/**
90
     * Gets the record type.
91
     * @return the record type.
92
     */
93
    public long getRecordType() { return this.recordId; }
94
95
    public short getVersion() {
96
		return version;
97
	}
98
99
	public int getLength() {
100
		return length;
101
	}
102
	public TextAutoNumberSchemeEnum[] getAutoNumberTypes() {
103
		return this.autoNumberSchemes;
104
	}
105
	public Short[] getStartNumbers() {
106
		return this.startNumbers;
107
	}
108
109
	/**
110
     * Write the contents of the record back, so it can be written
111
     * to disk
112
     *
113
     * @param out the output stream to write to.
114
     * @throws java.io.IOException if an error occurs.
115
     */
116
    public void writeOut(OutputStream out) throws IOException {
117
        out.write(header);
118
        out.write(data);
119
    }
120
121
    /**
122
     * Update the text length
123
     *
124
     * @param size the text length
125
     */
126
    public void setTextSize(int size){
127
        LittleEndian.putInt(data, 0, size);
128
    }
129
130
    /**
131
     * Reset the content to one info run with the default values
132
     * @param size  the site of parent text
133
     */
134
    public void reset(int size){
135
        data = new byte[10];
136
        // 01 00 00 00
137
        LittleEndian.putInt(data, 0, size);
138
        // 01 00 00 00
139
        LittleEndian.putInt(data, 4, 1); //mask
140
        // 00 00
141
        LittleEndian.putShort(data, 8, (short)0); //langId
142
143
        // Update the size (header bytes 5-8)
144
        LittleEndian.putInt(header, 4, data.length);
145
    }
146
}
(-)src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java (-2 / +3 lines)
Lines 84-90 Link Here
84
    public static final Type OutlineTextRefAtom = new Type(3998,OutlineTextRefAtom.class);
84
    public static final Type OutlineTextRefAtom = new Type(3998,OutlineTextRefAtom.class);
85
    public static final Type TextHeaderAtom = new Type(3999,TextHeaderAtom.class);
85
    public static final Type TextHeaderAtom = new Type(3999,TextHeaderAtom.class);
86
    public static final Type TextCharsAtom = new Type(4000,TextCharsAtom.class);
86
    public static final Type TextCharsAtom = new Type(4000,TextCharsAtom.class);
87
    public static final Type StyleTextPropAtom = new Type(4001,StyleTextPropAtom.class);
87
    public static final Type StyleTextPropAtom = new Type(4001, StyleTextPropAtom.class);//0x0fa1 RT_StyleTextPropAtom
88
    public static final Type BaseTextPropAtom = new Type(4002,null);
88
    public static final Type BaseTextPropAtom = new Type(4002,null);
89
    public static final Type TxMasterStyleAtom = new Type(4003,TxMasterStyleAtom.class);
89
    public static final Type TxMasterStyleAtom = new Type(4003,TxMasterStyleAtom.class);
90
    public static final Type TxCFStyleAtom = new Type(4004,null);
90
    public static final Type TxCFStyleAtom = new Type(4004,null);
Lines 95-100 Link Here
95
    public static final Type TxSIStyleAtom = new Type(4009,null);
95
    public static final Type TxSIStyleAtom = new Type(4009,null);
96
    public static final Type TextSpecInfoAtom = new Type(4010, TextSpecInfoAtom.class);
96
    public static final Type TextSpecInfoAtom = new Type(4010, TextSpecInfoAtom.class);
97
    public static final Type DefaultRulerAtom = new Type(4011,null);
97
    public static final Type DefaultRulerAtom = new Type(4011,null);
98
    public static final Type StyleTextProp9Atom = new Type(4012, StyleTextProp9Atom.class); //0x0FAC RT_StyleTextProp9Atom
98
    public static final Type FontEntityAtom = new Type(4023,FontEntityAtom.class);
99
    public static final Type FontEntityAtom = new Type(4023,FontEntityAtom.class);
99
    public static final Type FontEmbeddedData = new Type(4024,null);
100
    public static final Type FontEmbeddedData = new Type(4024,null);
100
    public static final Type CString = new Type(4026,CString.class);
101
    public static final Type CString = new Type(4026,CString.class);
Lines 146-152 Link Here
146
    public static final Type ProgTags = new Type(5000,DummyPositionSensitiveRecordWithChildren.class);
147
    public static final Type ProgTags = new Type(5000,DummyPositionSensitiveRecordWithChildren.class);
147
    public static final Type ProgStringTag = new Type(5001,null);
148
    public static final Type ProgStringTag = new Type(5001,null);
148
    public static final Type ProgBinaryTag = new Type(5002,DummyPositionSensitiveRecordWithChildren.class);
149
    public static final Type ProgBinaryTag = new Type(5002,DummyPositionSensitiveRecordWithChildren.class);
149
    public static final Type BinaryTagData = new Type(5003,DummyPositionSensitiveRecordWithChildren.class);
150
    public static final Type BinaryTagData = new Type(5003, BinaryTagDataBlob.class);//0x138b RT_BinaryTagDataBlob
150
    public static final Type PrpublicintOptions = new Type(6000,null);
151
    public static final Type PrpublicintOptions = new Type(6000,null);
151
    public static final Type PersistPtrFullBlock = new Type(6001,PersistPtrHolder.class);
152
    public static final Type PersistPtrFullBlock = new Type(6001,PersistPtrHolder.class);
152
    public static final Type PersistPtrIncrementalBlock = new Type(6002,PersistPtrHolder.class);
153
    public static final Type PersistPtrIncrementalBlock = new Type(6002,PersistPtrHolder.class);
(-)src/scratchpad/src/org/apache/poi/hslf/model/Slide.java (-3 / +80 lines)
Lines 18-38 Link Here
18
package org.apache.poi.hslf.model;
18
package org.apache.poi.hslf.model;
19
19
20
import java.awt.Graphics2D;
20
import java.awt.Graphics2D;
21
import java.util.Vector;
21
import java.util.LinkedList;
22
import java.util.List;
22
23
23
import org.apache.poi.ddf.EscherContainerRecord;
24
import org.apache.poi.ddf.EscherContainerRecord;
24
import org.apache.poi.ddf.EscherDgRecord;
25
import org.apache.poi.ddf.EscherDgRecord;
25
import org.apache.poi.ddf.EscherDggRecord;
26
import org.apache.poi.ddf.EscherDggRecord;
27
import org.apache.poi.ddf.EscherRecord;
26
import org.apache.poi.ddf.EscherSpRecord;
28
import org.apache.poi.ddf.EscherSpRecord;
29
import org.apache.poi.ddf.UnknownEscherRecord;
30
import org.apache.poi.hslf.record.BinaryTagDataBlob;
31
import org.apache.poi.hslf.record.CString;
27
import org.apache.poi.hslf.record.ColorSchemeAtom;
32
import org.apache.poi.hslf.record.ColorSchemeAtom;
28
import org.apache.poi.hslf.record.Comment2000;
33
import org.apache.poi.hslf.record.Comment2000;
34
import org.apache.poi.hslf.record.EscherTextboxWrapper;
29
import org.apache.poi.hslf.record.HeadersFootersContainer;
35
import org.apache.poi.hslf.record.HeadersFootersContainer;
36
import org.apache.poi.hslf.record.PPDrawing;
30
import org.apache.poi.hslf.record.Record;
37
import org.apache.poi.hslf.record.Record;
31
import org.apache.poi.hslf.record.RecordContainer;
38
import org.apache.poi.hslf.record.RecordContainer;
32
import org.apache.poi.hslf.record.RecordTypes;
39
import org.apache.poi.hslf.record.RecordTypes;
33
import org.apache.poi.hslf.record.SlideAtom;
40
import org.apache.poi.hslf.record.SlideAtom;
41
import org.apache.poi.hslf.record.StyleTextProp9Atom;
34
import org.apache.poi.hslf.record.TextHeaderAtom;
42
import org.apache.poi.hslf.record.TextHeaderAtom;
35
import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
43
import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
44
import org.apache.poi.util.LittleEndian;
36
45
37
/**
46
/**
38
 * This class represents a slide in a PowerPoint Document. It allows
47
 * This class represents a slide in a PowerPoint Document. It allows
Lines 53-59 Link Here
53
	/**
62
	/**
54
	 * Constructs a Slide from the Slide record, and the SlideAtomsSet
63
	 * Constructs a Slide from the Slide record, and the SlideAtomsSet
55
	 *  containing the text.
64
	 *  containing the text.
56
	 * Initialises TextRuns, to provide easier access to the text
65
	 * Initializes TextRuns, to provide easier access to the text
57
	 *
66
	 *
58
	 * @param slide the Slide record we're based on
67
	 * @param slide the Slide record we're based on
59
	 * @param notes the Notes sheet attached to us
68
	 * @param notes the Notes sheet attached to us
Lines 72-78 Link Here
72
		// For the text coming in from the SlideAtomsSet:
81
		// For the text coming in from the SlideAtomsSet:
73
		// Build up TextRuns from pairs of TextHeaderAtom and
82
		// Build up TextRuns from pairs of TextHeaderAtom and
74
		//  one of TextBytesAtom or TextCharsAtom
83
		//  one of TextBytesAtom or TextCharsAtom
75
		Vector textRuns = new Vector();
84
		final List<TextRun> textRuns = new LinkedList<TextRun>();
76
		if(_atomSet != null) {
85
		if(_atomSet != null) {
77
			findTextRuns(_atomSet.getSlideRecords(),textRuns);
86
			findTextRuns(_atomSet.getSlideRecords(),textRuns);
78
		} else {
87
		} else {
Lines 476-479 Link Here
476
            _runs = tmp;
485
            _runs = tmp;
477
        }
486
        }
478
    }
487
    }
488
    protected EscherContainerRecord findFirstEscherContainerRecordOfType(short type, EscherContainerRecord parent) {
489
    	if (null == parent) { return null; }
490
		final List<EscherContainerRecord> children = parent.getChildContainers();
491
		for (EscherContainerRecord child : children) {
492
			if (type == child.getRecordId()) {
493
				return child;
494
			}
495
		}
496
		return null;
497
    }
498
    protected EscherContainerRecord[] findAllEscherContainerRecordOfType(short type, EscherContainerRecord parent) {
499
    	if (null == parent) { return new EscherContainerRecord[0]; }
500
		final List<EscherContainerRecord> children = parent.getChildContainers();
501
		final List<EscherContainerRecord> result = new LinkedList<EscherContainerRecord>();
502
		for (EscherContainerRecord child : children) {
503
			if (type == child.getRecordId()) {
504
				result.add(child);
505
			}
506
		}
507
		return (EscherContainerRecord[]) result.toArray(new EscherContainerRecord[result.size()]);
508
    }
509
510
    protected Record buildFromUnknownEscherRecord(UnknownEscherRecord unknown) {
511
		byte[] bingo = unknown.getData();
512
		byte[] restoredRecord = new byte[8 + bingo.length];
513
		System.arraycopy(bingo, 0, restoredRecord, 8, bingo.length);
514
		short recordVersion = unknown.getVersion();
515
		short recordId = unknown.getRecordId();
516
		int recordLength = unknown.getRecordSize();
517
		LittleEndian.putShort(restoredRecord, 0, recordVersion);
518
		LittleEndian.putShort(restoredRecord, 2, recordId);
519
		LittleEndian.putInt(restoredRecord, 4, recordLength);
520
		return Record.createRecordForType(recordId, restoredRecord, 0, restoredRecord.length);
521
    }
522
    public StyleTextProp9Atom getNumberedListInfo() {
523
    	PPDrawing drawing = this.getPPDrawing();
524
    	EscherRecord[] escherRecords = drawing.getEscherRecords();
525
    	for (EscherRecord escherRecord : escherRecords) {
526
			if (escherRecord instanceof EscherContainerRecord && (short)0xf002 == escherRecord.getRecordId()) {
527
				EscherContainerRecord escherContainerF002 = (EscherContainerRecord) escherRecord;
528
				final EscherContainerRecord escherContainerF003 = findFirstEscherContainerRecordOfType((short)0xf003, escherContainerF002);
529
				final EscherContainerRecord[] escherContainersF004 = findAllEscherContainerRecordOfType((short)0xf004, escherContainerF003);
530
				for (EscherContainerRecord containerF004 : escherContainersF004) {
531
					final EscherContainerRecord escherContainerF011 = findFirstEscherContainerRecordOfType((short)0xf011, containerF004);
532
					if (null == escherContainerF011) { continue; }
533
					final EscherContainerRecord escherContainer1388 = findFirstEscherContainerRecordOfType((short)0x1388, escherContainerF011);
534
					if (null == escherContainer1388) { continue; }
535
					final EscherContainerRecord escherContainer138A = findFirstEscherContainerRecordOfType((short)0x138A, escherContainer1388);
536
					if (null == escherContainer138A) { continue; }
537
					int size = escherContainer138A.getChildRecords().size();
538
					if (2 != size) { continue; }
539
					final Record r0 = buildFromUnknownEscherRecord((UnknownEscherRecord) escherContainer138A.getChild(0));
540
					final Record r1 = buildFromUnknownEscherRecord((UnknownEscherRecord) escherContainer138A.getChild(1));
541
					if (!(r0 instanceof CString)) { continue; }
542
					if (!("___PPT9".equals(((CString) r0).getText()))) { continue; };
543
					if (!(r1 instanceof BinaryTagDataBlob )) { continue; }
544
					final BinaryTagDataBlob blob = (BinaryTagDataBlob) r1;
545
					if (1 != blob.getChildRecords().length) { continue; }
546
					return (StyleTextProp9Atom)blob.findFirstOfType(0x0FACL);
547
				}
548
			}
549
    	}
550
    	return null;
551
    }
552
553
	public EscherTextboxWrapper[] getTextboxWrappers() {
554
		return this.getPPDrawing().getTextboxWrappers();
555
	}
479
}
556
}
(-)src/scratchpad/src/org/apache/poi/hslf/record/EscherTextboxWrapper.java (+8 lines)
Lines 36-41 Link Here
36
	private EscherTextboxRecord _escherRecord;
36
	private EscherTextboxRecord _escherRecord;
37
	private long _type;
37
	private long _type;
38
	private int shapeId;
38
	private int shapeId;
39
	private StyleTextPropAtom styleTextPropAtom;
39
40
40
	/**
41
	/**
41
	 * Returns the underlying DDF Escher Record
42
	 * Returns the underlying DDF Escher Record
Lines 52-57 Link Here
52
		// Find the child records in the escher data
53
		// Find the child records in the escher data
53
		byte[] data = _escherRecord.getData();
54
		byte[] data = _escherRecord.getData();
54
		_children = Record.findChildRecords(data,0,data.length);
55
		_children = Record.findChildRecords(data,0,data.length);
56
		for (Record r : this._children) {
57
			if (r instanceof StyleTextPropAtom) { this.styleTextPropAtom = (StyleTextPropAtom) r; }
58
		}
55
	}
59
	}
56
60
57
	/**
61
	/**
Lines 104-107 Link Here
104
	public void setShapeId(int id){
108
	public void setShapeId(int id){
105
		shapeId = id;
109
		shapeId = id;
106
	}
110
	}
111
112
	public StyleTextPropAtom getStyleTextPropAtom() {
113
		return styleTextPropAtom;
114
	}
107
}
115
}
(-)src/scratchpad/src/org/apache/poi/hslf/record/BinaryTagDataBlob.java (+67 lines)
Line 0 Link Here
1
/* ====================================================================
2
   Licensed to the Apache Software Foundation (ASF) under one or more
3
   contributor license agreements.  See the NOTICE file distributed with
4
   this work for additional information regarding copyright ownership.
5
   The ASF licenses this file to You under the Apache License, Version 2.0
6
   (the "License"); you may not use this file except in compliance with
7
   the License.  You may obtain a copy of the License at
8
9
       http://www.apache.org/licenses/LICENSE-2.0
10
11
   Unless required by applicable law or agreed to in writing, software
12
   distributed under the License is distributed on an "AS IS" BASIS,
13
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
   See the License for the specific language governing permissions and
15
   limitations under the License.
16
==================================================================== */
17
18
package org.apache.poi.hslf.record;
19
20
import org.apache.poi.util.LittleEndian;
21
import java.io.IOException;
22
import java.io.OutputStream;
23
24
/**
25
 * If we come across a record we know has children of (potential)
26
 *  interest, but where the record itself is boring, but where other
27
 *  records may care about where this one lives, we create one
28
 *  of these. It allows us to get at the children, and track where on
29
 *  disk this is, but not much else.
30
 * Anything done using this should quite quickly be transitioned to its
31
 *  own proper record class!
32
 *
33
 * @author Nick Burch
34
 */
35
36
public final class BinaryTagDataBlob extends PositionDependentRecordContainer
37
{
38
	private byte[] _header;
39
	private long _type;
40
41
	/**
42
	 * Create a new holder for a boring record with children, but with
43
	 *  position dependent characteristics
44
	 */
45
	protected BinaryTagDataBlob(byte[] source, int start, int len) {
46
		// Just grab the header, not the whole contents
47
		_header = new byte[8];
48
		System.arraycopy(source,start,_header,0,8);
49
		_type = LittleEndian.getUShort(_header,2);
50
51
		// Find our children
52
		_children = Record.findChildRecords(source,start+8,len-8);
53
	}
54
55
	/**
56
	 * Return the value we were given at creation
57
	 */
58
	public long getRecordType() { return _type; }
59
60
	/**
61
	 * Write the contents of the record back, so it can be written
62
	 *  to disk
63
	 */
64
	public void writeOut(OutputStream out) throws IOException {
65
		writeOut(_header[0],_header[1],_type,_children,out);
66
	}
67
}
(-)src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestNumberedList.java (+131 lines)
Line 0 Link Here
1
/* ====================================================================
2
   Licensed to the Apache Software Foundation (ASF) under one or more
3
   contributor license agreements.  See the NOTICE file distributed with
4
   this work for additional information regarding copyright ownership.
5
   The ASF licenses this file to You under the Apache License, Version 2.0
6
   (the "License"); you may not use this file except in compliance with
7
   the License.  You may obtain a copy of the License at
8
9
       http://www.apache.org/licenses/LICENSE-2.0
10
11
   Unless required by applicable law or agreed to in writing, software
12
   distributed under the License is distributed on an "AS IS" BASIS,
13
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
   See the License for the specific language governing permissions and
15
   limitations under the License.
16
==================================================================== */
17
18
package org.apache.poi.hslf.usermodel;
19
20
import java.util.List;
21
22
import junit.framework.TestCase;
23
24
import org.apache.poi.hslf.model.Slide;
25
import org.apache.poi.hslf.model.TextRun;
26
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
27
import org.apache.poi.hslf.record.EscherTextboxWrapper;
28
import org.apache.poi.hslf.record.StyleTextProp9Atom;
29
import org.apache.poi.hslf.record.StyleTextPropAtom;
30
import org.apache.poi.hslf.record.TextAutoNumberSchemeEnum;
31
import org.apache.poi.POIDataSamples;
32
33
34
/**
35
 * Test that checks numbered list functionality.
36
 * 
37
 * @author Alex Nikiforov [mailto:anikif@gmail.com]
38
 */
39
public final class TestNumberedList extends TestCase {
40
    private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
41
42
	protected void setUp() throws Exception {
43
	}
44
45
	public void testNumberedList() throws Exception {
46
		SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("numbers.ppt"));
47
		assertTrue("No Exceptions while reading file", true);
48
49
		final Slide[] slides = ppt.getSlides();
50
		assertEquals(2, slides.length);
51
		checkSlide0(slides[0]);
52
		checkSlide1(slides[1]);
53
	}
54
	private void checkSlide0(final Slide s) {
55
		final StyleTextProp9Atom numberedListInfo = s.getNumberedListInfo();
56
		assertNotNull(numberedListInfo);
57
		{
58
			final Short[] startNumbers = numberedListInfo.getStartNumbers();
59
			assertNotNull(startNumbers);
60
			assertEquals(2, startNumbers.length);
61
			assertTrue(4 == startNumbers[0]);
62
			assertTrue(3 == startNumbers[1]);
63
		}		
64
		{
65
			final TextAutoNumberSchemeEnum[] enums = numberedListInfo.getAutoNumberTypes();
66
			assertNotNull(enums);
67
			assertEquals(2, enums.length);
68
			assertTrue(TextAutoNumberSchemeEnum.ANM_ArabicPeriod == enums[0]);
69
			assertTrue(TextAutoNumberSchemeEnum.ANM_AlphaLcParenRight == enums[1]);
70
		}
71
			
72
		TextRun[] textRuns = s.getTextRuns();
73
		assertEquals(2, textRuns.length);
74
75
		RichTextRun textRun = textRuns[0].getRichTextRuns()[0];
76
		assertEquals("titTe", textRun.getRawText());
77
		assertEquals(1, textRuns[0].getRichTextRuns().length);
78
		assertFalse(textRun.isBullet());
79
80
		assertEquals("This is a text placeholder that \rfollows the design pattern\rJust a test\rWithout any paragraph\rSecond paragraph first line c) ;\rSecond paragraph second line d) . \r", textRuns[1].getRawText());
81
		
82
		final EscherTextboxWrapper[] styleAtoms = s.getTextboxWrappers();
83
		assertEquals(textRuns.length, styleAtoms.length);
84
		final EscherTextboxWrapper wrapper =  styleAtoms[1];
85
		final StyleTextPropAtom styleTextPropAtom = wrapper.getStyleTextPropAtom();
86
		final List<TextPropCollection> textProps = styleTextPropAtom.getCharacterStyles();
87
		final TextPropCollection[] props = (TextPropCollection[]) textProps.toArray(new TextPropCollection[textProps.size()]);
88
		assertEquals(60, props[0].getCharactersCovered());
89
		assertEquals(34, props[1].getCharactersCovered());
90
		assertEquals(68, props[2].getCharactersCovered());
91
	}
92
	private void checkSlide1(final Slide s) {
93
		final StyleTextProp9Atom numberedListInfo = s.getNumberedListInfo();
94
		assertNotNull(numberedListInfo);
95
		{
96
			final Short[] startNumbers = numberedListInfo.getStartNumbers();
97
			assertNotNull(startNumbers);
98
			assertEquals(2, startNumbers.length);
99
			assertTrue(9 == startNumbers[0]);
100
			assertTrue(3 == startNumbers[1]);
101
		}		
102
		{
103
			final TextAutoNumberSchemeEnum[] enums = numberedListInfo.getAutoNumberTypes();
104
			assertNotNull(enums);
105
			assertEquals(2, enums.length);
106
			assertTrue(TextAutoNumberSchemeEnum.ANM_ArabicParenRight == enums[0]);
107
			assertTrue(TextAutoNumberSchemeEnum.ANM_AlphaUcPeriod == enums[1]);
108
		}
109
			
110
		TextRun[] textRuns = s.getTextRuns();
111
		assertEquals(2, textRuns.length);
112
113
		RichTextRun textRun = textRuns[0].getRichTextRuns()[0];
114
		assertEquals("Second Slide Title", textRun.getRawText());
115
		assertEquals(1, textRuns[0].getRichTextRuns().length);
116
		assertFalse(textRun.isBullet());
117
118
		assertEquals("This is a text placeholder that \rfollows the design pattern\rJust a test\rWithout any paragraph\rSecond paragraph first line c) ;\rSecond paragraph second line d) . \r", textRuns[1].getRawText());
119
		
120
		final EscherTextboxWrapper[] styleAtoms = s.getTextboxWrappers();
121
		assertEquals(textRuns.length, styleAtoms.length);
122
		final EscherTextboxWrapper wrapper =  styleAtoms[1];
123
		final StyleTextPropAtom styleTextPropAtom = wrapper.getStyleTextPropAtom();
124
		final List<TextPropCollection> textProps = styleTextPropAtom.getCharacterStyles();
125
		
126
		final TextPropCollection[] props = (TextPropCollection[]) textProps.toArray(new TextPropCollection[textProps.size()]);
127
		assertEquals(33, props[0].getCharactersCovered());
128
		assertEquals(61, props[1].getCharactersCovered());
129
		assertEquals(68, props[2].getCharactersCovered());
130
	}
131
}

Return to bug 53979