package jxl.biff; import common.Logger; import jxl.WorkbookSettings; import jxl.biff.formula.ExternalSheet; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; public class DVParser { private static Logger logger = Logger.getLogger(DVParser.class); public static class DVType { private int value; private static DVType[] types = new DVType[0]; DVType(int v) { this.value = v; DVType[] oldtypes = types; types = new DVType[oldtypes.length + 1]; System.arraycopy(oldtypes, 0, types, 0, oldtypes.length); types[oldtypes.length] = this; } static DVType getType(int v) { DVType found = null; for (int i = 0; i < types.length && found == null; i++) { if ((types[i]).value == v) found = types[i]; } return found; } public int getValue() { return this.value; } } public static class ErrorStyle { private int value; private static ErrorStyle[] types = new ErrorStyle[0]; ErrorStyle(int v) { this.value = v; ErrorStyle[] oldtypes = types; types = new ErrorStyle[oldtypes.length + 1]; System.arraycopy(oldtypes, 0, types, 0, oldtypes.length); types[oldtypes.length] = this; } static ErrorStyle getErrorStyle(int v) { ErrorStyle found = null; for (int i = 0; i < types.length && found == null; i++) { if ((types[i]).value == v) found = types[i]; } return found; } public int getValue() { return this.value; } } public static class Condition { private int value; private static Condition[] types = new Condition[0]; Condition(int v) { this.value = v; Condition[] oldtypes = types; types = new Condition[oldtypes.length + 1]; System.arraycopy(oldtypes, 0, types, 0, oldtypes.length); types[oldtypes.length] = this; } static Condition getCondition(int v) { Condition found = null; for (int i = 0; i < types.length && found == null; i++) { if ((types[i]).value == v) found = types[i]; } return found; } public int getValue() { return this.value; } } public static final DVType ANY = new DVType(0); public static final DVType INTEGER = new DVType(1); public static final DVType DECIMAL = new DVType(2); public static final DVType LIST = new DVType(3); public static final DVType DATE = new DVType(4); public static final DVType TIME = new DVType(5); public static final DVType TEXT_LENGTH = new DVType(6); public static final DVType FORMULA = new DVType(7); public static final ErrorStyle STOP = new ErrorStyle(0); public static final ErrorStyle WARNING = new ErrorStyle(1); public static final ErrorStyle INFO = new ErrorStyle(2); public static final Condition BETWEEN = new Condition(0); public static final Condition NOT_BETWEEN = new Condition(1); public static final Condition EQUAL = new Condition(2); public static final Condition NOT_EQUAL = new Condition(3); public static final Condition GREATER_THAN = new Condition(4); public static final Condition LESS_THAN = new Condition(5); public static final Condition GREATER_EQUAL = new Condition(6); public static final Condition LESS_EQUAL = new Condition(7); private static int STRING_LIST_GIVEN_MASK = 128; private static int EMPTY_CELLS_ALLOWED_MASK = 256; private static int SUPPRESS_ARROW_MASK = 512; private static int SHOW_PROMPT_MASK = 262144; private static int SHOW_ERROR_MASK = 524288; private DVType type; private ErrorStyle errorStyle; private Condition condition; private boolean stringListGiven; private boolean emptyCellsAllowed; private boolean suppressArrow; private boolean showPrompt; private boolean showError; private String promptTitle; private String errorTitle; private String promptText; private String errorText; private FormulaParser formula1; private FormulaParser formula2; private int column1; private int row1; private int column2; private int row2; public DVParser(byte[] data, ExternalSheet es, WorkbookMethods nt, WorkbookSettings ws) throws FormulaException { int options = IntegerHelper.getInt(data[0], data[1], data[2], data[3]); int typeVal = options & 0xF; this.type = DVType.getType(typeVal); int errorStyleVal = (options & 0x70) >> 4; this.errorStyle = ErrorStyle.getErrorStyle(errorStyleVal); int conditionVal = (options & 0xF00000) >> 20; this.condition = Condition.getCondition(conditionVal); this.stringListGiven = ((options & STRING_LIST_GIVEN_MASK) != 0); this.emptyCellsAllowed = ((options & EMPTY_CELLS_ALLOWED_MASK) != 0); this.suppressArrow = ((options & SUPPRESS_ARROW_MASK) != 0); this.showPrompt = ((options & SHOW_PROMPT_MASK) != 0); this.showError = ((options & SHOW_ERROR_MASK) != 0); int pos = 4; int length = IntegerHelper.getInt(data[pos], data[pos + 1]); this.promptTitle = StringHelper.getUnicodeString(data, length, pos + 2); pos += length * 2 + 2; length = IntegerHelper.getInt(data[pos], data[pos + 1]); this.errorTitle = StringHelper.getUnicodeString(data, length, pos + 2); pos += length * 2 + 2; length = IntegerHelper.getInt(data[pos], data[pos + 1]); this.promptText = StringHelper.getUnicodeString(data, length, pos + 2); pos += length * 2 + 2; length = IntegerHelper.getInt(data[pos], data[pos + 1]); this.errorText = StringHelper.getUnicodeString(data, length, pos + 2); pos += length * 2 + 2; int formulaLength = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 4; if (formulaLength != 0) { byte[] tokens = new byte[formulaLength]; System.arraycopy(data, pos, tokens, 0, formulaLength); this.formula1 = new FormulaParser(tokens, null, es, nt, ws); this.formula1.parse(); pos += formulaLength; } formulaLength = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 4; if (formulaLength != 0) { byte[] tokens = new byte[formulaLength]; System.arraycopy(data, pos, tokens, 0, formulaLength); this.formula2 = new FormulaParser(tokens, null, es, nt, ws); this.formula2.parse(); pos += formulaLength; } pos += 2; this.row1 = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 2; this.row2 = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 2; this.column1 = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 2; this.column2 = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 2; } public byte[] getData() { byte[] f1Bytes = (this.formula1 != null) ? this.formula1.getBytes() : new byte[0]; byte[] f2Bytes = (this.formula2 != null) ? this.formula2.getBytes() : new byte[0]; int dataLength = 4 + this.promptTitle.length() * 2 + 2 + this.errorTitle.length() * 2 + 2 + this.promptText.length() * 2 + 2 + this.errorText.length() * 2 + 2 + f1Bytes.length + 2 + f2Bytes.length + 2 + 4 + 10; byte[] data = new byte[dataLength]; int pos = 0; int options = 0; options |= this.type.getValue(); options |= this.errorStyle.getValue() << 4; options |= this.condition.getValue() << 20; if (this.stringListGiven) options |= STRING_LIST_GIVEN_MASK; if (this.emptyCellsAllowed) options |= EMPTY_CELLS_ALLOWED_MASK; if (this.suppressArrow) options |= SUPPRESS_ARROW_MASK; if (this.showPrompt) options |= SHOW_PROMPT_MASK; if (this.showError) options |= SHOW_ERROR_MASK; IntegerHelper.getFourBytes(options, data, pos); pos += 4; IntegerHelper.getTwoBytes(this.promptTitle.length(), data, pos); pos += 2; StringHelper.getUnicodeBytes(this.promptTitle, data, pos); pos += this.promptTitle.length() * 2; IntegerHelper.getTwoBytes(this.errorTitle.length(), data, pos); pos += 2; StringHelper.getUnicodeBytes(this.errorTitle, data, pos); pos += this.errorTitle.length() * 2; IntegerHelper.getTwoBytes(this.promptText.length(), data, pos); pos += 2; StringHelper.getUnicodeBytes(this.promptText, data, pos); pos += this.promptText.length() * 2; IntegerHelper.getTwoBytes(this.errorText.length(), data, pos); pos += 2; StringHelper.getUnicodeBytes(this.errorText, data, pos); pos += this.errorText.length() * 2; IntegerHelper.getTwoBytes(f1Bytes.length, data, pos); pos += 4; System.arraycopy(f1Bytes, 0, data, pos, f1Bytes.length); pos += f1Bytes.length; IntegerHelper.getTwoBytes(f2Bytes.length, data, pos); pos += 2; System.arraycopy(f2Bytes, 0, data, pos, f2Bytes.length); pos += f2Bytes.length; pos += 2; IntegerHelper.getTwoBytes(1, data, pos); pos += 2; IntegerHelper.getTwoBytes(this.row1, data, pos); pos += 2; IntegerHelper.getTwoBytes(this.row2, data, pos); pos += 2; IntegerHelper.getTwoBytes(this.column1, data, pos); pos += 2; IntegerHelper.getTwoBytes(this.column2, data, pos); pos += 2; return data; } public void insertRow(int row) { if (this.formula1 != null) this.formula1.rowInserted(0, row, true); if (this.formula2 != null) this.formula2.rowInserted(0, row, true); if (this.row1 >= row) this.row1++; if (this.row2 >= row) this.row2++; } public void insertColumn(int col) { if (this.formula1 != null) this.formula1.columnInserted(0, col, true); if (this.formula2 != null) this.formula2.columnInserted(0, col, true); if (this.column1 >= col) this.column1++; if (this.column2 >= col) this.column2++; } public void removeRow(int row) { if (this.formula1 != null) this.formula1.rowRemoved(0, row, true); if (this.formula2 != null) this.formula2.rowRemoved(0, row, true); if (this.row1 > row) this.row1--; if (this.row2 >= row) this.row2--; } public void removeColumn(int col) { if (this.formula1 != null) this.formula1.columnRemoved(0, col, true); if (this.formula2 != null) this.formula2.columnRemoved(0, col, true); if (this.column1 > col) this.column1--; if (this.column2 >= col) this.column2--; } public int getFirstColumn() { return this.column1; } public int getLastColumn() { return this.column2; } public int getFirstRow() { return this.row1; } public int getLastRow() { return this.row2; } }