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:
023: /**
024: * Title: Header Record<P>
025: * Description: Specifies a header for a sheet<P>
026: * REFERENCE: PG 321 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
027: * @author Andrew C. Oliver (acoliver at apache dot org)
028: * @author Shawn Laubach (slaubach at apache dot org) Modified 3/14/02
029: * @author Jason Height (jheight at chariot dot net dot au)
030: * @version 2.0-pre
031: */
032:
033: public class HeaderRecord extends Record {
034: public final static short sid = 0x14;
035: private byte field_1_header_len;
036: private byte field_2_reserved;
037: private byte field_3_unicode_flag;
038: private String field_4_header;
039:
040: public HeaderRecord() {
041: }
042:
043: /**
044: * Constructs an Header record and sets its fields appropriately.
045: * @param in the RecordInputstream to read the record from
046: */
047:
048: public HeaderRecord(RecordInputStream in) {
049: super (in);
050: }
051:
052: protected void validateSid(short id) {
053: if (id != sid) {
054: throw new RecordFormatException("NOT A HEADERRECORD");
055: }
056: }
057:
058: protected void fillFields(RecordInputStream in) {
059: if (in.remaining() > 0) {
060: field_1_header_len = in.readByte();
061: /** These two fields are a bit odd. They are not documented*/
062: field_2_reserved = in.readByte();
063: field_3_unicode_flag = in.readByte(); // unicode
064:
065: if (isMultibyte()) {
066: field_4_header = in.readUnicodeLEString(LittleEndian
067: .ubyteToInt(field_1_header_len));
068: } else {
069: field_4_header = in.readCompressedUnicode(LittleEndian
070: .ubyteToInt(field_1_header_len));
071: }
072: }
073: }
074:
075: /**
076: * see the unicode flag
077: *
078: * @return boolean flag
079: * true:footer string has at least one multibyte character
080: */
081: public boolean isMultibyte() {
082: return ((field_3_unicode_flag & 0xFF) == 1);
083: }
084:
085: /**
086: * set the length of the header string
087: *
088: * @param len length of the header string
089: * @see #setHeader(String)
090: */
091:
092: public void setHeaderLength(byte len) {
093: field_1_header_len = len;
094: }
095:
096: /**
097: * set the header string
098: *
099: * @param header string to display
100: * @see #setHeaderLength(byte)
101: */
102:
103: public void setHeader(String header) {
104: field_4_header = header;
105: field_3_unicode_flag = (byte) (StringUtil
106: .hasMultibyte(field_4_header) ? 1 : 0);
107: }
108:
109: /**
110: * get the length of the header string
111: *
112: * @return length of the header string
113: * @see #getHeader()
114: */
115:
116: public short getHeaderLength() {
117: return (short) (0xFF & field_1_header_len); // [Shawn] Fixed needing unsigned byte
118: }
119:
120: /**
121: * get the header string
122: *
123: * @return header string to display
124: * @see #getHeaderLength()
125: */
126:
127: public String getHeader() {
128: return field_4_header;
129: }
130:
131: public String toString() {
132: StringBuffer buffer = new StringBuffer();
133:
134: buffer.append("[HEADER]\n");
135: buffer.append(" .length = ").append(
136: getHeaderLength()).append("\n");
137: buffer.append(" .header = ").append(getHeader())
138: .append("\n");
139: buffer.append("[/HEADER]\n");
140: return buffer.toString();
141: }
142:
143: public int serialize(int offset, byte[] data) {
144: int len = 4;
145:
146: if (getHeaderLength() != 0) {
147: len += 3; // [Shawn] Fixed for two null bytes in the length
148: }
149: short bytelen = (short) (isMultibyte() ? getHeaderLength() * 2
150: : getHeaderLength());
151: LittleEndian.putShort(data, 0 + offset, sid);
152: LittleEndian.putShort(data, 2 + offset,
153: (short) ((len - 4) + bytelen));
154:
155: if (getHeaderLength() > 0) {
156: data[4 + offset] = (byte) getHeaderLength();
157: data[6 + offset] = field_3_unicode_flag;
158: if (isMultibyte()) {
159: StringUtil.putUnicodeLE(getHeader(), data, 7 + offset);
160: } else {
161: StringUtil.putCompressedUnicode(getHeader(), data,
162: 7 + offset); // [Shawn] Place the string in the correct offset
163: }
164: }
165: return getRecordSize();
166: }
167:
168: public int getRecordSize() {
169: int retval = 4;
170:
171: if (getHeaderLength() != 0) {
172: retval += 3; // [Shawn] Fixed for two null bytes in the length
173: }
174: return (isMultibyte() ? (retval + getHeaderLength() * 2)
175: : (retval + getHeaderLength()));
176: }
177:
178: public short getSid() {
179: return sid;
180: }
181:
182: public Object clone() {
183: HeaderRecord rec = new HeaderRecord();
184: rec.field_1_header_len = field_1_header_len;
185: rec.field_2_reserved = field_2_reserved;
186: rec.field_3_unicode_flag = field_3_unicode_flag;
187: rec.field_4_header = field_4_header;
188: return rec;
189: }
190: }
|