/**
         * Add new named area to this workbook with the given information.
         *
         * @param name name to be created.
         * @param sheet sheet containing the name
         * @param firstCol  first column this name refers to.
         * @param firstRow  first row this name refers to.
         * @param lastCol   last column this name refers to.
         * @param lastRow   last row this name refers to.
         * @param firstCol2 first column this name refers to.
         * @param firstRow2 first row this name refers to.
         * @param lastCol2  last column this name refers to.
         * @param lastRow2  last row this name refers to.
         * @param global   TRUE if this is a global name, FALSE if this is tied to
         *                 the sheet
         */
        public void addNameArea(BuiltInName name,
            WritableSheet sheet,
            int firstCol,
            int firstRow,
            int lastCol,
            int lastRow,
            int firstCol2,
            int firstRow2,
            int lastCol2,
            int lastRow2,
            bool global)
        {
            if (names == null)
                names = new ArrayList();

            int index = getInternalSheetIndex(sheet.getName());
            int externalSheetIndex = getExternalSheetIndex(sheet.getName());

            // Create a new name record.
            NameRecord nr = new NameRecord(name,
                             index,
                             externalSheetIndex,
                             firstRow2, lastRow2,
                             firstCol2, lastCol2,
                             firstRow, lastRow,
                             firstCol, lastCol,
                             global);

            // Add new name to name array.
            names.Add(nr);

            // Add new name to name hash table.
            string key = name.getName() == null ? NULLKEY : name.getName();
            nameRecords.Add(key, nr);
        }
        /**
         * A pseudo copy constructor.  Takes the handles to the font and formatting
         * records
         *
         * @exception IOException
         * @param w the workbook to copy
         * @param os the output stream to write the data to
         * @param cs TRUE if the workbook should close the output stream, FALSE
         * @param ws the configuration for this workbook
         */
        public WritableWorkbookImpl(Stream os,
            Workbook w,
            bool cs,
            WorkbookSettings ws)
            : base()
        {
            CSharpJExcel.Jxl.Read.Biff.WorkbookParser wp = (CSharpJExcel.Jxl.Read.Biff.WorkbookParser)w;

            // Reset the statically declared styles.  These are no longer needed
            // because the Styles class will intercept all calls within
            // CellValue.setCellDetails and if it detects a standard format, then it
            // will return a clone.  In short, the static cell values will
            // never get initialized anyway.  Still, just to be extra sure...
            //lock (SYNCHRONIZER)
            //    {
            //    WritableWorkbook.ARIAL_10_PT.uninitialize();
            //    WritableWorkbook.HYPERLINK_FONT.uninitialize();
            //    WritableWorkbook.NORMAL_STYLE.uninitialize();
            //    WritableWorkbook.HYPERLINK_STYLE.uninitialize();
            //    WritableWorkbook.HIDDEN_STYLE.uninitialize();
            //    DateRecord.defaultDateFormat.uninitialize();
            //    }

            closeStream = cs;
            sheets = new ArrayList();
            sharedStrings = new SharedStrings();
            nameRecords = new Dictionary<string, NameRecord>();
            fonts = wp.getFonts();
            formatRecords = wp.getFormattingRecords();
            wbProtected = false;
            settings = ws;
            rcirCells = new ArrayList();
            styles = new Styles();
            outputFile = new File(os, ws, wp.getCompoundFile());

            containsMacros = false;
            if (!ws.getPropertySetsDisabled())
                containsMacros = wp.containsMacros();

            // Copy the country settings
            if (wp.getCountryRecord() != null)
                countryRecord = new CountryRecord(wp.getCountryRecord());

            // Copy any add in functions
            addInFunctionNames = wp.getAddInFunctionNames();

            // Copy XCT records
            xctRecords = wp.getXCTRecords();

            // Copy any external sheets
            if (wp.getExternalSheetRecord() != null)
                {
                externSheet = new ExternalSheetRecord(wp.getExternalSheetRecord());

                // Get the associated supbooks
                CSharpJExcel.Jxl.Read.Biff.SupbookRecord[] readsr = wp.getSupbookRecords();
                supbooks = new ArrayList(readsr.Length);

                for (int i = 0; i < readsr.Length; i++)
                    {
                    CSharpJExcel.Jxl.Read.Biff.SupbookRecord readSupbook = readsr[i];
                    if (readSupbook.getType() == SupbookRecord.INTERNAL || readSupbook.getType() == SupbookRecord.EXTERNAL)
                        supbooks.Add(new SupbookRecord(readSupbook, settings));
                    else
                        {
                        if (readSupbook.getType() != SupbookRecord.ADDIN)
                            {
                            //logger.warn("unsupported supbook type - ignoring");
                            }
                        }
                    }
                }

            // Copy any drawings.  These must be present before we try and copy
            // the images from the read workbook
            if (wp.getDrawingGroup() != null)
                drawingGroup = new DrawingGroup(wp.getDrawingGroup());

            // Copy the property set references
            if (containsMacros && wp.getButtonPropertySet() != null)
                buttonPropertySet = new ButtonPropertySetRecord(wp.getButtonPropertySet());

            // Copy any names
            if (!settings.getNamesDisabled())
                {
                CSharpJExcel.Jxl.Read.Biff.NameRecord[] na = wp.getNameRecords();
                names = new ArrayList(na.Length);

                for (int i = 0; i < na.Length; i++)
                    {
                    if (na[i].isBiff8())
                        {
                        NameRecord n = new NameRecord(na[i], i);
                        names.Add(n);
                        string key = n.getName() == null ? NULLKEY : n.getName();
                        nameRecords.Add(key, n);
                        }
                    else
                        {
                        //logger.warn("Cannot copy Biff7 name records - ignoring");
                        }
                    }
                }

            copyWorkbook(w);

            // The copy process may have caused some critical fields in the
            // read drawing group to change.  Make sure these updates are reflected
            // in the writable drawing group
            if (drawingGroup != null)
                drawingGroup.updateData(wp.getDrawingGroup());
        }