    /* -*- 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/.
     */

    #include <searchresults.hxx>

    #include <svtools/simptabl.hxx>
    #include <svtools/treelistentry.hxx>
    #include <sfx2/bindings.hxx>
    #include <sfx2/dispatch.hxx>
    #include <dociter.hxx>
    #include <document.hxx>
    #include <rangeutl.hxx>
    #include <tabvwsh.hxx>
    #include <strings.hrc>
    #include <sc.hrc>
    #include <scresid.hxx>

    namespace sc {

    SearchResultsDlg::SearchResultsDlg( SfxBindings* _pBindings, vcl::Window* pParent ) :
        ModelessDialog(pParent, "SearchResultsDialog", "modules/scalc/ui/searchresults.ui"),
        aSkipped( ScResId( SCSTR_SKIPPED ) ),
        aTotal( ScResId( SCSTR_TOTAL ) ),
        mpBindings(_pBindings), mpDoc(nullptr)
    {
        get(mpSearchResults, "lbSearchResults");

        SvSimpleTableContainer *pContainer = get<SvSimpleTableContainer>("results");
        Size aControlSize(150, 120);
        aControlSize = pContainer->LogicToPixel(aControlSize, MapMode(MapUnit::MapAppFont));
        pContainer->set_width_request(aControlSize.Width());
        pContainer->set_height_request(aControlSize.Height());

        mpList = VclPtr<SvSimpleTable>::Create(*pContainer);
        long nTabs[] = {0, 40, 60};
        mpList->SetTabs(SAL_N_ELEMENTS(nTabs), nTabs);
        mpList->InsertHeaderEntry(ScResId(STR_SHEET) + "\t" + ScResId(STR_CELL) + "\t" + ScResId(STR_CONTENT));
        mpList->SetSelectHdl( LINK(this, SearchResultsDlg, ListSelectHdl) );
    }

    SearchResultsDlg::~SearchResultsDlg()
    {
        disposeOnce();
    }

    void SearchResultsDlg::dispose()
    {
        mpList.disposeAndClear();
        mpSearchResults.disposeAndClear();
        ModelessDialog::dispose();
    }

    namespace
    {
        class ListWrapper {
            OUStringBuffer maName;
            VclPtr<SvSimpleTable> mpList;
        public:
            size_t mnCount = 0;
            static const size_t mnMaximum = 1000;
            ListWrapper(const VclPtr<SvSimpleTable> &pList) :
                mpList(pList)
            {
                mpList->Clear();
                mpList->SetUpdateMode(false);
            }
            void Insert(const OUString &aTabName,
                        const ScAddress &rPos,
                        formula::FormulaGrammar::AddressConvention eConvention,
                        const OUString &aText)
            {
                if (mnCount++ < mnMaximum)
                {
                    maName.append(aTabName);
                    maName.append("\t");
                    maName.append(rPos.Format(ScRefFlags::ADDR_ABS,
                                              nullptr, eConvention));
                    maName.append("\t");
                    maName.append(aText);
                    mpList->InsertEntry(maName.makeStringAndClear());
                }
            }
        };
    }

    void SearchResultsDlg::FillResults( ScDocument* pDoc, const ScRangeList &rMatchedRanges, bool bCellNotes )
    {
        ListWrapper aList(mpList);
        std::vector<OUString> aTabNames = pDoc->GetAllTableNames();
        SCTAB nTabCount = aTabNames.size();

        // tdf#92160 - too many results blow the widget's mind
        size_t nMatchMax = rMatchedRanges.size();
        if (nMatchMax > ListWrapper::mnMaximum)
            nMatchMax = ListWrapper::mnMaximum;

        if (bCellNotes)
        {
            for (size_t i = 0, n = nMatchMax; i < n; ++i)
            {
                /* TODO: a CellNotes iterator would come handy and might speed
                 * things up a little, though we only loop through the
                 * search/replace result positions here. */
                ScRange const & rRange( rMatchedRanges[i] );
                // Bear in mind that mostly the range is one address position
                // or a column or a row joined.
                ScAddress aPos( rRange.aStart );
                for ( ; aPos.Tab() <= rRange.aEnd.Tab(); aPos.IncTab())
                {
                    if (aPos.Tab() >= nTabCount)
                        break;  // can this even happen? we just searched on existing sheets ...
                    for (aPos.SetCol( rRange.aStart.Col()); aPos.Col() <= rRange.aEnd.Col(); aPos.IncCol())
                    {
                        for (aPos.SetRow( rRange.aStart.Row()); aPos.Row() <= rRange.aEnd.Row(); aPos.IncRow())
                        {
                            const ScPostIt* pNote = pDoc->GetNote( aPos);
                            if (pNote)
                                aList.Insert(aTabNames[aPos.Tab()], aPos,
                                             pDoc->GetAddressConvention(),
                                             pNote->GetText());
                        }
                    }
                }
            }
        }
        else
        {
            for (size_t i = 0, n = nMatchMax; i < n; ++i)
            {
                ScCellIterator aIter(pDoc, rMatchedRanges[i]);
                for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
                {
                    ScAddress aPos = aIter.GetPos();
                    if (aPos.Tab() >= nTabCount)
                        // Out-of-bound sheet index.
                        continue;

                    aList.Insert(aTabNames[aPos.Tab()], aPos,
                                 pDoc->GetAddressConvention(),
                                 pDoc->GetString(aPos));
                }
            }
        }

        OUString aSearchResults = ScGlobal::ReplaceOrAppend( aTotal, "%1", OUString::number( aList.mnCount ) );
        if (aList.mnCount > ListWrapper::mnMaximum)
            aSearchResults += " " + ScGlobal::ReplaceOrAppend( aSkipped, "%1", OUString::number( ListWrapper::mnMaximum ) );
        mpSearchResults->SetText(aSearchResults);

        mpList->SetUpdateMode(true);

        mpDoc = pDoc;
    }

    bool SearchResultsDlg::Close()
    {
        if (mpBindings)
        {
            // Remove this dialog from the view frame after the dialog gets
            // dismissed, else it would keep popping up endlessly!
            SfxDispatcher* pDispacher = mpBindings ->GetDispatcher();
            SfxBoolItem aItem(SID_SEARCH_RESULTS_DIALOG, false);
            if (pDispacher)
            {
                pDispacher->ExecuteList(SID_SEARCH_RESULTS_DIALOG,
                    SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, { &aItem });
            }
        }

        return ModelessDialog::Close();
    }

    IMPL_LINK_NOARG( SearchResultsDlg, ListSelectHdl, SvTreeListBox*, void )
    {
        if (!mpDoc)
            return;

        SvTreeListEntry *pEntry = mpList->FirstSelected();
        OUString aTabStr = SvTabListBox::GetEntryText(pEntry, 0);
        OUString aPosStr = SvTabListBox::GetEntryText(pEntry, 1);

        SCTAB nTab = -1;
        if (!mpDoc->GetTable(aTabStr, nTab))
            // No sheet with specified name.
            return;

        ScAddress aPos;
        ScRefFlags nRes = aPos.Parse(aPosStr, mpDoc, mpDoc->GetAddressConvention());
        if (!(nRes & ScRefFlags::VALID))
            // Invalid address string.
            return;

        // Jump to the cell.
        ScTabViewShell* pScViewShell = ScTabViewShell::GetActiveViewShell();
        pScViewShell->SetTabNo(nTab);
        pScViewShell->SetCursor(aPos.Col(), aPos.Row());
        pScViewShell->AlignToCursor(aPos.Col(), aPos.Row(), SC_FOLLOW_JUMP);
    }

    SearchResultsDlgWrapper::SearchResultsDlgWrapper(
        vcl::Window* _pParent, sal_uInt16 nId, SfxBindings* pBindings, SfxChildWinInfo* /*pInfo*/ ) :
        SfxChildWindow(_pParent, nId)
    {
        SetWindow( VclPtr<SearchResultsDlg>::Create(pBindings, _pParent) );
    }

    SearchResultsDlgWrapper::~SearchResultsDlgWrapper() {}

    SfxChildWinInfo SearchResultsDlgWrapper::GetInfo() const
    {
        SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
        aInfo.bVisible = false;
        return aInfo;
    }

    SFX_IMPL_CHILDWINDOW_WITHID(SearchResultsDlgWrapper, SID_SEARCH_RESULTS_DIALOG);

    }

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

↑ V1029 Numeric Truncation Error. Result of the 'size' function is written to the 16-bit variable.