/// <summary>
        /// Takes as input a set of rectangles to perform a rectangular decomposition
        /// based on the ri. It creates a new set of rectangles each of them being
        /// marked as covered or not.
        ///
        /// </summary>
        /// <param name="alIn">List of input rectangle</param>
        /// <param name="ri">Overlapping Rectangle</param>
        /// <param name="alOut">New sets of reactangle</param>
        /// <param name="fRiAsInsideRect">Input Rectangle is rectangle covering alIn Rects or everything
        ///                               outside of ri must be marked as covered</param>
        static private void SplitRect(ArrayList alIn, ref CPRect ri, ArrayList alOut, bool fRiAsInsideRect)
        {
            alOut.Clear();
            for (int i = 0, c = alIn.Count; i < c; i++)
            {
                CPRect ro = (CPRect)alIn[i];

                SplitRect(ref ro, ri, alOut, fRiAsInsideRect);
            }
        }
        /// <summary>
        /// Slip a rectangle into a maximum of 5 pieces.
        /// ro is the out rectangle and ri is the exclusion rectangle.
        /// The number of resulting rectangles varies based on the position of ri relative to ro
        /// Each resulting reactangles are flaged  as covered or not.
        /// The ro covered flag is or'ed to allow for recursive calls
        ///
        ///      +-----------------+
        ///      |     :  2 :      |
        ///      |     :    :      |
        ///      |     ######      |
        ///      |     ###3##      |
        ///      | 1   ######  5   |
        ///      |     ######      |
        ///      |     :    :      |
        ///      |     :  4 :      |
        ///      |     :    :      |
        ///      +-----------------+
        /// </summary>
        /// <param name="ro">Outside Rectangle</param>
        /// <param name="ri">Inside Rectangle</param>
        /// <param name="alRect">Collection of resulting rectangles</param>
        /// <param name="fRiAsInsideRect"></param>
        static private void SplitRect(ref CPRect ro, CPRect ri, ArrayList alRect, bool fRiAsInsideRect)
        {
            // If ri is fully outside easy way out.
            if (!ro._fNotCovered || !ro.Intersect(ref ri))
            {
                ro._fNotCovered &= fRiAsInsideRect;
                alRect.Add(ro);
                return;
            }

            if (ro.Overlap(ref ri))
            {
                ro._fNotCovered &= !fRiAsInsideRect;
                alRect.Add(ro);
                return;
            }

            // right clip
            if (ri._right > ro._right)
            {
                ri._right = ro._right;
            }

            // bottom clip
            if (ri._bottom > ro._bottom)
            {
                ri._bottom = ro._bottom;
            }

            int left  = ro._left;
            int right = ri._left;

            if (right > left)
            {
                alRect.Add(new CPRect(left, ro._top, right, ro._bottom, ro._fNotCovered & fRiAsInsideRect));
                left = right;
            }

            right = ri._right;
            if (right > left)
            {
                SplitVertical(ref ro, ref ri, left, right, alRect, !fRiAsInsideRect);
                left = right;
            }

            right = ro._right;
            if (right > left)
            {
                alRect.Add(new CPRect(left, ro._top, right, ro._bottom, ro._fNotCovered & fRiAsInsideRect));
            }
        }
        /// <summary>
        /// Find a clickable point in a list of rectangle.
        /// Goes through the list of rectangle, stops on the first rectangle that is not covered
        /// and returns the mid point
        /// </summary>
        /// <param name="al">list of ractangle</param>
        /// <param name="x">X coordinate for a clickable point</param>
        /// <param name="y">Y coordinate for a clickable point</param>
        /// <returns>Clickable point found</returns>
        static private bool GetClickablePoint(ArrayList al, out int x, out int y)
        {
            for (int i = 0, c = al.Count; i < c; i++)
            {
                CPRect r = (CPRect)al[i];

                if (r._fNotCovered == true && (r._right - r._left) * (r._bottom - r._top) > 0)
                {
                    // Skip if the rectangle is empty
                    if (r._right > r._left && r._bottom > r._top)
                    {
                        // mid point rounded to the left
                        x = ((r._right - 1) + r._left) / 2;
                        y = ((r._bottom - 1) + r._top) / 2;
                        return(true);
                    }
                }
            }

            x = y = 0;
            return(false);
        }
 // return true if the 2 rectangle intersects
 internal bool Intersect(ref CPRect ri)
 {
     return(!(_top >= ri._bottom || ri._top >= _bottom || _left >= ri._right || ri._left >= _right));
 }
 // return true if ri completely covers this
 internal bool Overlap(ref CPRect ri)
 {
     return(ri._left <= _left && ri._right >= _right && ri._top <= _top && ri._bottom >= _bottom);
 }
        /// <summary>
        /// Slip a rectangle into a maximum of 5 pieces. 
        /// ro is the out rectangle and ri is the exclusion rectangle.
        /// The number of resulting rectangles varies based on the position of ri relative to ro 
        /// Each resulting reactangles are flaged  as covered or not.
        /// The ro covered flag is or'ed to allow for recursive calls
        ///
        ///      +-----------------+
        ///      |     :  2 :      |
        ///      |     :    :      |
        ///      |     ######      |
        ///      |     ###3##      |
        ///      | 1   ######  5   |
        ///      |     ######      |
        ///      |     :    :      |
        ///      |     :  4 :      |
        ///      |     :    :      |
        ///      +-----------------+
        /// </summary>
        /// <param name="ro">Outside Rectangle</param>
        /// <param name="ri">Inside Rectangle</param>
        /// <param name="alRect">Collection of resulting rectangles</param>
        /// <param name="fRiAsInsideRect"></param>
        static private void SplitRect(ref CPRect ro, CPRect ri, ArrayList alRect, bool fRiAsInsideRect)
        {
            // If ri is fully outside easy way out.
            if (!ro._fNotCovered || !ro.Intersect(ref ri))
            {
                ro._fNotCovered &= fRiAsInsideRect;
                alRect.Add(ro);
                return;
            }

            if (ro.Overlap(ref ri))
            {
                ro._fNotCovered &= !fRiAsInsideRect;
                alRect.Add(ro);
                return;
            }

            // right clip
            if (ri._right > ro._right)
            {
                ri._right = ro._right;
            }

            // bottom clip
            if (ri._bottom > ro._bottom)
            {
                ri._bottom = ro._bottom;
            }

            int left = ro._left;
            int right = ri._left;

            if (right > left)
            {
                alRect.Add(new CPRect(left, ro._top, right, ro._bottom, ro._fNotCovered & fRiAsInsideRect));
                left = right;
            }

            right = ri._right;
            if (right > left)
            {
                SplitVertical(ref ro, ref ri, left, right, alRect, !fRiAsInsideRect);
                left = right;
            }

            right = ro._right;
            if (right > left)
            {
                alRect.Add(new CPRect(left, ro._top, right, ro._bottom, ro._fNotCovered & fRiAsInsideRect));
            }
        }
        /// <summary>
        /// Takes as input a set of rectangles to perform a rectangular decomposition 
        /// based on the ri. It creates a new set of rectangles each of them being 
        /// marked as covered or not.
        /// 
        /// </summary>
        /// <param name="alIn">List of input rectangle</param>
        /// <param name="ri">Overlapping Rectangle</param>
        /// <param name="alOut">New sets of reactangle</param>
        /// <param name="fRiAsInsideRect">Input Rectangle is rectangle covering alIn Rects or everything
        ///                               outside of ri must be marked as covered</param>
        static private void SplitRect(ArrayList alIn, ref CPRect ri, ArrayList alOut, bool fRiAsInsideRect)
        {
            alOut.Clear();
            for (int i = 0, c = alIn.Count; i < c; i++)
            {
                CPRect ro = (CPRect)alIn[i];

                SplitRect(ref ro, ri, alOut, fRiAsInsideRect);
            }
        }
        /// <summary>
        /// Split a rectangle into a maximum of 3 rectangble.
        ///   ro is the outside rectangle and ri is the inside rectangle
        ///   ro might is split vertically in a a maximim of 3 rectangles sharing the same 
        ///   right and left margin
        /// </summary>
        /// <param name="ro">Outside Rectangle</param>
        /// <param name="ri">Inside Rectangle</param>
        /// <param name="left">Left Margin for the resulting rectangles</param>
        /// <param name="right">Right Margin for the resulting rectangles</param>
        /// <param name="alRect">Array of resulting rectangles</param>
        /// <param name="fRiAsInsideRect">Covered flag</param>
        static private void SplitVertical(ref CPRect ro, ref CPRect ri, int left, int right, ArrayList alRect, bool fRiAsInsideRect)
        {
            // bottom clip
            if (ri._bottom > ro._bottom)
            {
                ri._bottom = ro._bottom;
            }

            int top = ro._top;
            int bottom = ri._top;

            if (bottom > top)
            {
                alRect.Add(new CPRect(left, top, right, bottom, ro._fNotCovered));
                top = bottom;
            }

            bottom = ri._bottom;
            if (bottom > top)
            {
                alRect.Add(new CPRect(left, top, right, bottom, ro._fNotCovered & fRiAsInsideRect));
                top = bottom;
            }

            bottom = ro._bottom;
            if (bottom > top)
            {
                alRect.Add(new CPRect(left, top, right, bottom, ro._fNotCovered));
            }
        }
        // ------------------------------------------------------
        //
        // Private Methods
        //
        // ------------------------------------------------------

        #region Private Methods

        private static bool ClickableInRect(IntPtr hwnd, ref NativeMethods.Win32Point pt, bool fRiAsInsideRect, ArrayList alIn, ArrayList alOut)
        {
            if (!SafeNativeMethods.IsWindowVisible(hwnd))
            {
                return fRiAsInsideRect;
            }

            // Get the window rect. If this window has a width and it is effectivly invisible
            NativeMethods.Win32Rect rc = new NativeMethods.Win32Rect();

            if (!Misc.GetWindowRect(hwnd, ref rc))
            {
                return fRiAsInsideRect;
            }

            if ((rc.right - rc.left) <= 0 || (rc.bottom - rc.top) <= 0)
            {
                return fRiAsInsideRect;
            }

            // Try for transparency...
            if (fRiAsInsideRect)
            {
                int x = (rc.right + rc.left) / 2;
                int y = (rc.top + rc.bottom) / 2;

                try
                {
                    int lr = Misc.ProxySendMessageInt(hwnd, NativeMethods.WM_NCHITTEST, IntPtr.Zero, NativeMethods.Util.MAKELPARAM(x, y));

                    if (lr == NativeMethods.HTTRANSPARENT)
                    {
                        return true;
                    }
                }
// PRESHARP: Warning - Catch statements should not have empty bodies
#pragma warning disable 6502
                catch (TimeoutException)
                {
                    // Ignore this timeout error.  Avalon HwndWrappers have a problem with this WM_NCHITTEST call sometimes.
                }
#pragma warning restore 6502
            }

            // Copy the output bits
            alIn.Clear();
            alIn.AddRange(alOut);

            CPRect rcp = new CPRect(ref rc, false);

            ClickablePoint.SplitRect(alIn, ref rcp, alOut, fRiAsInsideRect);
            if (!GetClickablePoint(alOut, out pt.x, out pt.y))
            {
                return false;
            }

            return true;
        }
 // return true if ri completely covers this
 internal bool Overlap(ref CPRect ri)
 {
     return (ri._left <= _left && ri._right >= _right && ri._top <= _top && ri._bottom >= _bottom);
 }
 // return true if the 2 rectangle intersects
 internal bool Intersect(ref CPRect ri)
 {
     return !(_top >= ri._bottom || ri._top >= _bottom || _left >= ri._right || ri._left >= _right);
 }
        /// <summary>
        /// Go through the list of all element chidren and exclude them from the list of 
        /// visible/clickable rectangles.
        /// The element children may be listed in any order. A check on all of them must
        /// be performed. There is no easy way out.
        /// </summary>
        /// <param name="fragment"></param>
        /// <param name="alIn"></param>
        /// <param name="alOut"></param>
        internal static void ExcludeChildren(ProxyFragment fragment, ArrayList alIn, ArrayList alOut)
        {
            // First go through all the children to exclude whatever is on top
            for (ProxySimple simple = fragment.GetFirstChild(); simple != null; simple = fragment.GetNextSibling(simple))
            {
                // The exclusion for hwnd children is done by the GetPoint routine
                if (simple is ProxyHwnd)
                {
                    continue;
                }

                // Copy the output bits
                alIn.Clear();
                alIn.AddRange(alOut);

                NativeMethods.Win32Rect rc = new NativeMethods.Win32Rect(simple.BoundingRectangle);
                CPRect rcp = new CPRect(ref rc, false);

                ClickablePoint.SplitRect(alIn, ref rcp, alOut, true);

                // recurse on the children
                if (simple is ProxyFragment)
                {
                    ExcludeChildren((ProxyFragment)simple, alIn, alOut);
                }
            }
        }