public                                    SelectionCellRange[] Exclude(SelectionCellRange cellRangeToExclude)
        {
            if (cellRangeToExclude.IsEmpty)
            {
                return new SelectionCellRange[] { this }
            }
            ;

            SelectionCellRange cellRangeIntersection = this.Intersect(cellRangeToExclude);

            if (cellRangeIntersection.IsEmpty)
            {
                return new SelectionCellRange[] { this }
            }
            ;

            SelectionRange[]     itemRanges   = m_itemRange.Exclude(cellRangeToExclude.ItemRange);
            SelectionRange[]     columnRanges = m_columnRange.Exclude(cellRangeToExclude.ColumnRange);
            SelectionCellRange[] cellRanges   = new SelectionCellRange[itemRanges.Length + columnRanges.Length];
            int index = 0;

            foreach (SelectionRange itemRange in itemRanges)
            {
                cellRanges[index] = new SelectionCellRange(itemRange, m_columnRange);

                index++;
            }

            foreach (SelectionRange columnRange in columnRanges)
            {
                cellRanges[index] = new SelectionCellRange(cellRangeIntersection.ItemRange, columnRange);
                index++;
            }

            Debug.Assert(index == cellRanges.Length);
            return(cellRanges);
        }
        public bool Remove(SelectionRangeWithItems rangeWithItemsToRemove)
        {
            bool           removed       = false;
            SelectionRange rangeToRemove = rangeWithItemsToRemove.Range;

            object[] itemsToRemove        = rangeWithItemsToRemove.Items;
            int      itemsToRemoveCount   = (itemsToRemove == null) ? 0 : itemsToRemove.Length;
            int      itemOffsetToRemove   = 0;
            bool     rangeToRemoveIsEmpty = rangeToRemove.IsEmpty;

            do
            {
                for (int i = m_list.Count - 1; i >= 0; i--)
                {
                    SelectionRangeWithItems rangeWithItems = m_list[i];
                    SelectionRange          range          = rangeWithItems.Range;
                    SelectionRange          rangeIntersection;
                    object[] oldRangeItems = rangeWithItems.Items;

                    if (rangeToRemoveIsEmpty)
                    {
                        int itemOffset = Array.IndexOf(oldRangeItems, itemsToRemove[itemOffsetToRemove]);

                        if (itemOffset == -1)
                        {
                            continue;
                        }

                        rangeIntersection = new SelectionRange(range.GetIndexFromItemOffset(itemOffset));
                    }
                    else
                    {
                        rangeIntersection = range.Intersect(rangeToRemove);

                        if (rangeIntersection.IsEmpty)
                        {
                            continue;
                        }

                        if (!rangeWithItems.IsItemsEqual(rangeIntersection, rangeWithItemsToRemove))
                        {
                            continue;
                        }
                    }

                    removed       = true;
                    m_itemsCount -= rangeIntersection.Length;
                    SelectionRange[] newRanges = range.Exclude(rangeIntersection);

                    if (newRanges.Length == 0)
                    {
                        m_list.RemoveAt(i);
                    }
                    else
                    {
                        SelectionRange newRange = newRanges[0];
                        m_list[i] = new SelectionRangeWithItems(newRange, rangeWithItems.GetItems(newRange));

                        if (newRanges.Length > 1)
                        {
                            Debug.Assert(newRanges.Length == 2);
                            newRange = newRanges[1];
                            m_list.Insert(i + 1, new SelectionRangeWithItems(newRange, rangeWithItems.GetItems(newRange)));
                        }
                    }
                }

                itemOffsetToRemove++;
            } while((rangeToRemoveIsEmpty) && (itemOffsetToRemove < itemsToRemoveCount));

            return(removed);
        }