summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTzvetelina Tzeneva <tzvetelina@gmail.com>2011-12-22 17:27:32 +0100
committerC├ędric Bosdonnat <cedric.bosdonnat@free.fr>2011-12-22 17:53:53 +0100
commit062eaeffe7cb986255063bb9b0a5f3fb3fc8e34c (patch)
tree0f065352d000a11131203cf6832354bde597ff50
parent61329db01af7fd7c5915a4d81896d52fda7168db (diff)
sw: Improved document comparison based on RSIDs.
-rw-r--r--cui/source/options/treeopt.cxx1
-rw-r--r--cui/source/options/treeopt.src1
-rw-r--r--editeng/Package_inc.mk1
-rw-r--r--editeng/inc/editeng/rsiditem.hxx43
-rw-r--r--editeng/inc/editeng/svxenum.hxx6
-rw-r--r--editeng/source/items/textitem.cxx28
-rw-r--r--officecfg/registry/schema/org/openoffice/Office/Writer.xcs30
-rwxr-xr-xsvx/inc/svx/dialogs.hrc1
-rwxr-xr-xsvx/source/src/app.hrc3
-rw-r--r--sw/inc/doc.hxx10
-rw-r--r--sw/inc/globals.hrc1
-rw-r--r--sw/inc/helpid.h1
-rw-r--r--sw/inc/hintids.hxx143
-rw-r--r--sw/inc/modcfg.hxx46
-rw-r--r--sw/inc/ndtxt.hxx7
-rw-r--r--sw/inc/swmodule.hxx10
-rw-r--r--sw/inc/unoprnms.hxx4
-rw-r--r--sw/source/core/bastyp/init.cxx9
-rwxr-xr-x[-rw-r--r--]sw/source/core/doc/doc.cxx74
-rw-r--r--sw/source/core/doc/doccomp.cxx932
-rw-r--r--sw/source/core/doc/docnew.cxx9
-rw-r--r--sw/source/core/edit/editsh.cxx7
-rw-r--r--sw/source/core/frmedt/fecopy.cxx17
-rw-r--r--sw/source/core/inc/UndoSplitMove.hxx1
-rw-r--r--sw/source/core/text/atrstck.cxx4
-rw-r--r--sw/source/core/txtnode/ndtxt.cxx40
-rw-r--r--sw/source/core/undo/unspnd.cxx4
-rw-r--r--sw/source/core/unocore/unomap.cxx2
-rw-r--r--sw/source/core/unocore/unoprnms.cxx2
-rw-r--r--sw/source/filter/ascii/parasc.cxx3
-rw-r--r--sw/source/filter/html/css1atr.cxx3
-rw-r--r--sw/source/filter/html/htmlatr.cxx2
-rw-r--r--sw/source/filter/xml/xmlexp.cxx8
-rw-r--r--sw/source/ui/app/appopt.cxx1
-rw-r--r--sw/source/ui/app/docsh.cxx3
-rw-r--r--sw/source/ui/app/swmodul1.cxx40
-rw-r--r--sw/source/ui/config/modcfg.cxx80
-rw-r--r--sw/source/ui/config/optdlg.hrc8
-rwxr-xr-x[-rw-r--r--]sw/source/ui/config/optdlg.src74
-rwxr-xr-x[-rw-r--r--]sw/source/ui/config/optpage.cxx136
-rw-r--r--sw/source/ui/dialog/swdlgfact.cxx5
-rw-r--r--sw/source/ui/inc/optpage.hxx27
-rw-r--r--sw/source/ui/uno/SwXDocumentSettings.cxx28
-rw-r--r--xmloff/inc/xmloff/xmltoken.hxx2
-rw-r--r--xmloff/inc/xmloff/xmltypes.hxx1
-rw-r--r--xmloff/inc/xmloff/xmluconv.hxx7
-rw-r--r--xmloff/source/core/xmltoken.cxx2
-rw-r--r--xmloff/source/core/xmluconv.cxx28
-rw-r--r--xmloff/source/style/prhdlfac.cxx3
-rw-r--r--xmloff/source/style/xmlbahdl.cxx42
-rw-r--r--xmloff/source/style/xmlbahdl.hxx12
-rw-r--r--xmloff/source/text/txtprmap.cxx8
52 files changed, 1825 insertions, 135 deletions
diff --git a/cui/source/options/treeopt.cxx b/cui/source/options/treeopt.cxx
index 8053a3f25711..9d02f0fe4d84 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 9e4fdeb553b2..37bdc36d7c4f 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 61d060373462..0305a047032a 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 000000000000..e98fb8e4e129
--- /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@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 68849722059b..2d07e9fe7a77 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 e3069074573a..db0edf2c9ffd 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 73645dbd9c43..bacae25fccb8 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 0ece88fa594e..a1038f1ef1ce 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 e2ee4daf3a03..19a17e4e0807 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 c7255d94f00d..0251d46d3527 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 d68ada7ca26d..17e919d58f61 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 c5dc7f9dd3db..9f19b8ea2029 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 afd57f3bfb4a..9428072fa53a 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 14a3b2ac2f7e..b1fb71325b07 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 b4a772d2455f..b412aa43fadf 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 763923725958..aca0d48925db 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 8df75ee59bfb..e70963a19ccd 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 c80a8b80d125..e24a7f402f69 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
index 3a7becd66462..8be6aa72ab5b 100644..100755
--- 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 bd3ee2cdc3dd..1da77046d5cf 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 cba769405977..294a4d49ae74 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 f6e3da27c6dd..de33e7e86d13 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 e3056be2415e..0a2ed741e53f 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 c1a690bdbc72..f85c65cfd9ac 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 4f0824cb7f53..b120ca8a3162 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 46f9c2409fc9..19a968d77321 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 0fef0790c99a..787aed4ea48a 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 1554fdc54016..4e6a17c0a80e 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 28e9d48c31fd..0c0479c8c797 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 d7f210a91dec..807f78b40477 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 97414c2e53ad..dcd24dafd02d 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 7803c04c829f..08d8e9c586cb 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 ed058af26056..7d6d0e954126 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 d9afcb37c408..db0f26d9dbf4 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 6f5a9028e4e2..bf2487dd6d5b 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 ff2d3a8e4d64..ccd38e170456 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 bb23c61401fe..af6d32842c3e 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 8c19a5f8b72c..9906d5c3f5b8 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
index c47594865747..1fd1ae215450 100644..100755
--- 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
index c8be2e244780..37f03bcd5c38 100644..100755
--- 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 a31db0d97390..0edd38c4a2ad 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 382441962599..fd66d0331f1b 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 a56f5841f5b7..2711275c4b4a 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 b609dad06faa..3a07e309c999 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 922ad3f340d0..9aee08b6fc59 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 003fe8c8e021..7e9a460be64c 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 02970ebf02cc..9ccc67fe94ae 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 6ceb8850b014..3ec1a49febeb 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 9e258e8b88d9..a2d2ea18762c 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;
+ case XML_TYPE_HEX :
+ pPropHdl = new XMLHexPropHdl;
+ break;
case XML_TYPE_NUMBER :
pPropHdl = new XMLNumberPropHdl( 4 );
break;
diff --git a/xmloff/source/style/xmlbahdl.cxx b/xmloff/source/style/xmlbahdl.cxx
index a9f8b147c7f9..b34b37a166fd 100644
--- a/xmloff/source/style/xmlbahdl.cxx
+++ b/xmloff/source/style/xmlbahdl.cxx
@@ -545,6 +545,48 @@ sal_Bool XMLColorPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue,
///////////////////////////////////////////////////////////////////////////////
//
+// class XMLHexPropHdl
+//
+
+XMLHexPropHdl::~XMLHexPropHdl()
+{
+ // Nothing to do
+}
+
+sal_Bool XMLHexPropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_Bool bRet = sal_False;
+ sal_uInt32 nRsid;
+
+ bRet = SvXMLUnitConverter::convertHex( nRsid, rStrImpValue );
+ rValue <<= nRsid;
+
+ return bRet;
+}
+
+sal_Bool XMLHexPropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
+{
+ sal_Bool bRet = sal_False;
+ sal_uInt32 nRsid = 0;
+
+ OUStringBuffer aOut;
+ if( rValue >>= nRsid )
+ {
+ SvXMLUnitConverter::convertHex( aOut, nRsid );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ bRet = sal_True;
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+
+ return bRet;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
// class XMLStringPropHdl
//
diff --git a/xmloff/source/style/xmlbahdl.hxx b/xmloff/source/style/xmlbahdl.hxx
index 80f75b0159c7..83b7741b5758 100644
--- a/xmloff/source/style/xmlbahdl.hxx
+++ b/xmloff/source/style/xmlbahdl.hxx
@@ -156,6 +156,18 @@ public:
};
/**
+ PropertyHandler for the XML-data-type: XML_TYPE_HEX
+*/
+class XMLHexPropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLHexPropHdl();
+
+ virtual sal_Bool importXML( const ::rtl::OUString& rStrImpValue, ::com::sun::star::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const;
+ virtual sal_Bool exportXML( ::rtl::OUString& rStrExpValue, const ::com::sun::star::uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const;
+};
+
+/**
PropertyHandler for the XML-data-type: XML_TYPE_STRING
*/
class XMLStringPropHdl : public XMLPropertyHandler
diff --git a/xmloff/source/text/txtprmap.cxx b/xmloff/source/text/txtprmap.cxx
index 6a2582c755b2..29559a6db7dc 100644
--- a/xmloff/source/text/txtprmap.cxx
+++ b/xmloff/source/text/txtprmap.cxx
@@ -147,6 +147,10 @@ XMLPropertyMapEntry aXMLParaPropMap[] =
MT_E( "CharUnderlineHasColor", STYLE, TEXT_UNDERLINE_COLOR, XML_TYPE_TEXT_UNDERLINE_HASCOLOR|MID_FLAG_MERGE_ATTRIBUTE, CTF_UNDERLINE_HASCOLOR ),
// RES_CHRATR_WEIGHT
MT_E( "CharWeight", FO, FONT_WEIGHT, XML_TYPE_TEXT_WEIGHT, 0 ),
+ // RES_CHRATR_RSID
+ { "Rsid", sizeof("Rsid")-1, XML_NAMESPACE_OFFICE_EXT, XML_RSID, XML_TYPE_HEX|XML_TYPE_PROP_TEXT, 0, SvtSaveOptions::ODFVER_LATEST },
+ // RES_PARATR_RSID
+ { "ParRsid", sizeof("ParRsid")-1, XML_NAMESPACE_OFFICE_EXT, XML_PARRSID, XML_TYPE_HEX|XML_TYPE_PROP_TEXT, 0, SvtSaveOptions::ODFVER_LATEST },
// RES_CHRATR_WORDLINEMODE
MT_E( "CharWordMode", STYLE, TEXT_UNDERLINE_MODE, XML_TYPE_TEXT_LINE_MODE|MID_FLAG_MERGE_PROPERTY, 0 ),
MT_E( "CharWordMode", STYLE, TEXT_OVERLINE_MODE, XML_TYPE_TEXT_LINE_MODE|MID_FLAG_MERGE_PROPERTY, 0 ),
@@ -442,6 +446,10 @@ XMLPropertyMapEntry aXMLTextPropMap[] =
MT_E( "CharUnderlineHasColor", STYLE, TEXT_UNDERLINE_COLOR, XML_TYPE_TEXT_UNDERLINE_HASCOLOR|MID_FLAG_MERGE_ATTRIBUTE, CTF_UNDERLINE_HASCOLOR ),
// RES_CHRATR_WEIGHT
MT_E( "CharWeight", FO, FONT_WEIGHT, XML_TYPE_TEXT_WEIGHT, 0 ),
+ // RES_CHRATR_RSID
+ { "Rsid", sizeof("Rsid")-1, XML_NAMESPACE_OFFICE_EXT, XML_RSID, XML_TYPE_HEX|XML_TYPE_PROP_TEXT, 0, SvtSaveOptions::ODFVER_LATEST },
+ // RES_PARATR_RSID
+ { "ParRsid", sizeof("ParRsid")-1, XML_NAMESPACE_OFFICE_EXT, XML_PARRSID, XML_TYPE_HEX|XML_TYPE_PROP_TEXT, 0, SvtSaveOptions::ODFVER_LATEST },
// RES_CHRATR_WORDLINEMODE
MT_E( "CharWordMode", STYLE, TEXT_UNDERLINE_MODE, XML_TYPE_TEXT_LINE_MODE|MID_FLAG_MERGE_PROPERTY, 0 ),
MT_E( "CharWordMode", STYLE, TEXT_OVERLINE_MODE, XML_TYPE_TEXT_LINE_MODE|MID_FLAG_MERGE_PROPERTY, 0 ),