    /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
    /*
     * This file is part of the LibreOffice project.
     *
     * This Source Code Form is subject to the terms of the Mozilla Public
     * License, v. 2.0. If a copy of the MPL was not distributed with this
     * file, You can obtain one at http://mozilla.org/MPL/2.0/.
     *
     * This file incorporates work covered by the following license notice:
     *
     *   Licensed to the Apache Software Foundation (ASF) under one or more
     *   contributor license agreements. See the NOTICE file distributed
     *   with this work for additional information regarding copyright
     *   ownership. The ASF licenses this file to you under the Apache
     *   License, Version 2.0 (the "License"); you may not use this file
     *   except in compliance with the License. You may obtain a copy of
     *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
     */

    #include "accfrmobj.hxx"

    #include <accmap.hxx>
    #include "acccontext.hxx"

    #include <viewsh.hxx>
    #include <rootfrm.hxx>
    #include <flyfrm.hxx>
    #include <pagefrm.hxx>
    #include <cellfrm.hxx>
    #include <swtable.hxx>
    #include <dflyobj.hxx>
    #include <frmfmt.hxx>
    #include <fmtanchr.hxx>
    #include <dcontact.hxx>

    #include <pam.hxx>

    #include <vcl/window.hxx>

    namespace sw { namespace access {

    SwAccessibleChild::SwAccessibleChild()
        : mpFrame( nullptr )
        , mpDrawObj( nullptr )
        , mpWindow( nullptr )
    {}

    SwAccessibleChild::SwAccessibleChild( const SdrObject* pDrawObj )
        : mpFrame( nullptr )
        , mpDrawObj( nullptr )
        , mpWindow( nullptr )
    {
        Init( pDrawObj );
    }

    SwAccessibleChild::SwAccessibleChild( const SwFrame* pFrame )
        : mpFrame( nullptr )
        , mpDrawObj( nullptr )
        , mpWindow( nullptr )
    {
        Init( pFrame );
    }

    SwAccessibleChild::SwAccessibleChild( vcl::Window* pWindow )
        : mpFrame( nullptr )
        , mpDrawObj( nullptr )
        , mpWindow( nullptr )
    {
        Init( pWindow );
    }

    SwAccessibleChild::SwAccessibleChild( const SwFrame* pFrame,
                                          const SdrObject* pDrawObj,
                                          vcl::Window* pWindow )
        : mpFrame( nullptr )
        , mpDrawObj( nullptr )
        , mpWindow( nullptr )
    {
        if ( pFrame )
        {
            Init( pFrame );
        }
        else if ( pDrawObj )
        {
            Init( pDrawObj );
        }
        else if ( pWindow )
        {
            Init( pWindow );
        }
        OSL_ENSURE( (!pFrame || pFrame == mpFrame) &&
                (!pDrawObj || pDrawObj == mpDrawObj) &&
                (!pWindow || pWindow == mpWindow),
                "invalid frame/object/window combination" );

    }

    SwAccessibleChild::~SwAccessibleChild() = default;

    void SwAccessibleChild::Init( const SdrObject* pDrawObj )
    {
        mpDrawObj = pDrawObj;
        const SwVirtFlyDrawObj* pFlyDrawObj = dynamic_cast<const SwVirtFlyDrawObj*>(mpDrawObj);
        mpFrame = pFlyDrawObj ? pFlyDrawObj->GetFlyFrame() : nullptr;
        mpWindow = nullptr;
    }

    void SwAccessibleChild::Init( const SwFrame* pFrame )
    {
        mpFrame = pFrame;
        mpDrawObj = mpFrame && mpFrame->IsFlyFrame()
                    ? static_cast < const SwFlyFrame * >( mpFrame )->GetVirtDrawObj()
                    : nullptr;
        mpWindow = nullptr;
    }

    void SwAccessibleChild::Init( vcl::Window* pWindow )
    {
        mpWindow = pWindow;
        mpFrame = nullptr;
        mpDrawObj = nullptr;
    }

    bool SwAccessibleChild::IsAccessible( bool bPagePreview ) const
    {
        bool bRet( false );

        if ( mpFrame )
        {
            bRet = mpFrame->IsAccessibleFrame() &&
                   ( !mpFrame->IsCellFrame() ||
                     static_cast<const SwCellFrame *>( mpFrame )->GetTabBox()->GetSttNd() != nullptr ) &&
                   !mpFrame->IsInCoveredCell() &&
                   ( bPagePreview ||
                     !mpFrame->IsPageFrame() );
        }
        else if ( mpDrawObj )
        {
            bRet = true;
        }
        else if ( mpWindow )
        {
            bRet = true;
        }

        return bRet;
    }

    bool SwAccessibleChild::IsBoundAsChar() const
    {
        bool bRet( false );

        if ( mpFrame )
        {
            bRet = mpFrame->IsFlyFrame() &&
                   static_cast< const SwFlyFrame *>(mpFrame)->IsFlyInContentFrame();
        }
        else if ( mpDrawObj )
        {
            const SwFrameFormat* pFrameFormat = ::FindFrameFormat( mpDrawObj );
            bRet = pFrameFormat
                   && (RndStdIds::FLY_AS_CHAR == pFrameFormat->GetAnchor().GetAnchorId());
        }
        else if ( mpWindow )
        {
            bRet = false;
        }

        return bRet;
    }

    SwAccessibleChild& SwAccessibleChild::operator=( const SdrObject* pDrawObj )
    {
        Init( pDrawObj );
        return *this;
    }

    SwAccessibleChild& SwAccessibleChild::operator=( const SwFrame* pFrame )
    {
        Init( pFrame );
        return *this;
    }

    SwAccessibleChild& SwAccessibleChild::operator=( vcl::Window* pWindow )
    {
        Init( pWindow );
        return *this;
    }

    bool SwAccessibleChild::operator==( const SwAccessibleChild& r ) const
    {
        return mpFrame == r.mpFrame &&
               mpDrawObj == r.mpDrawObj &&
               mpWindow == r.mpWindow;
    }

    bool SwAccessibleChild::IsValid() const
    {
        return mpFrame != nullptr ||
               mpDrawObj != nullptr ||
               mpWindow != nullptr;
    }

    bool SwAccessibleChild::IsVisibleChildrenOnly() const
    {
        bool bRet( false );

        if ( !mpFrame )
        {
            bRet = true;
        }
        else
        {
            bRet = mpFrame->IsRootFrame() ||
                   !( mpFrame->IsTabFrame() ||
                      mpFrame->IsInTab() ||
                      ( IsBoundAsChar() &&
                        static_cast<const SwFlyFrame*>(mpFrame)->GetAnchorFrame()->IsInTab() ) );
        }

        return bRet;
    }

    SwRect SwAccessibleChild::GetBox( const SwAccessibleMap& rAccMap ) const
    {
        SwRect aBox;

        if ( mpFrame )
        {
            if ( mpFrame->IsPageFrame() &&
                 static_cast< const SwPageFrame * >( mpFrame )->IsEmptyPage() )
            {
                aBox = SwRect( mpFrame->getFrameArea().Left(), mpFrame->getFrameArea().Top()-1, 1, 1 );
            }
            else if ( mpFrame->IsTabFrame() )
            {
                aBox = SwRect( mpFrame->getFrameArea() );
                aBox.Intersection( mpFrame->GetUpper()->getFrameArea() );
            }
            else
            {
                aBox = mpFrame->getFrameArea();
            }
        }
        else if( mpDrawObj )
        {
            SwDrawContact const*const pContact(dynamic_cast<SwDrawContact const*>(::GetUserCall(mpDrawObj)));
            // assume that a) the SwVirt* objects that don't have this are handled
            // by the mpFrame case above b) for genuine SdrObject this must be set
            // if it's connected to layout
            assert(pContact);
            SwPageFrame const*const pPage(const_cast<SwAnchoredObject *>(
                pContact->GetAnchoredObj(mpDrawObj))->FindPageFrameOfAnchor());
            if (pPage) // may end up here with partial layout -> not visible
            {
                aBox = SwRect( mpDrawObj->GetCurrentBoundRect() );
                // tdf#91260 drawing object may be partially off-page
                aBox.Intersection(pPage->getFrameArea());
            }
        }
        else if ( mpWindow )
        {
            vcl::Window *pWin = rAccMap.GetShell()->GetWin();
            if (pWin)
            {
                aBox = SwRect( pWin->PixelToLogic(
                                                tools::Rectangle( mpWindow->GetPosPixel(),
                                                           mpWindow->GetSizePixel() ) ) );
            }
        }

        return aBox;
    }

    SwRect SwAccessibleChild::GetBounds( const SwAccessibleMap& rAccMap ) const
    {
        SwRect aBound;

        if( mpFrame )
        {
            if( mpFrame->IsPageFrame() &&
                static_cast< const SwPageFrame * >( mpFrame )->IsEmptyPage() )
            {
                aBound = SwRect( mpFrame->getFrameArea().Left(), mpFrame->getFrameArea().Top()-1, 0, 0 );
            }
            else
                aBound = mpFrame->GetPaintArea();
        }
        else if( mpDrawObj )
        {
            aBound = GetBox( rAccMap );
        }
        else if ( mpWindow )
        {
            aBound = GetBox( rAccMap );
        }

        return aBound;
    }

    bool SwAccessibleChild::AlwaysIncludeAsChild() const
    {
        bool bAlwaysIncludedAsChild( false );

        if ( mpWindow )
        {
            bAlwaysIncludedAsChild = true;
        }

        return bAlwaysIncludedAsChild;
    }

    const SwFrame* SwAccessibleChild::GetParent( const bool bInPagePreview ) const
    {
        const SwFrame* pParent( nullptr );

        if ( mpFrame )
        {
            if( mpFrame->IsFlyFrame() )
            {
                const SwFlyFrame* pFly = static_cast< const SwFlyFrame *>( mpFrame );
                if( pFly->IsFlyInContentFrame() )
                {
                    // For RndStdIds::FLY_AS_CHAR the parent is the anchor
                    pParent = pFly->GetAnchorFrame();
                    OSL_ENSURE( SwAccessibleChild( pParent ).IsAccessible( bInPagePreview ),
                            "parent is not accessible" );
                }
                else
                {
                    // In any other case the parent is the root frm
                    // (in page preview, the page frame)
                    if( bInPagePreview )
                        pParent = pFly->FindPageFrame();
                    else
                        pParent = pFly->getRootFrame();
                }
            }
            else
            {
                SwAccessibleChild aUpper( mpFrame->GetUpper() );
                while( aUpper.GetSwFrame() && !aUpper.IsAccessible(bInPagePreview) )
                {
                    aUpper = aUpper.GetSwFrame()->GetUpper();
                }
                pParent = aUpper.GetSwFrame();
            }
        }
        else if( mpDrawObj )
        {
            const SwDrawContact *pContact =
                static_cast< const SwDrawContact* >( GetUserCall( mpDrawObj ) );
            OSL_ENSURE( pContact, "sdr contact is missing" );
            if( pContact )
            {
                const SwFrameFormat *pFrameFormat = pContact->GetFormat();
                OSL_ENSURE( pFrameFormat, "frame format is missing" );
                if( pFrameFormat && RndStdIds::FLY_AS_CHAR == pFrameFormat->GetAnchor().GetAnchorId() )
                {
                    // For RndStdIds::FLY_AS_CHAR the parent is the anchor
                    pParent = pContact->GetAnchorFrame();
                    OSL_ENSURE( SwAccessibleChild( pParent ).IsAccessible( bInPagePreview ),
                            "parent is not accessible" );

                }
                else
                {
                    // In any other case the parent is the root frm
                    SwFrame const*const pAnchor(pContact->GetAnchorFrame());
                    if (pAnchor) // null if object removed from layout
                    {
                        if (bInPagePreview)
                            pParent = pAnchor->FindPageFrame();
                        else
                            pParent = pAnchor->getRootFrame();
                    }
                }
            }
        }
        else if ( mpWindow )
        {
            css::uno::Reference < css::accessibility::XAccessible > xAcc =
                                                        mpWindow->GetAccessible();
            if ( xAcc.is() )
            {
                css::uno::Reference < css::accessibility::XAccessibleContext > xAccContext =
                                                    xAcc->getAccessibleContext();
                if ( xAccContext.is() )
                {
                    css::uno::Reference < css::accessibility::XAccessible > xAccParent =
                                                    xAccContext->getAccessibleParent();
                    if ( xAccParent.is() )
                    {
                        SwAccessibleContext* pAccParentImpl =
                                    dynamic_cast< SwAccessibleContext *>( xAccParent.get() );
                        if ( pAccParentImpl )
                        {
                            pParent = pAccParentImpl->GetFrame();
                        }
                    }
                }
            }
        }

        return pParent;
    }

    } } // eof of namespace sw::access

    /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

↑ V522 There might be dereferencing of a potential null pointer 'pContact'.