Commits

t...@openoffice.org  committed 8b564af

CWS writercompare01: #i110237# the changes from Tzvetelina as-is

  • Participants
  • Parent commits 8565218

Comments (0)

Files changed (52)

File cui/source/options/treeopt.cxx

     { "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 },

File cui/source/options/treeopt.src

 	        < "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 ; >;

File editeng/inc/editeng/svxenum.hxx

 	SVX_NUM_CHARS_LOWER_LETTER_N
 };
 
+enum SvxCompareMode
+{
+	SVX_CMP_AUTO = 0,
+	SVX_CMP_BY_WORD,
+	SVX_CMP_BY_CHAR
+};
 
 #endif

File editeng/source/items/textitem.cxx

 #include <com/sun/star/lang/Locale.hpp>
 #include <com/sun/star/text/FontEmphasis.hpp>
 #include <com/sun/star/i18n/ScriptType.hpp>
+#include <svx/rsiditem.hxx>
 #include <editeng/memberids.hrc>
 #include <editeng/flstitem.hxx>
 #include <editeng/fontitem.hxx>
 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 );
 
     }
     return 0;
 }
+
+// class SvxRsidItem -----------------------------------------------------
+
+sal_Bool SvxRsidItem::QueryValue( uno::Any& rVal, BYTE nMemberId ) const
+{
+	rVal <<= ( (UINT32)GetValue() );
+  	return sal_True;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool SvxRsidItem::PutValue( const uno::Any& rVal, BYTE nMemberId )
+{
+	UINT32 nRsid = 0;
+	if( !( rVal >>= nRsid ) )
+		return sal_False;
+
+	SetValue( nRsid );
+	return sal_True;
+}
+
+// -----------------------------------------------------------------------
+
+SfxPoolItem* SvxRsidItem::Clone( SfxItemPool * ) const
+{
+	return new SvxRsidItem( *this );
+}
+
+// -----------------------------------------------------------------------
+
+SfxPoolItem* SvxRsidItem::Create(SvStream& rIn, USHORT nVer) const
+{
+	return new SvxRsidItem( rIn, Which() );
+}
+

File officecfg/registry/schema/org/openoffice/Office/Writer.xcs

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

File svx/inc/svx/dialogs.hrc

 #define	RID_OFA_TP_INTERNATIONAL_SD		(RID_OFA_START + 253)	
 #define	RID_OFA_TP_INTERNATIONAL_IMPR	(RID_OFA_START + 254)	
 #define	RID_OFA_TP_INTERNATIONAL		(RID_OFA_START + 252) // calc
+#define RID_SW_TP_COMPARISON_OPT		(RID_OFA_START + 253)
 
 //---------------------------------------------------------------------
 // ResId's fuer die Zeichen-TabPages

File svx/inc/svx/rsiditem.hxx

+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: rsiditem.hxx,v $
+ * $Revision: 1.0 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+ 
+#ifndef _SVX_RSIDITEM_HXX
+#define _SVX_RSIDITEM_HXX
+
+#include <svtools/intitem.hxx>
+#include <svx/svddef.hxx>
+#include "svx/svxdllapi.h"
+
+//----------------------
+// SvxRsidItem 
+//----------------------
+
+class SVX_DLLPUBLIC SvxRsidItem : public SfxUInt32Item
+{
+public:
+	TYPEINFO();
+
+	SvxRsidItem( UINT32 nRsid, USHORT nId ) : SfxUInt32Item( nId, nRsid ) {}
+	SvxRsidItem( SvStream& rIn, USHORT nId ) : SfxUInt32Item( nId, rIn ) {}
+
+	virtual SfxPoolItem* Clone( SfxItemPool* pPool = NULL ) const;
+	virtual SfxPoolItem* Create( SvStream& rIn, USHORT nVer ) const;
+
+	virtual sal_Bool QueryValue( com::sun::star::uno::Any& rVal, BYTE nMemberId = 0 ) const;
+	virtual sal_Bool PutValue( const com::sun::star::uno::Any& rVal, BYTE nMemberId = 0 );
+};
+
+#endif // _SVX_RSIDITEM_HXX

File svx/prj/d.lst

 ..\inc\svx\view3d.hxx %_DEST%\inc%_EXT%\svx\view3d.hxx
 ..\inc\svx\viewpt3d.hxx %_DEST%\inc%_EXT%\svx\viewpt3d.hxx
 ..\inc\svx\wghtitem.hxx %_DEST%\inc%_EXT%\svx\wghtitem.hxx
+..\inc\svx\rsiditem.hxx %_DEST%\inc%_EXT%\svx\rsiditem.hxx
 ..\inc\svx\widwitem.hxx %_DEST%\inc%_EXT%\svx\widwitem.hxx
 ..\inc\svx\wrlmitem.hxx %_DEST%\inc%_EXT%\svx\wrlmitem.hxx
 ..\inc\svx\xbitmap.hxx %_DEST%\inc%_EXT%\svx\xbitmap.hxx

File sw/inc/cmdid.h

 // --> OD 2004-10-28 #i36248#
 #define FN_SHAPE_STARTPOSITION_IN_HORI_L2R (FN_PARAM2+25)
 #define FN_SHAPE_ENDPOSITION_IN_HORI_L2R   (FN_PARAM2+26)
-
 // <--
 /*--------------------------------------------------------------------
 	Bereich: Druckoptionen

File sw/inc/doc.hxx

 	RedlineMode_t eRedlineMode;		// aktueller Redline Modus
 	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;		// Wenn != 0 hat UpdateExpFlds() keine Wirkung
     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
     */
 	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, 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,

File sw/inc/globals.hrc

 #define TP_SECTION_INDENTS          (RC_GLOBALS_BEGIN +  102)
 #define TP_OPTCOMPATIBILITY_PAGE	(RC_GLOBALS_BEGIN +  103)
 #define TP_MAILCONFIG               (RC_GLOBALS_BEGIN +  104)
+#define TP_COMPARISON_OPT           (RC_GLOBALS_BEGIN +  105)
 //maximum: RC_GLOBALS_BEGIN +  119
 
 #if STR_DOC_STAT > RC_GLOBALS_END

File sw/inc/helpid.h

 #define HID_TEXTGRID_PAGE				(HID_BASE + 482)
 #define HID_OPTCOMPATIBILITY_PAGE		(HID_BASE + 483)
 #define HID_COMPATIBILITY_OPTIONS_BOX	(HID_BASE + 484)
+#define HID_COMPARISON_OPT				(HID_BASE + 485)
 
 // AutoPilot Help-IDs *********************************************************
 

File sw/inc/hintids.hxx

 	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
 };
 
     RES_PARATR_SNAPTOGRID,                          // 72
     RES_PARATR_CONNECT_BORDER,                      // 73
     RES_PARATR_OUTLINELEVEL,                        // 74
+    RES_PARATR_RSID,								// 75
 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_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
     // OD 18.09.2003 #i18732# - insert new item and 5 dummies
-    RES_FOLLOW_TEXT_FLOW,                           // 115
+    RES_FOLLOW_TEXT_FLOW,                           // 116
 // --> collapsing borders FME 2005-05-27 #i29550#
-    RES_COLLAPSING_BORDERS,                         // 116
+    RES_COLLAPSING_BORDERS,                         // 117
 // <-- collapsing
     // OD 2004-05-04 #i28701# - use dummy1 for new item
-    RES_WRAP_INFLUENCE_ON_OBJPOS,                   // 117
-    RES_AUTO_STYLE,                                 // 118
-    RES_FRMATR_STYLE_NAME,                          // 119
-    RES_FRMATR_CONDITIONAL_STYLE_NAME,              // 120
+    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_MIRRORGRF = RES_GRFATR_BEGIN,        // 122
+    RES_GRFATR_CROPGRF,                             // 123
 
-    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_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,                              // 133
-    RES_GRFATR_DUMMY2,                              // 134
-    RES_GRFATR_DUMMY3,                              // 135
-    RES_GRFATR_DUMMY4,                              // 136
-    RES_GRFATR_DUMMY5,                              // 137
+    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
 };
 

File sw/inc/modcfg.hxx

 #include "tblenum.hxx"
 #include "itabenum.hxx"
 #include <tools/globname.hxx>
+#include <svx/svxenum.hxx>
 class SwModuleOptions;
 
 //-----------------------------------------------------------------------------
 	void					Load();
 	void 					SetModified(){ConfigItem::SetModified();}
 };
+/* ---------------------------------------------------------------------------
 
+ ---------------------------------------------------------------------------*/
+class SwCompareConfig : public utl::ConfigItem
+{
+	friend class SwModuleOptions;
+	
+	USHORT	   eCmpMode;		//Compare/CompareDocuments;
+	sal_Bool		bUseRsid;		//Compare/Settings/Use RSID
+	sal_Bool		bIgnorePieces;	//Compare/Settings/Ignore pieces of length
+	USHORT		nPieceLen;		//Compare/Settings/Ignore pieces of length
+
+	const com::sun::star::uno::Sequence<rtl::OUString>& GetPropertyNames();
+	public:
+		SwCompareConfig();
+		~SwCompareConfig();
+
+	virtual void			Commit();
+	void					Load();
+	void 					SetModified() {ConfigItem::SetModified(); }
+};
 /* ---------------------------------------------------------------------------
 
  ---------------------------------------------------------------------------*/
 	SwTableConfig					aWebTableConfig;
 
 	SwMiscConfig					aMiscConfig;
+	
+	SwCompareConfig					aCompareConfig;
 
 	//fiscus: don't show tips of text fields - it's not part of the configuration!
 	BOOL 		bHideFieldTips : 1;
 
 	BOOL 		IsHideFieldTips() const {return bHideFieldTips;}
 	void		SetHideFieldTips(BOOL bSet) {bHideFieldTips = bSet;}
+	
+	SvxCompareMode	GetCompareMode() const				{ return (SvxCompareMode)aCompareConfig.eCmpMode; }
+	void			SetCompareMode( SvxCompareMode eMode )		{ aCompareConfig.eCmpMode = eMode; 
+															aCompareConfig.SetModified(); }
+
+	BOOL			IsUseRsid() const					{ return aCompareConfig.bUseRsid; }
+	void			SetUseRsid( BOOL b )					{ aCompareConfig.bUseRsid = b; 
+															aCompareConfig.SetModified(); }
+
+	BOOL			IsIgnorePieces() const				{ return aCompareConfig.bIgnorePieces; }
+	void			SetIgnorePieces( BOOL b )			{ aCompareConfig.bIgnorePieces = b; 
+															aCompareConfig.SetModified(); }
+
+	USHORT			GetPieceLen() const					{ return aCompareConfig.nPieceLen; }
+	void			SetPieceLen( USHORT nLen )			{ aCompareConfig.nPieceLen = nLen; 
+															aCompareConfig.SetModified(); }
+																			
+	
 };
 #endif
 

File sw/inc/ndtxt.hxx

     virtual ::com::sun::star::uno::Reference<
         ::com::sun::star::rdf::XMetadatable > MakeUnoObject();
 
+	UINT32 GetRsid( xub_StrLen nStt, xub_StrLen nEnd ) const;
+	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)
 };
 

File sw/inc/swmodule.hxx

 #include <fldupde.hxx>
 #include <com/sun/star/linguistic2/XLinguServiceEventListener.hpp>
 #include <com/sun/star/linguistic2/XLanguageGuessing.hpp>
+#include <svx/svxenum.hxx>
 
 class SvStringsDtor;
 class Color;
 	sal_uInt16				GetRedlineMarkPos();
 	const Color&			GetRedlineMarkColor();
 
+	SvxCompareMode		GetCompareMode() const;
+	void				SetCompareMode( SvxCompareMode eMode );
+	BOOL				IsUseRsid() const;
+	void				SetUseRsid( BOOL b );
+	BOOL				IsIgnorePieces() const;
+	void				SetIgnorePieces( BOOL b );
+	USHORT				GetPieceLen() const;
+	void				SetPieceLen( USHORT nLen );
+
 	// returne den definierten DocStat - WordDelimiter
 	const String&		GetDocStatWordDelim() const;
 

File sw/inc/undobj.hxx

 	xub_StrLen nCntnt;
 	BOOL bTblFlag : 1;
 	BOOL bChkTblStt : 1;
+	UINT32 nParRsid;
 public:
 	SwUndoSplitNode( SwDoc* pDoc, const SwPosition& rPos, BOOL bChkTbl );
 	virtual ~SwUndoSplitNode();

File sw/inc/unoprnms.hxx

 /* 0738 */  UNO_NAME_META,       // #i91565#
 /* 0739 */  UNO_NAME_IS_TEMPLATE,
 /* 0740 */  UNO_NAME_VBA_DOCOBJ,
-/* 0741 */  SW_PROPNAME_END
+/* 0741 */  UNO_NAME_RSID,
+/* 0742 */  UNO_NAME_PARRSID,
+/* 0743 */  SW_PROPNAME_END
 };
 
 

File sw/source/core/bastyp/init.cxx

 #include <fmtfollowtextflow.hxx>
 // OD 2004-05-05 #i28701#
 #include <fmtwrapinfluenceonobjpos.hxx>
+#include <svx/rsiditem.hxx>
 
 #include <fmtmeta.hxx>
 
 	{ 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
     { 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
 	// --> OD 2008-02-19 #refactorlists#
     { 0, SFX_ITEM_POOLABLE },                           // RES_PARATR_LIST_ID
     { 0, SFX_ITEM_POOLABLE },                           // RES_PARATR_LIST_LEVEL
     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( FALSE, RES_CHRATR_BLINK );
 
 // 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;
     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 );
+	
 	// --> OD 2008-02-19 #refactorlists#
     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 );

File sw/source/core/doc/doc.cxx

 #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>
 #include <sfx2/linkmgr.hxx>
 #include <editeng/forbiddencharacterstable.hxx>
 #include <svx/svdmodel.hxx>
+#include <svx/rsiditem.hxx>
 #include <unotools/charclass.hxx>
 #include <unotools/localedatawrapper.hxx>
 
     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;
         }
     }
 
+	// 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: Sonderfall fuer SplitNode am Tabellenanfang:
 	//				steht die am Doc/Fly/Footer/..-Anfang oder direkt
 	//				hinter einer Tabelle, dann fuege davor
 							pFrmFmt );
 }
 
+// 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, UINT32 nVal )
+{
+	if ( !pTxtNode )
+	{
+		return false;
+	}
+
+	SvxRsidItem aRsid( nVal ? nVal : nRsid, RES_PARATR_RSID );
+	return pTxtNode->SetAttr( aRsid );
+}
+
+
 /*************************************************************************
 |*				  SwDoc::GetFldType()
 |*	  Beschreibung: liefert den am Doc eingerichteten Feldtypen zurueck

File sw/source/core/doc/doccomp.cxx

 #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 <docary.hxx>
 #include <pam.hxx>
 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
 #include <com/sun/star/document/XDocumentProperties.hpp>
 
+#include <set>
+#include <cctype>
+
 using namespace ::com::sun::star;
 
 
 	Compare( 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() {}
 	{
 		if( rData.GetChanged( nStt1 ) || GetChanged( nStt2 ) )
 		{
+			// Find a region of different lines between two pairs of identical 
+			// lines.
 			ULONG nSav1 = nStt1, nSav2 = nStt2;
 			while( nStt1 < nLen1 && rData.GetChanged( nStt1 )) ++nStt1;
 			while( nStt2 < nLen2 && GetChanged( nStt2 )) ++nStt2;
 
-			// rData ist das Original,
-			// this ist das, in das die Veraenderungen sollen
-			if( nSav2 != nStt2 && nSav1 != nStt1 )
-				CheckForChangesInLine( rData, nSav1, nStt1, nSav2, nStt2 );
-
-			if( nSav2 != nStt2 )
-				ShowInsert( nSav2, nStt2 );
-
-			if( nSav1 != nStt1 )
-				ShowDelete( rData, nSav1, nStt1, nStt2 );
-			++nCnt;
+			// Check if there are changed lines (only slightly different) and
+			// compare them in detail.
+			CheckForChangesInLine( rData, nSav1, nStt1, nSav2, nStt2 );
+				
+			nCnt++;
 		}
 		++nStt1, ++nStt2;
 	}
+
 	return nCnt;
 }
 
 	delete pMD2;
 }
 
-
-
 void Compare::CountDifference( const CompareData& rData, ULONG* pCounts )
 {
 	ULONG nLen = rData.GetLineCount();
 	delete pIndex;
 	delete pLineNum;
 }
-
+ 
 // ----------------------------------------------------------------------
 
 	// Suche die verschobenen Lines
 	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:
 								  const SwTxtNode& rSrcNd )
 {
 	BOOL bRet = FALSE;
+
 	// erstmal ganz einfach!
 	if( rDstNd.GetTxt() == rSrcNd.GetTxt() )
 	{
 
 BOOL SwCompareLine::ChangesInLine( const SwCompareLine& rLine,
 							SwPaM *& rpInsRing, SwPaM*& rpDelRing ) const
-{
+{	
 	BOOL bRet = 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();
-
-		xub_StrLen nDEnd = rDestNd.GetTxt().Len(), nSEnd = rSrcNd.GetTxt().Len();
-		xub_StrLen nStt;
-		xub_StrLen nEnd;
-
-		for( nStt = 0, nEnd = Min( nDEnd, nSEnd ); nStt < nEnd; ++nStt )
-			if( rDestNd.GetTxt().GetChar( nStt ) !=
-				rSrcNd.GetTxt().GetChar( nStt ) )
-				break;
-
-		while( nStt < nDEnd && nStt < nSEnd )
+		SwDoc* pDstDoc = rDstNd.GetDoc();
+		
+		int nLcsLen = 0;
+
+		int nDstLen = rDstNd.GetTxt().Len();
+		int nSrcLen = rSrcNd.GetTxt().Len();
+
+		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( CmpOptions.nIgnoreLen )
+			{
+				nLcsLen = aSeq.IgnoreIsolatedPieces( pLcsDst, pLcsSrc, nDstLen, 
+													nSrcLen, nLcsLen, 
+													CmpOptions.nIgnoreLen );
 			}
 		}
-
-		if( nStt || !nDEnd || !nSEnd || nDEnd < rDestNd.GetTxt().Len() ||
-			nSEnd < rSrcNd.GetTxt().Len() )
+		
+		// find the sum of the squares of the continuous substrings
+		int nSqSum = 0;
+		int nCnt = 1;
+		for( int i = 0; i < nLcsLen; i++ )
 		{
-			// jetzt ist zwischen nStt bis nDEnd das neu eingefuegte
-			// und zwischen nStt und nSEnd das geloeschte
-			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 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 )
 			{
-				{
-					BOOL bUndo = pDoc->DoesUndo();
-					pDoc->DoUndo( FALSE );
-					SwPaM aCpyPam( rSrcNd, nStt );
-					aCpyPam.SetMark();
-					aCpyPam.GetPoint()->nContent = nSEnd;
-                    aCpyPam.GetDoc()->CopyRange( aCpyPam, *aPam.GetPoint(),
-                            false );
-					pDoc->DoUndo( bUndo );
-				}
-
-				SwPaM* pTmp = new SwPaM( *aPam.GetPoint(), rpDelRing );
+				BOOL bUndo = pDstDoc->DoesUndo();
+				pDstDoc->DoUndo( FALSE );
+				SwPaM aCpyPam( rSrcNd, nSrcFrom );
+				aCpyPam.SetMark();
+				aCpyPam.GetPoint()->nContent = nSrcTo;
+				aCpyPam.GetDoc()->CopyRange( aCpyPam, *aPam.GetPoint(),
+					false );
+				pDstDoc->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 )
 				{
 						*pCorr->GetPoint() = *pTmp->GetMark();
 				}
 			}
-			bRet = TRUE;
 		}
+
+		delete[] pLcsDst;
+		delete[] pLcsSrc;
+		
+		bRet = TRUE;
 	}
+	
 	return bRet;
 }
 
 									ULONG& rStt, ULONG& rEnd,
 									ULONG& rThisStt, 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;
-
-		++rStt;
-		++rThisStt;
+		// 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 );
+		}
+
+		// Lines missing from destination are deleted
+		if( nSrcFrom != nSrcTo )
+		{
+			ShowDelete( rData, rStt + nSrcFrom, rStt + nSrcTo, rThisStt + nDstTo );
+		}
 	}
 }
 
 
 	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;
+	}
+
     StartUndo(UNDO_EMPTY, NULL);
 	BOOL bDocWasModified = IsModified();
 	SwDoc& rSrcDoc = (SwDoc&)rDoc;
 	return nRet;
 }
 
-
+// LineArrayComparator ---------------------------------------------------------
+
+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 )
+	{
+		ASSERT( 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;
+}
+
+// CharArrayComparator ---------------------------------------------------------
+
+bool CharArrayComparator::Compare( int nIdx1, int nIdx2 ) const
+{
+	if( nIdx1 < 0 || nIdx2 < 0 || nIdx1 >= GetLen1() || nIdx2 >= GetLen2() )
+	{
+		ASSERT( 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::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;
+		}
+	}
+}
+
+// CommonSubseq ----------------------------------------------------------------
+
+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();
+
+	assert( nLen1 >= 0 );
+	assert( nLen2 >= 0 );
+	assert( ( nLen1 + 1) * ( nLen2 + 1 ) <= maxSize );
+
+	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::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;
+}
+
+// FastCommonSubseq ------------------------------------------------------------
+
+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;
+}

File sw/source/core/doc/docnew.cxx

 #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>
     }
     // <--
 
+	// 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();
 }
 

File sw/source/core/edit/editsh.cxx

             ASSERT( 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 );
 	StartAllAction();
     GetDoc()->StartUndo(UNDO_EMPTY, NULL);
 
-	FOREACHPAM_START(this)
+	FOREACHPAM_START(this)		
 		// eine Tabellen Zelle wird jetzt zu einer normalen Textzelle!
 		GetDoc()->ClearBoxNumAttrs( PCURCRSR->GetPoint()->nNode );
 		GetDoc()->SplitNode( *PCURCRSR->GetPoint(), bCheckTableStart );

File sw/source/core/frmedt/fecopy.cxx

 				// es wird mehr als 1 Node in die akt. Box kopiert. Dann
 				// 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 );
-
+			
             {
                 SwNodeIndex aIndexBefore(rInsPos.nNode);
 
                 }
             }
 
+			// 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 ( ULONG nIdx = 0; nIdx <= nNodesCnt; nIdx++ )
+				{
+					SwTxtNode *pTxtNode = rDestNodes[ nDestStart + nIdx ]->GetTxtNode();
+					if ( pTxtNode )
+					{
+						GetDoc()->UpdateParRsid( pTxtNode );
+					}
+				}
+			}						
+			
 			SaveTblBoxCntnt( &rInsPos );
             if(bIncludingPageFrames && bStartWithTable)
             {

File sw/source/core/text/atrstck.cxx

     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

File sw/source/core/txtnode/ndtxt.cxx

 #include <hintids.hxx>
 #include <hints.hxx>
 
+#include <svx/rsiditem.hxx>
 #include <editeng/fontitem.hxx>
 #include <editeng/brkitem.hxx>
 #include <editeng/escpitem.hxx>
 
     return nRet;