[Libreoffice-commits] .: cui/source editeng/inc editeng/Package_inc.mk editeng/source officecfg/registry svx/inc svx/source sw/inc sw/source xmloff/inc xmloff/source

Cédric Bosdonnat cbosdo at kemper.freedesktop.org
Thu Dec 22 08:55:19 PST 2011


 cui/source/options/treeopt.cxx                             |    1 
 cui/source/options/treeopt.src                             |    1 
 editeng/Package_inc.mk                                     |    1 
 editeng/inc/editeng/rsiditem.hxx                           |   43 
 editeng/inc/editeng/svxenum.hxx                            |    6 
 editeng/source/items/textitem.cxx                          |   28 
 officecfg/registry/schema/org/openoffice/Office/Writer.xcs |   30 
 svx/inc/svx/dialogs.hrc                                    |    1 
 svx/source/src/app.hrc                                     |    3 
 sw/inc/doc.hxx                                             |   10 
 sw/inc/globals.hrc                                         |    1 
 sw/inc/helpid.h                                            |    1 
 sw/inc/hintids.hxx                                         |  143 +
 sw/inc/modcfg.hxx                                          |   46 
 sw/inc/ndtxt.hxx                                           |    7 
 sw/inc/swmodule.hxx                                        |   10 
 sw/inc/unoprnms.hxx                                        |    4 
 sw/source/core/bastyp/init.cxx                             |    9 
 sw/source/core/doc/doc.cxx                                 |   74 +
 sw/source/core/doc/doccomp.cxx                             |  932 ++++++++++++-
 sw/source/core/doc/docnew.cxx                              |    9 
 sw/source/core/edit/editsh.cxx                             |    7 
 sw/source/core/frmedt/fecopy.cxx                           |   17 
 sw/source/core/inc/UndoSplitMove.hxx                       |    1 
 sw/source/core/text/atrstck.cxx                            |    4 
 sw/source/core/txtnode/ndtxt.cxx                           |   40 
 sw/source/core/undo/unspnd.cxx                             |    4 
 sw/source/core/unocore/unomap.cxx                          |    2 
 sw/source/core/unocore/unoprnms.cxx                        |    2 
 sw/source/filter/ascii/parasc.cxx                          |    3 
 sw/source/filter/html/css1atr.cxx                          |    3 
 sw/source/filter/html/htmlatr.cxx                          |    2 
 sw/source/filter/xml/xmlexp.cxx                            |    8 
 sw/source/ui/app/appopt.cxx                                |    1 
 sw/source/ui/app/docsh.cxx                                 |    3 
 sw/source/ui/app/swmodul1.cxx                              |   40 
 sw/source/ui/config/modcfg.cxx                             |   80 +
 sw/source/ui/config/optdlg.hrc                             |    8 
 sw/source/ui/config/optdlg.src                             |   74 +
 sw/source/ui/config/optpage.cxx                            |  136 +
 sw/source/ui/dialog/swdlgfact.cxx                          |    5 
 sw/source/ui/inc/optpage.hxx                               |   27 
 sw/source/ui/uno/SwXDocumentSettings.cxx                   |   28 
 xmloff/inc/xmloff/xmltoken.hxx                             |    2 
 xmloff/inc/xmloff/xmltypes.hxx                             |    1 
 xmloff/inc/xmloff/xmluconv.hxx                             |    7 
 xmloff/source/core/xmltoken.cxx                            |    2 
 xmloff/source/core/xmluconv.cxx                            |   28 
 xmloff/source/style/prhdlfac.cxx                           |    3 
 xmloff/source/style/xmlbahdl.cxx                           |   42 
 xmloff/source/style/xmlbahdl.hxx                           |   12 
 xmloff/source/text/txtprmap.cxx                            |    8 
 52 files changed, 1825 insertions(+), 135 deletions(-)

New commits:
commit 062eaeffe7cb986255063bb9b0a5f3fb3fc8e34c
Author: Tzvetelina Tzeneva <tzvetelina at gmail.com>
Date:   Thu Dec 22 17:27:32 2011 +0100

    sw: Improved document comparison based on RSIDs.

diff --git a/cui/source/options/treeopt.cxx b/cui/source/options/treeopt.cxx
index 8053a3f..9d02f0f 100644
--- a/cui/source/options/treeopt.cxx
+++ b/cui/source/options/treeopt.cxx
@@ -385,6 +385,7 @@ static OptionsMapping_Impl const OptionsMap_Impl[] =
     { "Writer",             "Print",                RID_SW_TP_OPTPRINT_PAGE },
     { "Writer",             "Table",                RID_SW_TP_OPTTABLE_PAGE },
     { "Writer",             "Changes",              RID_SW_TP_REDLINE_OPT },
+    { "Writer",             "Comparison",           RID_SW_TP_COMPARISON_OPT },
     { "Writer",             "Compatibility",        RID_SW_TP_OPTCOMPATIBILITY_PAGE },
     { "Writer",             "AutoCaption",          RID_SW_TP_OPTCAPTION_PAGE },
     { "Writer",             "MailMerge",            RID_SW_TP_MAILCONFIG },
diff --git a/cui/source/options/treeopt.src b/cui/source/options/treeopt.src
index 9e4fdeb..37bdc36 100644
--- a/cui/source/options/treeopt.src
+++ b/cui/source/options/treeopt.src
@@ -148,6 +148,7 @@ Resource RID_OFADLG_OPTIONS_TREE_PAGES
             < "Print" ;       RID_SW_TP_OPTPRINT_PAGE  ; > ;
             < "Table" ;         RID_SW_TP_OPTTABLE_PAGE  ; > ;
             < "Changes" ;    RID_SW_TP_REDLINE_OPT    ; > ;
+            < "Comparison" ; RID_SW_TP_COMPARISON_OPT ; > ;
             < "Compatibility" ; RID_SW_TP_OPTCOMPATIBILITY_PAGE    ; > ;
             < "AutoCaption" ; RID_SW_TP_OPTCAPTION_PAGE ; > ;
             < "Mail Merge E-mail" ; RID_SW_TP_MAILCONFIG ; >;
diff --git a/editeng/Package_inc.mk b/editeng/Package_inc.mk
index 61d0603..0305a04 100644
--- a/editeng/Package_inc.mk
+++ b/editeng/Package_inc.mk
@@ -113,6 +113,7 @@ $(eval $(call gb_Package_add_file,editeng_inc,inc/editeng/postitem.hxx,editeng/p
 $(eval $(call gb_Package_add_file,editeng_inc,inc/editeng/prntitem.hxx,editeng/prntitem.hxx))
 $(eval $(call gb_Package_add_file,editeng_inc,inc/editeng/protitem.hxx,editeng/protitem.hxx))
 $(eval $(call gb_Package_add_file,editeng_inc,inc/editeng/prszitem.hxx,editeng/prszitem.hxx))
+$(eval $(call gb_Package_add_file,editeng_inc,inc/editeng/rsiditem.hxx,editeng/rsiditem.hxx))
 $(eval $(call gb_Package_add_file,editeng_inc,inc/editeng/scriptspaceitem.hxx,editeng/scriptspaceitem.hxx))
 $(eval $(call gb_Package_add_file,editeng_inc,inc/editeng/scripttypeitem.hxx,editeng/scripttypeitem.hxx))
 $(eval $(call gb_Package_add_file,editeng_inc,inc/editeng/shaditem.hxx,editeng/shaditem.hxx))
diff --git a/editeng/inc/editeng/rsiditem.hxx b/editeng/inc/editeng/rsiditem.hxx
new file mode 100644
index 0000000..e98fb8e
--- /dev/null
+++ b/editeng/inc/editeng/rsiditem.hxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Version: MPL 1.1 / GPLv3+ / LGPLv3+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License or as specified alternatively below. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Major Contributor(s):
+ * [ Copyright (C) 2009 Tzvetelina Tzeneva <tzvetelina at gmail.com> (initial developer) ]
+ */
+#ifndef _SVX_RSIDITEM_HXX
+#define _SVX_RSIDITEM_HXX
+
+#include <svl/intitem.hxx>
+#include "editeng/editengdllapi.h"
+
+//----------------------
+// SvxRsidItem
+//----------------------
+
+class EDITENG_DLLPUBLIC SvxRsidItem : public SfxUInt32Item
+{
+public:
+    TYPEINFO();
+
+    SvxRsidItem( sal_uInt32 nRsid, sal_uInt16 nId ) : SfxUInt32Item( nId, nRsid ) {}
+    SvxRsidItem( SvStream& rIn, sal_uInt16 nId ) : SfxUInt32Item( nId, rIn ) {}
+
+    virtual SfxPoolItem* Clone( SfxItemPool* pPool = NULL ) const;
+    virtual SfxPoolItem* Create( SvStream& rIn, sal_uInt16 nVer ) const;
+
+    virtual bool QueryValue( com::sun::star::uno::Any& rVal, sal_uInt8 nMemberId = 0 ) const;
+    virtual bool PutValue( const com::sun::star::uno::Any& rVal, sal_uInt8 nMemberId = 0 );
+};
+
+#endif // _SVX_RSIDITEM_HXX
diff --git a/editeng/inc/editeng/svxenum.hxx b/editeng/inc/editeng/svxenum.hxx
index 6884972..2d07e9f 100644
--- a/editeng/inc/editeng/svxenum.hxx
+++ b/editeng/inc/editeng/svxenum.hxx
@@ -222,6 +222,12 @@ enum SvxExtNumType
     SVX_NUM_CHARS_LOWER_LETTER_N
 };
 
+enum SvxCompareMode
+{
+    SVX_CMP_AUTO = 0,
+    SVX_CMP_BY_WORD,
+    SVX_CMP_BY_CHAR
+};
 
 #endif
 
diff --git a/editeng/source/items/textitem.cxx b/editeng/source/items/textitem.cxx
index e306907..db0edf2 100644
--- a/editeng/source/items/textitem.cxx
+++ b/editeng/source/items/textitem.cxx
@@ -73,6 +73,7 @@
 #include <com/sun/star/lang/Locale.hpp>
 #include <com/sun/star/text/FontEmphasis.hpp>
 #include <com/sun/star/i18n/ScriptType.hpp>
+#include <editeng/rsiditem.hxx>
 #include <editeng/memberids.hrc>
 #include <editeng/flstitem.hxx>
 #include <editeng/fontitem.hxx>
@@ -157,7 +158,7 @@ TYPEINIT1_FACTORY(SvxScriptTypeItem, SfxUInt16Item, new SvxScriptTypeItem);
 TYPEINIT1_FACTORY(SvxCharRotateItem, SfxUInt16Item, new SvxCharRotateItem(0, sal_False, 0));
 TYPEINIT1_FACTORY(SvxCharScaleWidthItem, SfxUInt16Item, new SvxCharScaleWidthItem(100, 0));
 TYPEINIT1_FACTORY(SvxCharReliefItem, SfxEnumItem, new SvxCharReliefItem(RELIEF_NONE, 0));
-
+TYPEINIT1_FACTORY(SvxRsidItem, SfxUInt32Item, new SvxRsidItem(0, 0));
 
 TYPEINIT1(SvxScriptSetItem, SfxSetItem );
 
@@ -3740,4 +3741,29 @@ short GetI18NScriptType( sal_uInt16 nItemType )
     return 0;
 }
 
+bool SvxRsidItem::QueryValue( uno::Any& rVal, sal_uInt8 ) const
+{
+    rVal <<= ( (sal_uInt32)GetValue() );
+    return true;
+}
+
+bool SvxRsidItem::PutValue( const uno::Any& rVal, sal_uInt8 )
+{
+    sal_uInt32 nRsid = 0;
+    if( !( rVal >>= nRsid ) )
+        return false;
+
+    SetValue( nRsid );
+    return true;
+}
+
+SfxPoolItem* SvxRsidItem::Clone( SfxItemPool * ) const
+{
+    return new SvxRsidItem( *this );
+}
+
+SfxPoolItem* SvxRsidItem::Create(SvStream& rIn, sal_uInt16 ) const
+{
+    return new SvxRsidItem( rIn, Which() );
+}
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/officecfg/registry/schema/org/openoffice/Office/Writer.xcs b/officecfg/registry/schema/org/openoffice/Office/Writer.xcs
index 73645db..bacae25 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Writer.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Writer.xcs
@@ -2810,6 +2810,36 @@
 				</prop>
 			</group>
 		</group>
+        <group oor:name="Comparison">
+            <info>
+                <desc>Contains settings for comparing files.</desc>
+            </info>
+            <prop oor:name="Mode" oor:type="xs:short">
+                <info>
+                    <author>OS</author>
+                    <desc>Defines the Comparison Mode.</desc>
+                </info>
+            </prop>
+
+            <prop oor:name="UseRSID" oor:type="xs:boolean">
+                <info>
+                    <author>OS</author>
+                    <desc>Specifies if RSIDs are used in comparison.</desc>
+                </info>
+            </prop>
+            <prop oor:name="IgnorePieces" oor:type="xs:boolean">
+                <info>
+                    <author>OS</author>
+                    <desc>Specifies if short pieces of matched text are ignored.</desc>
+                </info>
+            </prop>
+            <prop oor:name="IgnoreLength" oor:type="xs:short">
+                <info>
+                    <author>OS</author>
+                    <desc>Defines the length of ignored pieces.</desc>
+                </info>
+            </prop>
+        </group>
 		<group oor:name="Insert">
 			<info>
 				<desc>Specifies the settings for inserting various object types.</desc>
diff --git a/svx/inc/svx/dialogs.hrc b/svx/inc/svx/dialogs.hrc
index 0ece88f..a1038f1 100755
--- a/svx/inc/svx/dialogs.hrc
+++ b/svx/inc/svx/dialogs.hrc
@@ -136,6 +136,7 @@
 #define RID_SW_TP_OPTTABLE_PAGE         (RID_OFA_START + 210)
 #define RID_SW_TP_REDLINE_OPT           (RID_OFA_START + 212)
 #define RID_SW_TP_OPTCOMPATIBILITY_PAGE (RID_OFA_START + 255)
+#define RID_SW_TP_COMPARISON_OPT		(RID_OFA_START + 257)
 #define RID_SW_TP_HTML_CONTENT_OPT      (RID_OFA_START + 240)
 #define RID_SW_TP_HTML_OPTPRINT_PAGE    (RID_OFA_START + 242)
 #define RID_SW_TP_HTML_OPTTABLE_PAGE    (RID_OFA_START + 243)
diff --git a/svx/source/src/app.hrc b/svx/source/src/app.hrc
index e2ee4da..19a17e4 100755
--- a/svx/source/src/app.hrc
+++ b/svx/source/src/app.hrc
@@ -196,7 +196,8 @@
 #define RID_SW_TP_OPTCAPTION_PAGE       (RID_OFA_START + 256)
 #define SID_SC_TP_FORMULA               (RID_OFA_START + 257)
 #define SID_SC_TP_COMPATIBILITY         (RID_OFA_START + 258)
-#define RID_SC_TP_DEFAULTS          (RID_OFA_START + 259)
+#define RID_SC_TP_DEFAULTS              (RID_OFA_START + 259)
+#define RID_SW_TP_COMPARISON_OPT		(RID_OFA_START + 260)
 
 // Strings ------------------------------------------
 
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index c7255d9..0251d46 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -416,6 +416,9 @@ private:
     RedlineMode_t eRedlineMode;         // Current Redline Mode.
     SwCharCompressType eChrCmprType;    // for ASIAN: compress punctuation/kana
 
+    sal_uInt32  nRsid;				// current session ID of the document
+    sal_uInt32  nRsidRoot;			// session ID when the document was created
+
     sal_Int32   mReferenceCount;
     sal_Int32   mIdleBlockCount;
     sal_Int8    nLockExpFld;        // If != 0 UpdateExpFlds() has no effect!
@@ -732,6 +735,10 @@ public:
     virtual void setFieldUpdateFlags( /*[in]*/ SwFldUpdateFlags eMode );
     virtual SwCharCompressType getCharacterCompressionType() const;
     virtual void setCharacterCompressionType( /*[in]*/SwCharCompressType nType );
+    virtual sal_uInt32 getRsid() const;
+    virtual void setRsid( sal_uInt32 nVal );
+    virtual sal_uInt32 getRsidRoot() const;
+    virtual void setRsidRoot( sal_uInt32 nVal );
 
     /** IDocumentDeviceAccess
     */
@@ -859,6 +866,9 @@ public:
     virtual bool Overwrite(const SwPaM &rRg, const String& rStr);
     virtual bool InsertString(const SwPaM &rRg, const String&,
               const enum InsertFlags nInsertMode = INS_EMPTYEXPAND );
+    virtual bool UpdateRsid( SwTxtNode *pTxtNode, xub_StrLen nStt, xub_StrLen nEnd );
+    virtual bool UpdateParRsid( SwTxtNode *pTxtNode, sal_uInt32 nVal = 0 );
+    virtual bool UpdateRsid( const SwPaM &rRg, xub_StrLen nLen );
     virtual SwFlyFrmFmt* Insert(const SwPaM &rRg, const String& rGrfName, const String& rFltName, const Graphic* pGraphic,
                         const SfxItemSet* pFlyAttrSet, const SfxItemSet* pGrfAttrSet, SwFrmFmt*);
     virtual SwFlyFrmFmt* Insert(const SwPaM& rRg, const GraphicObject& rGrfObj, const SfxItemSet* pFlyAttrSet,
diff --git a/sw/inc/globals.hrc b/sw/inc/globals.hrc
index d68ada7..17e919d 100644
--- a/sw/inc/globals.hrc
+++ b/sw/inc/globals.hrc
@@ -273,6 +273,7 @@
 #define TP_OPTCOMPATIBILITY_PAGE    (RC_GLOBALS_BEGIN +  103)
 #define TP_MAILCONFIG               (RC_GLOBALS_BEGIN +  104)
 #define TP_TITLEPAGE                (RC_GLOBALS_BEGIN +  105)
+#define TP_COMPARISON_OPT           (RC_GLOBALS_BEGIN +  106)
 //maximum: RC_GLOBALS_BEGIN +  120
 
 
diff --git a/sw/inc/helpid.h b/sw/inc/helpid.h
index c5dc7f9..9f19b8e 100644
--- a/sw/inc/helpid.h
+++ b/sw/inc/helpid.h
@@ -308,6 +308,7 @@
 #define HID_TEXTGRID_PAGE                                       "SW_HID_TEXTGRID_PAGE"
 #define HID_OPTCOMPATIBILITY_PAGE                               "SW_HID_OPTCOMPATIBILITY_PAGE"
 #define HID_COMPATIBILITY_OPTIONS_BOX                           "SW_HID_COMPATIBILITY_OPTIONS_BOX"
+#define HID_COMPARISON_OPT				                        "SW_HID_COMPARISON_OPT"
 
 // AutoPilot Help-IDs
 
diff --git a/sw/inc/hintids.hxx b/sw/inc/hintids.hxx
index afd57f3..9428072 100644
--- a/sw/inc/hintids.hxx
+++ b/sw/inc/hintids.hxx
@@ -96,8 +96,8 @@ RES_CHRATR_BEGIN = HINT_BEGIN,
     RES_CHRATR_RELIEF,                      // 36
     RES_CHRATR_HIDDEN,                      // 37
     RES_CHRATR_OVERLINE,                    // 38
-    RES_CHRATR_DUMMY1,                      // 39
-    RES_CHRATR_DUMMY2,                      // 40
+    RES_CHRATR_RSID,						// 39
+    RES_CHRATR_DUMMY1,						// 40
 RES_CHRATR_END
 };
 
@@ -168,6 +168,7 @@ RES_PARATR_BEGIN = RES_TXTATR_END,
     RES_PARATR_SNAPTOGRID,                          // 72
     RES_PARATR_CONNECT_BORDER,                      // 73
     RES_PARATR_OUTLINELEVEL,                        // 74
+    RES_PARATR_RSID,								// 75
 RES_PARATR_END
 };
 
@@ -176,99 +177,99 @@ RES_PARATR_END
 enum RES_PARATR_LIST
 {
 RES_PARATR_LIST_BEGIN = RES_PARATR_END,
-    RES_PARATR_LIST_ID = RES_PARATR_LIST_BEGIN,     // 75
-    RES_PARATR_LIST_LEVEL,                          // 76
-    RES_PARATR_LIST_ISRESTART,                      // 77
-    RES_PARATR_LIST_RESTARTVALUE,                   // 78
-    RES_PARATR_LIST_ISCOUNTED,                      // 79
+    RES_PARATR_LIST_ID = RES_PARATR_LIST_BEGIN,     // 76
+    RES_PARATR_LIST_LEVEL,                          // 77
+    RES_PARATR_LIST_ISRESTART,                      // 78
+    RES_PARATR_LIST_RESTARTVALUE,                   // 79
+    RES_PARATR_LIST_ISCOUNTED,                      // 80
 RES_PARATR_LIST_END
 };
 
 enum RES_FRMATR
 {
 RES_FRMATR_BEGIN = RES_PARATR_LIST_END,
-    RES_FILL_ORDER = RES_FRMATR_BEGIN,              // 80
-    RES_FRM_SIZE,                                   // 81
-    RES_PAPER_BIN,                                  // 82
-    RES_LR_SPACE,                                   // 83
-    RES_UL_SPACE,                                   // 84
-    RES_PAGEDESC,                                   // 85
-    RES_BREAK,                                      // 86
-    RES_CNTNT,                                      // 87
-    RES_HEADER,                                     // 88
-    RES_FOOTER,                                     // 89
-    RES_PRINT,                                      // 90
-    RES_OPAQUE,                                     // 91
-    RES_PROTECT,                                    // 92
-    RES_SURROUND,                                   // 93
-    RES_VERT_ORIENT,                                // 94
-    RES_HORI_ORIENT,                                // 95
-    RES_ANCHOR,                                     // 96
-    RES_BACKGROUND,                                 // 97
-    RES_BOX,                                        // 98
-    RES_SHADOW,                                     // 99
-    RES_FRMMACRO,                                   // 100
-    RES_COL,                                        // 101
-    RES_KEEP,                                       // 102
-    RES_URL,                                        // 103
-    RES_EDIT_IN_READONLY,                           // 104
-    RES_LAYOUT_SPLIT,                               // 105
-    RES_CHAIN,                                      // 106
-    RES_TEXTGRID,                                   // 107
-    RES_LINENUMBER  ,                               // 108
-    RES_FTN_AT_TXTEND,                              // 109
-    RES_END_AT_TXTEND,                              // 110
-    RES_COLUMNBALANCE,                              // 111
-    RES_FRAMEDIR,                                   // 112
-    RES_HEADER_FOOTER_EAT_SPACING,                  // 113
-    RES_ROW_SPLIT,                                  // 114
-    RES_FOLLOW_TEXT_FLOW,                           // 115
-    RES_COLLAPSING_BORDERS,                         // 116
-    RES_WRAP_INFLUENCE_ON_OBJPOS,                   // 117
-    RES_AUTO_STYLE,                                 // 118
-    RES_FRMATR_STYLE_NAME,                          // 119
-    RES_FRMATR_CONDITIONAL_STYLE_NAME,              // 120
+    RES_FILL_ORDER = RES_FRMATR_BEGIN,              // 81
+    RES_FRM_SIZE,                                   // 82
+    RES_PAPER_BIN,                                  // 83
+    RES_LR_SPACE,                                   // 84
+    RES_UL_SPACE,                                   // 85
+    RES_PAGEDESC,                                   // 86
+    RES_BREAK,                                      // 87
+    RES_CNTNT,                                      // 88
+    RES_HEADER,                                     // 89
+    RES_FOOTER,                                     // 90
+    RES_PRINT,                                      // 91
+    RES_OPAQUE,                                     // 92
+    RES_PROTECT,                                    // 93
+    RES_SURROUND,                                   // 94
+    RES_VERT_ORIENT,                                // 95
+    RES_HORI_ORIENT,                                // 96
+    RES_ANCHOR,                                     // 97
+    RES_BACKGROUND,                                 // 98
+    RES_BOX,                                        // 99
+    RES_SHADOW,                                     // 100
+    RES_FRMMACRO,                                   // 101
+    RES_COL,                                        // 102
+    RES_KEEP,                                       // 103
+    RES_URL,                                        // 104
+    RES_EDIT_IN_READONLY,                           // 105
+    RES_LAYOUT_SPLIT,                               // 106
+    RES_CHAIN,                                      // 107
+    RES_TEXTGRID,                                   // 108
+    RES_LINENUMBER  ,                               // 109
+    RES_FTN_AT_TXTEND,                              // 110
+    RES_END_AT_TXTEND,                              // 111
+    RES_COLUMNBALANCE,                              // 112
+    RES_FRAMEDIR,                                   // 113
+    RES_HEADER_FOOTER_EAT_SPACING,                  // 114
+    RES_ROW_SPLIT,                                  // 115
+    RES_FOLLOW_TEXT_FLOW,                           // 116
+    RES_COLLAPSING_BORDERS,                         // 117
+    RES_WRAP_INFLUENCE_ON_OBJPOS,                   // 118
+    RES_AUTO_STYLE,                                 // 119
+    RES_FRMATR_STYLE_NAME,                          // 120
+    RES_FRMATR_CONDITIONAL_STYLE_NAME,              // 121
 RES_FRMATR_END
 };
 
 enum RES_GRFATR
 {
 RES_GRFATR_BEGIN = RES_FRMATR_END,
-    RES_GRFATR_MIRRORGRF = RES_GRFATR_BEGIN,        // 121
-    RES_GRFATR_CROPGRF,                             // 122
-
-    RES_GRFATR_ROTATION,                            // 123
-    RES_GRFATR_LUMINANCE,                           // 124
-    RES_GRFATR_CONTRAST,                            // 125
-    RES_GRFATR_CHANNELR,                            // 126
-    RES_GRFATR_CHANNELG,                            // 127
-    RES_GRFATR_CHANNELB,                            // 128
-    RES_GRFATR_GAMMA,                               // 129
-    RES_GRFATR_INVERT,                              // 130
-    RES_GRFATR_TRANSPARENCY,                        // 131
-    RES_GRFATR_DRAWMODE,                            // 132
-
-    RES_GRFATR_DUMMY1,                              // 133
-    RES_GRFATR_DUMMY2,                              // 134
-    RES_GRFATR_DUMMY3,                              // 135
-    RES_GRFATR_DUMMY4,                              // 136
-    RES_GRFATR_DUMMY5,                              // 137
+    RES_GRFATR_MIRRORGRF = RES_GRFATR_BEGIN,        // 122
+    RES_GRFATR_CROPGRF,                             // 123
+
+    RES_GRFATR_ROTATION,                            // 124
+    RES_GRFATR_LUMINANCE,                           // 125
+    RES_GRFATR_CONTRAST,                            // 126
+    RES_GRFATR_CHANNELR,                            // 127
+    RES_GRFATR_CHANNELG,                            // 128
+    RES_GRFATR_CHANNELB,                            // 129
+    RES_GRFATR_GAMMA,                               // 130
+    RES_GRFATR_INVERT,                              // 131
+    RES_GRFATR_TRANSPARENCY,                        // 132
+    RES_GRFATR_DRAWMODE,                            // 133
+
+    RES_GRFATR_DUMMY1,                              // 134
+    RES_GRFATR_DUMMY2,                              // 135
+    RES_GRFATR_DUMMY3,                              // 136
+    RES_GRFATR_DUMMY4,                              // 137
+    RES_GRFATR_DUMMY5,                              // 138
 RES_GRFATR_END
 };
 
 enum RES_BOXATR
 {
 RES_BOXATR_BEGIN = RES_GRFATR_END,
-    RES_BOXATR_FORMAT = RES_BOXATR_BEGIN,           // 138
-    RES_BOXATR_FORMULA,                             // 139
-    RES_BOXATR_VALUE,                               // 140
+    RES_BOXATR_FORMAT = RES_BOXATR_BEGIN,           // 139
+    RES_BOXATR_FORMULA,                             // 140
+    RES_BOXATR_VALUE,                               // 141
 RES_BOXATR_END
 };
 
 enum RES_UNKNOWNATR
 {
 RES_UNKNOWNATR_BEGIN = RES_BOXATR_END,
-    RES_UNKNOWNATR_CONTAINER = RES_UNKNOWNATR_BEGIN,// 141
+    RES_UNKNOWNATR_CONTAINER = RES_UNKNOWNATR_BEGIN,// 142
 RES_UNKNOWNATR_END
 };
 
diff --git a/sw/inc/modcfg.hxx b/sw/inc/modcfg.hxx
index 14a3b2a..b1fb713 100644
--- a/sw/inc/modcfg.hxx
+++ b/sw/inc/modcfg.hxx
@@ -39,6 +39,7 @@
 #include "tblenum.hxx"
 #include "itabenum.hxx"
 #include <tools/globname.hxx>
+#include <editeng/svxenum.hxx>
 class SwModuleOptions;
 
 class InsCaptionOpt;
@@ -77,6 +78,26 @@ class SwRevisionConfig : public utl::ConfigItem
     void                    SetModified(){ConfigItem::SetModified();}
 };
 
+class SwCompareConfig : public utl::ConfigItem
+{
+    friend class SwModuleOptions;
+
+    sal_uInt16      eCmpMode;		//Compare/CompareDocuments;
+    sal_Bool        bUseRsid;		//Compare/Settings/Use RSID
+    sal_Bool        bIgnorePieces;	//Compare/Settings/Ignore pieces of length
+    sal_uInt16      nPieceLen;		//Compare/Settings/Ignore pieces of length
+
+    const com::sun::star::uno::Sequence<rtl::OUString>& GetPropertyNames();
+    public:
+        SwCompareConfig();
+        ~SwCompareConfig();
+
+    virtual void    Commit();
+    virtual void    Notify( const ::com::sun::star::uno::Sequence< rtl::OUString >& ){ };
+    void            Load();
+    void            SetModified() {ConfigItem::SetModified(); }
+};
+
 class SwInsertConfig : public utl::ConfigItem
 {
     friend class SwModuleOptions;
@@ -167,6 +188,8 @@ class SW_DLLPUBLIC SwModuleOptions
 
     SwMiscConfig                    aMiscConfig;
 
+    SwCompareConfig					aCompareConfig;
+
     //fiscus: don't show tips of text fields - it's not part of the configuration!
     sal_Bool        bHideFieldTips : 1;
 
@@ -309,20 +332,37 @@ public:
     //convert word delimiter from or to user interface
     static String ConvertWordDelimiter(const String& rDelim, sal_Bool bFromUI);
 
-    sal_Bool        IsShowIndexPreview() const {return  aMiscConfig.bShowIndexPreview;}
+    sal_Bool    IsShowIndexPreview() const {return  aMiscConfig.bShowIndexPreview;}
     void        SetShowIndexPreview(sal_Bool bSet)
                     {aMiscConfig.bShowIndexPreview = bSet;
                     aMiscConfig.SetModified();}
 
-    sal_Bool        IsDefaultFontInCurrDocOnly() const { return aMiscConfig.bDefaultFontsInCurrDocOnly;}
+    sal_Bool    IsDefaultFontInCurrDocOnly() const { return aMiscConfig.bDefaultFontsInCurrDocOnly;}
     void        SetDefaultFontInCurrDocOnly(sal_Bool bSet)
                     {
                         aMiscConfig.bDefaultFontsInCurrDocOnly = bSet;
                         aMiscConfig.SetModified();
                     }
 
-    sal_Bool        IsHideFieldTips() const {return bHideFieldTips;}
+    sal_Bool    IsHideFieldTips() const {return bHideFieldTips;}
     void        SetHideFieldTips(sal_Bool bSet) {bHideFieldTips = bSet;}
+
+    SvxCompareMode  GetCompareMode() const { return (SvxCompareMode)aCompareConfig.eCmpMode; }
+    void            SetCompareMode( SvxCompareMode eMode ) { aCompareConfig.eCmpMode = eMode;
+                                                             aCompareConfig.SetModified(); }
+
+    sal_Bool    IsUseRsid() const { return aCompareConfig.bUseRsid; }
+    void        SetUseRsid( sal_Bool b ) { aCompareConfig.bUseRsid = b;
+                                                            aCompareConfig.SetModified(); }
+
+    sal_Bool    IsIgnorePieces() const { return aCompareConfig.bIgnorePieces; }
+    void        SetIgnorePieces( sal_Bool b ) { aCompareConfig.bIgnorePieces = b;
+                                                aCompareConfig.SetModified(); }
+
+    sal_uInt16  GetPieceLen() const { return aCompareConfig.nPieceLen; }
+    void        SetPieceLen( sal_uInt16 nLen ) { aCompareConfig.nPieceLen = nLen;
+                                                 aCompareConfig.SetModified(); }
+
 };
 #endif
 
diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index b4a772d..b412aa4 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -803,6 +803,13 @@ public:
 
     virtual void dumpAsXml( xmlTextWriterPtr writer = NULL );
 
+    sal_uInt32 GetRsid( xub_StrLen nStt, xub_StrLen nEnd ) const;
+    sal_uInt32 GetParRsid() const;
+
+    bool CompareRsid( const SwTxtNode &rTxtNode, xub_StrLen nStt1, xub_StrLen nStt2,
+            xub_StrLen nEnd1 = 0,  xub_StrLen nEnd2 = 0 ) const;
+    bool CompareParRsid( const SwTxtNode &rTxtNode ) const;
+
     DECL_FIXEDMEMPOOL_NEWDEL(SwTxtNode)
 };
 
diff --git a/sw/inc/swmodule.hxx b/sw/inc/swmodule.hxx
index 7639237..aca0d48 100644
--- a/sw/inc/swmodule.hxx
+++ b/sw/inc/swmodule.hxx
@@ -40,6 +40,7 @@
 #include <fldupde.hxx>
 #include <com/sun/star/linguistic2/XLinguServiceEventListener.hpp>
 #include <com/sun/star/linguistic2/XLanguageGuessing.hpp>
+#include <editeng/svxenum.hxx>
 
 class SvStringsDtor;
 class Color;
@@ -210,6 +211,15 @@ public:
     sal_uInt16              GetRedlineMarkPos();
     const Color&            GetRedlineMarkColor();
 
+    SvxCompareMode      GetCompareMode() const;
+    void                SetCompareMode( SvxCompareMode eMode );
+    sal_Bool            IsUseRsid() const;
+    void                SetUseRsid( sal_Bool b );
+    sal_Bool            IsIgnorePieces() const;
+    void				SetIgnorePieces( sal_Bool b );
+    sal_uInt16          GetPieceLen() const;
+    void                SetPieceLen( sal_uInt16 nLen );
+
     // Return defined DocStat - WordDelimiter.
     const String&       GetDocStatWordDelim() const;
 
diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx
index 8df75ee..e70963a 100644
--- a/sw/inc/unoprnms.hxx
+++ b/sw/inc/unoprnms.hxx
@@ -806,7 +806,9 @@ enum SwPropNameIds
 /* 0742 */  UNO_NAME_SEPARATOR_LINE_STYLE,
 /* 0743 */  UNO_NAME_FOOTNOTE_LINE_STYLE,
 /* 0744 */  UNO_NAME_EMBEDDED_OBJECT,
-/* 0745 */  SW_PROPNAME_END
+/* 0745 */  UNO_NAME_RSID,
+/* 0746 */  UNO_NAME_PARRSID,
+/* 0747 */  SW_PROPNAME_END
 
 // new items in this array must match SwPropNameTab aPropNameTab
 };
diff --git a/sw/source/core/bastyp/init.cxx b/sw/source/core/bastyp/init.cxx
index c80a8b8..e24a7f4 100644
--- a/sw/source/core/bastyp/init.cxx
+++ b/sw/source/core/bastyp/init.cxx
@@ -129,6 +129,7 @@
 
 #include <fmtfollowtextflow.hxx>
 #include <fmtwrapinfluenceonobjpos.hxx>
+#include <editeng/rsiditem.hxx>
 
 #include <fmtmeta.hxx>
 
@@ -298,8 +299,8 @@ SfxItemInfo aSlotTab[] =
     { SID_ATTR_CHAR_RELIEF, SFX_ITEM_POOLABLE },        // RES_CHRATR_RELIEF
     { SID_ATTR_CHAR_HIDDEN, SFX_ITEM_POOLABLE },        // RES_CHRATR_HIDDEN
     { SID_ATTR_CHAR_OVERLINE, SFX_ITEM_POOLABLE },      // RES_CHRATR_OVERLINE
+    { 0, SFX_ITEM_POOLABLE },							// RES_CHRATR_RSID
     { 0, SFX_ITEM_POOLABLE },                           // RES_CHRATR_DUMMY1
-    { 0, SFX_ITEM_POOLABLE },                           // RES_CHRATR_DUMMY2
 
     { 0, 0 },                                           // RES_TXTATR_REFMARK
     { 0, 0 },                                           // RES_TXTATR_TOXMARK
@@ -340,7 +341,7 @@ SfxItemInfo aSlotTab[] =
     { SID_ATTR_BORDER_CONNECT, SFX_ITEM_POOLABLE },     // RES_PARATR_CONNECT_BORDER
 
     { SID_ATTR_PARA_OUTLINE_LEVEL, SFX_ITEM_POOLABLE }, // RES_PARATR_OUTLINELEVEL //#outline level,zhaojianwei
-
+    { 0, SFX_ITEM_POOLABLE },							// RES_PARATR_RSID
     { 0, SFX_ITEM_POOLABLE },                           // RES_PARATR_LIST_ID
     { 0, SFX_ITEM_POOLABLE },                           // RES_PARATR_LIST_LEVEL
     { 0, SFX_ITEM_POOLABLE },                           // RES_PARATR_LIST_ISRESTART
@@ -478,6 +479,7 @@ void _InitCore()
     aAttrTab[ RES_CHRATR_SHADOWED- POOLATTR_BEGIN ] =       new SvxShadowedItem( sal_False, RES_CHRATR_SHADOWED );
     aAttrTab[ RES_CHRATR_UNDERLINE- POOLATTR_BEGIN ] =      new SvxUnderlineItem( UNDERLINE_NONE, RES_CHRATR_UNDERLINE );
     aAttrTab[ RES_CHRATR_WEIGHT- POOLATTR_BEGIN ] =         new SvxWeightItem( WEIGHT_NORMAL, RES_CHRATR_WEIGHT );
+    aAttrTab[ RES_CHRATR_RSID - POOLATTR_BEGIN ] =          new SvxRsidItem( 0, RES_CHRATR_RSID );
     aAttrTab[ RES_CHRATR_WORDLINEMODE- POOLATTR_BEGIN ] =   new SvxWordLineModeItem( sal_False, RES_CHRATR_WORDLINEMODE );
     aAttrTab[ RES_CHRATR_AUTOKERN- POOLATTR_BEGIN ] =       new SvxAutoKernItem( sal_False, RES_CHRATR_AUTOKERN );
     aAttrTab[ RES_CHRATR_BLINK - POOLATTR_BEGIN ] =         new SvxBlinkItem( sal_False, RES_CHRATR_BLINK );
@@ -509,7 +511,7 @@ void _InitCore()
 
 // CharakterAttr - Dummies
     aAttrTab[ RES_CHRATR_DUMMY1 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_CHRATR_DUMMY1 );
-    aAttrTab[ RES_CHRATR_DUMMY2 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_CHRATR_DUMMY2 );
+
 // CharakterAttr - Dummies
 
     aAttrTab[ RES_TXTATR_AUTOFMT- POOLATTR_BEGIN ] = new SwFmtAutoFmt;
@@ -557,6 +559,7 @@ void _InitCore()
     aAttrTab[ RES_PARATR_CONNECT_BORDER - POOLATTR_BEGIN ] = new SwParaConnectBorderItem;
 
     aAttrTab[ RES_PARATR_OUTLINELEVEL - POOLATTR_BEGIN ] = new SfxUInt16Item( RES_PARATR_OUTLINELEVEL, 0 );//#outline level,zhaojianwei
+    aAttrTab[ RES_PARATR_RSID - POOLATTR_BEGIN ] = new SvxRsidItem( 0, RES_PARATR_RSID );
 
     aAttrTab[ RES_PARATR_LIST_ID - POOLATTR_BEGIN ] = new SfxStringItem( RES_PARATR_LIST_ID, aEmptyStr );
     aAttrTab[ RES_PARATR_LIST_LEVEL - POOLATTR_BEGIN ] = new SfxInt16Item( RES_PARATR_LIST_LEVEL, 0 );
diff --git a/sw/source/core/doc/doc.cxx b/sw/source/core/doc/doc.cxx
old mode 100644
new mode 100755
index 3a7becd..8be6aa7
--- a/sw/source/core/doc/doc.cxx
+++ b/sw/source/core/doc/doc.cxx
@@ -34,6 +34,8 @@
 #include <tools/shl.hxx>
 #include <tools/globname.hxx>
 #include <svx/svxids.hrc>
+#include <rtl/random.h>
+
 #include <com/sun/star/i18n/WordType.hdl>
 #include <com/sun/star/i18n/ForbiddenCharacters.hdl>
 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
@@ -59,6 +61,7 @@
 #include <editeng/forbiddencharacterstable.hxx>
 #include <svx/svdmodel.hxx>
 #include <editeng/pbinitem.hxx>
+#include <editeng/rsiditem.hxx>
 #include <unotools/charclass.hxx>
 #include <unotools/localedatawrapper.hxx>
 
@@ -456,6 +459,33 @@ void SwDoc::setLinkUpdateMode( /*[in]*/sal_uInt16 eMode )
     nLinkUpdMode = eMode;
 }
 
+sal_uInt32 SwDoc::getRsid() const
+{
+    return nRsid;
+}
+
+void SwDoc::setRsid( sal_uInt32 nVal )
+{
+    // Increase the rsid with a random number smaller than 2^17. This way we
+    // expect to be able to edit a document 2^12 times before rsid overflows.
+    sal_uInt32 nIncrease = 0;
+    static rtlRandomPool aPool = rtl_random_createPool();
+    rtl_random_getBytes( aPool, &nIncrease, sizeof ( nIncrease ) );
+    nIncrease &= ( 1<<17 ) - 1;
+    nIncrease++; // make sure the new rsid is not the same
+    nRsid = nVal + nIncrease;
+}
+
+sal_uInt32 SwDoc::getRsidRoot() const
+{
+    return nRsidRoot;
+}
+
+void SwDoc::setRsidRoot( sal_uInt32 nVal )
+{
+    nRsidRoot = nVal;
+}
+
 SwFldUpdateFlags SwDoc::getFieldUpdateFlags( /*[in]*/bool bGlobalSettings ) const
 {
     SwFldUpdateFlags eRet = eFldUpdMode;
@@ -731,6 +761,15 @@ bool SwDoc::SplitNode( const SwPosition &rPos, bool bChkTableStart )
         }
     }
 
+    // Update the rsid of the old and the new node unless
+    // the old node is split at the beginning or at the end
+    SwTxtNode *pTxtNode =  rPos.nNode.GetNode().GetTxtNode();
+    xub_StrLen nPos = rPos.nContent.GetIndex();
+    if( pTxtNode && nPos && nPos != pTxtNode->Len() )
+    {
+        UpdateParRsid( pTxtNode );
+    }
+
     //JP 28.01.97: Special case for SplitNode at table start:
     //             If it is at the beginning of a Doc/Fly/Footer/... or right at after a table
     //             then insert a paragraph before it.
@@ -1066,6 +1105,41 @@ SwFieldType *SwDoc::GetSysFldType( const sal_uInt16 eWhich ) const
     return 0;
 }
 
+// Set the rsid from nStt to nEnd of pTxtNode to the current session number
+bool SwDoc::UpdateRsid( SwTxtNode *pTxtNode, xub_StrLen nStt, xub_StrLen nEnd )
+{
+    if ( !pTxtNode )
+    {
+        return false;
+    }
+
+    SvxRsidItem aRsid( nRsid, RES_CHRATR_RSID );
+    SwTxtAttr* pAttr = MakeTxtAttr( *this, aRsid, nStt, nEnd );
+    return pTxtNode->InsertHint( pAttr, INS_DEFAULT );
+}
+
+// Set the rsid of the next nLen symbols of rRg to the current session number
+bool SwDoc::UpdateRsid( const SwPaM &rRg, const xub_StrLen nLen )
+{
+    const SwPosition* pPos = rRg.GetPoint();
+    SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
+    xub_StrLen nInsPos = pPos->nContent.GetIndex();
+
+    return UpdateRsid( pTxtNode, nInsPos - nLen, nInsPos );
+}
+
+bool SwDoc::UpdateParRsid( SwTxtNode *pTxtNode, sal_uInt32 nVal )
+{
+    if ( !pTxtNode )
+    {
+        return false;
+    }
+
+    SvxRsidItem aRsid( nVal ? nVal : nRsid, RES_PARATR_RSID );
+    return pTxtNode->SetAttr( aRsid );
+}
+
+
 /*************************************************************************
  *             void SetDocStat( const SwDocStat& rStat );
  *************************************************************************/
diff --git a/sw/source/core/doc/doccomp.cxx b/sw/source/core/doc/doccomp.cxx
index bd3ee2c..1da7704 100644
--- a/sw/source/core/doc/doccomp.cxx
+++ b/sw/source/core/doc/doccomp.cxx
@@ -32,7 +32,9 @@
 #include <editeng/crsditem.hxx>
 #include <editeng/colritem.hxx>
 #include <editeng/boxitem.hxx>
+#include <editeng/svxenum.hxx>
 #include <editeng/udlnitem.hxx>
+#include <swmodule.hxx>
 #include <doc.hxx>
 #include <IDocumentUndoRedo.hxx>
 #include <docary.hxx>
@@ -49,6 +51,9 @@
 
 #include <vector>
 
+#include <set>
+#include <cctype>
+
 using namespace ::com::sun::star;
 
 using ::std::vector;
@@ -189,6 +194,147 @@ public:
     Compare( sal_uLong nDiff, CompareData& rData1, CompareData& rData2 );
 };
 
+class ArrayComparator
+{
+public:
+    virtual bool Compare( int nIdx1, int nIdx2 ) const = 0;
+    virtual int GetLen1() const = 0;
+    virtual int GetLen2() const = 0;
+};
+
+// Consider two lines equal if similar enough (e.g. look like different
+// versions of the same paragraph)
+class LineArrayComparator : public ArrayComparator
+{
+private:
+    int nLen1, nLen2;
+    const CompareData &rData1, &rData2;
+    int nFirst1, nFirst2;
+
+public:
+    LineArrayComparator( const CompareData &rD1, const CompareData &rD2,
+                            int nStt1, int nEnd1, int nStt2, int nEnd2 );
+
+    virtual bool Compare( int nIdx1, int nIdx2 ) const;
+    virtual int GetLen1() const { return nLen1; }
+    virtual int GetLen2() const { return nLen2; }
+};
+
+class WordArrayComparator : public ArrayComparator
+{
+private:
+    const SwTxtNode *pTxtNd1, *pTxtNd2;
+    int *pPos1, *pPos2;
+    int nCnt1, nCnt2;		// number of words
+    const unsigned nMul;
+
+    void CalcPositions( int *pPos, const SwTxtNode *pTxtNd, int &nCnt );
+
+public:
+    WordArrayComparator( const SwTxtNode *pNode1, const SwTxtNode *pNode2 );
+    ~WordArrayComparator();
+
+    virtual bool Compare( int nIdx1, int nIdx2 ) const;
+    virtual int GetLen1() const { return nCnt1; }
+    virtual int GetLen2() const { return nCnt2; }
+    int GetCharSequence( const int *pWordLcs1, const int *pWordLcs2,
+                        int *pSubseq1, int *pSubseq2, int nLcsLen );
+};
+
+class CharArrayComparator : public ArrayComparator
+{
+private:
+    const SwTxtNode *pTxtNd1, *pTxtNd2;
+
+public:
+    CharArrayComparator( const SwTxtNode *pNode1, const SwTxtNode *pNode2 )
+        : pTxtNd1( pNode1 ), pTxtNd2( pNode2 )
+    {
+    }
+
+    virtual bool Compare( int nIdx1, int nIdx2 ) const;
+    virtual int GetLen1() const { return pTxtNd1->GetTxt().Len(); }
+    virtual int GetLen2() const { return pTxtNd2->GetTxt().Len(); }
+};
+
+// Options set in Tools->Options->Writer->Comparison
+struct CmpOptionsContainer
+{
+    SvxCompareMode eCmpMode;
+    int nIgnoreLen;
+    bool bUseRsid;
+} CmpOptions;
+
+class CommonSubseq
+{
+private:
+    int *pData;
+    int nSize;
+
+protected:
+    ArrayComparator &rCmp;
+
+    CommonSubseq( ArrayComparator &rComparator, int nMaxSize )
+        : nSize( nMaxSize ), rCmp( rComparator )
+    {
+        pData = new int[ nSize ];
+    }
+
+    ~CommonSubseq()
+    {
+        delete[] pData;
+    }
+
+    int FindLCS( int *pLcs1 = 0, int *pLcs2 = 0, int nStt1 = 0,
+                    int nEnd1 = 0, int nStt2 = 0, int nEnd2 = 0 );
+
+public:
+    int IgnoreIsolatedPieces( int *pLcs1, int *pLcs2, int nLen1, int nLen2,
+                                int nLcsLen, int nPieceLen );
+};
+
+// Use Hirschberg's algrithm to find LCS in linear space
+class LgstCommonSubseq: public CommonSubseq
+{
+private:
+    static const int CUTOFF = 1<<20; // Stop recursion at this value
+
+    int *pL1, *pL2;
+    int *pBuff1, *pBuff2;
+
+    void FindL( int *pL, int nStt1, int nEnd1, int nStt2, int nEnd2  );
+    int HirschbergLCS( int *pLcs1, int *pLcs2, int nStt1, int nEnd1,
+                                                int nStt2, int nEnd2 );
+
+public:
+    LgstCommonSubseq( ArrayComparator &rComparator );
+    ~LgstCommonSubseq();
+
+    int Find( int *pSubseq1, int *pSubseq2 );
+};
+
+// Find a common subsequence in linear time
+class FastCommonSubseq: private CommonSubseq
+{
+private:
+    static const int CUTOFF = 2056;
+
+    int FindFastCS( int *pSeq1, int *pSeq2, int nStt1, int nEnd1,
+                                             int nStt2, int nEnd2  );
+
+public:
+    FastCommonSubseq( ArrayComparator &rComparator )
+        : CommonSubseq( rComparator, CUTOFF )
+    {
+    }
+
+    int Find( int *pSubseq1, int *pSubseq2 )
+    {
+        return FindFastCS( pSubseq1, pSubseq2, 0, rCmp.GetLen1(),
+                                                0, rCmp.GetLen2() );
+    }
+};
+
 CompareLine::~CompareLine() {}
 
 CompareData::CompareData()
@@ -250,20 +396,16 @@ sal_uLong CompareData::ShowDiffs( const CompareData& rData )
     {
         if( rData.GetChanged( nStt1 ) || GetChanged( nStt2 ) )
         {
+            // Find a region of different lines between two pairs of identical
+            // lines.
             sal_uLong nSav1 = nStt1, nSav2 = nStt2;
             while( nStt1 < nLen1 && rData.GetChanged( nStt1 )) ++nStt1;
             while( nStt2 < nLen2 && GetChanged( nStt2 )) ++nStt2;
 
-            // rData is the original,
-            // "this" recieves the changes
-            if( nSav2 != nStt2 && nSav1 != nStt1 )
-                CheckForChangesInLine( rData, nSav1, nStt1, nSav2, nStt2 );
+            // Check if there are changed lines (only slightly different) and
+            // compare them in detail.
+            CheckForChangesInLine( rData, nSav1, nStt1, nSav2, nStt2 );
 
-            if( nSav2 != nStt2 )
-                ShowInsert( nSav2, nStt2 );
-
-            if( nSav1 != nStt1 )
-                ShowDelete( rData, nSav1, nStt1, nStt2 );
             ++nCnt;
         }
         ++nStt1, ++nStt2;
@@ -968,7 +1110,8 @@ sal_Bool SwCompareLine::CompareNode( const SwNode& rDstNd, const SwNode& rSrcNd
     switch( rDstNd.GetNodeType() )
     {
     case ND_TEXTNODE:
-        bRet = CompareTxtNd( (SwTxtNode&)rDstNd, (SwTxtNode&)rSrcNd );
+        bRet = CompareTxtNd( (SwTxtNode&)rDstNd, (SwTxtNode&)rSrcNd )
+            && ( !CmpOptions.bUseRsid || ((SwTxtNode&)rDstNd).CompareParRsid( (SwTxtNode&)rSrcNd ) );
         break;
 
     case ND_TABLENODE:
@@ -1136,66 +1279,126 @@ sal_Bool SwCompareLine::ChangesInLine( const SwCompareLine& rLine,
                             SwPaM *& rpInsRing, SwPaM*& rpDelRing ) const
 {
     sal_Bool bRet = sal_False;
+
+    // Only compare textnodes
     if( ND_TEXTNODE == rNode.GetNodeType() &&
         ND_TEXTNODE == rLine.GetNode().GetNodeType() )
     {
-        SwTxtNode& rDestNd = *(SwTxtNode*)rNode.GetTxtNode();
+        SwTxtNode& rDstNd = *(SwTxtNode*)rNode.GetTxtNode();
         const SwTxtNode& rSrcNd = *rLine.GetNode().GetTxtNode();
+        SwDoc* pDstDoc = rDstNd.GetDoc();
 
-        xub_StrLen nDEnd = rDestNd.GetTxt().Len(), nSEnd = rSrcNd.GetTxt().Len();
-        xub_StrLen nStt;
-        xub_StrLen nEnd;
+        int nLcsLen = 0;
 
-        for( nStt = 0, nEnd = Min( nDEnd, nSEnd ); nStt < nEnd; ++nStt )
-            if( rDestNd.GetTxt().GetChar( nStt ) !=
-                rSrcNd.GetTxt().GetChar( nStt ) )
-                break;
+        int nDstLen = rDstNd.GetTxt().Len();
+        int nSrcLen = rSrcNd.GetTxt().Len();
 
-        while( nStt < nDEnd && nStt < nSEnd )
+        int nMinLen = std::min( nDstLen , nSrcLen );
+        int nAvgLen = ( nDstLen + nSrcLen )/2;
+
+        int *pLcsDst = new int[ nMinLen + 1 ];
+        int *pLcsSrc = new int[ nMinLen + 1 ];
+
+        if( CmpOptions.eCmpMode == SVX_CMP_BY_WORD )
         {
-            --nDEnd, --nSEnd;
-            if( rDestNd.GetTxt().GetChar( nDEnd ) !=
-                rSrcNd.GetTxt().GetChar( nSEnd ) )
+            int *pTmpLcsDst = new int[ nMinLen + 1 ];
+            int *pTmpLcsSrc = new int[ nMinLen + 1 ];
+
+            WordArrayComparator aCmp( &rDstNd, &rSrcNd );
+
+            LgstCommonSubseq aSeq( aCmp );
+
+            nLcsLen = aSeq.Find( pTmpLcsDst, pTmpLcsSrc );
+
+            if( CmpOptions.nIgnoreLen )
             {
-                ++nDEnd, ++nSEnd;
-                break;
+                nLcsLen = aSeq.IgnoreIsolatedPieces( pTmpLcsDst, pTmpLcsSrc,
+                                                aCmp.GetLen1(), aCmp.GetLen2(),
+                                                nLcsLen, CmpOptions.nIgnoreLen );
             }
+
+            nLcsLen = aCmp.GetCharSequence( pTmpLcsDst, pTmpLcsSrc,
+                                            pLcsDst, pLcsSrc, nLcsLen );
+
+            delete[] pTmpLcsDst;
+            delete[] pTmpLcsSrc;
         }
+        else
+        {
+            CharArrayComparator aCmp( &rDstNd, &rSrcNd );
+            LgstCommonSubseq aSeq( aCmp );
+
+            nLcsLen = aSeq.Find( pLcsDst, pLcsSrc );
 
-        if( nStt || !nDEnd || !nSEnd || nDEnd < rDestNd.GetTxt().Len() ||
-            nSEnd < rSrcNd.GetTxt().Len() )
+            if( CmpOptions.nIgnoreLen )
+            {
+                nLcsLen = aSeq.IgnoreIsolatedPieces( pLcsDst, pLcsSrc, nDstLen,
+                                                    nSrcLen, nLcsLen,
+                                                    CmpOptions.nIgnoreLen );
+            }
+        }
+
+        // find the sum of the squares of the continuous substrings
+        int nSqSum = 0;
+        int nCnt = 1;
+        for( int i = 0; i < nLcsLen; i++ )
         {
-            // The newly inserted is now between nStt and nDEnd
-            // and the deleted is between nStt and nSEnd
-            SwDoc* pDoc = rDestNd.GetDoc();
-            SwPaM aPam( rDestNd, nDEnd );
-            if( nStt != nDEnd )
+            if( i != nLcsLen - 1 && pLcsDst[i] + 1 == pLcsDst[i + 1]
+                                && pLcsSrc[i] + 1 == pLcsSrc[i + 1] )
+            {
+                nCnt++;
+            }
+            else
+            {
+                nSqSum += nCnt*nCnt;
+                nCnt = 1;
+            }
+        }
+
+        // Don't compare if there aren't enough similarities
+        if ( nAvgLen >= 8 && nSqSum*32 < nAvgLen*nAvgLen )
+        {
+            return sal_False;
+        }
+
+        // Show the differences
+        int nSkip = 0;
+        for( int i = 0; i <= nLcsLen; i++ )
+        {
+            int nDstFrom = i ? (pLcsDst[i - 1] + 1) : 0;
+            int nDstTo = ( i == nLcsLen ) ? nDstLen : pLcsDst[i];
+            int nSrcFrom = i ? (pLcsSrc[i - 1] + 1) : 0;
+            int nSrcTo = ( i == nLcsLen ) ? nSrcLen : pLcsSrc[i];
+
+            SwPaM aPam( rDstNd, nDstTo + nSkip );
+
+            if ( nDstFrom < nDstTo )
             {
                 SwPaM* pTmp = new SwPaM( *aPam.GetPoint(), rpInsRing );
                 if( !rpInsRing )
                     rpInsRing = pTmp;
-
                 pTmp->SetMark();
-                pTmp->GetMark()->nContent = nStt;
+                pTmp->GetMark()->nContent = nDstFrom + nSkip;
             }
 
-            if( nStt != nSEnd )
+            if ( nSrcFrom < nSrcTo )
             {
-                {
-                    ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
-                    SwPaM aCpyPam( rSrcNd, nStt );
-                    aCpyPam.SetMark();
-                    aCpyPam.GetPoint()->nContent = nSEnd;
-                    aCpyPam.GetDoc()->CopyRange( aCpyPam, *aPam.GetPoint(),
-                            false );
-                }
+                sal_Bool bUndo = pDstDoc->GetIDocumentUndoRedo().DoesUndo();
+                pDstDoc->GetIDocumentUndoRedo().DoUndo( sal_False );
+                SwPaM aCpyPam( rSrcNd, nSrcFrom );
+                aCpyPam.SetMark();
+                aCpyPam.GetPoint()->nContent = nSrcTo;
+                aCpyPam.GetDoc()->CopyRange( aCpyPam, *aPam.GetPoint(),
+                    false );
+                pDstDoc->GetIDocumentUndoRedo().DoUndo( bUndo );
 
                 SwPaM* pTmp = new SwPaM( *aPam.GetPoint(), rpDelRing );
                 if( !rpDelRing )
                     rpDelRing = pTmp;
 
                 pTmp->SetMark();
-                pTmp->GetMark()->nContent = nDEnd;
+                pTmp->GetMark()->nContent = nDstTo + nSkip;
+                nSkip += nSrcTo - nSrcFrom;
 
                 if( rpInsRing )
                 {
@@ -1204,9 +1407,14 @@ sal_Bool SwCompareLine::ChangesInLine( const SwCompareLine& rLine,
                         *pCorr->GetPoint() = *pTmp->GetMark();
                 }
             }
-            bRet = sal_True;
         }
+
+        delete[] pLcsDst;
+        delete[] pLcsSrc;
+
+        bRet = sal_True;
     }
+
     return bRet;
 }
 
@@ -1381,15 +1589,52 @@ void SwCompareData::CheckForChangesInLine( const CompareData& rData,
                                     sal_uLong& rStt, sal_uLong& rEnd,
                                     sal_uLong& rThisStt, sal_uLong& rThisEnd )
 {
-    while( rStt < rEnd && rThisStt < rThisEnd )
+    LineArrayComparator aCmp( (CompareData&)*this, rData, rThisStt, rThisEnd,
+                              rStt, rEnd );
+
+    int nMinLen = std::min( aCmp.GetLen1(), aCmp.GetLen2() );
+    int *pLcsDst = new int[ nMinLen ];
+    int *pLcsSrc = new int[ nMinLen ];
+
+    FastCommonSubseq subseq( aCmp );
+    int nLcsLen = subseq.Find( pLcsDst, pLcsSrc );
+    for (int i = 0; i <= nLcsLen; i++)
     {
-        SwCompareLine* pDstLn = (SwCompareLine*)GetLine( rThisStt );
-        SwCompareLine* pSrcLn = (SwCompareLine*)rData.GetLine( rStt );
-        if( !pDstLn->ChangesInLine( *pSrcLn, pInsRing, pDelRing ) )
-            break;
+        // Beginning of inserted lines (inclusive)
+        int nDstFrom = i ? pLcsDst[i - 1] + 1 : 0;
+        // End of inserted lines (exclusive)
+        int nDstTo = ( i == nLcsLen ) ? aCmp.GetLen1() : pLcsDst[i];
+        // Begining of deleted lines (inclusive)
+        int nSrcFrom = i ? pLcsSrc[i - 1] + 1 : 0;
+        // End of deleted lines (exclusive)
+        int nSrcTo = ( i == nLcsLen ) ? aCmp.GetLen2() : pLcsSrc[i];
+
+        if( i )
+        {
+            SwCompareLine* pDstLn = (SwCompareLine*)GetLine( rThisStt + nDstFrom - 1 );
+            SwCompareLine* pSrcLn = (SwCompareLine*)rData.GetLine( rStt + nSrcFrom - 1 );
+
+            // Show differences in detail for lines that
+            // were matched as only slightly different
+            if( !pDstLn->ChangesInLine( *pSrcLn, pInsRing, pDelRing ) )
+            {
+                ShowInsert( rThisStt + nDstFrom - 1, rThisStt + nDstFrom );
+                ShowDelete( rData, rStt + nSrcFrom - 1, rStt + nSrcFrom,
+                                                    rThisStt + nDstFrom );
+            }
+        }
+
+        // Lines missing from source are inserted
+        if( nDstFrom != nDstTo )
+        {
+            ShowInsert( rThisStt + nDstFrom, rThisStt + nDstTo );
+        }
 
-        ++rStt;
-        ++rThisStt;
+        // Lines missing from destination are deleted
+        if( nSrcFrom != nSrcTo )
+        {
+            ShowDelete( rData, rStt + nSrcFrom, rStt + nSrcTo, rThisStt + nDstTo );
+        }
     }
 }
 
@@ -1537,6 +1782,29 @@ long SwDoc::CompareDoc( const SwDoc& rDoc )
 
     long nRet = 0;
 
+    // Get comparison options
+    CmpOptions.eCmpMode = SW_MOD()->GetCompareMode();
+    if( CmpOptions.eCmpMode == SVX_CMP_AUTO )
+    {
+        if( getRsidRoot() == rDoc.getRsidRoot() )
+        {
+            CmpOptions.eCmpMode = SVX_CMP_BY_CHAR;
+            CmpOptions.bUseRsid = true;
+            CmpOptions.nIgnoreLen = 2;
+        }
+        else
+        {
+            CmpOptions.eCmpMode = SVX_CMP_BY_WORD;
+            CmpOptions.bUseRsid = false;
+            CmpOptions.nIgnoreLen = 3;
+        }
+    }
+    else
+    {
+        CmpOptions.bUseRsid = getRsidRoot() == rDoc.getRsidRoot() && SW_MOD()->IsUseRsid();
+        CmpOptions.nIgnoreLen = SW_MOD()->IsIgnorePieces() ? SW_MOD()->GetPieceLen() : 0;
+    }
+
     GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
     sal_Bool bDocWasModified = IsModified();
     SwDoc& rSrcDoc = (SwDoc&)rDoc;
@@ -1831,4 +2099,566 @@ long SwDoc::MergeDoc( const SwDoc& rDoc )
     return nRet;
 }
 
+LineArrayComparator::LineArrayComparator( const CompareData &rD1,
+                                            const CompareData &rD2, int nStt1,
+                                            int nEnd1, int nStt2, int nEnd2 )
+    : rData1( rD1 ), rData2( rD2 ), nFirst1( nStt1 ), nFirst2( nStt2 )
+{
+    nLen1 = nEnd1 - nStt1;
+    nLen2 = nEnd2 - nStt2;
+}
+
+bool LineArrayComparator::Compare( int nIdx1, int nIdx2 ) const
+{
+    if( nIdx1 < 0 || nIdx2 < 0 || nIdx1 >= nLen1 || nIdx2 >= nLen2 )
+    {
+        OSL_ENSURE( 0, "Index out of range!" );
+        return false;
+    }
+
+    const SwTxtNode *pTxtNd1 = ( ( SwCompareLine* )rData1.GetLine( nFirst1 + nIdx1 ) )->GetNode().GetTxtNode();
+    const SwTxtNode *pTxtNd2 = ( ( SwCompareLine* )rData2.GetLine( nFirst2 + nIdx2 ) )->GetNode().GetTxtNode();
+
+    if( !pTxtNd1 || !pTxtNd2
+        || ( CmpOptions.bUseRsid && !pTxtNd1->CompareParRsid( *pTxtNd2 ) ) )
+    {
+        return false;
+    }
+
+    int nPar1Len = pTxtNd1->Len();
+    int nPar2Len = pTxtNd2->Len();
+
+    if( std::min( nPar1Len, nPar2Len ) * 3 < std::max( nPar1Len, nPar2Len ) )
+    {
+        return false;
+    }
+
+    int nBorderLen = ( nPar1Len + nPar2Len )/16;
+
+    if( nBorderLen < 3 )
+    {
+        nBorderLen = std::min( 3, std::min( nPar1Len, nPar2Len ) );
+    }
+
+    std::set<unsigned> aHashes;
+    unsigned nHash = 0;
+    unsigned nMul = 251;
+    unsigned nPow = 1;
+    int i;
+
+    for( i = 0; i < nBorderLen - 1; i++ )
+    {
+        nPow *= nMul;
+    }
+    for( i = 0; i < nBorderLen; i++ )
+    {
+        nHash = nHash*nMul + pTxtNd1->GetTxt().GetChar( i );
+    }
+    aHashes.insert( nHash );
+    for( ; i < nPar1Len; i++ )
+    {
+        nHash = nHash - nPow*pTxtNd1->GetTxt().GetChar( i - nBorderLen );
+        nHash = nHash*nMul + pTxtNd1->GetTxt().GetChar( i );
+
+        aHashes.insert( nHash );
+    }
+
+    nHash = 0;
+    for( i = 0; i < nBorderLen; i++ )
+    {
+        nHash = nHash*nMul + pTxtNd2->GetTxt().GetChar( i );
+    }
+
+    if( aHashes.find( nHash ) != aHashes.end() )
+    {
+        return true;
+    }
+
+    for( ; i < nPar2Len; i++ )
+    {
+        nHash = nHash - nPow*pTxtNd2->GetTxt().GetChar( i - nBorderLen );
+        nHash = nHash*nMul + pTxtNd2->GetTxt().GetChar( i );
+        if( aHashes.find( nHash ) != aHashes.end() )
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool CharArrayComparator::Compare( int nIdx1, int nIdx2 ) const
+{
+    if( nIdx1 < 0 || nIdx2 < 0 || nIdx1 >= GetLen1() || nIdx2 >= GetLen2() )
+    {
+        OSL_ENSURE( 0, "Index out of range!" );
+        return false;
+    }
+
+    return ( !CmpOptions.bUseRsid
+            || pTxtNd1->CompareRsid(  *pTxtNd2, nIdx1 + 1, nIdx2 + 1 ) )
+            && pTxtNd1->GetTxt().GetChar( nIdx1 )
+            == pTxtNd2->GetTxt().GetChar( nIdx2 );
+}
+
+WordArrayComparator::WordArrayComparator( const SwTxtNode *pNode1,
+                                            const SwTxtNode *pNode2 )
+    : pTxtNd1( pNode1 ), pTxtNd2( pNode2 ), nMul( 251 )
+{
+    pPos1 = new int[ pTxtNd1->GetTxt().Len() + 1 ];
+    pPos2 = new int[ pTxtNd2->GetTxt().Len() + 1 ];
+
+    CalcPositions( pPos1, pTxtNd1, nCnt1 );
+    CalcPositions( pPos2, pTxtNd2, nCnt2 );
+}
+
+WordArrayComparator::~WordArrayComparator()
+{
+    delete[] pPos1;
+    delete[] pPos2;
+}
+
+bool WordArrayComparator::Compare( int nIdx1, int nIdx2 ) const
+{
+    int nLen = pPos1[ nIdx1 + 1 ] - pPos1[ nIdx1 ];
+    if( nLen != pPos2[ nIdx2 + 1 ] - pPos2[ nIdx2 ] )
+    {
+        return false;
+    }
+    for( int i = 0; i < nLen; i++)
+    {
+        if( pTxtNd1->GetTxt().GetChar( pPos1[ nIdx1 ] + i )
+            != pTxtNd2->GetTxt().GetChar( pPos2[ nIdx2 ] + i )
+            || ( CmpOptions.bUseRsid && !pTxtNd1->CompareRsid( *pTxtNd2,
+                                pPos1[ nIdx1 ] + i, pPos2[ nIdx2 ] + i ) ) )
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+int WordArrayComparator::GetCharSequence( const int *pWordLcs1,
+            const int *pWordLcs2, int *pSubseq1, int *pSubseq2, int nLcsLen )
+{
+    int nLen = 0;
+    for( int i = 0; i < nLcsLen; i++ )
+    {
+        // Check for hash collisions
+        if( pPos1[ pWordLcs1[i] + 1 ] - pPos1[ pWordLcs1[i] ]
+            != pPos2[ pWordLcs2[i] + 1 ] - pPos2[ pWordLcs2[i] ] )
+        {
+            continue;
+        }
+        for( int j = 0; j < pPos1[pWordLcs1[i]+1] - pPos1[pWordLcs1[i]]; j++)
+        {
+            pSubseq1[ nLen ] = pPos1[ pWordLcs1[i] ] + j;
+            pSubseq2[ nLen ] = pPos2[ pWordLcs2[i] ] + j;
+
+            if( pTxtNd1->GetTxt().GetChar( pPos1[ pWordLcs1[i] ] + j )
+             != pTxtNd2->GetTxt().GetChar( pPos2[ pWordLcs2[i] ] + j ) )
+            {
+                nLen -= j;
+                break;
+            }
+
+            nLen++;
+        }
+    }
+    return nLen;
+}
+
+void WordArrayComparator::CalcPositions( int *pPos, const SwTxtNode *pTxtNd,
+                                         int &nCnt )
+{
+    nCnt = -1;
+    for( int i = 0; i <= pTxtNd->GetTxt().Len(); i++ )
+    {
+        if( i == 0 || i == pTxtNd->GetTxt().Len()
+                    || !isalnum( pTxtNd->GetTxt().GetChar( i - 1 ) )
+                    || !isalnum( pTxtNd->GetTxt().GetChar( i ) ) )
+        { // Begin new word
+            nCnt++;
+            pPos[ nCnt ] = i;
+        }
+    }
+}
+
+
+int CommonSubseq::FindLCS( int *pLcs1, int *pLcs2, int nStt1, int nEnd1,
+                                                    int nStt2, int nEnd2 )
+{
+    int nLen1 = nEnd1 ? nEnd1 - nStt1 : rCmp.GetLen1();
+    int nLen2 = nEnd2 ? nEnd2 - nStt2 : rCmp.GetLen2();
+
+    OSL_ASSERT( nLen1 >= 0 );
+    OSL_ASSERT( nLen2 >= 0 );
+
+    int **pLcs = new int*[ nLen1 + 1 ];
+    pLcs[ 0 ] = pData;
+
+    for( int i = 1; i < nLen1 + 1; i++ )
+        pLcs[ i ] = pLcs[ i - 1 ] + nLen2 + 1;
+
+    for( int i = 0; i <= nLen1; i++ )
+        pLcs[i][0] = 0;
+
+    for( int j = 0; j <= nLen2; j++ )
+        pLcs[0][j] = 0;
+
+    // Find lcs
+    for( int i = 1; i <= nLen1; i++ )
+    {
+        for( int j = 1; j <= nLen2; j++ )
+        {
+            if( rCmp.Compare( nStt1 + i - 1, nStt2 + j - 1 ) )
+                pLcs[i][j] = pLcs[i - 1][j - 1] + 1;
+            else
+                pLcs[i][j] = std::max( pLcs[i][j - 1], pLcs[i - 1][j] );
+        }
+    }
+
+    int nLcsLen = pLcs[ nLen1 ][ nLen2 ];
+
+    // Recover the lcs in the two sequences
+    if( pLcs1 && pLcs2 )
+    {
+        int nIdx1 = nLen1;
+        int nIdx2 = nLen2;
+        int nIdx = nLcsLen - 1;
+
+        while( nIdx1 > 0 && nIdx2 > 0 )
+        {
+            if( pLcs[ nIdx1 ][ nIdx2 ] == pLcs[ nIdx1 - 1 ][ nIdx2 ] )
+                nIdx1--;
+            else if( pLcs[ nIdx1 ][ nIdx2 ] == pLcs[ nIdx1 ][ nIdx2 - 1 ] )
+                nIdx2--;
+            else
+            {
+                nIdx1--, nIdx2--;
+                pLcs1[ nIdx ] = nIdx1 + nStt1;
+                pLcs2[ nIdx ] = nIdx2 + nStt2;
+                nIdx--;
+            }
+        }
+    }
+
+    delete[] pLcs;
+
+    return nLcsLen;
+}
+
+int CommonSubseq::IgnoreIsolatedPieces( int *pLcs1, int *pLcs2, int nLen1,
+                                        int nLen2, int nLcsLen, int nPieceLen )
+{
+    if( !nLcsLen )
+    {
+        return 0;
+    }
+
+    int nNext = 0;
+
+    // Don't ignore text at the beginning of the paragraphs
+    if( pLcs1[ 0 ] == 0 && pLcs2[ 0 ] == 0 )
+    {
+        while( nNext < nLcsLen - 1 && pLcs1[ nNext ] + 1 == pLcs1[ nNext + 1 ]
+                                && pLcs2[ nNext ] + 1 == pLcs2[ nNext + 1 ] )
+        {
+            nNext++;
+        }
+        nNext++;
+    }
+
+    int nCnt = 1;
+
+    for( int i = nNext; i < nLcsLen; i++ )
+    {
+        if( i != nLcsLen - 1 && pLcs1[ i ] + 1 == pLcs1[ i + 1 ]
+                            && pLcs2[ i ] + 1 == pLcs2[ i + 1 ] )
+        {
+            nCnt++;
+        }
+        else
+        {
+            if( nCnt > nPieceLen
+                // Don't ignore text at the end of the paragraphs
+                || ( i == nLcsLen - 1
+                && pLcs1[i] == nLen1 - 1 && pLcs2[i] == nLen2 - 1 ))
+            {
+                for( int j = i + 1 - nCnt; j <= i; j++ )
+                {
+                    pLcs2[ nNext ] = pLcs2[ j ];
+                    pLcs1[ nNext ] = pLcs1[ j ];
+                    nNext++;
+                }
+            }
+            nCnt = 1;
+        }
+    }
+
+    return nNext;
+}
+
+LgstCommonSubseq::LgstCommonSubseq( ArrayComparator &rComparator )
+    : CommonSubseq( rComparator, CUTOFF )
+{
+    pBuff1 = new int[ rComparator.GetLen2() + 1 ];
+    pBuff2 = new int[ rComparator.GetLen2() + 1 ];
+
+    pL1 = new int[ rComparator.GetLen2() + 1 ];
+    pL2 = new int[ rComparator.GetLen2() + 1 ];
+}
+
+LgstCommonSubseq::~LgstCommonSubseq()
+{
+    delete[] pBuff1;
+    delete[] pBuff2;
+
+    delete[] pL1;
+    delete[] pL2;
+}
+
+void LgstCommonSubseq::FindL( int *pL, int nStt1, int nEnd1,
+                                        int nStt2, int nEnd2  )
+{
+    int nLen1 = nEnd1 ? nEnd1 - nStt1 : rCmp.GetLen1();
+    int nLen2 = nEnd2 ? nEnd2 - nStt2 : rCmp.GetLen2();
+
+    int *currL = pBuff1;
+    int *prevL = pBuff2;
+
+    // Avoid memory corruption
+    if( nLen2 > rCmp.GetLen2() )
+    {
+        assert( false );
+        return;
+    }
+
+    memset( pBuff1, 0, sizeof( *pBuff1 ) * ( nLen2 + 1 ) );
+    memset( pBuff2, 0, sizeof( *pBuff2 ) * ( nLen2 + 1 ) );
+
+    // Find lcs
+    for( int i = 1; i <= nLen1; i++ )
+    {
+        for( int j = 1; j <= nLen2; j++ )
+        {
+            if( rCmp.Compare( nStt1 + i - 1, nStt2 + j - 1 ) )
+                currL[j] = prevL[j - 1] + 1;
+            else
+                currL[j] = std::max( currL[j - 1], prevL[j] );
+        }
+        int *tmp = currL;
+        currL = prevL;
+        prevL = tmp;
+    }
+    memcpy( pL, prevL, ( nLen2 + 1 ) * sizeof( *prevL ) );
+}
+
+int LgstCommonSubseq::HirschbergLCS( int *pLcs1, int *pLcs2, int nStt1,
+                                    int nEnd1, int nStt2, int nEnd2 )
+{
+    static int nLen1;
+    static int nLen2;
+    nLen1 = nEnd1 - nStt1;
+    nLen2 = nEnd2 - nStt2;
+
+    if( ( nLen1 + 1 ) * ( nLen2 + 1 ) <= CUTOFF )
+    {
+        if( !nLen1 || !nLen2 )
+        {
+            return 0;
+        }
+        return FindLCS(pLcs1, pLcs2, nStt1, nEnd1, nStt2, nEnd2);
+    }
+
+    int nMid = nLen1/2;
+
+    FindL( pL1, nStt1, nStt1 + nMid, nStt2, nEnd2 );
+    FindL( pL2, nStt1 + nMid, nEnd1, nStt2, nEnd2 );
+
+    int nMaxPos = 0;
+    static int nMaxVal;
+    nMaxVal = -1;
+
+    static int i;
+    for( i = 0; i <= nLen2; i++ )
+    {
+        if( pL1[i] + ( pL2[nLen2] - pL2[i] ) > nMaxVal )
+        {
+            nMaxPos = i;
+            nMaxVal = pL1[i]+( pL2[nLen2] - pL2[i] );
+        }
+    }
+
+    int nRet = HirschbergLCS( pLcs1, pLcs2, nStt1, nStt1 + nMid,
+                                            nStt2, nStt2 + nMaxPos );
+    nRet += HirschbergLCS( pLcs1 + nRet, pLcs2 + nRet, nStt1 + nMid, nEnd1,
+                                                    nStt2 + nMaxPos, nEnd2 );
+
+    return nRet;
+}
+
+int LgstCommonSubseq::Find( int *pSubseq1, int *pSubseq2 )
+{
+    int nStt = 0;
+    int nCutEnd = 0;
+    int nEnd1 = rCmp.GetLen1();
+    int nEnd2 = rCmp.GetLen2();
+
+    // Check for corresponding lines in the beginning of the sequences
+    while( nStt < nEnd1 && nStt < nEnd2 && rCmp.Compare( nStt, nStt ) )
+    {
+        pSubseq1[ nStt ] = nStt;
+        pSubseq2[ nStt ] = nStt;
+        nStt++;
+    }
+
+    pSubseq1 += nStt;
+    pSubseq2 += nStt;
+
+    // Check for corresponding lines in the end of the sequences
+    while( nStt < nEnd1 && nStt < nEnd2
+                        && rCmp.Compare( nEnd1 - 1, nEnd2 - 1 ) )
+    {
+        nCutEnd++;
+        nEnd1--;
+        nEnd2--;
+    }
+
+    int nLen = HirschbergLCS( pSubseq1, pSubseq2, nStt, nEnd1, nStt, nEnd2 );
+
+    for( int i = 0; i < nCutEnd; i++ )
+    {
+        pSubseq1[ nLen + i ] = nEnd1 + i;
+        pSubseq2[ nLen + i ] = nEnd2 + i;
+    }
+
+    return nStt + nLen + nCutEnd;
+}
+
+int FastCommonSubseq::FindFastCS( int *pSeq1, int *pSeq2, int nStt1,
+                                    int nEnd1, int nStt2, int nEnd2  )
+{
+    int nCutBeg = 0;
+    int nCutEnd = 0;
+
+    // Check for corresponding lines in the beginning of the sequences
+    while( nStt1 < nEnd1 && nStt2 < nEnd2 && rCmp.Compare( nStt1, nStt2 ) )
+    {
+        pSeq1[ nCutBeg ] = nStt1++;
+        pSeq2[ nCutBeg ] = nStt2++;
+        nCutBeg++;
+    }
+
+    pSeq1 += nCutBeg;
+    pSeq2 += nCutBeg;
+
+    // Check for corresponding lines in the end of the sequences
+    while( nStt1 < nEnd1 && nStt2 < nEnd2
+                        && rCmp.Compare( nEnd1 - 1, nEnd2 - 1 ) )
+    {
+        nCutEnd++;
+        nEnd1--;
+        nEnd2--;
+    }
+
+    int nLen1 = nEnd1 - nStt1;
+    int nLen2 = nEnd2 - nStt2;
+
+    // Return if a sequence is empty
+    if( nLen1 <= 0 || nLen2 <= 0 )
+    {
+        for( int i = 0; i < nCutEnd; i++ )
+        {
+            pSeq1[ i ] = nEnd1 + i;
+            pSeq2[ i ] = nEnd2 + i;
+        }
+        return nCutBeg + nCutEnd;
+    }
+
+    // Cut to LCS for small values
+    if( nLen1 < 3 || nLen2 < 3 || ( nLen1 + 1 ) * ( nLen2 + 1 ) <= CUTOFF )
+    {
+        int nLcsLen = FindLCS( pSeq1, pSeq2, nStt1, nEnd1, nStt2, nEnd2);
+
+        for( int i = 0; i < nCutEnd; i++ )
+        {
+            pSeq1[ nLcsLen + i ] = nEnd1 + i;
+            pSeq2[ nLcsLen + i ] = nEnd2 + i;
+        }
+        return nCutBeg + nLcsLen + nCutEnd;
+    }
+
+    int nMid1 = nLen1/2;
+    int nMid2 = nLen2/2;
+
+    int nRad;
+    int nPos1 = -1, nPos2 = -1;
+
+    // Find a point of correspondence in the middle of the sequences
+    for( nRad = 0; nRad*nRad < std::min( nMid1, nMid2 ); nRad++ )
+    {
+        // Search to the left and to the right of the middle of the first sequence
+        for( int i = nMid1 - nRad; i <= nMid1 + nRad; i++ )
+        {
+            if( rCmp.Compare( nStt1 + i, nStt2 + nMid2 - nRad ) )
+            {
+                nPos1 = nStt1 + i;
+                nPos2 = nStt2 + nMid2 - nRad;
+                break;
+            }
+            if( rCmp.Compare( nStt1 + i, nStt2 + nMid2 + nRad ) )
+            {
+                nPos1 = nStt1 + i;
+                nPos2 = nStt2 + nMid2 - nRad;
+                break;
+            }
+        }
+        // Search to the left and to the right of the middle of the second sequence
+        for( int i = nMid2 - nRad; i <= nMid2 + nRad; i++ )
+        {
+            if( rCmp.Compare( nStt2 + nMid2 - nRad, nStt2 + i ) )
+            {
+                nPos2 = nStt2 + i;
+                nPos1 = nStt1 + nMid1 - nRad;
+                break;
+            }
+            if( rCmp.Compare( nStt2 + nMid2 - nRad, nStt2 + i ) )
+            {
+                nPos2 = nStt2 + i;
+                nPos1 = nStt1 + nMid1 - nRad;
+                break;
+            }
+        }
+    }
+
+    // return if no point of correspondence found
+    if( nPos1 == -1 )
+    {
+        for( int i = 0; i < nCutEnd; i++ )
+        {
+            pSeq1[ i ] = nEnd1 + i;
+            pSeq2[ i ] = nEnd2 + i;
+        }
+        return nCutBeg + nCutEnd;
+    }
+
+    // Run the same on the sequences to the left of the correspondence point
+    int nLen = FindFastCS( pSeq1, pSeq2, nStt1, nPos1, nStt2, nPos2 );
+
+    pSeq1[ nLen ] = nPos1;
+    pSeq2[ nLen ] = nPos2;
+
+    // Run the same on the sequences to the right of the correspondence point
+    nLen += FindFastCS( pSeq1 + nLen + 1, pSeq2 + nLen + 1,
+                         nPos1 + 1, nEnd1, nPos2 + 1, nEnd2 ) + 1;
+
+    for( int i = 0; i < nCutEnd; i++ )
+    {
+        pSeq1[ nLen + i ] = nEnd1 + i;
+        pSeq2[ nLen + i ] = nEnd2 + i;
+    }
+
+    return nLen + nCutBeg + nCutEnd;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index cba7694..294a4d4 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -39,6 +39,7 @@
 #include <vcl/svapp.hxx>
 #include <vcl/virdev.hxx>
 #include <rtl/logfile.hxx>
+#include <rtl/random.h>
 #include <sfx2/printer.hxx>
 #include <sfx2/docfile.hxx>
 #include <sfx2/frame.hxx>
@@ -431,6 +432,14 @@ SwDoc::SwDoc()
         pStyleAccess = createStyleManager( &aIgnorableParagraphItems );
     }
 
+    // Initialize the session id of the current document to a random number
+    // smaller than 2^21.
+    static rtlRandomPool aPool = rtl_random_createPool();
+    rtl_random_getBytes( aPool, &nRsid, sizeof ( nRsid ) );
+    nRsid &= ( 1<<21 ) - 1;
+    nRsid++;
+    nRsidRoot = nRsid;
+
     ResetModified();
 }
 
diff --git a/sw/source/core/edit/editsh.cxx b/sw/source/core/edit/editsh.cxx
index f6e3da2..de33e7e 100644
--- a/sw/source/core/edit/editsh.cxx
+++ b/sw/source/core/edit/editsh.cxx
@@ -122,6 +122,13 @@ void SwEditShell::Insert2(const String &rStr, const bool bForceExpandHints )
             OSL_ENSURE( bSuccess, "Doc->Insert() failed." );
             (void) bSuccess;
 
+            GetDoc()->UpdateRsid( *_pStartCrsr, rStr.Len() );
+
+            // Set paragraph rsid if beginning of paragraph
+            SwTxtNode *pTxtNode = _pStartCrsr->GetPoint()->nNode.GetNode().GetTxtNode();
+            if( pTxtNode && pTxtNode->Len() == 1)
+                GetDoc()->UpdateParRsid( pTxtNode );
+
             SaveTblBoxCntnt( _pStartCrsr->GetPoint() );
 
         } while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != __pStartCrsr );
diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx
index e3056be..0a2ed74 100644
--- a/sw/source/core/frmedt/fecopy.cxx
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -1043,6 +1043,7 @@ sal_Bool SwFEShell::Paste( SwDoc* pClpDoc, sal_Bool bIncludingPageFrames )
                 // muessen die BoxAttribute aber entfernt werden.
                 GetDoc()->ClearBoxNumAttrs( rInsPos.nNode );
             }
+
             //find out if the clipboard document starts with a table
             bool bStartWithTable = 0 != aCpyPam.Start()->nNode.GetNode().FindTableNode();
             SwPosition aInsertPosition( rInsPos );
@@ -1063,6 +1064,22 @@ sal_Bool SwFEShell::Paste( SwDoc* pClpDoc, sal_Bool bIncludingPageFrames )
                 }
             }
 
+            // Update the rsid of each pasted text node.
+            {
+                xub_StrLen nNodesCnt = aCpyPam.End()->nNode.GetIndex() - aCpyPam.Start()->nNode.GetIndex();
+                SwNodes &rDestNodes = GetDoc()->GetNodes();
+                xub_StrLen nDestStart = PCURCRSR->GetPoint()->nNode.GetIndex() - nNodesCnt;
+
+                for ( sal_uInt64 nIdx = 0; nIdx <= nNodesCnt; nIdx++ )
+                {
+                    SwTxtNode *pTxtNode = rDestNodes[ nDestStart + nIdx ]->GetTxtNode();
+                    if ( pTxtNode )
+                    {
+                        GetDoc()->UpdateParRsid( pTxtNode );
+                    }
+                }
+            }
+
             SaveTblBoxCntnt( &rInsPos );
             if(bIncludingPageFrames && bStartWithTable)
             {
diff --git a/sw/source/core/inc/UndoSplitMove.hxx b/sw/source/core/inc/UndoSplitMove.hxx
index c1a690b..f85c65c 100644
--- a/sw/source/core/inc/UndoSplitMove.hxx
+++ b/sw/source/core/inc/UndoSplitMove.hxx
@@ -40,6 +40,7 @@ class SwUndoSplitNode: public SwUndo
     xub_StrLen nCntnt;
     sal_Bool bTblFlag : 1;
     sal_Bool bChkTblStt : 1;
+    sal_uInt32 nParRsid;
 
 public:
     SwUndoSplitNode( SwDoc* pDoc, const SwPosition& rPos, sal_Bool bChkTbl );
diff --git a/sw/source/core/text/atrstck.cxx b/sw/source/core/text/atrstck.cxx
index 4f0824c..b120ca8 100644
--- a/sw/source/core/text/atrstck.cxx
+++ b/sw/source/core/text/atrstck.cxx
@@ -121,8 +121,8 @@ const sal_uInt8 StackPos[ static_cast<sal_uInt16>(RES_TXTATR_WITHEND_END) -
     33, // RES_CHRATR_RELIEF,                    // 36
     34, // RES_CHRATR_HIDDEN,                    // 37
     35, // RES_CHRATR_OVERLINE,                  // 38
-     0, // RES_CHRATR_DUMMY1,                    // 39
-     0, // RES_CHRATR_DUMMY2,                    // 40
+     0, // RES_CHRATR_RSID,                      // 39
+     0, // RES_DUMMY1,                           // 40
     36, // RES_TXTATR_REFMARK,                   // 41
     37, // RES_TXTATR_TOXMARK,                   // 42
     38, // RES_TXTATR_META,                      // 43
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index 46f9c24..19a968d 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -33,6 +33,7 @@
 #include <editeng/brkitem.hxx>
 #include <editeng/escpitem.hxx>
 #include <editeng/lrspitem.hxx>
+#include <editeng/rsiditem.hxx>
 #include <editeng/tstpitem.hxx>
 #include <svl/urihelper.hxx>
 #ifndef _SVSTDARR_HXX
@@ -4742,6 +4743,45 @@ sal_uInt16 SwTxtNode::ResetAllAttr()
     return nRet;
 }
 
+
+sal_uInt32 SwTxtNode::GetRsid( xub_StrLen nStt, xub_StrLen nEnd ) const
+{
+    SfxItemSet aSet( (SfxItemPool&) (GetDoc()->GetAttrPool()), RES_CHRATR_RSID, RES_CHRATR_RSID );
+    if ( GetAttr(aSet, nStt, nEnd) )
+    {
+        SvxRsidItem* pRsid = (SvxRsidItem*)aSet.GetItem(RES_CHRATR_RSID);
+        if( pRsid )
+            return pRsid->GetValue();
+    }
+
+    return 0;
+}
+
+sal_uInt32 SwTxtNode::GetParRsid() const
+{
+    SvxRsidItem &rItem = ( SvxRsidItem& ) GetAttr( RES_PARATR_RSID );
+
+    return rItem.GetValue();
+}
+
+bool SwTxtNode::CompareParRsid( const SwTxtNode &rTxtNode ) const
+{
+    sal_uInt32 nThisRsid = GetParRsid();
+    sal_uInt32 nRsid = rTxtNode.GetParRsid();
+
+    return nThisRsid == nRsid;
+}
+
+bool SwTxtNode::CompareRsid( const SwTxtNode &rTxtNode, xub_StrLen nStt1, xub_StrLen nStt2,
+                            xub_StrLen nEnd1,  xub_StrLen nEnd2 ) const
+
+{
+    sal_uInt32 nThisRsid = GetRsid( nStt1, nEnd1 ? nEnd1 : nStt1 );
+    sal_uInt32 nRsid = rTxtNode.GetRsid( nStt2, nEnd2 ? nEnd2 : nStt2 );
+
+    return nThisRsid == nRsid;
+}
+
 // sw::Metadatable
 ::sfx2::IXmlIdRegistry& SwTxtNode::GetRegistry()
 {
diff --git a/sw/source/core/undo/unspnd.cxx b/sw/source/core/undo/unspnd.cxx
index 0fef079..787aed4 100644
--- a/sw/source/core/undo/unspnd.cxx
+++ b/sw/source/core/undo/unspnd.cxx
@@ -71,6 +71,8 @@ SwUndoSplitNode::SwUndoSplitNode( SwDoc* pDoc, const SwPosition& rPos,
         pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT, pDoc->GetRedlineAuthor() );
         SetRedlineMode( pDoc->GetRedlineMode() );
     }
+
+    nParRsid = pTxtNd->GetParRsid();
 }
 
 SwUndoSplitNode::~SwUndoSplitNode()
@@ -147,6 +149,8 @@ void SwUndoSplitNode::UndoImpl(::sw::UndoRedoContext & rContext)
                 pDoc->RstTxtAttrs( rPam, sal_True );
                 pHistory->TmpRollback( pDoc, 0, false );
             }
+
+            pDoc->UpdateParRsid( pTNd, nParRsid );
         }
     }
 
diff --git a/sw/source/core/unocore/unomap.cxx b/sw/source/core/unocore/unomap.cxx
index 1554fdc..4e6a17c 100644
--- a/sw/source/core/unocore/unomap.cxx
+++ b/sw/source/core/unocore/unomap.cxx
@@ -84,6 +84,7 @@ SwUnoPropertyMapProvider::~SwUnoPropertyMapProvider()
     { SW_PROP_NMID(UNO_NAME_CHAR_FONT_CHAR_SET), RES_CHRATR_FONT,       CPPU_E2T(CPPUTYPE_INT16),   PropertyAttribute::MAYBEVOID, MID_FONT_CHAR_SET },                    \
     { SW_PROP_NMID(UNO_NAME_CHAR_FONT_PITCH), RES_CHRATR_FONT,      CPPU_E2T(CPPUTYPE_INT16),                   PropertyAttribute::MAYBEVOID, MID_FONT_PITCH   },     \
     { SW_PROP_NMID(UNO_NAME_CHAR_POSTURE), RES_CHRATR_POSTURE   ,  CPPU_E2T(CPPUTYPE_FONTSLANT),        PropertyAttribute::MAYBEVOID, MID_POSTURE},                   \
+    { SW_PROP_NMID(UNO_NAME_RSID), RES_CHRATR_RSID, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, 0 }, \
     { SW_PROP_NMID(UNO_NAME_CHAR_LOCALE), RES_CHRATR_LANGUAGE ,   CPPU_E2T(CPPUTYPE_LOCALE)  ,          PropertyAttribute::MAYBEVOID,  MID_LANG_LOCALE },
 
 #define _CJK_FONT_PROPERTIES \
@@ -154,6 +155,7 @@ SwUnoPropertyMapProvider::~SwUnoPropertyMapProvider()
 // UNO_NAME_BREAK_TYPE and UNO_NAME_PAGE_DESC_NAME which can not be used
 // by the SwXTextTableCursor
 #define COMMON_CRSR_PARA_PROPERTIES_WITHOUT_FN_01 \
+        { SW_PROP_NMID(UNO_NAME_PARRSID), RES_PARATR_RSID, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, 0 }, \
         { SW_PROP_NMID(UNO_NAME_PARA_IS_HYPHENATION), RES_PARATR_HYPHENZONE,        CPPU_E2T(CPPUTYPE_BOOLEAN),     PropertyAttribute::MAYBEVOID, MID_IS_HYPHEN         },                                        \
         { SW_PROP_NMID(UNO_NAME_PARA_HYPHENATION_MAX_LEADING_CHARS), RES_PARATR_HYPHENZONE,         CPPU_E2T(CPPUTYPE_INT16),   PropertyAttribute::MAYBEVOID, MID_HYPHEN_MIN_LEAD   },                              \
         { SW_PROP_NMID(UNO_NAME_PARA_HYPHENATION_MAX_TRAILING_CHARS), RES_PARATR_HYPHENZONE,        CPPU_E2T(CPPUTYPE_INT16),   PropertyAttribute::MAYBEVOID, MID_HYPHEN_MIN_TRAIL  },                              \
diff --git a/sw/source/core/unocore/unoprnms.cxx b/sw/source/core/unocore/unoprnms.cxx
index 28e9d48..0c0479c 100644
--- a/sw/source/core/unocore/unoprnms.cxx
+++ b/sw/source/core/unocore/unoprnms.cxx
@@ -781,6 +781,8 @@ const SwPropNameTab aPropNameTab = {
 /* 0742 UNO_NAME_SEPARATOR_LINE_STYLE */ {MAP_CHAR_LEN("SeparatorLineStyle")},
 /* 0743 UNO_NAME_FOOTNOTE_LINE_STYLE */ {MAP_CHAR_LEN("FootnoteLineStyle")},
 /* 0744 UNO_NAME_EMBEDDED_OBJECT */ {MAP_CHAR_LEN("EmbeddedObject")},
+/* 0745 UNO_NAME_RSID */	         {MAP_CHAR_LEN("Rsid")},
+/* 0746 UNO_NAME_PARRSID */	         {MAP_CHAR_LEN("ParRsid")},
 
 // new items in this array must match enum SwPropNameIds
 };
diff --git a/sw/source/filter/ascii/parasc.cxx b/sw/source/filter/ascii/parasc.cxx
index d7f210a..807f78b 100644
--- a/sw/source/filter/ascii/parasc.cxx
+++ b/sw/source/filter/ascii/parasc.cxx
@@ -503,6 +503,9 @@ sal_uLong SwASCIIParser::ReadChars()
 void SwASCIIParser::InsertText( const String& rStr )
 {
     pDoc->InsertString( *pPam, rStr );
+    pDoc->UpdateRsid( *pPam, rStr.Len() );
+    pDoc->UpdateParRsid( pPam->GetPoint()->nNode.GetNode().GetTxtNode() );
+
     if( pItemSet && pBreakIt && nScript != ( SCRIPTTYPE_LATIN |
                                              SCRIPTTYPE_ASIAN |
                                              SCRIPTTYPE_COMPLEX ) )
diff --git a/sw/source/filter/html/css1atr.cxx b/sw/source/filter/html/css1atr.cxx
index 97414c2..dcd24da 100644
--- a/sw/source/filter/html/css1atr.cxx
+++ b/sw/source/filter/html/css1atr.cxx
@@ -3747,8 +3747,8 @@ SwAttrFnTab aCSS1AttrFnTab = {
 /* RES_CHRATR_RELIEF */             0,
 /* RES_CHRATR_HIDDEN */             0,
 /* RES_CHRATR_OVERLINE */           OutCSS1_SvxOverline,
+/* RES_CHRATR_RSID */               0,
 /* RES_CHRATR_DUMMY1 */             0,
-/* RES_CHRATR_DUMMY2 */             0,
 
 /* RES_TXTATR_REFMARK */            0,
 /* RES_TXTATR_TOXMARK */            0,
@@ -3786,6 +3786,7 @@ SwAttrFnTab aCSS1AttrFnTab = {
 /* RES_PARATR_SNAPTOGRID*/          0, // new
 /* RES_PARATR_CONNECT_TO_BORDER */  0, // new
 /* RES_PARATR_OUTLINELEVEL */       0, // new since cws outlinelevel
+/* RES_PARATR_RSID */               0, // new
 
 /* RES_PARATR_LIST_ID */            0, // new
 /* RES_PARATR_LIST_LEVEL */         0, // new
diff --git a/sw/source/filter/html/htmlatr.cxx b/sw/source/filter/html/htmlatr.cxx
index 7803c04..08d8e9c 100644
--- a/sw/source/filter/html/htmlatr.cxx
+++ b/sw/source/filter/html/htmlatr.cxx
@@ -3365,8 +3365,8 @@ SwAttrFnTab aHTMLAttrFnTab = {
 /* RES_CHRATR_RELIEF */             0,
 /* RES_CHRATR_HIDDEN */             0,
 /* RES_CHRATR_OVERLINE */           OutHTML_CSS1Attr,
+/* RES_CHRATR_RSID */               0,
 /* RES_CHRATR_DUMMY1 */             0,
-/* RES_CHRATR_DUMMY2 */             0,
 
 /* RES_TXTATR_REFMARK */            0,
 /* RES_TXTATR_TOXMARK */            0,
diff --git a/sw/source/filter/xml/xmlexp.cxx b/sw/source/filter/xml/xmlexp.cxx
index ed058af..7d6d0e9 100644
--- a/sw/source/filter/xml/xmlexp.cxx
+++ b/sw/source/filter/xml/xmlexp.cxx
@@ -156,6 +156,14 @@ sal_uInt32 SwXMLExport::exportDoc( enum XMLTokenEnum eClass )
     if( (getExportFlags() & (EXPORT_FONTDECLS|EXPORT_STYLES|
                              EXPORT_MASTERSTYLES|EXPORT_CONTENT)) != 0 )
     {
+        if( getDefaultVersion() == SvtSaveOptions::ODFVER_LATEST )
+        {
+            _GetNamespaceMap().Add(
+                GetXMLToken(XML_NP_OFFICE_EXT),
+                GetXMLToken(XML_N_OFFICE_EXT),
+                XML_NAMESPACE_OFFICE_EXT);
+        }
+
         GetTextParagraphExport()->SetBlockMode( bBlock );
 
         const SfxPoolItem* pItem;
diff --git a/sw/source/ui/app/appopt.cxx b/sw/source/ui/app/appopt.cxx
index d9afcb3..db0f26d 100644
--- a/sw/source/ui/app/appopt.cxx
+++ b/sw/source/ui/app/appopt.cxx
@@ -504,6 +504,7 @@ SfxTabPage* SwModule::CreateTabPage( sal_uInt16 nId, Window* pParent, const SfxI
         case RID_SW_TP_OPTSHDWCRSR:
         case RID_SW_TP_HTML_OPTSHDWCRSR:
         case RID_SW_TP_REDLINE_OPT:
+        case RID_SW_TP_COMPARISON_OPT:
         case RID_SW_TP_OPTLOAD_PAGE:
         case RID_SW_TP_OPTCOMPATIBILITY_PAGE:
         case RID_SW_TP_MAILCONFIG:
diff --git a/sw/source/ui/app/docsh.cxx b/sw/source/ui/app/docsh.cxx
index 6f5a902..bf2487d 100644
--- a/sw/source/ui/app/docsh.cxx
+++ b/sw/source/ui/app/docsh.cxx
@@ -507,6 +507,9 @@ sal_Bool SwDocShell::SaveAs( SfxMedium& rMedium )
         pDoc->SetOle2Link( aOldOLELnk );
 
         SW_MOD()->SetEmbeddedLoadSave( sal_False );
+
+        // Increase RSID
+        pDoc->setRsid( pDoc->getRsid() );
     }
     SetError( nErr ? nErr : nVBWarning, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
 
diff --git a/sw/source/ui/app/swmodul1.cxx b/sw/source/ui/app/swmodul1.cxx
index ff2d3a8..ccd38e1 100644
--- a/sw/source/ui/app/swmodul1.cxx
+++ b/sw/source/ui/app/swmodul1.cxx
@@ -655,4 +655,44 @@ void SwModule::ApplyDefaultPageMode(sal_Bool bIsSquaredPageMode)
     pUsrPref->SetDefaultPageMode(bIsSquaredPageMode);
 }
 
+SvxCompareMode SwModule::GetCompareMode() const
+{
+    return pModuleConfig->GetCompareMode();
+}
+
+void SwModule::SetCompareMode( SvxCompareMode eMode )
+{
+    pModuleConfig->SetCompareMode( eMode );
+}
+
+sal_Bool SwModule::IsUseRsid() const
+{
+    return pModuleConfig->IsUseRsid();
+}
+
+void SwModule::SetUseRsid( sal_Bool b )
+{
+    pModuleConfig->SetUseRsid( b );
+}
+
+sal_Bool SwModule::IsIgnorePieces() const
+{
+    return pModuleConfig->IsIgnorePieces();
+}
+
+void SwModule::SetIgnorePieces( sal_Bool b )
+{
+    pModuleConfig->SetIgnorePieces( b );
+}
+
+sal_uInt16 SwModule::GetPieceLen() const
+{
+    return pModuleConfig->GetPieceLen();
+}
+
+void SwModule::SetPieceLen( sal_uInt16 nLen )
+{
+    pModuleConfig->SetPieceLen( nLen );
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/config/modcfg.cxx b/sw/source/ui/config/modcfg.cxx
index bb23c61..af6d328 100644
--- a/sw/source/ui/config/modcfg.cxx
+++ b/sw/source/ui/config/modcfg.cxx
@@ -1332,4 +1332,84 @@ void SwMiscConfig::Load()
     }
 }
 
+const Sequence<OUString>& SwCompareConfig::GetPropertyNames()
+{
+    static Sequence<OUString> aNames;
+    if(!aNames.getLength())
+    {
+        const int nCount = 4;
+        aNames.realloc(nCount);
+        static const char* aPropNames[] =
+        {
+            "Mode",							// 0
+            "UseRSID",						// 1
+            "IgnorePieces",				// 2
+            "IgnoreLength"					// 3
+        };
+        OUString* pNames = aNames.getArray();
+        for(int i = 0; i < nCount; i++)
+            pNames[i] = OUString::createFromAscii(aPropNames[i]);
+    }
+    return aNames;
+}
+
+SwCompareConfig::SwCompareConfig() :
+    ConfigItem(C2U("Office.Writer/Comparison"),
+        CONFIG_MODE_DELAYED_UPDATE|CONFIG_MODE_RELEASE_TREE)
+{
+    eCmpMode = SVX_CMP_AUTO;
+    bUseRsid = 0;
+    bIgnorePieces = 0;
+    nPieceLen = 1;
+
+    Load();
+}
+
+SwCompareConfig::~SwCompareConfig()
+{
+}
+
+void SwCompareConfig::Commit()
+{
+    const Sequence<OUString>& aNames = GetPropertyNames();
+    Sequence<Any> aValues(aNames.getLength());
+    Any* pValues = aValues.getArray();
+
+   const Type& rType = ::getBooleanCppuType();
+
+    pValues[0] <<= (sal_Int32) eCmpMode;
+    pValues[1].setValue(&bUseRsid, rType);
+    pValues[2].setValue(&bIgnorePieces, rType);
+    pValues[3] <<= (sal_Int32) nPieceLen;
+
+    PutProperties(aNames, aValues);
+}
+
+void SwCompareConfig::Load()
+{
+    const Sequence<OUString>& aNames = GetPropertyNames();
+    Sequence<Any> aValues = GetProperties(aNames);
+    const Any* pValues = aValues.getConstArray();
+    DBG_ASSERT(aValues.getLength() == aNames.getLength(), "GetProperties failed");
+    if(aValues.getLength() == aNames.getLength())
+    {
+        for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+        {
+            if(pValues[nProp].hasValue())
+            {
+                sal_Int32 nVal = 0;
+                pValues[nProp] >>= nVal;
+
+                switch(nProp)
+                {
+                    case 0 : eCmpMode = (SvxCompareMode) nVal; break;;
+                    case 1 : bUseRsid = *(sal_Bool*)pValues[nProp].getValue(); break;
+                    case 2 : bIgnorePieces = *(sal_Bool*)pValues[nProp].getValue(); break;
+                    case 3 : nPieceLen = nVal; break;
+                }
+            }
+        }
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/config/optdlg.hrc b/sw/source/ui/config/optdlg.hrc
index 8c19a5f..9906d5c 100644
--- a/sw/source/ui/config/optdlg.hrc
+++ b/sw/source/ui/config/optdlg.hrc
@@ -180,3 +180,11 @@
 #define CB_MATH_BASELINE_ALIGNMENT    16
 
 
+#define FL_CMP						141
+#define RB_AUTO						142
+#define RB_WORD						143
+#define RB_CHAR						144
+#define FL_SET						145
+#define CB_RSID						146
+#define CB_IGNORE					147
+#define NF_LEN						148
diff --git a/sw/source/ui/config/optdlg.src b/sw/source/ui/config/optdlg.src
old mode 100644
new mode 100755
index c475948..1fd1ae2
--- a/sw/source/ui/config/optdlg.src
+++ b/sw/source/ui/config/optdlg.src
@@ -882,3 +882,77 @@ StringArray STR_PRINTOPTUI
     };
 };
 
+
+/**************************************************************************/
+/*                                                                        */
+/* 	TabPage Comparison                                           		  */
+/*                                                                        */
+/**************************************************************************/
+TabPage TP_COMPARISON_OPT
+{
+    HelpID = HID_COMPARISON_OPT;
+    SVLook = TRUE ;
+    Hide = TRUE;
+    Size = MAP_APPFONT ( 260 , 185 );
+    FixedLine FL_CMP
+    {
+        Pos = MAP_APPFONT ( 6 , 3 ) ;
+        Size = MAP_APPFONT ( 248 , 8 ) ;
+        Text [ en-US ] = "Compare documents";
+    };
+    RadioButton RB_AUTO
+    {
+        Pos = MAP_APPFONT ( 12 , 14 ) ;
+        Size = MAP_APPFONT ( 70 , 10 ) ;
+        Text [ en-US ] = "~Auto";
+        TabStop = TRUE ;
+        Group = TRUE ;
+    };
+    RadioButton RB_WORD
+    {
+        Pos = MAP_APPFONT ( 12 , 27 ) ;
+        Size = MAP_APPFONT ( 70 , 10 ) ;
+        Text [ en-US ] = "By ~word";
+    };
+    RadioButton RB_CHAR
+    {
+        Pos = MAP_APPFONT ( 12 , 40 ) ;
+        Size = MAP_APPFONT ( 70 , 10 ) ;
+        Text [ en-US ] = "By ~character";
+    };
+    FixedLine FL_SET
+    {
+        Pos = MAP_APPFONT ( 6 , 56 ) ;
+        Size = MAP_APPFONT ( 248 , 8 ) ;
+        Text [ en-US ] = "Settings";
+    };
+    CheckBox CB_RSID
+    {
+        Pos = MAP_APPFONT ( 12 , 69 ) ;
+        Size = MAP_APPFONT ( 70 , 10 ) ;
+        Text [ en-US ] = "Use ~RSID";
+        TabStop = TRUE ;
+        Group = TRUE ;
+    };
+    CheckBox CB_IGNORE
+    {
+        Pos = MAP_APPFONT ( 12 , 82 ) ;
+        Size = MAP_APPFONT ( 70 , 10 ) ;
+        Text [ en-US ] = "Ignore ~pieces of length";
+    };
+    NumericField NF_LEN
+    {
+        Pos = MAP_APPFONT ( 100 , 80 ) ;
+        Size = MAP_APPFONT ( 25 , 12 ) ;
+        Border = TRUE ;
+        Left = TRUE ;
+        First = 1 ;
+        Minimum = 1 ;
+        Maximum = 99;
+        Repeat = TRUE ;
+        Spin = TRUE ;
+        SpinSize = 1 ;
+        StrictFormat = TRUE ;
+        TabStop = TRUE ;
+    };
+};
diff --git a/sw/source/ui/config/optpage.cxx b/sw/source/ui/config/optpage.cxx
old mode 100644
new mode 100755
index c8be2e2..37f03bc
--- a/sw/source/ui/config/optpage.cxx
+++ b/sw/source/ui/config/optpage.cxx
@@ -68,6 +68,7 @@
 #include <editeng/fhgtitem.hxx>
 #include <editeng/fontitem.hxx>
 #include <editeng/langitem.hxx>
+#include <editeng/svxenum.hxx>
 #include <sfx2/request.hxx>
 #include <sfx2/printer.hxx>
 #include <sfx2/bindings.hxx>
@@ -1729,6 +1730,139 @@ void SwRedlineOptionsTabPage::InitFontStyle(SvxFontPrevWindow& rExampleWin)
 }
 
 
+//----------------------------------------------------------
+SwCompareOptionsTabPage::SwCompareOptionsTabPage(  Window* pParent, const SfxItemSet& rSet )
+    : SfxTabPage( pParent, SW_RES( TP_COMPARISON_OPT ), rSet ),
+
+    aComparisonFL(	this, SW_RES( FL_CMP ) ),
+    aAutoRB(		this, SW_RES( RB_AUTO ) ),
+    aWordRB(		this, SW_RES( RB_WORD ) ),
+    aCharRB(		this, SW_RES( RB_CHAR ) ),
+    aSettingsFL(	this, SW_RES( FL_SET ) ),
+    aRsidCB(		this, SW_RES( CB_RSID) ),
+    aIgnoreCB(		this, SW_RES( CB_IGNORE ) ),
+    aLenNF(			this, SW_RES( NF_LEN ) )
+{
+    FreeResource();
+    Link aLnk( LINK( this, SwCompareOptionsTabPage, ComparisonHdl ) );
+    aAutoRB.SetClickHdl( aLnk );
+    aWordRB.SetClickHdl( aLnk );
+    aCharRB.SetClickHdl( aLnk );
+
+    aIgnoreCB.SetClickHdl( LINK( this, SwCompareOptionsTabPage, IgnoreHdl) );
+}
+
+SwCompareOptionsTabPage::~SwCompareOptionsTabPage()
+{
+}
+
+SfxTabPage* SwCompareOptionsTabPage::Create( Window* pParent, const SfxItemSet& rAttrSet )
+{
+    return new SwCompareOptionsTabPage( pParent, rAttrSet );
+}
+
+sal_Bool SwCompareOptionsTabPage::FillItemSet( SfxItemSet& )
+{
+    sal_Bool bRet = sal_False;
+    SwModuleOptions *pOpt = SW_MOD()->GetModuleConfig();
+
+    if( aAutoRB.IsChecked() != aAutoRB.GetSavedValue() ||
+        aWordRB.IsChecked() != aWordRB.GetSavedValue() ||
+        aCharRB.IsChecked() != aCharRB.GetSavedValue() )
+    {
+        SvxCompareMode eCmpMode;
+
+        if ( aAutoRB.IsChecked() ) eCmpMode = SVX_CMP_AUTO;
+        if ( aWordRB.IsChecked() ) eCmpMode = SVX_CMP_BY_WORD;
+        if ( aCharRB.IsChecked() ) eCmpMode = SVX_CMP_BY_CHAR;
+
+        pOpt->SetCompareMode( eCmpMode );
+        bRet = sal_True;
+    }
+
+    if( aRsidCB.IsChecked() != aRsidCB.GetSavedValue() )
+    {
+        pOpt->SetUseRsid( aRsidCB.IsChecked() );
+        bRet = sal_True;
+    }
+
+    if( aIgnoreCB.IsChecked() != aIgnoreCB.GetSavedValue() )
+    {
+        pOpt->SetIgnorePieces( aIgnoreCB.IsChecked() );
+        bRet = sal_True;
+    }
+
+    if( aLenNF.IsModified() )
+    {
+        pOpt->SetPieceLen( aLenNF.GetValue() );
+        bRet = sal_True;
+    }
+
+    return bRet;
+}
+
+void SwCompareOptionsTabPage::Reset( const SfxItemSet& )
+{
+    SwModuleOptions *pOpt = SW_MOD()->GetModuleConfig();
+
+    SvxCompareMode eCmpMode = pOpt->GetCompareMode();
+    if( eCmpMode == SVX_CMP_AUTO )
+    {
+        aAutoRB.Check();
+        aSettingsFL.Disable();
+        aRsidCB.Disable();
+        aIgnoreCB.Disable();
+        aLenNF.Disable();
+    }
+    else if( eCmpMode == SVX_CMP_BY_WORD )
+    {
+        aWordRB.Check();
+        aSettingsFL.Enable();
+        aRsidCB.Enable();
+        aIgnoreCB.Enable();
+        aLenNF.Enable();
+    }
+    else if( eCmpMode == SVX_CMP_BY_CHAR)
+    {
+        aCharRB.Check();
+        aSettingsFL.Enable();
+        aRsidCB.Enable();
+        aIgnoreCB.Enable();
+        aLenNF.Enable();
+    }
+    aAutoRB.SaveValue();
+    aWordRB.SaveValue();
+    aCharRB.SaveValue();
+
+    aRsidCB.Check( pOpt->IsUseRsid() );
+    aRsidCB.SaveValue();
+
+    aIgnoreCB.Check( pOpt->IsIgnorePieces() );
+    aIgnoreCB.SaveValue();
+
+    aLenNF.Enable( aIgnoreCB.IsChecked() && eCmpMode );
+
+    aLenNF.SetValue( pOpt->GetPieceLen() );
+    aLenNF.SaveValue();
+}
+
+IMPL_LINK( SwCompareOptionsTabPage, ComparisonHdl, RadioButton*, EMPTYARG )
+{
+    bool bChecked = !aAutoRB.IsChecked();
+    aSettingsFL.Enable( bChecked );
+    aRsidCB.Enable( bChecked );
+    aIgnoreCB.Enable( bChecked );
+    aLenNF.Enable( bChecked && aIgnoreCB.IsChecked() );
+
+    return 0;
+}
+
+IMPL_LINK( SwCompareOptionsTabPage, IgnoreHdl, CheckBox*, EMPTYARG )
+{
+    aLenNF.Enable( aIgnoreCB.IsChecked() );
+    return 0;
+}
+
 #ifdef DBG_UTIL
 
 void lcl_SetPosSize(Window& rWin, Point aPos, Size aSize)
@@ -1863,6 +1997,8 @@ IMPL_LINK_INLINE_START( SwTestTabPage, AutoClickHdl, CheckBox *, EMPTYARG )
     return 0;
 }
 IMPL_LINK_INLINE_END( SwTestTabPage, AutoClickHdl, CheckBox *, EMPTYARG )
+
+
 #endif
 
 
diff --git a/sw/source/ui/dialog/swdlgfact.cxx b/sw/source/ui/dialog/swdlgfact.cxx
index a31db0d..0edd38c 100644
--- a/sw/source/ui/dialog/swdlgfact.cxx
+++ b/sw/source/ui/dialog/swdlgfact.cxx
@@ -1612,6 +1612,7 @@ GlossarySetActGroup SwAbstractDialogFactory_Impl::SetGlossaryActGroupFunc( sal_u
     return 0;
 }
 
+
 //------------------ Factories for TabPages
 CreateTabPage SwAbstractDialogFactory_Impl::GetTabPageCreatorFunc( sal_uInt16 nId )
 {
@@ -1665,6 +1666,10 @@ CreateTabPage SwAbstractDialogFactory_Impl::GetTabPageCreatorFunc( sal_uInt16 nI
         case RID_SW_TP_MAILCONFIG:
             pRet = SwMailConfigPage::Create;
         break;
+        case RID_SW_TP_COMPARISON_OPT :
+        case TP_COMPARISON_OPT :
+            pRet = SwCompareOptionsTabPage::Create;
+        break;
     }
 
     return pRet;
diff --git a/sw/source/ui/inc/optpage.hxx b/sw/source/ui/inc/optpage.hxx
index 3824419..fd66d03 100644
--- a/sw/source/ui/inc/optpage.hxx
+++ b/sw/source/ui/inc/optpage.hxx
@@ -45,6 +45,7 @@ class SvStringsDtor;
 class SfxPrinter;
 class SwWrtShell;
 class FontList;
+class SwCompareConfig;
 
 class SwContentOptPage : public SfxTabPage
 {
@@ -396,5 +397,31 @@ private:
 };
 #endif // DBG_UTIL
 
+class SwCompareOptionsTabPage : public SfxTabPage
+{
+    FixedLine aComparisonFL;
+    RadioButton aAutoRB;
+    RadioButton aWordRB;
+    RadioButton aCharRB;
+
+    FixedLine aSettingsFL;
+    CheckBox aRsidCB;
+    CheckBox aIgnoreCB;
+    NumericField aLenNF;
+
+    SwCompareOptionsTabPage( Window* pParent, const SfxItemSet& rSet );
+    ~SwCompareOptionsTabPage();
+
+    DECL_LINK( ComparisonHdl, RadioButton *pRB);
+    DECL_LINK( IgnoreHdl, CheckBox *pCB);
+
+public:
+
+    static SfxTabPage*	Create( Window* pParent, const SfxItemSet& rAttrSet );
+
+    virtual	sal_Bool    FillItemSet( SfxItemSet& rSet );
+    virtual	void 		Reset( const SfxItemSet& rSet );
+};
+
 #endif
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/uno/SwXDocumentSettings.cxx b/sw/source/ui/uno/SwXDocumentSettings.cxx
index a56f584..2711275 100644
--- a/sw/source/ui/uno/SwXDocumentSettings.cxx
+++ b/sw/source/ui/uno/SwXDocumentSettings.cxx
@@ -115,6 +115,8 @@ enum SwDocumentSettingsPropertyHandles
     HANDLE_USE_OLD_PRINTER_METRICS,
     HANDLE_PROTECT_FORM,
     HANDLE_TABS_RELATIVE_TO_INDENT,
+    HANDLE_RSID,
+    HANDLE_RSID_ROOT,
     // #i89181#
     HANDLE_TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST,
     HANDLE_MODIFYPASSWORDINFO,
@@ -174,6 +176,8 @@ MasterPropertySetInfo * lcl_createSettingsInfo()
         { RTL_CONSTASCII_STRINGPARAM("UnxForceZeroExtLeading"), HANDLE_UNIX_FORCE_ZERO_EXT_LEADING, CPPUTYPE_BOOLEAN, 0, 0},
         { RTL_CONSTASCII_STRINGPARAM("UseOldPrinterMetrics"), HANDLE_USE_OLD_PRINTER_METRICS, CPPUTYPE_BOOLEAN, 0, 0},
         { RTL_CONSTASCII_STRINGPARAM("TabsRelativeToIndent"), HANDLE_TABS_RELATIVE_TO_INDENT, CPPUTYPE_BOOLEAN, 0, 0},
+        { RTL_CONSTASCII_STRINGPARAM("Rsid"), HANDLE_RSID, CPPUTYPE_INT32, 0, 0},
+        { RTL_CONSTASCII_STRINGPARAM("RsidRoot"), HANDLE_RSID_ROOT, CPPUTYPE_INT32, 0, 0},
         { RTL_CONSTASCII_STRINGPARAM("ProtectForm"), HANDLE_PROTECT_FORM, CPPUTYPE_BOOLEAN, 0, 0},
         // #i89181#
         { RTL_CONSTASCII_STRINGPARAM("TabAtLeftIndentForParagraphsInList"), HANDLE_TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST, CPPUTYPE_BOOLEAN, 0, 0},
@@ -657,6 +661,20 @@ void SwXDocumentSettings::_setSingleValue( const comphelper::PropertyInfo & rInf
             mpDoc->set(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT, bTmp);
         }
         break;
+        case HANDLE_RSID:
+        {
+            sal_uInt32 nTmp = 0;
+            rValue >>= nTmp;
+            mpDoc->setRsid( nTmp );
+        }
+        break;
+        case HANDLE_RSID_ROOT:
+        {
+            sal_uInt32 nTmp = 0;
+            rValue >>= nTmp;
+            mpDoc->setRsidRoot( nTmp );
+        }
+        break;
         case HANDLE_PROTECT_FORM:
         {
             sal_Bool bTmp = *(sal_Bool*)rValue.getValue();
@@ -1029,6 +1047,16 @@ void SwXDocumentSettings::_getSingleValue( const comphelper::PropertyInfo & rInf
             rValue.setValue( &bTmp, ::getBooleanCppuType() );
         }
         break;
+        case HANDLE_RSID:
+        {
+            rValue <<= static_cast < sal_Int32 > ( mpDoc->getRsid() );
+        }
+        break;
+        case HANDLE_RSID_ROOT:
+        {
+            rValue <<= static_cast < sal_Int32 > ( mpDoc->getRsidRoot() );
+        }
+        break;
         case HANDLE_PROTECT_FORM:
         {
             sal_Bool bTmp = mpDoc->get(IDocumentSettingAccess::PROTECT_FORM);
diff --git a/xmloff/inc/xmloff/xmltoken.hxx b/xmloff/inc/xmloff/xmltoken.hxx
index b609dad..3a07e30 100644
--- a/xmloff/inc/xmloff/xmltoken.hxx
+++ b/xmloff/inc/xmloff/xmltoken.hxx
@@ -1498,6 +1498,8 @@ namespace xmloff { namespace token {
         XML_ROW_HEIGHT,
         XML_ROW_NUMBER,
         XML_ROWS,
+        XML_RSID,
+        XML_PARRSID,
         XML_RUBY,
         XML_RUBY_ALIGN,
         XML_RUBY_BASE,
diff --git a/xmloff/inc/xmloff/xmltypes.hxx b/xmloff/inc/xmloff/xmltypes.hxx
index 922ad3f..9aee08b 100644
--- a/xmloff/inc/xmloff/xmltypes.hxx
+++ b/xmloff/inc/xmloff/xmltypes.hxx
@@ -152,6 +152,7 @@
 #define XML_TYPE_NEG_PERCENT8       0x00002022          // (100-x)%
 #define XML_TYPE_NEG_PERCENT16      0x00002023          // (100-x)
 #define XML_TYPE_DOUBLE_PERCENT     0x00002024          //  50% (source is a double from 0.0 to 1.0)
+#define XML_TYPE_HEX				0x00002025			// 00544F1B
 
 // special basic types
 #define XML_TYPE_RECTANGLE_LEFT     0x00000100          // the Left member of a awt::Rectangle as a measure
diff --git a/xmloff/inc/xmloff/xmluconv.hxx b/xmloff/inc/xmloff/xmluconv.hxx
index 003fe8c..7e9a460 100644
--- a/xmloff/inc/xmloff/xmluconv.hxx
+++ b/xmloff/inc/xmloff/xmluconv.hxx
@@ -247,6 +247,13 @@ public:
 
     ::rtl::OUString encodeStyleName( const ::rtl::OUString& rName,
                                      sal_Bool *pEncoded=0 ) const;
+    /** convert string (hex) to number (sal_uInt32) */
+    static sal_Bool convertHex( sal_uInt32& nVal,
+                              const ::rtl::OUString& rValue );
+
+    /** convert number (sal_uInt32) to string (hex) */
+    static void convertHex( ::rtl::OUStringBuffer& rBuffer,
+                               sal_uInt32 nVal );
 
 };
 
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index 02970eb..9ccc67f 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -1503,6 +1503,8 @@ namespace xmloff { namespace token {
         TOKEN( "row-height",                      XML_ROW_HEIGHT ),
         TOKEN( "row-number",                      XML_ROW_NUMBER ),
         TOKEN( "rows",                            XML_ROWS ),
+        TOKEN( "rsid",                            XML_RSID ),
+        TOKEN( "paragraph-rsid",                  XML_PARRSID ),
         TOKEN( "ruby",                            XML_RUBY ),
         TOKEN( "ruby-align",                      XML_RUBY_ALIGN ),
         TOKEN( "ruby-base",                       XML_RUBY_BASE ),
diff --git a/xmloff/source/core/xmluconv.cxx b/xmloff/source/core/xmluconv.cxx
index 6ceb885..3ec1a49 100644
--- a/xmloff/source/core/xmluconv.cxx
+++ b/xmloff/source/core/xmluconv.cxx
@@ -931,4 +931,32 @@ OUString SvXMLUnitConverter::encodeStyleName(
     return aBuffer.makeStringAndClear();
 }
 
+/** convert string (hex) to number (sal_uInt32) */
+sal_Bool SvXMLUnitConverter::convertHex( sal_uInt32& nVal,
+                                       const OUString& rValue )
+{
+    if( rValue.getLength() != 8 )
+        return sal_False;
+
+    nVal = 0;
+    for ( int i = 0; i < 8; i++ )
+    {
+        nVal = ( nVal << 4 )
+            | sal::static_int_cast< sal_uInt32 >( lcl_gethex( rValue[i] ) );
+    }
+
+    return sal_True;
+}
+
+/** convert number (sal_uInt32) to string (hex) */
+void SvXMLUnitConverter::convertHex( OUStringBuffer& rBuffer,
+                                        sal_uInt32 nVal )
+{
+    for ( int i = 0; i < 8; i++ )
+    {
+        rBuffer.append( sal_Unicode( aHexTab[ nVal >> 28 ] ) );
+        nVal <<= 4;
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/style/prhdlfac.cxx b/xmloff/source/style/prhdlfac.cxx
index 9e258e8..a2d2ea1 100644
--- a/xmloff/source/style/prhdlfac.cxx
+++ b/xmloff/source/style/prhdlfac.cxx
@@ -210,6 +210,9 @@ const XMLPropertyHandler* XMLPropertyHandlerFactory::CreatePropertyHandler( sal_
         case XML_TYPE_COLOR :
             pPropHdl = new XMLColorPropHdl;
             break;

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list