/**
         * Gets the built in name for the value
         */
        public static BuiltInName getBuiltInName(int val)
        {
            BuiltInName ret = FILTER_DATABASE;

            for (int i = 0; i < builtInNames.Length; i++)
            {
                if (builtInNames[i].getValue() == val)
                {
                    ret = builtInNames[i];
                }
            }
            return(ret);
        }
        /**
         * Create a new name record with the given information for 2-range entities.
         *
         * @param theName      Name to be created.
         * @param theIndex     Index of this name.
         * @param extSheet     External sheet index this name refers to.
         * @param theStartRow  First row this name refers to.
         * @param theEndRow    Last row this name refers to.
         * @param theStartCol  First column this name refers to.
         * @param theEndCol    Last column this name refers to.
         * @param theStartRow2 First row this name refers to (2nd instance).
         * @param theEndRow2   Last row this name refers to (2nd instance).
         * @param theStartCol2 First column this name refers to (2nd instance).
         * @param theEndCol2   Last column this name refers to (2nd instance).
         * @param global       TRUE if this is a global name
         */
        public NameRecord(BuiltInName theName,
            int theIndex,
            int extSheet,
            int theStartRow,
            int theEndRow,
            int theStartCol,
            int theEndCol,
            int theStartRow2,
            int theEndRow2,
            int theStartCol2,
            int theEndCol2,
            bool global)
            : base(Type.NAME)
        {
            builtInName = theName;
            index = theIndex;
            sheetRef = global ? 0 : index + 1; // 0 indicates a global name, otherwise
            // the 1-based index of the sheet

            ranges = new NameRange[2];
            ranges[0] = new NameRange(extSheet,
                                      theStartRow,
                                      theEndRow,
                                      theStartCol,
                                      theEndCol);
            ranges[1] = new NameRange(extSheet,
                                      theStartRow2,
                                      theEndRow2,
                                      theStartCol2,
                                      theEndCol2);
        }
        /**
         * Constructs this object from the raw data
         *
         * @param t the raw data
         * @param ws the workbook settings
         * @param ind the index in the name table
         */
        public NameRecord(Record t,WorkbookSettings ws,int ind)
            : base(t)
        {
            index = ind;
            isbiff8 = true;

            try
                {
                ranges = new ArrayList();

                byte[] data = getRecord().getData();
                int option = IntegerHelper.getInt(data[0],data[1]);
                int length = data[3];
                sheetRef = IntegerHelper.getInt(data[8],data[9]);

                if ((option & builtIn) != 0)
                    {
                    builtInName = BuiltInName.getBuiltInName(data[15]);
                    }
                else
                    {
                    name = StringHelper.getString(data,length,15,ws);
                    }

                if ((option & commandMacro) != 0)
                    {
                    // This is a command macro, so it has no cell references
                    return;
                    }

                int pos = length + 15;

                if (data[pos] == cellReference)
                    {
                    int sheet = IntegerHelper.getInt(data[pos + 1],data[pos + 2]);
                    int row = IntegerHelper.getInt(data[pos + 3],data[pos + 4]);
                    int columnMask = IntegerHelper.getInt(data[pos + 5],data[pos + 6]);
                    int column = columnMask & 0xff;

                    // Check that we are not dealing with offsets
                    Assert.verify((columnMask & 0xc0000) == 0);

                    NameRange r = new NameRange(sheet,column,row,column,row);
                    ranges.Add(r);
                    }
                else if (data[pos] == areaReference)
                    {
                    int sheet1 = 0;
                    int r1 = 0;
                    int columnMask = 0;
                    int c1 = 0;
                    int r2 = 0;
                    int c2 = 0;
                    NameRange range = null;

                    while (pos < data.Length)
                        {
                        sheet1 = IntegerHelper.getInt(data[pos + 1],data[pos + 2]);
                        r1 = IntegerHelper.getInt(data[pos + 3],data[pos + 4]);
                        r2 = IntegerHelper.getInt(data[pos + 5],data[pos + 6]);

                        columnMask = IntegerHelper.getInt(data[pos + 7],data[pos + 8]);
                        c1 = columnMask & 0xff;

                        // Check that we are not dealing with offsets
                        Assert.verify((columnMask & 0xc0000) == 0);

                        columnMask = IntegerHelper.getInt(data[pos + 9],data[pos + 10]);
                        c2 = columnMask & 0xff;

                        // Check that we are not dealing with offsets
                        Assert.verify((columnMask & 0xc0000) == 0);

                        range = new NameRange(sheet1,c1,r1,c2,r2);
                        ranges.Add(range);

                        pos += 11;
                        }
                    }
                else if (data[pos] == subExpression)
                    {
                    int sheet1 = 0;
                    int r1 = 0;
                    int columnMask = 0;
                    int c1 = 0;
                    int r2 = 0;
                    int c2 = 0;
                    NameRange range = null;

                    // Consume unnecessary parsed tokens
                    if (pos < data.Length &&
                        data[pos] != cellReference &&
                        data[pos] != areaReference)
                        {
                        if (data[pos] == subExpression)
                            {
                            pos += 3;
                            }
                        else if (data[pos] == union)
                            {
                            pos += 1;
                            }
                        }

                    while (pos < data.Length)
                        {
                        sheet1 = IntegerHelper.getInt(data[pos + 1],data[pos + 2]);
                        r1 = IntegerHelper.getInt(data[pos + 3],data[pos + 4]);
                        r2 = IntegerHelper.getInt(data[pos + 5],data[pos + 6]);

                        columnMask = IntegerHelper.getInt(data[pos + 7],data[pos + 8]);
                        c1 = columnMask & 0xff;

                        // Check that we are not dealing with offsets
                        Assert.verify((columnMask & 0xc0000) == 0);

                        columnMask = IntegerHelper.getInt(data[pos + 9],data[pos + 10]);
                        c2 = columnMask & 0xff;

                        // Check that we are not dealing with offsets
                        Assert.verify((columnMask & 0xc0000) == 0);

                        range = new NameRange(sheet1,c1,r1,c2,r2);
                        ranges.Add(range);

                        pos += 11;

                        // Consume unnecessary parsed tokens
                        if (pos < data.Length &&
                            data[pos] != cellReference &&
                            data[pos] != areaReference)
                            {
                            if (data[pos] == subExpression)
                                {
                                pos += 3;
                                }
                            else if (data[pos] == union)
                                {
                                pos += 1;
                                }
                            }
                        }
                    }
                else
                    {
                    string n = name != null ? name : builtInName.getName();
                    //logger.warn("Cannot read name ranges for " + n + " - setting to empty");
                    NameRange range = new NameRange(0,0,0,0,0);
                    ranges.Add(range);
                    }
                }
            catch (Exception t1)
                {
                // Generate a warning
                // Names are really a nice to have, and we don't want to halt the
                // reading process for functionality that probably won't be used
                //logger.warn("Cannot read name");
                name = "ERROR";
                }
        }
        /**
         * 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);
        }