001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017:
018: package org.apache.poi.hssf.record;
019:
020: import org.apache.poi.util.LittleEndian;
021: import org.apache.poi.util.StringUtil;
022: import org.apache.poi.util.BitField;
023: import org.apache.poi.util.BitFieldFactory;
024:
025: /**
026: * Title: Style Record<P>
027: * Description: Describes a builtin to the gui or user defined style<P>
028: * REFERENCE: PG 390 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
029: * @author Andrew C. Oliver (acoliver at apache dot org)
030: * @author aviks : string fixes for UserDefined Style
031: * @version 2.0-pre
032: */
033:
034: public class StyleRecord extends Record {
035: public final static short sid = 0x293;
036: public final static short STYLE_USER_DEFINED = 0;
037: public final static short STYLE_BUILT_IN = 1;
038:
039: // shared by both user defined and builtin styles
040: private short field_1_xf_index; // TODO: bitfield candidate
041:
042: // only for built in styles
043: private byte field_2_builtin_style;
044: private byte field_3_outline_style_level;
045:
046: // only for user defined styles
047: private short field_2_name_length; //OO doc says 16 bit length, so we believe
048: private byte field_3_string_options;
049: private BitField fHighByte;
050: private String field_4_name;
051:
052: public StyleRecord() {
053: }
054:
055: /**
056: * Constructs a Style record and sets its fields appropriately.
057: * @param in the RecordInputstream to read the record from
058: */
059:
060: public StyleRecord(RecordInputStream in) {
061: super (in);
062: }
063:
064: protected void validateSid(short id) {
065: if (id != sid) {
066: throw new RecordFormatException("NOT A STYLE RECORD");
067: }
068: }
069:
070: protected void fillFields(RecordInputStream in) {
071: fHighByte = BitFieldFactory.getInstance(0x01); //have to init here, since we are being called
072: //from super, and class level init hasnt been done.
073: field_1_xf_index = in.readShort();
074: if (getType() == STYLE_BUILT_IN) {
075: field_2_builtin_style = in.readByte();
076: field_3_outline_style_level = in.readByte();
077: } else if (getType() == STYLE_USER_DEFINED) {
078: field_2_name_length = in.readShort();
079: field_3_string_options = in.readByte();
080:
081: byte[] string = in.readRemainder();
082: if (fHighByte.isSet(field_3_string_options)) {
083: field_4_name = StringUtil.getFromUnicodeBE(string, 0,
084: field_2_name_length);
085: } else {
086: field_4_name = StringUtil.getFromCompressedUnicode(
087: string, 0, field_2_name_length);
088: }
089: }
090:
091: // todo sanity check exception to make sure we're one or the other
092: }
093:
094: /**
095: * set the entire index field (including the type) (see bit setters that reference this method)
096: * @param index bitmask
097: */
098:
099: public void setIndex(short index) {
100: field_1_xf_index = index;
101: }
102:
103: // bitfields for field 1
104:
105: /**
106: * set the type of the style (builtin or user-defined)
107: * @see #STYLE_USER_DEFINED
108: * @see #STYLE_BUILT_IN
109: * @param type of style (userdefined/builtin)
110: * @see #setIndex(short)
111: */
112:
113: public void setType(short type) {
114: field_1_xf_index = setField(field_1_xf_index, type, 0x8000, 15);
115: }
116:
117: /**
118: * set the actual index of the style extended format record
119: * @see #setIndex(short)
120: * @param index of the xf record
121: */
122:
123: public void setXFIndex(short index) {
124: field_1_xf_index = setField(field_1_xf_index, index, 0x1FFF, 0);
125: }
126:
127: // end bitfields
128: // only for user defined records
129:
130: /**
131: * if this is a user defined record set the length of the style name
132: * @param length of the style's name
133: * @see #setName(String)
134: */
135:
136: public void setNameLength(byte length) {
137: field_2_name_length = length;
138: }
139:
140: /**
141: * set the style's name
142: * @param name of the style
143: * @see #setNameLength(byte)
144: */
145:
146: public void setName(String name) {
147: field_4_name = name;
148: //TODO set name length and string options
149: }
150:
151: // end user defined
152: // only for buildin records
153:
154: /**
155: * if this is a builtin style set teh number of the built in style
156: * @param builtin style number (0-7)
157: *
158: */
159:
160: public void setBuiltin(byte builtin) {
161: field_2_builtin_style = builtin;
162: }
163:
164: /**
165: * set the row or column level of the style (if builtin 1||2)
166: */
167:
168: public void setOutlineStyleLevel(byte level) {
169: field_3_outline_style_level = level;
170: }
171:
172: // end builtin records
173: // field 1
174:
175: /**
176: * get the entire index field (including the type) (see bit getters that reference this method)
177: * @return bitmask
178: */
179:
180: public short getIndex() {
181: return field_1_xf_index;
182: }
183:
184: // bitfields for field 1
185:
186: /**
187: * get the type of the style (builtin or user-defined)
188: * @see #STYLE_USER_DEFINED
189: * @see #STYLE_BUILT_IN
190: * @return type of style (userdefined/builtin)
191: * @see #getIndex()
192: */
193:
194: public short getType() {
195: return (short) ((field_1_xf_index & 0x8000) >> 15);
196: }
197:
198: /**
199: * get the actual index of the style extended format record
200: * @see #getIndex()
201: * @return index of the xf record
202: */
203:
204: public short getXFIndex() {
205: return (short) (field_1_xf_index & 0x1FFF);
206: }
207:
208: // end bitfields
209: // only for user defined records
210:
211: /**
212: * if this is a user defined record get the length of the style name
213: * @return length of the style's name
214: * @see #getName()
215: */
216:
217: public short getNameLength() {
218: return field_2_name_length;
219: }
220:
221: /**
222: * get the style's name
223: * @return name of the style
224: * @see #getNameLength()
225: */
226:
227: public String getName() {
228: return field_4_name;
229: }
230:
231: // end user defined
232: // only for buildin records
233:
234: /**
235: * if this is a builtin style get the number of the built in style
236: * @return builtin style number (0-7)
237: *
238: */
239:
240: public byte getBuiltin() {
241: return field_2_builtin_style;
242: }
243:
244: /**
245: * get the row or column level of the style (if builtin 1||2)
246: */
247:
248: public byte getOutlineStyleLevel() {
249: return field_3_outline_style_level;
250: }
251:
252: // end builtin records
253: public String toString() {
254: StringBuffer buffer = new StringBuffer();
255:
256: buffer.append("[STYLE]\n");
257: buffer.append(" .xf_index_raw = ").append(
258: Integer.toHexString(getIndex())).append("\n");
259: buffer.append(" .type = ").append(
260: Integer.toHexString(getType())).append("\n");
261: buffer.append(" .xf_index = ").append(
262: Integer.toHexString(getXFIndex())).append("\n");
263: if (getType() == STYLE_BUILT_IN) {
264: buffer.append(" .builtin_style = ").append(
265: Integer.toHexString(getBuiltin())).append("\n");
266: buffer.append(" .outline_level = ").append(
267: Integer.toHexString(getOutlineStyleLevel()))
268: .append("\n");
269: } else if (getType() == STYLE_USER_DEFINED) {
270: buffer.append(" .name_length = ").append(
271: Integer.toHexString(getNameLength())).append("\n");
272: buffer.append(" .name = ").append(getName())
273: .append("\n");
274: }
275: buffer.append("[/STYLE]\n");
276: return buffer.toString();
277: }
278:
279: private short setField(int fieldValue, int new_value, int mask,
280: int shiftLeft) {
281: return (short) ((fieldValue & ~mask) | ((new_value << shiftLeft) & mask));
282: }
283:
284: public int serialize(int offset, byte[] data) {
285: LittleEndian.putShort(data, 0 + offset, sid);
286: if (getType() == STYLE_BUILT_IN) {
287: LittleEndian.putShort(data, 2 + offset, ((short) 0x04)); // 4 bytes (8 total)
288: } else {
289: LittleEndian.putShort(data, 2 + offset,
290: ((short) (getRecordSize() - 4)));
291: }
292: LittleEndian.putShort(data, 4 + offset, getIndex());
293: if (getType() == STYLE_BUILT_IN) {
294: data[6 + offset] = getBuiltin();
295: data[7 + offset] = getOutlineStyleLevel();
296: } else {
297: LittleEndian.putShort(data, 6 + offset, getNameLength());
298: data[8 + offset] = this .field_3_string_options;
299: StringUtil
300: .putCompressedUnicode(getName(), data, 9 + offset);
301: }
302: return getRecordSize();
303: }
304:
305: public int getRecordSize() {
306: int retval;
307:
308: if (getType() == STYLE_BUILT_IN) {
309: retval = 8;
310: } else {
311: if (fHighByte.isSet(field_3_string_options)) {
312: retval = 9 + 2 * getNameLength();
313: } else {
314: retval = 9 + getNameLength();
315: }
316: }
317: return retval;
318: }
319:
320: public short getSid() {
321: return sid;
322: }
323: }
|