1 2 /* ==================================================================== 3 * The Apache Software License, Version 1.1 4 * 5 * Copyright (c) 2002 The Apache Software Foundation. All rights 6 * reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. The end-user documentation included with the redistribution, 21 * if any, must include the following acknowledgment: 22 * "This product includes software developed by the 23 * Apache Software Foundation (http://www.apache.org/)." 24 * Alternately, this acknowledgment may appear in the software itself, 25 * if and wherever such third-party acknowledgments normally appear. 26 * 27 * 4. The names "Apache" and "Apache Software Foundation" and 28 * "Apache POI" must not be used to endorse or promote products 29 * derived from this software without prior written permission. For 30 * written permission, please contact apache@apache.org. 31 * 32 * 5. Products derived from this software may not be called "Apache", 33 * "Apache POI", nor may "Apache" appear in their name, without 34 * prior written permission of the Apache Software Foundation. 35 * 36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 39 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 43 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 47 * SUCH DAMAGE. 48 * ==================================================================== 49 * 50 * This software consists of voluntary contributions made by many 51 * individuals on behalf of the Apache Software Foundation. For more 52 * information on the Apache Software Foundation, please see 53 * <http://www.apache.org/>. 54 */ 55 56 package org.apache.poi.hssf.record; 57 58 import org.apache.poi.util.LittleEndian; 59 import org.apache.poi.util.StringUtil; 60 61 /** 62 * Title: Style Record<P> 63 * Description: Describes a builtin to the gui or user defined style<P> 64 * REFERENCE: PG 390 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> 65 * @author Andrew C. Oliver (acoliver at apache dot org) 66 * @version 2.0-pre 67 */ 68 69 public class StyleRecord 70 extends Record 71 { 72 public final static short sid = 0x293; 73 public final static short STYLE_USER_DEFINED = 0; 74 public final static short STYLE_BUILT_IN = 1; 75 76 // shared by both user defined and builtin styles 77 private short field_1_xf_index; // TODO: bitfield candidate 78 79 // only for built in styles 80 private byte field_2_builtin_style; 81 private byte field_3_outline_style_level; 82 83 // only for user defined styles 84 private byte field_2_name_length; 85 private String field_3_name; 86 87 public StyleRecord() 88 { 89 } 90 91 /** 92 * Constructs a Style record and sets its fields appropriately. 93 * 94 * @param id id must be 0x293 or an exception will be throw upon validation 95 * @param size the size of the data area of the record 96 * @param data data of the record (should not contain sid/len) 97 */ 98 99 public StyleRecord(short id, short size, byte [] data) 100 { 101 super(id, size, data); 102 } 103 104 /** 105 * Constructs a Style record and sets its fields appropriately. 106 * 107 * @param id id must be 0x293 or an exception will be throw upon validation 108 * @param size the size of the data area of the record 109 * @param data data of the record (should not contain sid/len) 110 * @param offset 111 */ 112 113 public StyleRecord(short id, short size, byte [] data, int offset) 114 { 115 super(id, size, data, offset); 116 } 117 118 protected void validateSid(short id) 119 { 120 if (id != sid) 121 { 122 throw new RecordFormatException("NOT A STYLE RECORD"); 123 } 124 } 125 126 protected void fillFields(byte [] data, short size, int offset) 127 { 128 field_1_xf_index = LittleEndian.getShort(data, 0 + offset); 129 if (getType() == 1) 130 { 131 field_2_builtin_style = data[ 2 + offset ]; 132 field_3_outline_style_level = data[ 3 + offset ]; 133 } 134 else if (getType() == 0) 135 { 136 field_2_name_length = data[ 2 + offset ]; 137 field_3_name = new String(data, 3 + offset, 138 LittleEndian.ubyteToInt(field_2_name_length)); 139 } 140 141 // todo sanity check exception to make sure we're one or the other 142 } 143 144 /** 145 * set the entire index field (including the type) (see bit setters that reference this method) 146 * @param index bitmask 147 */ 148 149 public void setIndex(short index) 150 { 151 field_1_xf_index = index; 152 } 153 154 // bitfields for field 1 155 156 /** 157 * set the type of the style (builtin or user-defined) 158 * @see #STYLE_USER_DEFINED 159 * @see #STYLE_BUILT_IN 160 * @param type of style (userdefined/builtin) 161 * @see #setIndex(short) 162 */ 163 164 public void setType(short type) 165 { 166 field_1_xf_index = setField(field_1_xf_index, type, 0x8000, 15); 167 } 168 169 /** 170 * set the actual index of the style extended format record 171 * @see #setIndex(short) 172 * @param index of the xf record 173 */ 174 175 public void setXFIndex(short index) 176 { 177 field_1_xf_index = setField(field_1_xf_index, index, 0x1FFF, 0); 178 } 179 180 // end bitfields 181 // only for user defined records 182 183 /** 184 * if this is a user defined record set the length of the style name 185 * @param length of the style's name 186 * @see #setName(String) 187 */ 188 189 public void setNameLength(byte length) 190 { 191 field_2_name_length = length; 192 } 193 194 /** 195 * set the style's name 196 * @param name of the style 197 * @see #setNameLength(byte) 198 */ 199 200 public void setName(String name) 201 { 202 field_3_name = name; 203 } 204 205 // end user defined 206 // only for buildin records 207 208 /** 209 * if this is a builtin style set teh number of the built in style 210 * @param builtin style number (0-7) 211 * 212 */ 213 214 public void setBuiltin(byte builtin) 215 { 216 field_2_builtin_style = builtin; 217 } 218 219 /** 220 * set the row or column level of the style (if builtin 1||2) 221 */ 222 223 public void setOutlineStyleLevel(byte level) 224 { 225 field_3_outline_style_level = level; 226 } 227 228 // end builtin records 229 // field 1 230 231 /** 232 * get the entire index field (including the type) (see bit getters that reference this method) 233 * @return bitmask 234 */ 235 236 public short getIndex() 237 { 238 return field_1_xf_index; 239 } 240 241 // bitfields for field 1 242 243 /** 244 * get the type of the style (builtin or user-defined) 245 * @see #STYLE_USER_DEFINED 246 * @see #STYLE_BUILT_IN 247 * @return type of style (userdefined/builtin) 248 * @see #getIndex() 249 */ 250 251 public short getType() 252 { 253 return ( short ) ((field_1_xf_index & 0x8000) >> 15); 254 } 255 256 /** 257 * get the actual index of the style extended format record 258 * @see #getIndex() 259 * @return index of the xf record 260 */ 261 262 public short getXFIndex() 263 { 264 return ( short ) (field_1_xf_index & 0x1FFF); 265 } 266 267 // end bitfields 268 // only for user defined records 269 270 /** 271 * if this is a user defined record get the length of the style name 272 * @return length of the style's name 273 * @see #getName() 274 */ 275 276 public byte getNameLength() 277 { 278 return field_2_name_length; 279 } 280 281 /** 282 * get the style's name 283 * @return name of the style 284 * @see #getNameLength() 285 */ 286 287 public String getName() 288 { 289 return field_3_name; 290 } 291 292 // end user defined 293 // only for buildin records 294 295 /** 296 * if this is a builtin style get the number of the built in style 297 * @return builtin style number (0-7) 298 * 299 */ 300 301 public byte getBuiltin() 302 { 303 return field_2_builtin_style; 304 } 305 306 /** 307 * get the row or column level of the style (if builtin 1||2) 308 */ 309 310 public byte getOutlineStyleLevel() 311 { 312 return field_3_outline_style_level; 313 } 314 315 // end builtin records 316 public String toString() 317 { 318 StringBuffer buffer = new StringBuffer(); 319 320 buffer.append("[STYLE]\n"); 321 buffer.append(" .xf_index_raw = ") 322 .append(Integer.toHexString(getIndex())).append("\n"); 323 buffer.append(" .type = ") 324 .append(Integer.toHexString(getType())).append("\n"); 325 buffer.append(" .xf_index = ") 326 .append(Integer.toHexString(getXFIndex())).append("\n"); 327 if (getType() == STYLE_BUILT_IN) 328 { 329 buffer.append(" .builtin_style = ") 330 .append(Integer.toHexString(getBuiltin())).append("\n"); 331 buffer.append(" .outline_level = ") 332 .append(Integer.toHexString(getOutlineStyleLevel())) 333 .append("\n"); 334 } 335 else if (getType() == STYLE_USER_DEFINED) 336 { 337 buffer.append(" .name_length = ") 338 .append(Integer.toHexString(getNameLength())).append("\n"); 339 buffer.append(" .name = ").append(getName()) 340 .append("\n"); 341 } 342 buffer.append("[/STYLE]\n"); 343 return buffer.toString(); 344 } 345 346 private short setField(int fieldValue, int new_value, int mask, 347 int shiftLeft) 348 { 349 return ( short ) ((fieldValue & ~mask) 350 | ((new_value << shiftLeft) & mask)); 351 } 352 353 public int serialize(int offset, byte [] data) 354 { 355 LittleEndian.putShort(data, 0 + offset, sid); 356 if (getType() == STYLE_BUILT_IN) 357 { 358 LittleEndian.putShort(data, 2 + offset, 359 (( short ) 0x04)); // 4 bytes (8 total) 360 } 361 else 362 { 363 LittleEndian.putShort(data, 2 + offset, 364 (( short ) (0x03 + getNameLength()))); 365 } 366 LittleEndian.putShort(data, 4 + offset, getIndex()); 367 if (getType() == STYLE_BUILT_IN) 368 { 369 data[ 6 + offset ] = getBuiltin(); 370 data[ 7 + offset ] = getOutlineStyleLevel(); 371 } 372 else 373 { 374 data[ 6 + offset ] = getNameLength(); 375 StringUtil.putCompressedUnicode(getName(), data, 7 + offset); 376 } 377 return getRecordSize(); 378 } 379 380 public int getRecordSize() 381 { 382 int retval; 383 384 if (getType() == STYLE_BUILT_IN) 385 { 386 retval = 8; 387 } 388 else 389 { 390 retval = 7 + getNameLength(); 391 } 392 return retval; 393 } 394 395 public short getSid() 396 { 397 return this.sid; 398 } 399 } 400