tdf#119227 fix freeze when copying a large bulleted list

freeze goes from 5 seconds to about 1 second for me

(1) used unordered_map instead of map
(2) don't create temporary SfxItemSet's just to check equality

Change-Id: I17939adb9ffd53bc56339d7a62ef217ade26de36
Reviewed-on: https://gerrit.libreoffice.org/85298
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
(cherry picked from commit 568b820bc2d52c007ee08ad7a3849c94a458115d)
Reviewed-on: https://gerrit.libreoffice.org/85366
diff --git a/sw/source/core/txtnode/thints.cxx b/sw/source/core/txtnode/thints.cxx
index 34bbe03..b46c3ea 100644
--- a/sw/source/core/txtnode/thints.cxx
+++ b/sw/source/core/txtnode/thints.cxx
@@ -80,6 +80,7 @@
#include <algorithm>
#include <map>
#include <memory>
#include <unordered_map>

#include <rdfhelper.hxx>
#include <hints.hxx>
@@ -2661,7 +2662,7 @@ bool SwpHints::MergePortions( SwTextNode& rNode )
    bool bRet = false;
    typedef std::multimap< int, std::pair<SwTextAttr*, bool> > PortionMap;
    PortionMap aPortionMap;
    std::map<int, bool> RsidOnlyAutoFormatFlagMap;
    std::unordered_map<int, bool> RsidOnlyAutoFormatFlagMap;
    sal_Int32 nLastPorStart = COMPLETE_STRING;
    int nKey = 0;

@@ -2791,43 +2792,45 @@ bool SwpHints::MergePortions( SwTextNode& rNode )
                    // in the RSID, which should have no effect on text layout
                    if (RES_TXTATR_AUTOFMT == p1->Which())
                    {
                        SfxItemSet set1(*p1->GetAutoFormat().GetStyleHandle());
                        SfxItemSet set2(*p2->GetAutoFormat().GetStyleHandle());

                        set1.ClearItem(RES_CHRATR_RSID);
                        set2.ClearItem(RES_CHRATR_RSID);
                        const SfxItemSet& rSet1 = *p1->GetAutoFormat().GetStyleHandle();
                        const SfxItemSet& rSet2 = *p2->GetAutoFormat().GetStyleHandle();

                        // sadly SfxItemSet::operator== does not seem to work?
                        SfxItemIter iter1(set1);
                        SfxItemIter iter2(set2);
                        if (set1.Count() == set2.Count())
                        SfxItemIter iter1(rSet1);
                        SfxItemIter iter2(rSet2);
                        for (SfxPoolItem const* pItem1 = iter1.GetCurItem(),
                                              * pItem2 = iter2.GetCurItem();
                             pItem1 && pItem2;
                             pItem1 = iter1.NextItem(),
                             pItem2 = iter2.NextItem())
                        {
                            for (SfxPoolItem const* pItem1 = iter1.GetCurItem(),
                                                  * pItem2 = iter2.GetCurItem();
                                 pItem1 && pItem2;
                                 pItem1 = iter1.NextItem(),
                                 pItem2 = iter2.NextItem())
                            if (pItem1->Which() == RES_CHRATR_RSID)
                                pItem1 = iter1.NextItem();
                            if (pItem2->Which() == RES_CHRATR_RSID)
                                pItem2 = iter2.NextItem();
                            if (!pItem1 && !pItem2)
                                break;
                            if (!pItem1 || !pItem2)
                            {
                                if (pItem1 != pItem2) // all are poolable
                                {
                                    assert(IsInvalidItem(pItem1) || IsInvalidItem(pItem2) || pItem1->Which() != pItem2->Which() || *pItem1 != *pItem2);
                                    eMerge = DIFFER;
                                    break;
                                }
                                if (iter1.IsAtEnd())
                                {
                                    assert(iter2.IsAtEnd());
                                    eMerge = DIFFER_ONLY_RSID;
                                }
                                eMerge = DIFFER;
                                break;
                            }
                            if (DIFFER == eMerge)
                                break; // outer loop too
                            if (pItem1 != pItem2) // all are poolable
                            {
                                assert(IsInvalidItem(pItem1) || IsInvalidItem(pItem2) || pItem1->Which() != pItem2->Which() || *pItem1 != *pItem2);
                                eMerge = DIFFER;
                                break;
                            }
                            if (iter1.IsAtEnd() || iter2.IsAtEnd())
                            {
                                eMerge = DIFFER;
                                break;
                            }
                        }
                        if (DIFFER == eMerge)
                            break; // outer loop too
                        else
                        {
                            eMerge = DIFFER;
                            break;
                        }
                            eMerge = DIFFER_ONLY_RSID;
                    }
                    else
                    {