package jxl.biff; import common.Assert; import common.Logger; import java.io.IOException; import java.text.DateFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import jxl.format.Colour; import jxl.format.RGB; import jxl.write.biff.File; public class FormattingRecords { private static Logger logger = Logger.getLogger(FormattingRecords.class); private HashMap formats; private ArrayList formatsList; private ArrayList xfRecords; private int nextCustomIndexNumber; private Fonts fonts; private PaletteRecord palette; private static final int customFormatStartIndex = 164; private static final int maxFormatRecordsIndex = 441; private static final int minXFRecords = 21; public FormattingRecords(Fonts f) { this.xfRecords = new ArrayList(10); this.formats = new HashMap(10); this.formatsList = new ArrayList(10); this.fonts = f; this.nextCustomIndexNumber = 164; } public final void addStyle(XFRecord xf) throws NumFormatRecordsException { if (!xf.isInitialized()) { int pos = this.xfRecords.size(); xf.initialize(pos, this, this.fonts); this.xfRecords.add(xf); } else if (xf.getXFIndex() >= this.xfRecords.size()) { this.xfRecords.add(xf); } } public final void addFormat(DisplayFormat fr) throws NumFormatRecordsException { if (fr.isInitialized() && fr.getFormatIndex() >= 441) { logger.warn("Format index exceeds Excel maximum - assigning custom number"); fr.initialize(this.nextCustomIndexNumber); this.nextCustomIndexNumber++; } if (!fr.isInitialized()) { fr.initialize(this.nextCustomIndexNumber); this.nextCustomIndexNumber++; } if (this.nextCustomIndexNumber > 441) { this.nextCustomIndexNumber = 441; throw new NumFormatRecordsException(); } if (fr.getFormatIndex() >= this.nextCustomIndexNumber) this.nextCustomIndexNumber = fr.getFormatIndex() + 1; if (!fr.isBuiltIn()) { this.formatsList.add(fr); this.formats.put(new Integer(fr.getFormatIndex()), fr); } } public final boolean isDate(int pos) { XFRecord xfr = this.xfRecords.get(pos); if (xfr.isDate()) return true; FormatRecord fr = (FormatRecord)this.formats.get(new Integer(xfr.getFormatRecord())); return (fr == null) ? false : fr.isDate(); } public final DateFormat getDateFormat(int pos) { XFRecord xfr = this.xfRecords.get(pos); if (xfr.isDate()) return xfr.getDateFormat(); FormatRecord fr = (FormatRecord)this.formats.get(new Integer(xfr.getFormatRecord())); if (fr == null) return null; return fr.isDate() ? fr.getDateFormat() : null; } public final NumberFormat getNumberFormat(int pos) { XFRecord xfr = this.xfRecords.get(pos); if (xfr.isNumber()) return xfr.getNumberFormat(); FormatRecord fr = (FormatRecord)this.formats.get(new Integer(xfr.getFormatRecord())); if (fr == null) return null; return fr.isNumber() ? fr.getNumberFormat() : null; } FormatRecord getFormatRecord(int index) { return (FormatRecord)this.formats.get(new Integer(index)); } public void write(File outputFile) throws IOException { Iterator i = this.formatsList.iterator(); FormatRecord fr = null; while (i.hasNext()) { fr = i.next(); outputFile.write(fr); } i = this.xfRecords.iterator(); XFRecord xfr = null; while (i.hasNext()) { xfr = (XFRecord)i.next(); outputFile.write(xfr); } BuiltInStyle style = new BuiltInStyle(16, 3); outputFile.write(style); style = new BuiltInStyle(17, 6); outputFile.write(style); style = new BuiltInStyle(18, 4); outputFile.write(style); style = new BuiltInStyle(19, 7); outputFile.write(style); style = new BuiltInStyle(0, 0); outputFile.write(style); style = new BuiltInStyle(20, 5); outputFile.write(style); } protected final Fonts getFonts() { return this.fonts; } public final XFRecord getXFRecord(int index) { return this.xfRecords.get(index); } protected final int getNumberOfFormatRecords() { return this.formatsList.size(); } public IndexMapping rationalizeFonts() { return this.fonts.rationalize(); } public IndexMapping rationalize(IndexMapping fontMapping, IndexMapping formatMapping) { XFRecord xfr = null; for (Iterator it = this.xfRecords.iterator(); it.hasNext(); ) { xfr = it.next(); if (xfr.getFormatRecord() >= 164) xfr.setFormatIndex(formatMapping.getNewIndex(xfr.getFormatRecord())); xfr.setFontIndex(fontMapping.getNewIndex(xfr.getFontIndex())); } ArrayList newrecords = new ArrayList(21); IndexMapping mapping = new IndexMapping(this.xfRecords.size()); int numremoved = 0; int numXFRecords = Math.min(21, this.xfRecords.size()); int j; for (j = 0; j < numXFRecords; j++) { newrecords.add(this.xfRecords.get(j)); mapping.setMapping(j, j); } if (numXFRecords < 21) { logger.warn("There are less than the expected minimum number of XF records"); return mapping; } for (j = 21; j < this.xfRecords.size(); j++) { XFRecord xf = this.xfRecords.get(j); boolean duplicate = false; Iterator iterator = newrecords.iterator(); while (iterator.hasNext() && !duplicate) { XFRecord xf2 = iterator.next(); if (xf2.equals(xf)) { duplicate = true; mapping.setMapping(j, mapping.getNewIndex(xf2.getXFIndex())); numremoved++; } } if (!duplicate) { newrecords.add(xf); mapping.setMapping(j, j - numremoved); } } for (Iterator i = this.xfRecords.iterator(); i.hasNext(); ) { XFRecord xf = i.next(); xf.rationalize(mapping); } this.xfRecords = newrecords; return mapping; } public IndexMapping rationalizeDisplayFormats() { ArrayList newformats = new ArrayList(); int numremoved = 0; IndexMapping mapping = new IndexMapping(this.nextCustomIndexNumber); Iterator i = this.formatsList.iterator(); DisplayFormat df = null; DisplayFormat df2 = null; boolean duplicate = false; while (i.hasNext()) { df = i.next(); Assert.verify(!df.isBuiltIn()); Iterator i2 = newformats.iterator(); duplicate = false; while (i2.hasNext() && !duplicate) { df2 = i2.next(); if (df2.equals(df)) { duplicate = true; mapping.setMapping(df.getFormatIndex(), mapping.getNewIndex(df2.getFormatIndex())); numremoved++; } } if (!duplicate) { newformats.add(df); int indexnum = df.getFormatIndex() - numremoved; if (indexnum > 441) { logger.warn("Too many number formats - using default format."); indexnum = 0; } mapping.setMapping(df.getFormatIndex(), df.getFormatIndex() - numremoved); } } this.formatsList = newformats; i = this.formatsList.iterator(); while (i.hasNext()) { df = i.next(); df.initialize(mapping.getNewIndex(df.getFormatIndex())); } return mapping; } public PaletteRecord getPalette() { return this.palette; } public void setPalette(PaletteRecord pr) { this.palette = pr; } public void setColourRGB(Colour c, int r, int g, int b) { if (this.palette == null) this.palette = new PaletteRecord(); this.palette.setColourRGB(c, r, g, b); } public RGB getColourRGB(Colour c) { if (this.palette == null) return c.getDefaultRGB(); return this.palette.getColourRGB(c); } }