[Libreoffice-commits] core.git: include/svl svl/source sw/inc sw/source

2023-09-08 Thread Armin Le Grand (allotropia) (via logerrit)
 include/svl/itemset.hxx  |   44 +
 svl/source/items/itemset.cxx |  972 +++
 svl/source/items/poolcach.cxx|2 
 sw/inc/swatrset.hxx  |2 
 sw/source/core/attr/swatrset.cxx |   12 
 5 files changed, 530 insertions(+), 502 deletions(-)

New commits:
commit c1f3b34f871d2a6bb9ee7b912492be1164eec96f
Author: Armin Le Grand (allotropia) 
AuthorDate: Tue Aug 29 11:17:59 2023 +0200
Commit: Armin Le Grand 
CommitDate: Fri Sep 8 17:38:24 2023 +0200

ITEM: preparations for more/easier changes II

Again this is a change to improve understandabilty/changeability
of SfxItemSet code plus some cleanups. Still did a callgrind round
to check - it slightly got faster. In a start/load(complex SW doc)/
show/shutdown cycle compared with master I get 96.722 mio cycles
compared with 99.851 mio in master.

Main focus was to isolate two aspects: preparation and cleanup of
an Item for usage in an SfxItemSet. For that we now have
  implCreateItemEntry: to do all needed actions to create/prepare
an Item for membership, including evtl. AddRef/Cloning/using
ItemPool stuff.
  implCleanupItemEntry: to do all needed actios to correctly
clean that Item up again.
All formally accesses distributed over SfxItemSet (and other places)
are cleaned-up to use these. The Item-counter in DBG code that I
already added helped a lot to do this.

Also cleaned up PutImpl to 1st check if action is necessary (Item is
already in place) or not, reducing spot to cleanup an Item that
was handed over as bPassingOwnership to one place.

I also added a 2nd flag, bItemIsSetMember, that tells if the Item
given as input is already member of an SfxItemSet, in that case a
shortcut can be used (increase AddRef, use).

Adapted all places AFAP to use the new container interface
(begin(), end(), ...) where useful.
Made GetItemState inline and directly use the tooling method. Same
for InvalidateItem.
Added much more comments to describe what's going on or to hint at
problems (check for CAUTION).
Removed PutDirect - not needed anymore, probably was there to not get
recursive death loop with callbacks in SW.
More smaller changes.

Checked with all apps, played around. Still, stuff may come up, so
I put on gerrit  the tests will show and give further hints. At last
SfxItemSet is a minefield :-)

Had to adapt SfxItemSet::implCreateItemEntry when input Item is
a StaticDefaultItem. SfxItemPool::PutImpl needs to be called in
that case.

Had to correct bItemIsSetMember in all cases if the transfer
of SfxPoolItems is between SfxItemSets with different
SfxItemPools. This is and will be necessary as long as the
Items are stored at the pool.

After a hard deep-dive I found the error: m_nCount was not in
all cases correct, invalid items get counted.

 Win build *insists* for initialzation of local var aEntry in
 SfxItemSet::PutImpl, triggers warning C4701:
 "potentially uninitialized local variable 'aEntry' used". This
 is not the case here, but I know of no way to silence the
 warning in another way, so added an extra-call to begin().

Re-added to use static pool defaults directly, possible After
the fix 6d8c6e8d60956fd36094035a526c1a29a902204b, thanks for
that. This avoids some cloning of Items.

CAUTION: static default items are not *that* static as it seems
(or: should be). If they are freed with the Pool (see
::ReleaseDefaults) they will be deleted. If the target pool is
different from the source pool static default items from the
source pool can be used that then might be deleted (sigh).

A solution would be to change all pools to really work on
static instances of default items.

Another one would be to know here that the
targetPool != sourcePool, so maybe extend
bItemIsSetMember -> bSamePool.

A good test for this is CppunitTest_chart2_uichart/testTdf98690.
Until solving/cleaning up we unfortunately *have* to continue
to clone static default items...

Change-Id: Ibd8dc6d612f594a5ad88c75fcee8726d89a6090c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156306
Tested-by: Jenkins
Reviewed-by: Armin Le Grand 

diff --git a/include/svl/itemset.hxx b/include/svl/itemset.hxx
index 37141a0a79b3..ba14c21b8e6c 100644
--- a/include/svl/itemset.hxx
+++ b/include/svl/itemset.hxx
@@ -85,9 +85,7 @@ private:
 const SfxItemSet&   operator=(const SfxItemSet &) = delete;
 
 protected:
-voidPutDirect(const SfxPoolItem );
-
-virtual const SfxPoolItem*  PutImpl( const SfxPoolItem&, sal_uInt16 
nWhich, bool bPassingOwnership );
+virtual const SfxPoolItem*  PutImpl( const SfxPoolItem&, sal_uInt16 
nWhich, bool bItemIsSetMember, bool 

[Libreoffice-commits] core.git: include/svl svl/source sw/inc sw/source

2023-08-10 Thread Armin Le Grand (allotropia) (via logerrit)
 include/svl/itemset.hxx  |   16 -
 svl/source/items/itemset.cxx |  108 +++
 sw/inc/swatrset.hxx  |   18 +-
 sw/source/core/attr/swatrset.cxx |  106 +-
 4 files changed, 176 insertions(+), 72 deletions(-)

New commits:
commit 23d1395a7856119173b37a6d787171f519554623
Author: Armin Le Grand (allotropia) 
AuthorDate: Thu Aug 10 15:54:23 2023 +0200
Commit: Armin Le Grand 
CommitDate: Thu Aug 10 20:43:21 2023 +0200

ITEM: improve SfxItemSet notification callback

When browsing cachegrind data I stumbled over the notification
callback used by Writer in SfxItemSet::Changed. That is a
virtual method that gets called in quite some places to forward
item changes, SW uses it to record these.
For that purpose always (quite some) data gets prepared without
checking if this is necessary, this uses calls to ::Get and
::GetDefaultItem to have either the old or new Item from the
parent or default (pool).
This is not needed - except for Writer. Even there this
mechanism is not always active. Thus I:

- removed SfxItemSet::Changed, replaced with a settable callback
member of type std::function<...>. Thus one less virtual function
and depenence in SfxItemSet
- added a callback functor to SwAttrSet that can be set at the
SfxItemSet it is derived from
- setting/releasing this only in used cases. It is not even used
all the time in SW.
- moved the creation/processing of needed data to a member
function in SW (SwAttrSet::changeCallback). All processing and
evtl. needed data is now created there - on demand.
- adapted all places in SfxItemSet where that mechanism is used
to only call it if set & without pre-calculating anything
- since all former calls/usages were pretty similar I could put
all of this to SwAttrSet::changeCallback

This leads to use that only when needed now. Naturally, SW will
potentially profit less than the other apps.

Here are callgrind numbers with this change using OfficeStart,
DocLoad, DocClose, OfficeShutdown. This change also has potential
avantages @runtime/UI which also did all preparations to call
SfxItemSet::Changed all the time:

Writer doc: 0,9907 ~1%
old: 93842 mio
new: 92971 mio

Draw/Impress doc: 0,9971 ~2,8%
old: 170023 mio
new: 169544 mio
::Get reduces from 1416103 to 293874 calls
::GetDefaultItem reduces from 2252336 to 1927209 calls (nearly half)

Calc doc: 0.9868 ~1,3%
old: 194708 mio
new: 192130 mio
::Get reduces from 882298 to 880087 calls
::GetDefaultItem reduces from 4611901 to 2633555 calls (nearly half)

Of course this highly depends on the used test documents, so it can
only be a excerpt result.

Also adapted SfxItemSet::MergeRange a little bit: Do nothing not only
when a single new slot is already contaioned, but check if all slots
are already present. This works well and fast using the formally added
caching mechanism.

Change-Id: I4d369d2e5b21aa7a21687177518150515e3de954
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/19
Tested-by: Jenkins
Reviewed-by: Noel Grandin 
Reviewed-by: Armin Le Grand 

diff --git a/include/svl/itemset.hxx b/include/svl/itemset.hxx
index 468893557b5e..a3736427b002 100644
--- a/include/svl/itemset.hxx
+++ b/include/svl/itemset.hxx
@@ -42,9 +42,20 @@ class SAL_WARN_UNUSED SVL_DLLPUBLIC SfxItemSet
 const SfxItemSet* m_pParent;   ///< derivation
 sal_uInt16m_nCount;///< number of items
 sal_uInt16m_nTotalCount;   ///< number of WhichIDs, also size of 
m_ppItems array
+
+// bitfield (better packaging if a bool needs to be added)
+bool  m_bItemsFixed : 1; ///< true if this is a 
SfxItemSetFixed object, so does not *own* m_ppItems
+
 SfxPoolItem const** m_ppItems; ///< pointer to array of items, we 
allocate and free this unless m_bItemsFixed==true
 WhichRangesContainer m_pWhichRanges;  ///< array of Which Ranges
-bool  m_bItemsFixed; ///< true if this is a SfxItemSetFixed 
object
+
+// Notification-Callback mechanism for SwAttrSet in SW, functionPtr for 
callback
+std::function m_aCallback;
+
+protected:
+// Notification-Callback mechanism for SwAttrSet in SW
+void setCallback(const std::function ) { m_aCallback = func; }
+void clearCallback() { m_aCallback = nullptr; }
 
 friend class SfxItemPoolCache;
 friend class SfxAllItemSet;
@@ -59,9 +70,6 @@ private:
 const SfxItemSet&   operator=(const SfxItemSet &) = delete;
 
 protected:
-// Notification-Callback
-virtual voidChanged( const SfxPoolItem& rOld, const 
SfxPoolItem& rNew );
-
 voidPutDirect(const SfxPoolItem );
 
 virtual const SfxPoolItem*  PutImpl( const 

[Libreoffice-commits] core.git: include/svl svl/source sw/inc sw/source

2022-06-20 Thread Caolán McNamara (via logerrit)
 include/svl/style.hxx |6 +++---
 svl/source/items/style.cxx|8 
 sw/inc/docstyle.hxx   |2 +-
 sw/source/uibase/app/docstyle.cxx |   10 +-
 4 files changed, 13 insertions(+), 13 deletions(-)

New commits:
commit 94be0c12fe419cc7f50f5cfc6cdf161805e7490f
Author: Caolán McNamara 
AuthorDate: Mon Jun 20 09:44:28 2022 +0100
Commit: Caolán McNamara 
CommitDate: Mon Jun 20 14:41:48 2022 +0200

SfxStyleSheetBasePool::Find can be const

Change-Id: I5cf2737d05cfe4b0be936a77cfb96db053483438
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136141
Tested-by: Jenkins
Reviewed-by: Caolán McNamara 

diff --git a/include/svl/style.hxx b/include/svl/style.hxx
index b5b7aa3adcf5..29127eb77356 100644
--- a/include/svl/style.hxx
+++ b/include/svl/style.hxx
@@ -192,7 +192,7 @@ public:
 /** Constructor.
  * The iterator will only iterate over style sheets which have the family 
\p eFam
  */
-SfxStyleSheetIterator(SfxStyleSheetBasePool *pBase,
+SfxStyleSheetIterator(const SfxStyleSheetBasePool *pBase,
   SfxStyleFamily eFam, SfxStyleSearchBits 
n=SfxStyleSearchBits::All );
 SfxStyleSearchBits GetSearchMask() const;
 SfxStyleFamily GetSearchFamily() const;
@@ -207,7 +207,7 @@ public:
 
 protected:
 
-SfxStyleSheetBasePool*  pBasePool;
+const SfxStyleSheetBasePool*  pBasePool;
 SfxStyleFamily  nSearchFamily;
 SfxStyleSearchBits  nMask;
 
@@ -274,7 +274,7 @@ public:
 
 SfxStyleSheetBase*  First(SfxStyleFamily eFamily, SfxStyleSearchBits eMask 
= SfxStyleSearchBits::All);
 SfxStyleSheetBase*  Next();
-virtual SfxStyleSheetBase*  Find( const OUString&, SfxStyleFamily eFam, 
SfxStyleSearchBits n=SfxStyleSearchBits::All );
+virtual SfxStyleSheetBase*  Find( const OUString&, SfxStyleFamily eFam, 
SfxStyleSearchBits n=SfxStyleSearchBits::All ) const;
 
 virtual boolSetParent(SfxStyleFamily eFam,
   const OUString ,
diff --git a/svl/source/items/style.cxx b/svl/source/items/style.cxx
index 50952a8857d2..0179635f7493 100644
--- a/svl/source/items/style.cxx
+++ b/svl/source/items/style.cxx
@@ -385,12 +385,12 @@ struct DoesStyleMatchStyleSheetPredicate final : public 
svl::StyleSheetPredicate
 
 }
 
-SfxStyleSheetIterator::SfxStyleSheetIterator(SfxStyleSheetBasePool *pBase,
+SfxStyleSheetIterator::SfxStyleSheetIterator(const SfxStyleSheetBasePool 
*pBase,
  SfxStyleFamily eFam, 
SfxStyleSearchBits n)
-: pCurrentStyle(nullptr)
+: pBasePool(pBase)
+, pCurrentStyle(nullptr)
 , mnCurrentPosition(0)
 {
-pBasePool=pBase;
 nSearchFamily=eFam;
 bSearchUsed=false;
 if( (( n & SfxStyleSearchBits::AllVisible ) != 
SfxStyleSearchBits::AllVisible )
@@ -690,7 +690,7 @@ SfxStyleSheetBasePool& SfxStyleSheetBasePool::operator+=( 
const SfxStyleSheetBas
 
 SfxStyleSheetBase* SfxStyleSheetBasePool::Find(const OUString& rName,
SfxStyleFamily eFamily,
-   SfxStyleSearchBits eMask)
+   SfxStyleSearchBits eMask) const
 {
 SfxStyleSheetIterator aIter(this, eFamily, eMask);
 return aIter.Find(rName);
diff --git a/sw/inc/docstyle.hxx b/sw/inc/docstyle.hxx
index 91a03b8614b9..d727245c059e 100644
--- a/sw/inc/docstyle.hxx
+++ b/sw/inc/docstyle.hxx
@@ -222,7 +222,7 @@ public:
 SfxStyleSearchBits nMask = SfxStyleSearchBits::All) override;
 
 virtual SfxStyleSheetBase* Find( const OUString&, SfxStyleFamily eFam,
-SfxStyleSearchBits 
n=SfxStyleSearchBits::All ) override;
+SfxStyleSearchBits 
n=SfxStyleSearchBits::All ) const override;
 
 virtual bool SetParent( SfxStyleFamily eFam, const OUString ,
 const OUString  ) override;
diff --git a/sw/source/uibase/app/docstyle.cxx 
b/sw/source/uibase/app/docstyle.cxx
index efaf6853e0ad..7bc284a4824f 100644
--- a/sw/source/uibase/app/docstyle.cxx
+++ b/sw/source/uibase/app/docstyle.cxx
@@ -2578,8 +2578,8 @@ bool  SwDocStyleSheetPool::SetParent( SfxStyleFamily eFam,
 return bRet;
 }
 
-SfxStyleSheetBase* SwDocStyleSheetPool::Find( const OUString& rName,
-  SfxStyleFamily eFam, 
SfxStyleSearchBits n )
+SfxStyleSheetBase* SwDocStyleSheetPool::Find(const OUString& rName,
+ SfxStyleFamily eFam, 
SfxStyleSearchBits n) const
 {
 SfxStyleSearchBits nSMask = n;
 if( SfxStyleFamily::Para == eFam &&  
m_rDoc.getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) )
@@ -2706,14 +2706,14 @@ SfxStyleSheetBase*  SwStyleSheetIterator::First()
 // Delete current
 mxIterSheet->Reset();
 
-SwDoc& rDoc = static_cast(pBasePool)->GetDoc();
+const SwDoc& 

[Libreoffice-commits] core.git: include/svl svl/source sw/inc sw/source

2017-12-02 Thread Eike Rathke
 include/svl/zforlist.hxx  |4 
 svl/source/numbers/zforlist.cxx   |2 ++
 sw/inc/cellatr.hxx|8 +++-
 sw/source/core/attr/cellatr.cxx   |   11 ++-
 sw/source/core/doc/docsort.cxx|2 +-
 sw/source/core/edit/edtab.cxx |3 +--
 sw/source/core/fields/cellfml.cxx |5 +++--
 sw/source/core/table/swtable.cxx  |   17 -
 sw/source/core/undo/untbl.cxx |4 ++--
 sw/source/core/unocore/unotbl.cxx |6 ++
 sw/source/filter/xml/xmlfmte.cxx  |2 +-
 sw/source/filter/xml/xmltble.cxx  |2 +-
 12 files changed, 42 insertions(+), 24 deletions(-)

New commits:
commit afbd0960f0b8d8b27cc9582279367540cc8aad84
Author: Eike Rathke 
Date:   Fri Dec 1 23:50:23 2017 +0100

Get rid of the css::util::NumberFormat::TEXT abuse as "special" "key"

It is a bit, not a key, which demanded special treatment at all
places, and a key with the same value could not be handled at all.

Abusing the css::util::NumberFormat::TEXT flag as number format
key to signal the "special" meaning, having a number format key
equal to that value would had resulted in undesired behaviour.
The bit value is 256 and a key 256 means 156 user defined number
formats in the default locale, rarely in the wild but can happen.

Change-Id: Idfd5b07d524c222df3491d201095ef65ad4a46c9
Reviewed-on: https://gerrit.libreoffice.org/45705
Tested-by: Jenkins 
Reviewed-by: Eike Rathke 

diff --git a/include/svl/zforlist.hxx b/include/svl/zforlist.hxx
index 3e59064281c2..5b84d0078408 100644
--- a/include/svl/zforlist.hxx
+++ b/include/svl/zforlist.hxx
@@ -54,6 +54,10 @@ namespace com { namespace sun { namespace star {
 #define SV_COUNTRY_LANGUAGE_OFFSET 1  // Max count of formats per 
country/language
 #define SV_MAX_COUNT_STANDARD_FORMATS  100// Max count of builtin default 
formats per CL
 
+/// The built-in @ Text format, offset within a locale, key in the locale the
+/// number formatter was constructed with.
+constexpr sal_uInt32 NF_STANDARD_FORMAT_TEXT = SV_MAX_COUNT_STANDARD_FORMATS;
+
 #define NUMBERFORMAT_ENTRY_NOT_FOUND (sal_uInt32)(0x)   /// MAX_ULONG
 
 
diff --git a/svl/source/numbers/zforlist.cxx b/svl/source/numbers/zforlist.cxx
index a6e7af89562f..bfa23d2f5f58 100644
--- a/svl/source/numbers/zforlist.cxx
+++ b/svl/source/numbers/zforlist.cxx
@@ -86,6 +86,8 @@ using namespace ::std;
 #define ZF_STANDARD_LOGICAL SV_MAX_COUNT_STANDARD_FORMATS-1 //  99
 #define ZF_STANDARD_TEXTSV_MAX_COUNT_STANDARD_FORMATS   // 100
 
+static_assert( ZF_STANDARD_TEXT == NF_STANDARD_FORMAT_TEXT, "definition 
mismatch" );
+
 /* Locale that is set if an unknown locale (from another system) is loaded of
  * legacy documents. Can not be SYSTEM because else, for example, a German "DM"
  * (old currency) is recognized as a date (#53155#). */
diff --git a/sw/inc/cellatr.hxx b/sw/inc/cellatr.hxx
index 2dfb8c193b87..30027fc64c77 100644
--- a/sw/inc/cellatr.hxx
+++ b/sw/inc/cellatr.hxx
@@ -28,11 +28,17 @@
 
 namespace rtl { class OUString; }
 
+/** The number formatter's default locale's @ Text format.
+Not necessarily system locale, but the locale the formatter was constructed
+with. For this SvNumberFormatter::IsTextFormat() always returns true.
+ */
+constexpr sal_uInt32 getSwDefaultTextFormat() { return 
NF_STANDARD_FORMAT_TEXT; }
+
 class SW_DLLPUBLIC SwTableBoxNumFormat : public SfxUInt32Item
 {
 bool m_bAuto; ///< automatically given flag
 public:
-SwTableBoxNumFormat( sal_uInt32 nFormat = css::util::NumberFormat::TEXT,
+SwTableBoxNumFormat( sal_uInt32 nFormat = getSwDefaultTextFormat(),
 bool bAuto = false );
 
 // "pure virtual methods" of SfxPoolItem
diff --git a/sw/source/core/attr/cellatr.cxx b/sw/source/core/attr/cellatr.cxx
index e8ec2c59a049..abc80746442d 100644
--- a/sw/source/core/attr/cellatr.cxx
+++ b/sw/source/core/attr/cellatr.cxx
@@ -31,8 +31,17 @@
 #include 
 #include 
 
+// The % SV_COUNTRY_LANGUAGE_OFFSET result checks if nFormat is a mere built-in
+// @ Text format of *any* locale and if so uses the default text format. Text
+// is text, the locale doesn't matter for Writer's number formatting purposes.
+// The advantage is that this is the pool's default item value and some places
+// benefit from this special treatment in that they don't have to handle/store
+// attribute specifics, especially when writing a document.
 SwTableBoxNumFormat::SwTableBoxNumFormat( sal_uInt32 nFormat, bool bFlag )
-: SfxUInt32Item( RES_BOXATR_FORMAT, nFormat ), m_bAuto( bFlag )
+: SfxUInt32Item( RES_BOXATR_FORMAT,
+(((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 
getSwDefaultTextFormat()) ?
+ getSwDefaultTextFormat() : nFormat))
+, m_bAuto( bFlag )
 {
 }
 
diff --git a/sw/source/core/doc/docsort.cxx b/sw/source/core/doc/docsort.cxx
index cd146f81dc61..3aa5fa635e20 

[Libreoffice-commits] core.git: include/svl svl/source sw/inc sw/source

2013-06-26 Thread Oliver-Rainer Wittmann
 include/svl/undo.hxx   |2 +
 svl/source/undo/undo.cxx   |   21 
 sw/inc/IDocumentUndoRedo.hxx   |6 ++-
 sw/source/core/edit/edundo.cxx |   15 +++--
 sw/source/core/inc/UndoManager.hxx |6 +--
 sw/source/core/layout/trvlfrm.cxx  |   61 +++--
 sw/source/core/undo/docundo.cxx|   21 ++--
 sw/source/ui/shells/textsh1.cxx|5 +++
 8 files changed, 95 insertions(+), 42 deletions(-)

New commits:
commit 25d84e2826de81d1e7a55ff0fdab7845b7a78e74
Author: Oliver-Rainer Wittmann o...@apache.org
Date:   Wed Jun 26 12:15:55 2013 +

Resolves: #i121751# restore cursor/selection on Undo/Redo language...

change for all text

- group intrinsic actions of language change for all text into one Undo 
action
- secure SwRootFrm::CalcRects(..) - catch NULL pointer
- correct CursorGuard - really restore the cursor

(cherry picked from commit 4207db473430e02a65a5f4d57db6e46a8db29a19)

Conflicts:
svl/inc/svl/undo.hxx
svl/source/undo/undo.cxx
sw/inc/IDocumentUndoRedo.hxx
sw/source/core/edit/edundo.cxx
sw/source/core/inc/UndoManager.hxx
sw/source/core/layout/trvlfrm.cxx
sw/source/core/undo/docundo.cxx

Change-Id: I972988bbc21a519e0956ff196aa93a46287b9a2e

diff --git a/include/svl/undo.hxx b/include/svl/undo.hxx
index c1054a6..3e59baa 100644
--- a/include/svl/undo.hxx
+++ b/include/svl/undo.hxx
@@ -240,6 +240,7 @@ namespace svl
 
 virtual size_t  GetRedoActionCount( bool const i_currentLevel 
= CurrentLevel ) const = 0;
 virtual OUStringGetRedoActionComment( size_t nNo=0, bool const 
i_currentLevel = CurrentLevel ) const = 0;
+virtual SfxUndoAction*  GetRedoAction( size_t nNo=0, bool const 
i_currentLevel = CurrentLevel ) const = 0;
 
 virtual sal_BoolUndo() = 0;
 virtual sal_BoolRedo() = 0;
@@ -358,6 +359,7 @@ public:
 virtual SfxUndoAction*  GetUndoAction( size_t nNo=0 ) const;
 virtual size_t  GetRedoActionCount( bool const i_currentLevel = 
CurrentLevel ) const;
 virtual OUStringGetRedoActionComment( size_t nNo=0, bool const 
i_currentLevel = CurrentLevel ) const;
+virtual SfxUndoAction*  GetRedoAction( size_t nNo=0, bool const 
i_currentLevel = CurrentLevel ) const;
 virtual sal_BoolUndo();
 virtual sal_BoolRedo();
 virtual voidClear();
diff --git a/svl/source/undo/undo.cxx b/svl/source/undo/undo.cxx
index dac5dc3..d27de22 100644
--- a/svl/source/undo/undo.cxx
+++ b/svl/source/undo/undo.cxx
@@ -830,11 +830,30 @@ size_t SfxUndoManager::ImplGetRedoActionCount_Lock( bool 
const i_currentLevel )
 
 //
 
+SfxUndoAction* SfxUndoManager::GetRedoAction( size_t nNo, bool const 
i_currentLevel ) const
+{
+UndoManagerGuard aGuard( *m_pData );
+
+const SfxUndoArray* pUndoArray = i_currentLevel ? m_pData-pActUndoArray : 
m_pData-pUndoArray;
+if ( (pUndoArray-nCurUndoAction + nNo)  pUndoArray-aUndoActions.size() )
+{
+return NULL;
+}
+return pUndoArray-aUndoActions[ pUndoArray-nCurUndoAction + nNo 
].pAction;
+}
+
+//
+
 OUString SfxUndoManager::GetRedoActionComment( size_t nNo, bool const 
i_currentLevel ) const
 {
+String sComment;
 UndoManagerGuard aGuard( *m_pData );
 const SfxUndoArray* pUndoArray = i_currentLevel ? m_pData-pActUndoArray : 
m_pData-pUndoArray;
-return pUndoArray-aUndoActions[ pUndoArray-nCurUndoAction + nNo 
].pAction-GetComment();
+if ( (pUndoArray-nCurUndoAction + nNo)  pUndoArray-aUndoActions.size() )
+{
+sComment = pUndoArray-aUndoActions[ pUndoArray-nCurUndoAction + nNo 
].pAction-GetComment();
+}
+return sComment;
 }
 
 //
diff --git a/sw/inc/IDocumentUndoRedo.hxx b/sw/inc/IDocumentUndoRedo.hxx
index 26e76f0..a50a4f0 100644
--- a/sw/inc/IDocumentUndoRedo.hxx
+++ b/sw/inc/IDocumentUndoRedo.hxx
@@ -156,11 +156,13 @@ public:
 */
 virtual sal_Bool Redo() = 0;
 
-/** Get comment of first Redo action.
+/** Get Id and comment of first Redo action.
 @param o_pStr   if not 0, receives comment of first Redo action.
+@param o_pIdif not 0, receives Id of first Redo action.
 @return true if there is a Redo action, false if none
 */
-virtual bool GetFirstRedoInfo(OUString *const o_pStr) const = 0;
+virtual bool GetFirstRedoInfo(OUString *const o_pStr,
+  SwUndoId *const o_pId = 0) const = 0;
 
 /** Get comments of Redo actions.
 @return comments of all top-level Redo actions.
diff --git a/sw/source/core/edit/edundo.cxx b/sw/source/core/edit/edundo.cxx
index bd27446..4fa0cee