summaryrefslogtreecommitdiff
path: root/sw/source/core/doc
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/doc')
-rw-r--r--sw/source/core/doc/SwStyleNameMapper.cxx1142
-rw-r--r--sw/source/core/doc/acmplwrd.cxx473
-rw-r--r--sw/source/core/doc/dbgoutsw.cxx1040
-rw-r--r--sw/source/core/doc/doc.cxx2836
-rw-r--r--sw/source/core/doc/docbasic.cxx276
-rw-r--r--sw/source/core/doc/docbm.cxx1746
-rw-r--r--sw/source/core/doc/docchart.cxx277
-rw-r--r--sw/source/core/doc/doccomp.cxx1883
-rw-r--r--sw/source/core/doc/doccorr.cxx360
-rw-r--r--sw/source/core/doc/docdde.cxx418
-rw-r--r--sw/source/core/doc/docdesc.cxx1018
-rw-r--r--sw/source/core/doc/docdraw.cxx1093
-rw-r--r--sw/source/core/doc/docedt.cxx2845
-rw-r--r--sw/source/core/doc/docfld.cxx2829
-rw-r--r--sw/source/core/doc/docfly.cxx1063
-rw-r--r--sw/source/core/doc/docfmt.cxx2688
-rw-r--r--sw/source/core/doc/docftn.cxx505
-rw-r--r--sw/source/core/doc/docglbl.cxx856
-rw-r--r--sw/source/core/doc/docglos.cxx203
-rw-r--r--sw/source/core/doc/doclay.cxx2369
-rw-r--r--sw/source/core/doc/docnew.cxx1275
-rw-r--r--sw/source/core/doc/docnum.cxx2972
-rw-r--r--sw/source/core/doc/docredln.cxx3868
-rw-r--r--sw/source/core/doc/docruby.cxx361
-rw-r--r--sw/source/core/doc/docsort.cxx1036
-rw-r--r--sw/source/core/doc/docstat.cxx67
-rw-r--r--sw/source/core/doc/doctxm.cxx2464
-rw-r--r--sw/source/core/doc/docxforms.cxx123
-rw-r--r--sw/source/core/doc/extinput.cxx300
-rw-r--r--sw/source/core/doc/fmtcol.cxx717
-rw-r--r--sw/source/core/doc/ftnidx.cxx398
-rw-r--r--sw/source/core/doc/gctable.cxx451
-rw-r--r--sw/source/core/doc/htmltbl.cxx1903
-rw-r--r--sw/source/core/doc/lineinfo.cxx154
-rw-r--r--sw/source/core/doc/list.cxx303
-rw-r--r--sw/source/core/doc/notxtfrm.cxx1098
-rw-r--r--sw/source/core/doc/number.cxx1686
-rw-r--r--sw/source/core/doc/poolfmt.cxx2591
-rw-r--r--sw/source/core/doc/sortopt.cxx103
-rw-r--r--sw/source/core/doc/swserv.cxx371
-rw-r--r--sw/source/core/doc/swstylemanager.cxx173
-rw-r--r--sw/source/core/doc/swstylemanager.hxx38
-rwxr-xr-xsw/source/core/doc/tblafmt.cxx1106
-rw-r--r--sw/source/core/doc/tblcpy.cxx1099
-rw-r--r--sw/source/core/doc/tblrwcl.cxx4770
-rw-r--r--sw/source/core/doc/visiturl.cxx139
46 files changed, 55486 insertions, 0 deletions
diff --git a/sw/source/core/doc/SwStyleNameMapper.cxx b/sw/source/core/doc/SwStyleNameMapper.cxx
new file mode 100644
index 000000000000..d25c7d8417cb
--- /dev/null
+++ b/sw/source/core/doc/SwStyleNameMapper.cxx
@@ -0,0 +1,1142 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <SwStyleNameMapper.hxx>
+#define _SVSTDARR_STRINGSDTOR
+#include <svl/svstdarr.hxx>
+#include <tools/resmgr.hxx>
+#include <poolfmt.hxx>
+#ifndef _RDIC_HRC
+#include <rcid.hrc>
+#endif
+#include <tools/debug.hxx>
+extern ResMgr* pSwResMgr;
+// Initialise UI names to 0
+SvStringsDtor *SwStyleNameMapper::pTextUINameArray = 0,
+ *SwStyleNameMapper::pListsUINameArray = 0,
+ *SwStyleNameMapper::pExtraUINameArray = 0,
+ *SwStyleNameMapper::pRegisterUINameArray = 0,
+ *SwStyleNameMapper::pDocUINameArray = 0,
+ *SwStyleNameMapper::pHTMLUINameArray = 0,
+ *SwStyleNameMapper::pFrmFmtUINameArray = 0,
+ *SwStyleNameMapper::pChrFmtUINameArray = 0,
+ *SwStyleNameMapper::pHTMLChrFmtUINameArray = 0,
+ *SwStyleNameMapper::pPageDescUINameArray = 0,
+ *SwStyleNameMapper::pNumRuleUINameArray = 0,
+
+// Initialise programmatic names to 0
+ *SwStyleNameMapper::pTextProgNameArray = 0,
+ *SwStyleNameMapper::pListsProgNameArray = 0,
+ *SwStyleNameMapper::pExtraProgNameArray = 0,
+ *SwStyleNameMapper::pRegisterProgNameArray = 0,
+ *SwStyleNameMapper::pDocProgNameArray = 0,
+ *SwStyleNameMapper::pHTMLProgNameArray = 0,
+ *SwStyleNameMapper::pFrmFmtProgNameArray = 0,
+ *SwStyleNameMapper::pChrFmtProgNameArray = 0,
+ *SwStyleNameMapper::pHTMLChrFmtProgNameArray = 0,
+ *SwStyleNameMapper::pPageDescProgNameArray = 0,
+ *SwStyleNameMapper::pNumRuleProgNameArray = 0;
+
+NameToIdHash *SwStyleNameMapper::pParaUIMap = 0,
+ *SwStyleNameMapper::pCharUIMap = 0,
+ *SwStyleNameMapper::pPageUIMap = 0,
+ *SwStyleNameMapper::pFrameUIMap = 0,
+ *SwStyleNameMapper::pNumRuleUIMap = 0,
+
+ *SwStyleNameMapper::pParaProgMap = 0,
+ *SwStyleNameMapper::pCharProgMap = 0,
+ *SwStyleNameMapper::pPageProgMap = 0,
+ *SwStyleNameMapper::pFrameProgMap = 0,
+ *SwStyleNameMapper::pNumRuleProgMap = 0;
+
+// SwTableEntry so we can pass the length to the String CTOR
+struct SwTableEntry
+{
+ sal_uInt8 nLength;
+ const sal_Char *pChar;
+};
+
+#define ENTRY( s ) { sizeof (s)-1, s }
+
+// Hard coded Programmatic Name tables
+const struct SwTableEntry TextProgNameTable [] =
+{
+ ENTRY( "Standard" ), // RES_POOLCOLL_STANDARD
+ ENTRY( "Text body" ),
+ ENTRY( "First line indent" ),
+ ENTRY( "Hanging indent" ),
+ ENTRY( "Text body indent" ),
+ ENTRY( "Salutation" ),
+ ENTRY( "Signature" ),
+ ENTRY( "List Indent" ), // RES_POOLCOLL_CONFRONTATION
+ ENTRY( "Marginalia" ),
+ ENTRY( "Heading" ),
+ ENTRY( "Heading 1" ),
+ ENTRY( "Heading 2" ),
+ ENTRY( "Heading 3" ),
+ ENTRY( "Heading 4" ),
+ ENTRY( "Heading 5" ),
+ ENTRY( "Heading 6" ),
+ ENTRY( "Heading 7" ),
+ ENTRY( "Heading 8" ),
+ ENTRY( "Heading 9" ),
+ ENTRY( "Heading 10" ), // RES_POOLCOLL_TEXT_END
+ { 0, NULL }
+};
+
+const struct SwTableEntry ListsProgNameTable [] =
+{
+ ENTRY( "List" ), // STR_POCO_PRGM_NUMBUL_BASE
+ ENTRY( "Numbering 1 Start" ), // STR_POCO_PRGM_NUM_LEVEL1S
+ ENTRY( "Numbering 1" ),
+ ENTRY( "Numbering 1 End" ),
+ ENTRY( "Numbering 1 Cont." ),
+ ENTRY( "Numbering 2 Start" ),
+ ENTRY( "Numbering 2" ),
+ ENTRY( "Numbering 2 End" ),
+ ENTRY( "Numbering 2 Cont." ),
+ ENTRY( "Numbering 3 Start" ),
+ ENTRY( "Numbering 3" ),
+ ENTRY( "Numbering 3 End" ),
+ ENTRY( "Numbering 3 Cont." ),
+ ENTRY( "Numbering 4 Start" ),
+ ENTRY( "Numbering 4" ),
+ ENTRY( "Numbering 4 End" ),
+ ENTRY( "Numbering 4 Cont." ),
+ ENTRY( "Numbering 5 Start" ),
+ ENTRY( "Numbering 5" ),
+ ENTRY( "Numbering 5 End" ),
+ ENTRY( "Numbering 5 Cont." ),
+ ENTRY( "List 1 Start" ),
+ ENTRY( "List 1" ),
+ ENTRY( "List 1 End" ),
+ ENTRY( "List 1 Cont." ),
+ ENTRY( "List 2 Start" ),
+ ENTRY( "List 2" ),
+ ENTRY( "List 2 End" ),
+ ENTRY( "List 2 Cont." ),
+ ENTRY( "List 3 Start" ),
+ ENTRY( "List 3" ),
+ ENTRY( "List 3 End" ),
+ ENTRY( "List 3 Cont." ),
+ ENTRY( "List 4 Start" ),
+ ENTRY( "List 4" ),
+ ENTRY( "List 4 End" ),
+ ENTRY( "List 4 Cont." ),
+ ENTRY( "List 5 Start" ),
+ ENTRY( "List 5" ),
+ ENTRY( "List 5 End" ),
+ ENTRY( "List 5 Cont." ), // STR_POCO_PRGM_BUL_NONUM5
+ { 0, NULL }
+};
+
+const struct SwTableEntry ExtraProgNameTable [] =
+{
+ ENTRY( "Header" ), // RES_POOLCOLL_EXTRA_BEGIN
+ ENTRY( "Header left" ),
+ ENTRY( "Header right" ),
+ ENTRY( "Footer" ),
+ ENTRY( "Footer left" ),
+ ENTRY( "Footer right" ),
+ ENTRY( "Table Contents" ),
+ ENTRY( "Table Heading" ),
+ ENTRY( "Caption" ),
+ ENTRY( "Illustration" ),
+ ENTRY( "Table" ),
+ ENTRY( "Text" ),
+ ENTRY( "Frame contents" ),
+ ENTRY( "Footnote" ),
+ ENTRY( "Addressee" ),
+ ENTRY( "Sender" ),
+ ENTRY( "Endnote" ),
+ ENTRY( "Drawing" ), // RES_POOLCOLL_LABEL_DRAWING
+ { 0, NULL }
+};
+
+const struct SwTableEntry RegisterProgNameTable [] =
+{
+ ENTRY( "Index" ), // STR_POCO_PRGM_REGISTER_BASE
+ ENTRY( "Index Heading" ), // STR_POCO_PRGM_TOX_IDXH
+ ENTRY( "Index 1" ),
+ ENTRY( "Index 2" ),
+ ENTRY( "Index 3" ),
+ ENTRY( "Index Separator" ),
+ ENTRY( "Contents Heading" ),
+ ENTRY( "Contents 1" ),
+ ENTRY( "Contents 2" ),
+ ENTRY( "Contents 3" ),
+ ENTRY( "Contents 4" ),
+ ENTRY( "Contents 5" ),
+ ENTRY( "User Index Heading" ),
+ ENTRY( "User Index 1" ),
+ ENTRY( "User Index 2" ),
+ ENTRY( "User Index 3" ),
+ ENTRY( "User Index 4" ),
+ ENTRY( "User Index 5" ),
+ ENTRY( "Contents 6" ),
+ ENTRY( "Contents 7" ),
+ ENTRY( "Contents 8" ),
+ ENTRY( "Contents 9" ),
+ ENTRY( "Contents 10" ),
+ ENTRY( "Illustration Index Heading" ),
+ ENTRY( "Illustration Index 1" ),
+ ENTRY( "Object index heading" ),
+ ENTRY( "Object index 1" ),
+ ENTRY( "Table index heading" ),
+ ENTRY( "Table index 1" ),
+ ENTRY( "Bibliography Heading" ),
+ ENTRY( "Bibliography 1" ),
+ ENTRY( "User Index 6" ),
+ ENTRY( "User Index 7" ),
+ ENTRY( "User Index 8" ),
+ ENTRY( "User Index 9" ),
+ ENTRY( "User Index 10" ), // STR_POCO_PRGM_TOX_USER10
+ { 0, NULL }
+};
+
+const struct SwTableEntry DocProgNameTable [] =
+{
+ ENTRY( "Title" ), // STR_POCO_PRGM_DOC_TITEL
+ ENTRY( "Subtitle" ),
+ { 0, NULL }
+};
+
+const struct SwTableEntry HTMLProgNameTable [] =
+{
+ ENTRY( "Quotations" ),
+ ENTRY( "Preformatted Text" ),
+ ENTRY( "Horizontal Line" ),
+ ENTRY( "List Contents" ),
+ ENTRY( "List Heading" ), // STR_POCO_PRGM_HTML_DT
+ { 0, NULL }
+};
+
+const struct SwTableEntry FrmFmtProgNameTable [] =
+{
+ ENTRY( "Frame" ), // RES_POOLFRM_FRAME
+ ENTRY( "Graphics" ),
+ ENTRY( "OLE" ),
+ ENTRY( "Formula" ),
+ ENTRY( "Marginalia" ),
+ ENTRY( "Watermark" ),
+ ENTRY( "Labels" ), // RES_POOLFRM_LABEL
+ { 0, NULL }
+};
+
+const struct SwTableEntry ChrFmtProgNameTable [] =
+{
+ ENTRY( "Footnote Symbol" ), // RES_POOLCHR_FOOTNOTE
+ ENTRY( "Page Number" ),
+ ENTRY( "Caption characters" ),
+ ENTRY( "Drop Caps" ),
+ ENTRY( "Numbering Symbols" ),
+ ENTRY( "Bullet Symbols" ),
+ ENTRY( "Internet link" ),
+ ENTRY( "Visited Internet Link" ),
+ ENTRY( "Placeholder" ),
+ ENTRY( "Index Link" ),
+ ENTRY( "Endnote Symbol" ),
+ ENTRY( "Line numbering" ),
+ ENTRY( "Main index entry" ),
+ ENTRY( "Footnote anchor" ),
+ ENTRY( "Endnote anchor" ),
+ ENTRY( "Rubies" ), // RES_POOLCHR_RUBYTEXT
+ ENTRY( "Vertical Numbering Symbols" ), // RES_POOLCHR_VERT_NUMBER
+ { 0, NULL }
+};
+
+const struct SwTableEntry HTMLChrFmtProgNameTable [] =
+{
+ ENTRY( "Emphasis" ), // RES_POOLCHR_HTML_EMPHASIS
+ ENTRY( "Citation" ),
+ ENTRY( "Strong Emphasis" ),
+ ENTRY( "Source Text" ),
+ ENTRY( "Example" ),
+ ENTRY( "User Entry" ),
+ ENTRY( "Variable" ),
+ ENTRY( "Definition" ),
+ ENTRY( "Teletype" ), // RES_POOLCHR_HTML_TELETYPE
+ { 0, NULL }
+};
+
+const struct SwTableEntry PageDescProgNameTable [] =
+{
+ ENTRY( "Standard" ), // STR_POOLPAGE_PRGM_STANDARD
+ ENTRY( "First Page" ),
+ ENTRY( "Left Page" ),
+ ENTRY( "Right Page" ),
+ ENTRY( "Envelope" ),
+ ENTRY( "Index" ),
+ ENTRY( "HTML" ),
+ ENTRY( "Footnote" ),
+ ENTRY( "Endnote" ), // STR_POOLPAGE_PRGM_ENDNOTE
+ ENTRY( "Landscape" ),
+ { 0, NULL }
+};
+
+const struct SwTableEntry NumRuleProgNameTable [] =
+{
+ ENTRY( "Numbering 1" ), // STR_POOLNUMRULE_PRGM_NUM1
+ ENTRY( "Numbering 2" ),
+ ENTRY( "Numbering 3" ),
+ ENTRY( "Numbering 4" ),
+ ENTRY( "Numbering 5" ),
+ ENTRY( "List 1" ),
+ ENTRY( "List 2" ),
+ ENTRY( "List 3" ),
+ ENTRY( "List 4" ),
+ ENTRY( "List 5" ), // STR_POOLNUMRULE_PRGM_BUL5
+ { 0, NULL }
+};
+#undef ENTRY
+
+sal_Bool SwStyleNameMapper::SuffixIsUser ( const String & rString )
+{
+ const sal_Unicode *pChar = rString.GetBuffer();
+ sal_Int32 nLen = rString.Len();
+ sal_Bool bRet = sal_False;
+ if( nLen > 8 &&
+ pChar[nLen-7] == ' ' &&
+ pChar[nLen-6] == '(' &&
+ pChar[nLen-5] == 'u' &&
+ pChar[nLen-4] == 's' &&
+ pChar[nLen-3] == 'e' &&
+ pChar[nLen-2] == 'r' &&
+ pChar[nLen-1] == ')' )
+ bRet = sal_True;
+ return bRet;
+}
+void SwStyleNameMapper::CheckSuffixAndDelete ( String & rString )
+{
+ const sal_Unicode *pChar = rString.GetBuffer();
+ xub_StrLen nLen = rString.Len();
+ if (nLen > 8 &&
+ pChar[nLen-7] == ' ' &&
+ pChar[nLen-6] == '(' &&
+ pChar[nLen-5] == 'u' &&
+ pChar[nLen-4] == 's' &&
+ pChar[nLen-3] == 'e' &&
+ pChar[nLen-2] == 'r' &&
+ pChar[nLen-1] == ')')
+ {
+ rString.Erase ( nLen - 7, 7 );
+ }
+}
+const NameToIdHash & SwStyleNameMapper::getHashTable ( SwGetPoolIdFromName eFlags, sal_Bool bProgName )
+{
+ NameToIdHash *pHash = 0;
+ const SvStringsDtor *pStrings;
+
+ switch ( eFlags )
+ {
+ case nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL:
+ {
+ sal_uInt16 nIndex;
+ sal_uInt16 nId;
+
+ pHash = bProgName ? pParaProgMap : pParaUIMap;
+ if ( !pHash )
+ {
+ pHash = new NameToIdHash ( RES_POOLCOLL_TEXT_END - RES_POOLCOLL_TEXT_BEGIN +
+ RES_POOLCOLL_LISTS_END - RES_POOLCOLL_LISTS_BEGIN +
+ RES_POOLCOLL_EXTRA_END - RES_POOLCOLL_EXTRA_BEGIN +
+ RES_POOLCOLL_REGISTER_END - RES_POOLCOLL_REGISTER_BEGIN +
+ RES_POOLCOLL_DOC_END - RES_POOLCOLL_DOC_BEGIN +
+ RES_POOLCOLL_HTML_END - RES_POOLCOLL_HTML_BEGIN );
+ pStrings = bProgName ? &GetTextProgNameArray() : &GetTextUINameArray();
+ for ( nIndex = 0, nId = RES_POOLCOLL_TEXT_BEGIN ; nId < RES_POOLCOLL_TEXT_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ pStrings = bProgName ? &GetListsProgNameArray() : &GetListsUINameArray();
+ for ( nIndex = 0, nId = RES_POOLCOLL_LISTS_BEGIN ; nId < RES_POOLCOLL_LISTS_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ pStrings = bProgName ? &GetExtraProgNameArray() : &GetExtraUINameArray();
+ for ( nIndex = 0, nId = RES_POOLCOLL_EXTRA_BEGIN ; nId < RES_POOLCOLL_EXTRA_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ pStrings = bProgName ? &GetRegisterProgNameArray() : &GetRegisterUINameArray();
+ for ( nIndex = 0, nId = RES_POOLCOLL_REGISTER_BEGIN ; nId < RES_POOLCOLL_REGISTER_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ pStrings = bProgName ? &GetDocProgNameArray() : &GetDocUINameArray();
+ for ( nIndex = 0, nId = RES_POOLCOLL_DOC_BEGIN ; nId < RES_POOLCOLL_DOC_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ pStrings = bProgName ? &GetHTMLProgNameArray() : &GetHTMLUINameArray();
+ for ( nIndex = 0, nId = RES_POOLCOLL_HTML_BEGIN ; nId < RES_POOLCOLL_HTML_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+
+ if ( bProgName )
+ pParaProgMap = pHash;
+ else
+ pParaUIMap = pHash;
+ }
+ }
+ break;
+ case nsSwGetPoolIdFromName::GET_POOLID_CHRFMT:
+ {
+ pHash = bProgName ? pCharProgMap : pCharUIMap;
+ if ( !pHash )
+ {
+ sal_uInt16 nIndex;
+ sal_uInt16 nId;
+
+ pHash = new NameToIdHash ( RES_POOLCHR_NORMAL_END - RES_POOLCHR_NORMAL_BEGIN +
+ RES_POOLCHR_HTML_END - RES_POOLCHR_HTML_BEGIN );
+ pStrings = bProgName ? &GetChrFmtProgNameArray() : &GetChrFmtUINameArray();
+ for ( nIndex = 0, nId = RES_POOLCHR_NORMAL_BEGIN ; nId < RES_POOLCHR_NORMAL_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ pStrings = bProgName ? &GetHTMLChrFmtProgNameArray() : &GetHTMLChrFmtUINameArray();
+ for ( nIndex = 0, nId = RES_POOLCHR_HTML_BEGIN ; nId < RES_POOLCHR_HTML_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ if (bProgName )
+ pCharProgMap = pHash;
+ else
+ pCharUIMap = pHash;
+ }
+ }
+ break;
+ case nsSwGetPoolIdFromName::GET_POOLID_FRMFMT:
+ {
+ pHash = bProgName ? pFrameProgMap : pFrameUIMap;
+ if ( !pHash )
+ {
+ pHash = new NameToIdHash ( RES_POOLFRM_END - RES_POOLFRM_BEGIN );
+ pStrings = bProgName ? &GetFrmFmtProgNameArray() : &GetFrmFmtUINameArray();
+ for ( sal_uInt16 nIndex=0,nId = RES_POOLFRM_BEGIN ; nId < RES_POOLFRM_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ if ( bProgName )
+ pFrameProgMap = pHash;
+ else
+ pFrameUIMap = pHash;
+ }
+ }
+ break;
+ case nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC:
+ {
+ pHash = bProgName ? pPageProgMap : pPageUIMap;
+ if ( !pHash )
+ {
+ pHash = new NameToIdHash ( RES_POOLPAGE_END - RES_POOLPAGE_BEGIN );
+ pStrings = bProgName ? &GetPageDescProgNameArray() : &GetPageDescUINameArray();
+ for ( sal_uInt16 nIndex=0,nId = RES_POOLPAGE_BEGIN ; nId < RES_POOLPAGE_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ if ( bProgName )
+ pPageProgMap = pHash;
+ else
+ pPageUIMap = pHash;
+ }
+ }
+ break;
+ case nsSwGetPoolIdFromName::GET_POOLID_NUMRULE:
+ {
+ pHash = bProgName ? pNumRuleProgMap : pNumRuleUIMap;
+ if ( !pHash )
+ {
+ pHash = new NameToIdHash ( RES_POOLNUMRULE_END - RES_POOLNUMRULE_BEGIN );
+ pStrings = bProgName ? &GetNumRuleProgNameArray() : &GetNumRuleUINameArray();
+ for ( sal_uInt16 nIndex=0,nId = RES_POOLNUMRULE_BEGIN ; nId < RES_POOLNUMRULE_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ if ( bProgName )
+ pNumRuleProgMap = pHash;
+ else
+ pNumRuleUIMap = pHash;
+ }
+ }
+ break;
+ }
+#ifdef _NEED_TO_DEBUG_MAPPING
+ static sal_Bool bTested = sal_False;
+ if ( !bTested )
+ {
+ bTested = sal_True;
+ {
+ for ( sal_uInt16 nIndex = 0, nId = RES_POOLCOLL_TEXT_BEGIN ; nId < RES_POOLCOLL_TEXT_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ *((sal_Int32*)0) = 42;
+ }
+ for ( nIndex = 0, nId = RES_POOLCOLL_LISTS_BEGIN ; nId < RES_POOLCOLL_LISTS_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ *((sal_Int32*)0) = 42;
+ }
+ for ( nIndex = 0, nId = RES_POOLCOLL_EXTRA_BEGIN ; nId < RES_POOLCOLL_EXTRA_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ *((sal_Int32*)0) = 42;
+ }
+ for ( nIndex = 0, nId = RES_POOLCOLL_REGISTER_BEGIN ; nId < RES_POOLCOLL_REGISTER_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ *((sal_Int32*)0) = 42;
+ }
+ for ( nIndex = 0, nId = RES_POOLCOLL_DOC_BEGIN ; nId < RES_POOLCOLL_DOC_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ *((sal_Int32*)0) = 42;
+ }
+ for ( nIndex = 0, nId = RES_POOLCOLL_HTML_BEGIN ; nId < RES_POOLCOLL_HTML_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ *((sal_Int32*)0) = 42;
+ }
+ }
+ {
+ for ( sal_uInt16 nIndex = 0, nId = RES_POOLCHR_NORMAL_BEGIN ; nId < RES_POOLCHR_NORMAL_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ *((sal_Int32*)0) = 42;
+ }
+ for ( nIndex = 0, nId = RES_POOLCHR_HTML_BEGIN ; nId < RES_POOLCHR_HTML_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ *((sal_Int32*)0) = 42;
+ }
+ }
+ {
+ for ( sal_uInt16 nIndex=0,nId = RES_POOLFRM_BEGIN ; nId < RES_POOLFRM_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ *((sal_Int32*)0) = 42;
+ }
+ }
+ {
+ for ( sal_uInt16 nIndex=0,nId = RES_POOLPAGE_BEGIN ; nId < RES_POOLPAGE_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ *((sal_Int32*)0) = 42;
+ }
+ }
+ {
+ for ( sal_uInt16 nIndex=0,nId = RES_POOLNUMRULE_BEGIN ; nId < RES_POOLNUMRULE_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ *((sal_Int32*)0) = 42;
+ }
+ }
+ }
+#endif
+ return *pHash;
+}
+// This gets the UI Name from the programmatic name
+const String& SwStyleNameMapper::GetUIName ( const String& rName, SwGetPoolIdFromName eFlags )
+{
+ sal_uInt16 nId = GetPoolIdFromProgName ( rName, eFlags );
+ return nId != USHRT_MAX ? GetUIName( nId, rName ) : rName;
+}
+
+
+// Get the programmatic Name from the UI name
+const String& SwStyleNameMapper::GetProgName( const String& rName, SwGetPoolIdFromName eFlags )
+{
+ sal_uInt16 nId = GetPoolIdFromUIName ( rName, eFlags );
+ return nId != USHRT_MAX ? GetProgName( nId, rName ) : rName;
+}
+
+// Get the programmatic name from the UI name in rName and put it into rFillName
+void SwStyleNameMapper::FillProgName ( const String& rName, String& rFillName, SwGetPoolIdFromName eFlags, sal_Bool bDisambiguate )
+{
+ sal_uInt16 nId = GetPoolIdFromUIName ( rName, eFlags );
+ if ( bDisambiguate && nId == USHRT_MAX )
+ {
+ // rName isn't in our UI name table...check if it's in the programmatic one
+ nId = GetPoolIdFromProgName ( rName, eFlags );
+
+ rFillName = rName;
+ if (nId == USHRT_MAX )
+ {
+ // It isn't ...make sure the suffix isn't already " (user)"...if it is,
+ // we need to add another one
+ if ( SuffixIsUser ( rFillName ) )
+ rFillName.AppendAscii ( RTL_CONSTASCII_STRINGPARAM ( " (user)" ) );
+ }
+ else
+ {
+ // It's in the programmatic name table...append suffix
+ rFillName.AppendAscii ( RTL_CONSTASCII_STRINGPARAM ( " (user)" ) );
+ }
+ }
+ else
+ {
+ // If we aren't trying to disambiguate, then just do a normal fill
+ fillNameFromId ( nId, rFillName, sal_True);
+ }
+}
+// Get the UI name from the programmatic name in rName and put it into rFillName
+void SwStyleNameMapper::FillUIName ( const String& rName, String& rFillName, SwGetPoolIdFromName eFlags, sal_Bool bDisambiguate )
+{
+ sal_uInt16 nId = GetPoolIdFromProgName ( rName, eFlags );
+ if ( bDisambiguate && nId == USHRT_MAX )
+ {
+ rFillName = rName;
+ // rName isn't in our Prog name table...check if it has a " (user)" suffix, if so remove it
+ CheckSuffixAndDelete ( rFillName );
+ }
+ else
+ {
+ // If we aren't trying to disambiguate, then just do a normal fill
+ fillNameFromId ( nId, rFillName, sal_False);
+ }
+}
+
+const String& SwStyleNameMapper::getNameFromId( sal_uInt16 nId, const String& rFillName, sal_Bool bProgName )
+{
+ sal_uInt16 nStt = 0;
+ const SvStringsDtor* pStrArr = 0;
+
+ switch( (USER_FMT | COLL_GET_RANGE_BITS | POOLGRP_NOCOLLID) & nId )
+ {
+ case COLL_TEXT_BITS:
+ if( RES_POOLCOLL_TEXT_BEGIN <= nId && nId < RES_POOLCOLL_TEXT_END )
+ {
+ pStrArr = bProgName ? &GetTextProgNameArray() : &GetTextUINameArray();
+ nStt = RES_POOLCOLL_TEXT_BEGIN;
+ }
+ break;
+ case COLL_LISTS_BITS:
+ if( RES_POOLCOLL_LISTS_BEGIN <= nId && nId < RES_POOLCOLL_LISTS_END )
+ {
+ pStrArr = bProgName ? &GetListsProgNameArray() : &GetListsUINameArray();
+ nStt = RES_POOLCOLL_LISTS_BEGIN;
+ }
+ break;
+ case COLL_EXTRA_BITS:
+ if( RES_POOLCOLL_EXTRA_BEGIN <= nId && nId < RES_POOLCOLL_EXTRA_END )
+ {
+ pStrArr = bProgName ? &GetExtraProgNameArray() : &GetExtraUINameArray();
+ nStt = RES_POOLCOLL_EXTRA_BEGIN;
+ }
+ break;
+ case COLL_REGISTER_BITS:
+ if( RES_POOLCOLL_REGISTER_BEGIN <= nId && nId < RES_POOLCOLL_REGISTER_END )
+ {
+ pStrArr = bProgName ? &GetRegisterProgNameArray() : &GetRegisterUINameArray();
+ nStt = RES_POOLCOLL_REGISTER_BEGIN;
+ }
+ break;
+ case COLL_DOC_BITS:
+ if( RES_POOLCOLL_DOC_BEGIN <= nId && nId < RES_POOLCOLL_DOC_END )
+ {
+ pStrArr = bProgName ? &GetDocProgNameArray() : &GetDocUINameArray();
+ nStt = RES_POOLCOLL_DOC_BEGIN;
+ }
+ break;
+ case COLL_HTML_BITS:
+ if( RES_POOLCOLL_HTML_BEGIN <= nId && nId < RES_POOLCOLL_HTML_END )
+ {
+ pStrArr = bProgName ? &GetHTMLProgNameArray() : &GetHTMLUINameArray();
+ nStt = RES_POOLCOLL_HTML_BEGIN;
+ }
+ break;
+ case POOLGRP_CHARFMT:
+ if( RES_POOLCHR_NORMAL_BEGIN <= nId && nId < RES_POOLCHR_NORMAL_END )
+ {
+ pStrArr = bProgName ? &GetChrFmtProgNameArray() : &GetChrFmtUINameArray();
+ nStt = RES_POOLCHR_NORMAL_BEGIN;
+ }
+ else if( RES_POOLCHR_HTML_BEGIN <= nId && nId < RES_POOLCHR_HTML_END )
+ {
+ pStrArr = bProgName ? &GetHTMLChrFmtProgNameArray() : &GetHTMLChrFmtUINameArray();
+ nStt = RES_POOLCHR_HTML_BEGIN;
+ }
+ break;
+ case POOLGRP_FRAMEFMT:
+ if( RES_POOLFRM_BEGIN <= nId && nId < RES_POOLFRM_END )
+ {
+ pStrArr = bProgName ? &GetFrmFmtProgNameArray() : &GetFrmFmtUINameArray();
+ nStt = RES_POOLFRM_BEGIN;
+ }
+ break;
+ case POOLGRP_PAGEDESC:
+ if( RES_POOLPAGE_BEGIN <= nId && nId < RES_POOLPAGE_END )
+ {
+ pStrArr = bProgName ? &GetPageDescProgNameArray() : &GetPageDescUINameArray();
+ nStt = RES_POOLPAGE_BEGIN;
+ }
+ break;
+ case POOLGRP_NUMRULE:
+ if( RES_POOLNUMRULE_BEGIN <= nId && nId < RES_POOLNUMRULE_END )
+ {
+ pStrArr = bProgName ? &GetNumRuleProgNameArray() : &GetNumRuleUINameArray();
+ nStt = RES_POOLNUMRULE_BEGIN;
+ }
+ break;
+ }
+ return pStrArr ? *(pStrArr->operator[] ( nId - nStt ) ) : rFillName;
+}
+void SwStyleNameMapper::fillNameFromId( sal_uInt16 nId, String& rFillName, sal_Bool bProgName )
+{
+ sal_uInt16 nStt = 0;
+ const SvStringsDtor* pStrArr = 0;
+
+ switch( (USER_FMT | COLL_GET_RANGE_BITS | POOLGRP_NOCOLLID) & nId )
+ {
+ case COLL_TEXT_BITS:
+ if( RES_POOLCOLL_TEXT_BEGIN <= nId && nId < RES_POOLCOLL_TEXT_END )
+ {
+ pStrArr = bProgName ? &GetTextProgNameArray() : &GetTextUINameArray();
+ nStt = RES_POOLCOLL_TEXT_BEGIN;
+ }
+ break;
+ case COLL_LISTS_BITS:
+ if( RES_POOLCOLL_LISTS_BEGIN <= nId && nId < RES_POOLCOLL_LISTS_END )
+ {
+ pStrArr = bProgName ? &GetListsProgNameArray() : &GetListsUINameArray();
+ nStt = RES_POOLCOLL_LISTS_BEGIN;
+ }
+ break;
+ case COLL_EXTRA_BITS:
+ if( RES_POOLCOLL_EXTRA_BEGIN <= nId && nId < RES_POOLCOLL_EXTRA_END )
+ {
+ pStrArr = bProgName ? &GetExtraProgNameArray() : &GetExtraUINameArray();
+ nStt = RES_POOLCOLL_EXTRA_BEGIN;
+ }
+ break;
+ case COLL_REGISTER_BITS:
+ if( RES_POOLCOLL_REGISTER_BEGIN <= nId && nId < RES_POOLCOLL_REGISTER_END )
+ {
+ pStrArr = bProgName ? &GetRegisterProgNameArray() : &GetRegisterUINameArray();
+ nStt = RES_POOLCOLL_REGISTER_BEGIN;
+ }
+ break;
+ case COLL_DOC_BITS:
+ if( RES_POOLCOLL_DOC_BEGIN <= nId && nId < RES_POOLCOLL_DOC_END )
+ {
+ pStrArr = bProgName ? &GetDocProgNameArray() : &GetDocUINameArray();
+ nStt = RES_POOLCOLL_DOC_BEGIN;
+ }
+ break;
+ case COLL_HTML_BITS:
+ if( RES_POOLCOLL_HTML_BEGIN <= nId && nId < RES_POOLCOLL_HTML_END )
+ {
+ pStrArr = bProgName ? &GetHTMLProgNameArray() : &GetHTMLUINameArray();
+ nStt = RES_POOLCOLL_HTML_BEGIN;
+ }
+ break;
+ case POOLGRP_CHARFMT:
+ if( RES_POOLCHR_NORMAL_BEGIN <= nId && nId < RES_POOLCHR_NORMAL_END )
+ {
+ pStrArr = bProgName ? &GetChrFmtProgNameArray() : &GetChrFmtUINameArray();
+ nStt = RES_POOLCHR_NORMAL_BEGIN;
+ }
+ else if( RES_POOLCHR_HTML_BEGIN <= nId && nId < RES_POOLCHR_HTML_END )
+ {
+ pStrArr = bProgName ? &GetHTMLChrFmtProgNameArray() : &GetHTMLChrFmtUINameArray();
+ nStt = RES_POOLCHR_HTML_BEGIN;
+ }
+ break;
+ case POOLGRP_FRAMEFMT:
+ if( RES_POOLFRM_BEGIN <= nId && nId < RES_POOLFRM_END )
+ {
+ pStrArr = bProgName ? &GetFrmFmtProgNameArray() : &GetFrmFmtUINameArray();
+ nStt = RES_POOLFRM_BEGIN;
+ }
+ break;
+ case POOLGRP_PAGEDESC:
+ if( RES_POOLPAGE_BEGIN <= nId && nId < RES_POOLPAGE_END )
+ {
+ pStrArr = bProgName ? &GetPageDescProgNameArray() : &GetPageDescUINameArray();
+ nStt = RES_POOLPAGE_BEGIN;
+ }
+ break;
+ case POOLGRP_NUMRULE:
+ if( RES_POOLNUMRULE_BEGIN <= nId && nId < RES_POOLNUMRULE_END )
+ {
+ pStrArr = bProgName ? &GetNumRuleProgNameArray() : &GetNumRuleUINameArray();
+ nStt = RES_POOLNUMRULE_BEGIN;
+ }
+ break;
+ }
+ if (pStrArr)
+ rFillName = *(pStrArr->operator[] ( nId - nStt ) );
+}
+// Get the UI Name from the pool ID
+void SwStyleNameMapper::FillUIName ( sal_uInt16 nId, String& rFillName )
+{
+ fillNameFromId ( nId, rFillName, sal_False );
+}
+// Get the UI Name from the pool ID
+const String& SwStyleNameMapper::GetUIName ( sal_uInt16 nId, const String& rName )
+{
+ return getNameFromId ( nId, rName, sal_False );
+}
+
+// Get the programmatic Name from the pool ID
+void SwStyleNameMapper::FillProgName ( sal_uInt16 nId, String& rFillName )
+{
+ fillNameFromId ( nId, rFillName, sal_True );
+}
+// Get the programmatic Name from the pool ID
+const String& SwStyleNameMapper::GetProgName ( sal_uInt16 nId, const String& rName )
+{
+ return getNameFromId ( nId, rName, sal_True );
+}
+// This gets the PoolId from the UI Name
+sal_uInt16 SwStyleNameMapper::GetPoolIdFromUIName( const String& rName, SwGetPoolIdFromName eFlags )
+{
+ const NameToIdHash & rHashMap = getHashTable ( eFlags, sal_False );
+ NameToIdHash::const_iterator aIter = rHashMap.find ( &rName );
+ return aIter != rHashMap.end() ? (*aIter).second : USHRT_MAX;
+}
+// Get the Pool ID from the programmatic name
+sal_uInt16 SwStyleNameMapper::GetPoolIdFromProgName( const String& rName, SwGetPoolIdFromName eFlags )
+{
+ const NameToIdHash & rHashMap = getHashTable ( eFlags, sal_True );
+ NameToIdHash::const_iterator aIter = rHashMap.find ( &rName );
+ return aIter != rHashMap.end() ? (*aIter).second : USHRT_MAX;
+}
+
+SvStringsDtor* SwStyleNameMapper::NewUINameArray( SvStringsDtor*& pNameArray, sal_uInt16 nStt, sal_uInt16 nEnd )
+{
+ if( !pNameArray )
+ {
+ pNameArray = new SvStringsDtor( static_cast < sal_Int8 > (nEnd - nStt), 1 );
+ while( nStt < nEnd )
+ {
+ const ResId rRId( nStt, *pSwResMgr );
+ String* pStr = new String( rRId );
+ pNameArray->Insert( pStr, pNameArray->Count() );
+ ++nStt;
+ }
+ }
+ return pNameArray;
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetTextUINameArray()
+{
+ return pTextUINameArray ? *pTextUINameArray :
+ *NewUINameArray( pTextUINameArray, RC_POOLCOLL_TEXT_BEGIN,
+ ( RC_POOLCOLL_TEXT_BEGIN +
+ (RES_POOLCOLL_TEXT_END - RES_POOLCOLL_TEXT_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetListsUINameArray()
+{
+ return pListsUINameArray ? *pListsUINameArray :
+ *NewUINameArray( pListsUINameArray, RC_POOLCOLL_LISTS_BEGIN,
+ ( RC_POOLCOLL_LISTS_BEGIN +
+ (RES_POOLCOLL_LISTS_END - RES_POOLCOLL_LISTS_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetExtraUINameArray()
+{
+ return pExtraUINameArray ? *pExtraUINameArray :
+ *NewUINameArray( pExtraUINameArray, RC_POOLCOLL_EXTRA_BEGIN,
+ ( RC_POOLCOLL_EXTRA_BEGIN +
+ (RES_POOLCOLL_EXTRA_END - RES_POOLCOLL_EXTRA_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetRegisterUINameArray()
+{
+ return pRegisterUINameArray ? *pRegisterUINameArray :
+ *NewUINameArray( pRegisterUINameArray, RC_POOLCOLL_REGISTER_BEGIN,
+ ( RC_POOLCOLL_REGISTER_BEGIN +
+ (RES_POOLCOLL_REGISTER_END - RES_POOLCOLL_REGISTER_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetDocUINameArray()
+{
+ return pDocUINameArray ? *pDocUINameArray :
+ *NewUINameArray( pDocUINameArray, RC_POOLCOLL_DOC_BEGIN,
+ ( RC_POOLCOLL_DOC_BEGIN +
+ (RES_POOLCOLL_DOC_END - RES_POOLCOLL_DOC_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetHTMLUINameArray()
+{
+ return pHTMLUINameArray ? *pHTMLUINameArray :
+ *NewUINameArray( pHTMLUINameArray, RC_POOLCOLL_HTML_BEGIN,
+ ( RC_POOLCOLL_HTML_BEGIN +
+ (RES_POOLCOLL_HTML_END - RES_POOLCOLL_HTML_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetFrmFmtUINameArray()
+{
+ return pFrmFmtUINameArray ? *pFrmFmtUINameArray :
+ *NewUINameArray( pFrmFmtUINameArray, RC_POOLFRMFMT_BEGIN,
+ ( RC_POOLFRMFMT_BEGIN +
+ (RES_POOLFRM_END - RES_POOLFRM_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetChrFmtUINameArray()
+{
+ return pChrFmtUINameArray ? *pChrFmtUINameArray :
+ *NewUINameArray( pChrFmtUINameArray, RC_POOLCHRFMT_BEGIN,
+ ( RC_POOLCHRFMT_BEGIN +
+ (RES_POOLCHR_NORMAL_END - RES_POOLCHR_NORMAL_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetHTMLChrFmtUINameArray()
+{
+ return pHTMLChrFmtUINameArray ? *pHTMLChrFmtUINameArray :
+ *NewUINameArray( pHTMLChrFmtUINameArray, RC_POOLCHRFMT_HTML_BEGIN,
+ ( RC_POOLCHRFMT_HTML_BEGIN +
+ (RES_POOLCHR_HTML_END - RES_POOLCHR_HTML_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetPageDescUINameArray()
+{
+ return pPageDescUINameArray ? *pPageDescUINameArray :
+ *NewUINameArray( pPageDescUINameArray, RC_POOLPAGEDESC_BEGIN,
+ ( RC_POOLPAGEDESC_BEGIN +
+ (RES_POOLPAGE_END - RES_POOLPAGE_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetNumRuleUINameArray()
+{
+ return pNumRuleUINameArray ? *pNumRuleUINameArray :
+ *NewUINameArray( pNumRuleUINameArray, RC_POOLNUMRULE_BEGIN,
+ ( RC_POOLNUMRULE_BEGIN +
+ (RES_POOLNUMRULE_END - RES_POOLNUMRULE_BEGIN )) );
+}
+
+SvStringsDtor* SwStyleNameMapper::NewProgNameArray( SvStringsDtor*& pProgNameArray, const SwTableEntry *pTable, sal_uInt8 nCount )
+{
+ if( !pProgNameArray )
+ {
+ pProgNameArray = new SvStringsDtor( nCount, 1 );
+ while (pTable->nLength)
+ {
+ String* pStr = new String( pTable->pChar, pTable->nLength, RTL_TEXTENCODING_ASCII_US );
+ pProgNameArray->Insert( pStr, pProgNameArray->Count() );
+ pTable++;
+ }
+ }
+ return pProgNameArray;
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetTextProgNameArray()
+{
+ return pTextProgNameArray ? *pTextProgNameArray :
+ *NewProgNameArray( pTextProgNameArray, TextProgNameTable,
+ sizeof ( TextProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetListsProgNameArray()
+{
+ return pListsProgNameArray ? *pListsProgNameArray :
+ *NewProgNameArray( pListsProgNameArray, ListsProgNameTable,
+ sizeof ( ListsProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetExtraProgNameArray()
+{
+ return pExtraProgNameArray ? *pExtraProgNameArray :
+ *NewProgNameArray( pExtraProgNameArray, ExtraProgNameTable,
+ sizeof ( ExtraProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetRegisterProgNameArray()
+{
+ return pRegisterProgNameArray ? *pRegisterProgNameArray :
+ *NewProgNameArray( pRegisterProgNameArray, RegisterProgNameTable,
+ sizeof ( RegisterProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetDocProgNameArray()
+{
+ return pDocProgNameArray ? *pDocProgNameArray :
+ *NewProgNameArray( pDocProgNameArray, DocProgNameTable,
+ sizeof ( DocProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetHTMLProgNameArray()
+{
+ return pHTMLProgNameArray ? *pHTMLProgNameArray :
+ *NewProgNameArray( pHTMLProgNameArray, HTMLProgNameTable,
+ sizeof ( HTMLProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetFrmFmtProgNameArray()
+{
+ return pFrmFmtProgNameArray ? *pFrmFmtProgNameArray :
+ *NewProgNameArray( pFrmFmtProgNameArray, FrmFmtProgNameTable,
+ sizeof ( FrmFmtProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetChrFmtProgNameArray()
+{
+ return pChrFmtProgNameArray ? *pChrFmtProgNameArray :
+ *NewProgNameArray( pChrFmtProgNameArray, ChrFmtProgNameTable,
+ sizeof ( ChrFmtProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetHTMLChrFmtProgNameArray()
+{
+ return pHTMLChrFmtProgNameArray ? *pHTMLChrFmtProgNameArray :
+ *NewProgNameArray( pHTMLChrFmtProgNameArray, HTMLChrFmtProgNameTable,
+ sizeof ( HTMLChrFmtProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetPageDescProgNameArray()
+{
+ return pPageDescProgNameArray ? *pPageDescProgNameArray :
+ *NewProgNameArray( pPageDescProgNameArray, PageDescProgNameTable,
+ sizeof ( PageDescProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetNumRuleProgNameArray()
+{
+ return pNumRuleProgNameArray ? *pNumRuleProgNameArray :
+ *NewProgNameArray( pNumRuleProgNameArray, NumRuleProgNameTable,
+ sizeof ( NumRuleProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+
+const String SwStyleNameMapper::GetSpecialExtraProgName( const String& rExtraUIName )
+{
+ String aRes = rExtraUIName;
+ sal_Bool bChgName = sal_False;
+ const SvStringsDtor& rExtraArr = GetExtraUINameArray();
+ static sal_uInt16 nIds[] =
+ {
+ RES_POOLCOLL_LABEL_DRAWING - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_ABB - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_TABLE - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_FRAME- RES_POOLCOLL_EXTRA_BEGIN,
+ 0
+ };
+ const sal_uInt16 * pIds;
+ for ( pIds = nIds; *pIds; ++pIds)
+ {
+ if (aRes == *rExtraArr[ *pIds ])
+ {
+ bChgName = sal_True;
+ break;
+ }
+ }
+ if (bChgName)
+ aRes = *GetExtraProgNameArray()[*pIds];
+ return aRes;
+}
+
+const String SwStyleNameMapper::GetSpecialExtraUIName( const String& rExtraProgName )
+{
+ String aRes = rExtraProgName;
+ sal_Bool bChgName = sal_False;
+ const SvStringsDtor& rExtraArr = GetExtraProgNameArray();
+ static sal_uInt16 nIds[] =
+ {
+ RES_POOLCOLL_LABEL_DRAWING - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_ABB - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_TABLE - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_FRAME- RES_POOLCOLL_EXTRA_BEGIN,
+ 0
+ };
+ const sal_uInt16 * pIds;
+
+ for ( pIds = nIds; *pIds; ++pIds)
+ {
+ if (aRes == *rExtraArr[ *pIds ])
+ {
+ bChgName = sal_True;
+ break;
+ }
+ }
+ if (bChgName)
+ aRes = *GetExtraUINameArray()[*pIds];
+ return aRes;
+}
+
diff --git a/sw/source/core/doc/acmplwrd.cxx b/sw/source/core/doc/acmplwrd.cxx
new file mode 100644
index 000000000000..e53679d8d92e
--- /dev/null
+++ b/sw/source/core/doc/acmplwrd.cxx
@@ -0,0 +1,473 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <tools/urlobj.hxx>
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <unotools/transliterationwrapper.hxx>
+#include <acmplwrd.hxx>
+#include <doc.hxx>
+#include <ndindex.hxx>
+#include <docary.hxx>
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <pagedesc.hxx>
+#include <poolfmt.hxx>
+#include <calbck.hxx>
+#include <editeng/svxacorr.hxx>
+
+#include <editeng/acorrcfg.hxx>
+#include <sfx2/docfile.hxx>
+#include <docsh.hxx>
+
+#include <vector>
+/* -----------------------------05.08.2002 12:43------------------------------
+
+ ---------------------------------------------------------------------------*/
+class SwAutoCompleteClient : public SwClient
+{
+ SwAutoCompleteWord* pAutoCompleteWord;
+ SwDoc* pDoc;
+#ifdef DBG_UTIL
+ static sal_uLong nSwAutoCompleteClientCount;
+#endif
+public:
+ SwAutoCompleteClient(SwAutoCompleteWord& rToTell, SwDoc& rSwDoc);
+ SwAutoCompleteClient(const SwAutoCompleteClient& rClient);
+ ~SwAutoCompleteClient();
+
+ SwAutoCompleteClient& operator=(const SwAutoCompleteClient& rClient);
+
+ virtual void Modify( SfxPoolItem *pOld, SfxPoolItem *pNew);
+ const SwDoc& GetDoc(){return *pDoc;}
+#ifdef DBG_UTIL
+ static sal_uLong GetElementCount() {return nSwAutoCompleteClientCount;}
+#endif
+};
+/* -----------------------------05.08.2002 12:48------------------------------
+
+ ---------------------------------------------------------------------------*/
+typedef std::vector<SwAutoCompleteClient> SwAutoCompleteClientVector;
+
+class SwAutoCompleteWord_Impl
+{
+ SwAutoCompleteClientVector aClientVector;
+ SwAutoCompleteWord& rAutoCompleteWord;
+public:
+ SwAutoCompleteWord_Impl(SwAutoCompleteWord& rParent) :
+ rAutoCompleteWord(rParent){}
+ void AddDocument(SwDoc& rDoc);
+ void RemoveDocument(const SwDoc& rDoc);
+};
+
+/* -----------------------------05.08.2002 14:11------------------------------
+
+ ---------------------------------------------------------------------------*/
+typedef const SwDoc* SwDocPtr;
+typedef std::vector<SwDocPtr> SwDocPtrVector;
+class SwAutoCompleteString : public String
+{
+#ifdef DBG_UTIL
+ static sal_uLong nSwAutoCompleteStringCount;
+#endif
+ SwDocPtrVector aSourceDocs;
+ public:
+ SwAutoCompleteString(const String& rStr, xub_StrLen nPos, xub_StrLen nLen);
+
+ ~SwAutoCompleteString();
+ void AddDocument(const SwDoc& rDoc);
+ //returns true if last document reference has been removed
+ sal_Bool RemoveDocument(const SwDoc& rDoc);
+#ifdef DBG_UTIL
+ static sal_uLong GetElementCount() {return nSwAutoCompleteStringCount;}
+#endif
+};
+#ifdef DBG_UTIL
+ sal_uLong SwAutoCompleteClient::nSwAutoCompleteClientCount = 0;
+ sal_uLong SwAutoCompleteString::nSwAutoCompleteStringCount = 0;
+#endif
+/* -----------------------------06.08.2002 08:57------------------------------
+
+ ---------------------------------------------------------------------------*/
+SwAutoCompleteClient::SwAutoCompleteClient(SwAutoCompleteWord& rToTell, SwDoc& rSwDoc) :
+ pAutoCompleteWord(&rToTell),
+ pDoc(&rSwDoc)
+{
+ pDoc->GetPageDescFromPool(RES_POOLPAGE_STANDARD)->Add(this);
+#ifdef DBG_UTIL
+ ++nSwAutoCompleteClientCount;
+#endif
+}
+/* -----------------------------05.08.2002 14:07------------------------------
+
+ ---------------------------------------------------------------------------*/
+SwAutoCompleteClient::SwAutoCompleteClient(const SwAutoCompleteClient& rClient) :
+ SwClient(),
+ pAutoCompleteWord(rClient.pAutoCompleteWord),
+ pDoc(rClient.pDoc)
+{
+ pDoc->GetPageDescFromPool(RES_POOLPAGE_STANDARD)->Add(this);
+#ifdef DBG_UTIL
+ ++nSwAutoCompleteClientCount;
+#endif
+}
+/* -----------------------------05.08.2002 14:10------------------------------
+
+ ---------------------------------------------------------------------------*/
+SwAutoCompleteClient::~SwAutoCompleteClient()
+{
+#ifdef DBG_UTIL
+ --nSwAutoCompleteClientCount;
+#endif
+}
+/* -----------------06.03.2003 15:30-----------------
+
+ --------------------------------------------------*/
+SwAutoCompleteClient& SwAutoCompleteClient::operator=(const SwAutoCompleteClient& rClient)
+{
+ pAutoCompleteWord = rClient.pAutoCompleteWord;
+ pDoc = rClient.pDoc;
+ if(rClient.GetRegisteredIn())
+ rClient.pRegisteredIn->Add(this);
+ else if(GetRegisteredIn())
+ pRegisteredIn->Remove(this);
+ return *this;
+}
+/* -----------------------------05.08.2002 12:49------------------------------
+
+ ---------------------------------------------------------------------------*/
+void SwAutoCompleteClient::Modify(SfxPoolItem *pOld, SfxPoolItem *)
+{
+ switch( pOld ? pOld->Which() : 0 )
+ {
+ case RES_REMOVE_UNO_OBJECT:
+ case RES_OBJECTDYING:
+ if( (void*)GetRegisteredIn() == ((SwPtrMsgPoolItem *)pOld)->pObject )
+ ((SwModify*)GetRegisteredIn())->Remove(this);
+ pAutoCompleteWord->DocumentDying(*pDoc);
+ break;
+
+ }
+}
+/* -----------------------------05.08.2002 13:03------------------------------
+
+ ---------------------------------------------------------------------------*/
+void SwAutoCompleteWord_Impl::AddDocument(SwDoc& rDoc)
+{
+ SwAutoCompleteClientVector::iterator aIt;
+ for(aIt = aClientVector.begin(); aIt != aClientVector.end(); aIt++)
+ {
+ if(&aIt->GetDoc() == &rDoc)
+ return;
+ }
+ aClientVector.push_back(SwAutoCompleteClient(rAutoCompleteWord, rDoc));
+}
+/* -----------------------------05.08.2002 14:33------------------------------
+
+ ---------------------------------------------------------------------------*/
+void SwAutoCompleteWord_Impl::RemoveDocument(const SwDoc& rDoc)
+{
+ SwAutoCompleteClientVector::iterator aIt;
+ for(aIt = aClientVector.begin(); aIt != aClientVector.end(); aIt++)
+ {
+ if(&aIt->GetDoc() == &rDoc)
+ {
+ aClientVector.erase(aIt);
+ return;
+ }
+ }
+}
+/* -----------------------------06.08.2002 08:54------------------------------
+
+ ---------------------------------------------------------------------------*/
+SwAutoCompleteString::SwAutoCompleteString(const String& rStr, xub_StrLen nPos, xub_StrLen nLen) :
+ String( rStr, nPos, nLen )
+{
+#ifdef DBG_UTIL
+ ++nSwAutoCompleteStringCount;
+#endif
+}
+/* -----------------------------05.08.2002 14:22------------------------------
+
+ ---------------------------------------------------------------------------*/
+SwAutoCompleteString::~SwAutoCompleteString()
+{
+#ifdef DBG_UTIL
+ --nSwAutoCompleteStringCount;
+#endif
+}
+/* -----------------------------05.08.2002 14:17------------------------------
+
+ ---------------------------------------------------------------------------*/
+void SwAutoCompleteString::AddDocument(const SwDoc& rDoc)
+{
+ SwDocPtrVector::iterator aIt;
+ for(aIt = aSourceDocs.begin(); aIt != aSourceDocs.end(); aIt++)
+ {
+ if(*aIt == &rDoc)
+ return;
+ }
+ SwDocPtr pNew = &rDoc;
+ aSourceDocs.push_back(pNew);
+}
+/* -----------------------------05.08.2002 14:36------------------------------
+
+ ---------------------------------------------------------------------------*/
+sal_Bool SwAutoCompleteString::RemoveDocument(const SwDoc& rDoc)
+{
+ SwDocPtrVector::iterator aIt;
+ for(aIt = aSourceDocs.begin(); aIt != aSourceDocs.end(); aIt++)
+ {
+ if(*aIt == &rDoc)
+ {
+ aSourceDocs.erase(aIt);
+ return !aSourceDocs.size();
+ }
+ }
+ return sal_False;
+}
+/* ---------------------------------------------------------------------------
+
+ ---------------------------------------------------------------------------*/
+SwAutoCompleteWord::SwAutoCompleteWord( sal_uInt16 nWords, sal_uInt16 nMWrdLen )
+ : aWordLst( 0, 255 ), aLRULst( 0, 255 ),
+ pImpl(new SwAutoCompleteWord_Impl(*this)),
+ nMaxCount( nWords ),
+ nMinWrdLen( nMWrdLen ),
+ bLockWordLst( sal_False )
+{
+}
+
+SwAutoCompleteWord::~SwAutoCompleteWord()
+{
+ for(sal_uInt16 nPos = aWordLst.Count(); nPos; nPos--)
+ {
+ SwAutoCompleteString* pCurrent = (SwAutoCompleteString*)aWordLst[ nPos - 1 ];
+ aWordLst.Remove( nPos - 1 );
+ delete pCurrent;
+ }
+ delete pImpl;
+#ifdef DBG_UTIL
+ sal_uLong nStrings = SwAutoCompleteString::GetElementCount();
+ sal_uLong nClients = SwAutoCompleteClient::GetElementCount();
+ DBG_ASSERT(!nStrings && !nClients, "AutoComplete: clients or string count mismatch");
+#endif
+}
+
+sal_Bool SwAutoCompleteWord::InsertWord( const String& rWord, SwDoc& rDoc )
+{
+ SwDocShell* pDocShell = rDoc.GetDocShell();
+ SfxMedium* pMedium = pDocShell ? pDocShell->GetMedium() : 0;
+ // strings from help module should not be added
+ if( pMedium )
+ {
+ const INetURLObject& rURL = pMedium->GetURLObject();
+ if ( rURL.GetProtocol() == INET_PROT_VND_SUN_STAR_HELP )
+ return sal_False;
+ }
+
+ String aNewWord(rWord);
+ aNewWord.EraseAllChars( CH_TXTATR_INWORD );
+ aNewWord.EraseAllChars( CH_TXTATR_BREAKWORD );
+
+ pImpl->AddDocument(rDoc);
+ sal_Bool bRet = sal_False;
+ xub_StrLen nWrdLen = aNewWord.Len();
+ while( nWrdLen && '.' == aNewWord.GetChar( nWrdLen-1 ))
+ --nWrdLen;
+
+ if( !bLockWordLst && nWrdLen >= nMinWrdLen )
+ {
+ SwAutoCompleteString* pAutoString;
+ StringPtr pNew = pAutoString = new SwAutoCompleteString( aNewWord, 0, nWrdLen );
+ pAutoString->AddDocument(rDoc);
+ sal_uInt16 nInsPos;
+ if( aWordLst.Insert( pNew, nInsPos ) )
+ {
+ bRet = sal_True;
+ if( aLRULst.Count() < nMaxCount )
+ aLRULst.Insert( pNew, 0 );
+ else
+ {
+ // der letzte muss entfernt werden
+ // damit der neue vorne Platz hat
+ String* pDel = (String*)aLRULst[ nMaxCount - 1 ];
+
+ void** ppData = (void**)aLRULst.GetData();
+ memmove( ppData+1, ppData, (nMaxCount - 1) * sizeof( void* ));
+ *ppData = pNew;
+
+ aWordLst.Remove( pDel );
+ delete (SwAutoCompleteString*)pDel;
+ }
+ }
+ else
+ {
+ delete (SwAutoCompleteString*)pNew;
+ // dann aber auf jedenfall nach "oben" moven
+ pNew = aWordLst[ nInsPos ];
+
+ //add the document to the already inserted string
+ SwAutoCompleteString* pCurrent = (SwAutoCompleteString*)pNew;
+ pCurrent->AddDocument(rDoc);
+
+ nInsPos = aLRULst.GetPos( (void*)pNew );
+ ASSERT( USHRT_MAX != nInsPos, "String nicht gefunden" );
+ if( nInsPos )
+ {
+ void** ppData = (void**)aLRULst.GetData();
+ memmove( ppData+1, ppData, nInsPos * sizeof( void* ) );
+ *ppData = pNew;
+ }
+ }
+ }
+ return bRet;
+}
+
+void SwAutoCompleteWord::SetMaxCount( sal_uInt16 nNewMax )
+{
+ if( nNewMax < nMaxCount && aLRULst.Count() > nNewMax )
+ {
+ // dann die unten ueberhaengenden entfernen
+ sal_uInt16 nLRUIndex = nNewMax-1;
+ while( nNewMax < aWordLst.Count() && nLRUIndex < aLRULst.Count())
+ {
+ sal_uInt16 nPos = aWordLst.GetPos( (String*)aLRULst[ nLRUIndex++ ] );
+ ASSERT( USHRT_MAX != nPos, "String nicht gefunden" );
+ void * pDel = aWordLst[nPos];
+ aWordLst.Remove(nPos);
+ delete (SwAutoCompleteString*)pDel;
+ }
+ aLRULst.Remove( nNewMax-1, aLRULst.Count() - nNewMax );
+ }
+ nMaxCount = nNewMax;
+}
+
+void SwAutoCompleteWord::SetMinWordLen( sal_uInt16 n )
+{
+ // will man wirklich alle Worte, die kleiner als die neue Min Laenge
+ // sind entfernen?
+ // JP 02.02.99 - erstmal nicht.
+
+ // JP 11.03.99 - mal testhalber eingebaut
+ if( n < nMinWrdLen )
+ {
+ for( sal_uInt16 nPos = 0; nPos < aWordLst.Count(); ++nPos )
+ if( aWordLst[ nPos ]->Len() < n )
+ {
+ void* pDel = aWordLst[ nPos ];
+ aWordLst.Remove(nPos);
+
+ sal_uInt16 nDelPos = aLRULst.GetPos( pDel );
+ ASSERT( USHRT_MAX != nDelPos, "String nicht gefunden" );
+ aLRULst.Remove( nDelPos );
+ --nPos;
+ delete (SwAutoCompleteString*)pDel;
+ }
+ }
+
+ nMinWrdLen = n;
+}
+
+sal_Bool SwAutoCompleteWord::GetRange( const String& rWord, sal_uInt16& rStt,
+ sal_uInt16& rEnd ) const
+{
+ const StringPtr pStr = (StringPtr)&rWord;
+ aWordLst.Seek_Entry( pStr, &rStt );
+ rEnd = rStt;
+
+ const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
+ while( rEnd < aWordLst.Count() && rSCmp.isMatch( rWord, *aWordLst[ rEnd ]))
+ ++rEnd;
+
+ return rStt < rEnd;
+}
+
+void SwAutoCompleteWord::CheckChangedList( const SvStringsISortDtor& rNewLst )
+{
+ sal_uInt16 nMyLen = aWordLst.Count(), nNewLen = rNewLst.Count();
+ sal_uInt16 nMyPos = 0, nNewPos = 0;
+
+ for( ; nMyPos < nMyLen && nNewPos < nNewLen; ++nMyPos, ++nNewPos )
+ {
+ const StringPtr pStr = rNewLst[ nNewPos ];
+ while( aWordLst[ nMyPos ] != pStr )
+ {
+ void* pDel = aWordLst[ nMyPos ];
+ aWordLst.Remove(nMyPos);
+
+ sal_uInt16 nPos = aLRULst.GetPos( pDel );
+ ASSERT( USHRT_MAX != nPos, "String nicht gefunden" );
+ aLRULst.Remove( nPos );
+ delete (SwAutoCompleteString*)pDel;
+ if( nMyPos >= --nMyLen )
+ break;
+ }
+ }
+ //remove the elements at the end of the array
+ if( nMyPos < nMyLen )
+ {
+ //clear LRU array first then delete the string object
+ for( ; nNewPos < nMyLen; ++nNewPos )
+ {
+ void* pDel = aWordLst[ nNewPos ];
+ sal_uInt16 nPos = aLRULst.GetPos( pDel );
+ ASSERT( USHRT_MAX != nPos, "String nicht gefunden" );
+ aLRULst.Remove( nPos );
+ delete (SwAutoCompleteString*)pDel;
+ }
+ //remove from array
+ aWordLst.Remove( nMyPos, nMyLen - nMyPos );
+ }
+}
+/* -----------------------------05.08.2002 12:54------------------------------
+
+ ---------------------------------------------------------------------------*/
+void SwAutoCompleteWord::DocumentDying(const SwDoc& rDoc)
+{
+ pImpl->RemoveDocument(rDoc);
+
+ SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get()->GetAutoCorrect();
+ const sal_Bool bDelete = !pACorr->GetSwFlags().bAutoCmpltKeepList;
+ for(sal_uInt16 nPos = aWordLst.Count(); nPos; nPos--)
+ {
+ SwAutoCompleteString* pCurrent = (SwAutoCompleteString*)aWordLst[ nPos - 1 ];
+ if(pCurrent->RemoveDocument(rDoc) && bDelete)
+ {
+ aWordLst.Remove( nPos - 1 );
+ sal_uInt16 nLRUPos = aLRULst.GetPos( (void*)pCurrent );
+ DBG_ASSERT(nLRUPos < USHRT_MAX, "word not found in LRU list" );
+ aLRULst.Remove( nLRUPos );
+ delete pCurrent;
+ }
+ }
+}
+
diff --git a/sw/source/core/doc/dbgoutsw.cxx b/sw/source/core/doc/dbgoutsw.cxx
new file mode 100644
index 000000000000..08dab4aff359
--- /dev/null
+++ b/sw/source/core/doc/dbgoutsw.cxx
@@ -0,0 +1,1040 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#ifdef DEBUG
+
+#include <tools/string.hxx>
+#include <svl/poolitem.hxx>
+#include <svl/itemiter.hxx>
+#include <string>
+#include <map>
+#include <node.hxx>
+#include <ndtxt.hxx>
+#include <ndhints.hxx>
+#include <txatbase.hxx>
+#include <pam.hxx>
+#include <docary.hxx>
+#include <swundo.hxx>
+#include <undobj.hxx>
+#include <numrule.hxx>
+#include <doc.hxx>
+#include <frmfmt.hxx>
+#include <fmtanchr.hxx>
+#include <swrect.hxx>
+#include <ndarr.hxx>
+#include <paratr.hxx>
+#include <SwNodeNum.hxx>
+#include <dbgoutsw.hxx>
+#include <SwRewriter.hxx>
+#include <iostream>
+#include <cstdio>
+
+using namespace std;
+
+static ByteString aDbgOutResult;
+bool bDbgOutStdErr = false;
+bool bDbgOutPrintAttrSet = false;
+
+char* db_pretty_print(const String* str, int flags, char* fmt)
+{
+ (void) fmt;
+ (void) flags;
+ return const_cast<char*>(dbg_out(*str));
+}
+
+template<class T>
+String lcl_dbg_out_SvPtrArr(const T & rArr)
+{
+ String aStr("[ ", RTL_TEXTENCODING_ASCII_US);
+
+ for (sal_Int16 n = 0; n < rArr.Count(); n++)
+ {
+ if (n > 0)
+ aStr += String(", ", RTL_TEXTENCODING_ASCII_US);
+
+ if (rArr[n])
+ aStr += lcl_dbg_out(*rArr[n]);
+ else
+ aStr += String("(null)", RTL_TEXTENCODING_ASCII_US);
+ }
+
+ aStr += String(" ]", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const void * pVoid)
+{
+ char sBuffer[1024];
+
+ sprintf(sBuffer, "%p", pVoid);
+
+ String aTmpStr(sBuffer, RTL_TEXTENCODING_ASCII_US);
+
+ return dbg_out(aTmpStr);
+}
+
+SW_DLLPUBLIC const char * dbg_out(const String & aStr)
+{
+ aDbgOutResult = ByteString(aStr, RTL_TEXTENCODING_ASCII_US);
+
+ if (bDbgOutStdErr)
+ fprintf(stderr, "%s", aDbgOutResult.GetBuffer());
+
+ return aDbgOutResult.GetBuffer();
+}
+
+SW_DLLPUBLIC const char * dbg_out(const ::rtl::OUString & aStr)
+{
+ return OUStringToOString(aStr, RTL_TEXTENCODING_ASCII_US).getStr();
+}
+
+
+struct CompareUShort
+{
+ bool operator()(sal_uInt16 a, sal_uInt16 b) const
+ {
+ return a < b;
+ }
+};
+
+map<sal_uInt16,String,CompareUShort> & GetItemWhichMap()
+{
+ static map<sal_uInt16,String,CompareUShort> aItemWhichMap;
+ static bool bInitialized = false;
+
+ if (! bInitialized)
+ {
+ aItemWhichMap[RES_CHRATR_CASEMAP] = String("CHRATR_CASEMAP", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CHARSETCOLOR] = String("CHRATR_CHARSETCOLOR", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_COLOR] = String("CHRATR_COLOR", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CONTOUR] = String("CHRATR_CONTOUR", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CROSSEDOUT] = String("CHRATR_CROSSEDOUT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_ESCAPEMENT] = String("CHRATR_ESCAPEMENT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_FONT] = String("CHRATR_FONT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_FONTSIZE] = String("CHRATR_FONTSIZE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_KERNING] = String("CHRATR_KERNING", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_LANGUAGE] = String("CHRATR_LANGUAGE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_POSTURE] = String("CHRATR_POSTURE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_PROPORTIONALFONTSIZE] = String("CHRATR_PROPORTIONALFONTSIZE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_SHADOWED] = String("CHRATR_SHADOWED", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_UNDERLINE] = String("CHRATR_UNDERLINE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_OVERLINE] = String("CHRATR_OVERLINE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_WEIGHT] = String("CHRATR_WEIGHT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_WORDLINEMODE] = String("CHRATR_WORDLINEMODE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_AUTOKERN] = String("CHRATR_AUTOKERN", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_BLINK] = String("CHRATR_BLINK", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_NOHYPHEN] = String("CHRATR_NOHYPHEN", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_NOLINEBREAK] = String("CHRATR_NOLINEBREAK", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_BACKGROUND] = String("CHRATR_BACKGROUND", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CJK_FONT] = String("CHRATR_CJK_FONT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CJK_FONTSIZE] = String("CHRATR_CJK_FONTSIZE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CJK_LANGUAGE] = String("CHRATR_CJK_LANGUAGE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CJK_POSTURE] = String("CHRATR_CJK_POSTURE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CJK_WEIGHT] = String("CHRATR_CJK_WEIGHT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CTL_FONT] = String("CHRATR_CTL_FONT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CTL_FONTSIZE] = String("CHRATR_CTL_FONTSIZE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CTL_LANGUAGE] = String("CHRATR_CTL_LANGUAGE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CTL_POSTURE] = String("CHRATR_CTL_POSTURE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CTL_WEIGHT] = String("CHRATR_CTL_WEIGHT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_ROTATE] = String("CHRATR_ROTATE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_EMPHASIS_MARK] = String("CHRATR_EMPHASIS_MARK", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_TWO_LINES] = String("CHRATR_TWO_LINES", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_SCALEW] = String("CHRATR_SCALEW", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_RELIEF] = String("CHRATR_RELIEF", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_HIDDEN] = String("CHRATR_HIDDEN", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_AUTOFMT] = String("TXTATR_AUTOFMT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_INETFMT] = String("TXTATR_INETFMT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_REFMARK] = String("TXTATR_REFMARK", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_TOXMARK] = String("TXTATR_TOXMARK", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_CHARFMT] = String("TXTATR_CHARFMT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_DUMMY5] = String("TXTATR_DUMMY5", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_CJK_RUBY] = String("TXTATR_CJK_RUBY", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_UNKNOWN_CONTAINER] = String("TXTATR_UNKNOWN_CONTAINER", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_META] = String("TXTATR_META", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_METAFIELD] = String("TXTATR_METAFIELD", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_FIELD] = String("TXTATR_FIELD", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_FLYCNT] = String("TXTATR_FLYCNT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_FTN] = String("TXTATR_FTN", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_DUMMY4] = String("TXTATR_DUMMY4", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_DUMMY3] = String("TXTATR_DUMMY3", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_DUMMY1] = String("TXTATR_DUMMY1", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_DUMMY2] = String("TXTATR_DUMMY2", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_LINESPACING] = String("PARATR_LINESPACING", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_ADJUST] = String("PARATR_ADJUST", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_SPLIT] = String("PARATR_SPLIT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_ORPHANS] = String("PARATR_ORPHANS", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_WIDOWS] = String("PARATR_WIDOWS", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_TABSTOP] = String("PARATR_TABSTOP", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_HYPHENZONE] = String("PARATR_HYPHENZONE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_DROP] = String("PARATR_DROP", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_REGISTER] = String("PARATR_REGISTER", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_NUMRULE] = String("PARATR_NUMRULE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_SCRIPTSPACE] = String("PARATR_SCRIPTSPACE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_HANGINGPUNCTUATION] = String("PARATR_HANGINGPUNCTUATION", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_FORBIDDEN_RULES] = String("PARATR_FORBIDDEN_RULES", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_VERTALIGN] = String("PARATR_VERTALIGN", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_SNAPTOGRID] = String("PARATR_SNAPTOGRID", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_CONNECT_BORDER] = String("PARATR_CONNECT_BORDER", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_FILL_ORDER] = String("FILL_ORDER", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_FRM_SIZE] = String("FRM_SIZE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PAPER_BIN] = String("PAPER_BIN", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_LR_SPACE] = String("LR_SPACE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_UL_SPACE] = String("UL_SPACE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PAGEDESC] = String("PAGEDESC", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_BREAK] = String("BREAK", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CNTNT] = String("CNTNT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_HEADER] = String("HEADER", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_FOOTER] = String("FOOTER", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PRINT] = String("PRINT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_OPAQUE] = String("OPAQUE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PROTECT] = String("PROTECT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_SURROUND] = String("SURROUND", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_VERT_ORIENT] = String("VERT_ORIENT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_HORI_ORIENT] = String("HORI_ORIENT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_ANCHOR] = String("ANCHOR", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_BACKGROUND] = String("BACKGROUND", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_BOX] = String("BOX", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_SHADOW] = String("SHADOW", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_FRMMACRO] = String("FRMMACRO", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_COL] = String("COL", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_KEEP] = String("KEEP", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_URL] = String("URL", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_EDIT_IN_READONLY] = String("EDIT_IN_READONLY", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_LAYOUT_SPLIT] = String("LAYOUT_SPLIT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHAIN] = String("CHAIN", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TEXTGRID] = String("TEXTGRID", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_LINENUMBER ] = String("LINENUMBER ", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_FTN_AT_TXTEND] = String("FTN_AT_TXTEND", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_END_AT_TXTEND] = String("END_AT_TXTEND", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_COLUMNBALANCE] = String("COLUMNBALANCE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_FRAMEDIR] = String("FRAMEDIR", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_HEADER_FOOTER_EAT_SPACING] = String("HEADER_FOOTER_EAT_SPACING", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_ROW_SPLIT] = String("ROW_SPLIT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_MIRRORGRF] = String("GRFATR_MIRRORGRF", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_CROPGRF] = String("GRFATR_CROPGRF", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_ROTATION] = String("GRFATR_ROTATION", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_LUMINANCE] = String("GRFATR_LUMINANCE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_CONTRAST] = String("GRFATR_CONTRAST", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_CHANNELR] = String("GRFATR_CHANNELR", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_CHANNELG] = String("GRFATR_CHANNELG", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_CHANNELB] = String("GRFATR_CHANNELB", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_GAMMA] = String("GRFATR_GAMMA", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_INVERT] = String("GRFATR_INVERT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_TRANSPARENCY] = String("GRFATR_TRANSPARENCY", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_DRAWMODE] = String("GRFATR_DRAWMODE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_BOXATR_FORMAT] = String("BOXATR_FORMAT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_BOXATR_FORMULA] = String("BOXATR_FORMULA", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_BOXATR_VALUE] = String("BOXATR_VALUE", RTL_TEXTENCODING_ASCII_US);
+
+ bInitialized = true;
+ }
+
+ return aItemWhichMap;
+}
+
+const String lcl_dbg_out(const SfxPoolItem & rItem)
+{
+ String aStr("[ ", RTL_TEXTENCODING_ASCII_US);
+
+ if (GetItemWhichMap().find(rItem.Which()) != GetItemWhichMap().end())
+ aStr += GetItemWhichMap()[rItem.Which()];
+ else
+ aStr += String::CreateFromInt32(rItem.Which());
+
+ aStr += String(" ]", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SfxPoolItem & rItem)
+{
+ return dbg_out(lcl_dbg_out(rItem));
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SfxPoolItem * pItem)
+{
+ return dbg_out(pItem ? lcl_dbg_out(*pItem) :
+ String("(nil)", RTL_TEXTENCODING_ASCII_US));
+}
+
+SW_DLLPUBLIC const String lcl_dbg_out(const SfxItemSet & rSet)
+{
+ SfxItemIter aIter(rSet);
+ const SfxPoolItem * pItem;
+ bool bFirst = true;
+ String aStr = String("[ ", RTL_TEXTENCODING_ASCII_US);
+
+ pItem = aIter.FirstItem();
+
+ while (pItem )
+ {
+ if (!bFirst)
+ aStr += String(", ", RTL_TEXTENCODING_ASCII_US);
+
+ if ((sal_uIntPtr)pItem != SAL_MAX_SIZE)
+ aStr += lcl_dbg_out(*pItem);
+ else
+ aStr += String("invalid", RTL_TEXTENCODING_ASCII_US);
+
+ bFirst = false;
+
+ pItem = aIter.NextItem();
+ }
+
+ aStr += String(" ]", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SfxItemSet & rSet)
+{
+ return dbg_out(lcl_dbg_out(rSet));
+}
+
+const String lcl_dbg_out(const SwTxtAttr & rAttr)
+{
+ String aStr("[ ", RTL_TEXTENCODING_ASCII_US);
+
+ aStr += String::CreateFromInt32(*rAttr.GetStart());
+ aStr += String("->", RTL_TEXTENCODING_ASCII_US);
+ aStr += String::CreateFromInt32(*rAttr.GetEnd());
+ aStr += String(" ", RTL_TEXTENCODING_ASCII_US);
+ aStr += lcl_dbg_out(rAttr.GetAttr());
+
+ aStr += String(" ]", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwTxtAttr & rAttr)
+{
+ return dbg_out(lcl_dbg_out(rAttr));
+}
+
+const String lcl_dbg_out(const SwpHints & rHints)
+{
+ String aStr("[ SwpHints\n", RTL_TEXTENCODING_ASCII_US);
+
+ for (sal_uInt16 i = 0; i < rHints.Count(); i++)
+ {
+ aStr += String(" ", RTL_TEXTENCODING_ASCII_US);
+ aStr += lcl_dbg_out(*rHints[i]);
+ aStr += String("\n", RTL_TEXTENCODING_ASCII_US);
+ }
+
+ aStr += String("]\n", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwpHints &rHints)
+{
+ return dbg_out(lcl_dbg_out(rHints));
+}
+
+String lcl_dbg_out(const SwPosition & rPos)
+{
+ String aStr("( ", RTL_TEXTENCODING_ASCII_US);
+
+ aStr += String::CreateFromInt32(rPos.nNode.GetIndex());
+ aStr += String(", ", RTL_TEXTENCODING_ASCII_US);
+ aStr += String::CreateFromInt32(rPos.nContent.GetIndex());
+ aStr += String(": ", RTL_TEXTENCODING_ASCII_US);
+ aStr += String::CreateFromInt32
+ (reinterpret_cast<sal_IntPtr>(rPos.nContent.GetIdxReg()), 16);
+
+ aStr += String(" )", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwPosition & rPos)
+{
+ return dbg_out(lcl_dbg_out(rPos));
+}
+
+String lcl_dbg_out(const SwPaM & rPam)
+{
+ String aStr("[ Pt: ", RTL_TEXTENCODING_ASCII_US);
+
+ aStr += lcl_dbg_out(*rPam.GetPoint());
+
+ if (rPam.HasMark())
+ {
+ aStr += String(", Mk: ", RTL_TEXTENCODING_ASCII_US);
+ aStr += lcl_dbg_out(*rPam.GetMark());
+ }
+
+ aStr += String(" ]", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwPaM & rPam)
+{
+ return dbg_out(lcl_dbg_out(rPam));
+}
+
+String lcl_dbg_out(const SwNodeNum & )
+{
+ return String();/*rNum.ToString();*/
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwNodeNum & rNum)
+{
+ return dbg_out(lcl_dbg_out(rNum));
+}
+
+String lcl_dbg_out(const SwRect & rRect)
+{
+ String aResult("[ [", RTL_TEXTENCODING_ASCII_US);
+
+ aResult += String::CreateFromInt32(rRect.Left());
+ aResult += String(", ", RTL_TEXTENCODING_ASCII_US);
+ aResult += String::CreateFromInt32(rRect.Top());
+ aResult += String("], [", RTL_TEXTENCODING_ASCII_US);
+ aResult += String::CreateFromInt32(rRect.Right());
+ aResult += String(", ", RTL_TEXTENCODING_ASCII_US);
+ aResult += String::CreateFromInt32(rRect.Bottom());
+
+ aResult += String("] ]", RTL_TEXTENCODING_ASCII_US);
+
+ return aResult;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwRect & rRect)
+{
+ return dbg_out(lcl_dbg_out(rRect));
+}
+
+String lcl_dbg_out(const SwFrmFmt & rFrmFmt)
+{
+ String aResult("[ ", RTL_TEXTENCODING_ASCII_US);
+
+ char sBuffer[256];
+ sprintf(sBuffer, "%p", &rFrmFmt);
+
+ aResult += String(sBuffer, RTL_TEXTENCODING_ASCII_US);
+ aResult += String("(", RTL_TEXTENCODING_ASCII_US);
+ aResult += rFrmFmt.GetName();
+ aResult += String(")", RTL_TEXTENCODING_ASCII_US);
+
+ if (rFrmFmt.IsAuto())
+ aResult += String("*", RTL_TEXTENCODING_ASCII_US);
+
+ aResult += String(" ,", RTL_TEXTENCODING_ASCII_US);
+ aResult += lcl_dbg_out(rFrmFmt.FindLayoutRect());
+ aResult += String(" ]", RTL_TEXTENCODING_ASCII_US);
+
+ return aResult;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwFrmFmt & rFrmFmt)
+{
+ return dbg_out(lcl_dbg_out(rFrmFmt));
+}
+
+const String lcl_AnchoredFrames(const SwNode & rNode)
+{
+ String aResult("[", RTL_TEXTENCODING_ASCII_US);
+
+ const SwDoc * pDoc = rNode.GetDoc();
+ if (pDoc)
+ {
+ const SwSpzFrmFmts * pFrmFmts = pDoc->GetSpzFrmFmts();
+
+ if (pFrmFmts)
+ {
+ bool bFirst = true;
+ for (sal_uInt16 nI = 0; nI < pFrmFmts->Count(); nI++)
+ {
+ const SwFmtAnchor & rAnchor = (*pFrmFmts)[nI]->GetAnchor();
+ const SwPosition * pPos = rAnchor.GetCntntAnchor();
+
+ if (pPos && &pPos->nNode.GetNode() == &rNode)
+ {
+ if (! bFirst)
+ aResult += String(", ", RTL_TEXTENCODING_ASCII_US);
+
+ if ((*pFrmFmts)[nI])
+ aResult += lcl_dbg_out(*(*pFrmFmts)[nI]);
+ bFirst = false;
+ }
+ }
+ }
+ }
+
+ aResult += String("]", RTL_TEXTENCODING_ASCII_US);
+
+ return aResult;
+}
+
+String lcl_dbg_out_NumType(sal_Int16 nType)
+{
+ String aTmpStr;
+
+ switch (nType)
+ {
+ case SVX_NUM_NUMBER_NONE:
+ aTmpStr += String(" NONE", RTL_TEXTENCODING_ASCII_US);
+
+ break;
+ case SVX_NUM_CHARS_UPPER_LETTER:
+ aTmpStr += String(" CHARS_UPPER_LETTER",
+ RTL_TEXTENCODING_ASCII_US);
+
+ break;
+ case SVX_NUM_CHARS_LOWER_LETTER:
+ aTmpStr += String(" CHARS_LOWER_LETTER",
+ RTL_TEXTENCODING_ASCII_US);
+
+ break;
+ case SVX_NUM_ROMAN_UPPER:
+ aTmpStr += String(" ROMAN_UPPER",
+ RTL_TEXTENCODING_ASCII_US);
+
+ break;
+ case SVX_NUM_ROMAN_LOWER:
+ aTmpStr += String(" ROMAN_LOWER",
+ RTL_TEXTENCODING_ASCII_US);
+
+ break;
+ case SVX_NUM_ARABIC:
+ aTmpStr += String(" ARABIC",
+ RTL_TEXTENCODING_ASCII_US);
+
+ break;
+ default:
+ aTmpStr += String(" ??",
+ RTL_TEXTENCODING_ASCII_US);
+
+ break;
+ }
+
+ return aTmpStr;
+}
+
+String lcl_dbg_out(const SwNode & rNode)
+{
+ String aTmpStr;
+
+ aTmpStr += String("<node ", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += String("index=\"", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += String::CreateFromInt32(rNode.GetIndex());
+ aTmpStr += String("\"", RTL_TEXTENCODING_ASCII_US);
+
+#ifdef DBG_UTIL
+ aTmpStr += String(" serial=\"", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += String::CreateFromInt32(rNode.GetSerial());
+ aTmpStr += String("\"", RTL_TEXTENCODING_ASCII_US);
+#endif
+
+ aTmpStr += String(" type=\"", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += String::CreateFromInt32(sal_Int32( rNode.GetNodeType() ) );
+ aTmpStr += String("\"", RTL_TEXTENCODING_ASCII_US);
+
+ aTmpStr += String(" pointer=\"", RTL_TEXTENCODING_ASCII_US);
+
+ char aBuffer[128];
+ sprintf(aBuffer, "%p", &rNode);
+ aTmpStr += String(aBuffer, RTL_TEXTENCODING_ASCII_US);
+
+ aTmpStr += String("\">", RTL_TEXTENCODING_ASCII_US);
+
+ const SwTxtNode * pTxtNode = rNode.GetTxtNode();
+
+ if (rNode.IsTxtNode())
+ {
+ const SfxItemSet * pAttrSet = pTxtNode->GetpSwAttrSet();
+
+ aTmpStr += String("<txt>", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += pTxtNode->GetTxt().Copy(0, 10);
+ aTmpStr += String("</txt>", RTL_TEXTENCODING_ASCII_US);
+
+ if (rNode.IsTableNode())
+ aTmpStr += String("<tbl/>", RTL_TEXTENCODING_ASCII_US);
+
+ aTmpStr += String("<outlinelevel>", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += String::CreateFromInt32(pTxtNode->GetAttrOutlineLevel()-1);
+ aTmpStr += String("</outlinelevel>", RTL_TEXTENCODING_ASCII_US);
+
+ const SwNumRule * pNumRule = pTxtNode->GetNumRule();
+
+ if (pNumRule != NULL)
+ {
+ aTmpStr += String("<number>", RTL_TEXTENCODING_ASCII_US);
+ if ( pTxtNode->GetNum() )
+ {
+ aTmpStr += lcl_dbg_out(*(pTxtNode->GetNum()));
+ }
+ aTmpStr += String("</number>", RTL_TEXTENCODING_ASCII_US);
+
+ aTmpStr += String("<rule>", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += pNumRule->GetName();
+
+ const SfxPoolItem * pItem = NULL;
+
+ if (pAttrSet && SFX_ITEM_SET ==
+ pAttrSet->GetItemState(RES_PARATR_NUMRULE, sal_False, &pItem))
+ {
+ aTmpStr += String("(", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr +=
+ static_cast<const SwNumRuleItem *>(pItem)->GetValue();
+ aTmpStr += String(")", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += String("*", RTL_TEXTENCODING_ASCII_US);
+ }
+
+ const SwNumFmt * pNumFmt = NULL;
+ aTmpStr += String("</rule>", RTL_TEXTENCODING_ASCII_US);
+
+ if (pTxtNode->GetActualListLevel() > 0)
+ pNumFmt = pNumRule->GetNumFmt( static_cast< sal_uInt16 >(pTxtNode->GetActualListLevel()) );
+
+ if (pNumFmt)
+ {
+ aTmpStr += String("<numformat>", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr +=
+ lcl_dbg_out_NumType(pNumFmt->GetNumberingType());
+ aTmpStr += String("</numformat>", RTL_TEXTENCODING_ASCII_US);
+ }
+ }
+
+ if (pTxtNode->IsCountedInList())
+ aTmpStr += String("<counted/>", RTL_TEXTENCODING_ASCII_US);
+
+ SwFmtColl * pColl = pTxtNode->GetFmtColl();
+
+ if (pColl)
+ {
+ aTmpStr += String("<coll>", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += pColl->GetName();
+
+ aTmpStr += String("(", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += String::CreateFromInt32
+ //(static_cast<SwTxtFmtColl *>(pColl)->GetOutlineLevel());//#outline level,zhaojianwei
+ (static_cast<SwTxtFmtColl *>(pColl)->GetAssignedOutlineStyleLevel());//<-end,zhaojianwei
+
+ const SwNumRuleItem & rItem =
+ static_cast<const SwNumRuleItem &>
+ (pColl->GetFmtAttr(RES_PARATR_NUMRULE));
+ const String sNumruleName = rItem.GetValue();
+
+ if (sNumruleName.Len() > 0)
+ {
+ aTmpStr += String(", ", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += sNumruleName;
+ }
+ aTmpStr += String(")", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += String("</coll>", RTL_TEXTENCODING_ASCII_US);
+ }
+
+ SwFmtColl * pCColl = pTxtNode->GetCondFmtColl();
+
+ if (pCColl)
+ {
+ aTmpStr += String("<ccoll>", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += pCColl->GetName();
+ aTmpStr += String("</ccoll>", RTL_TEXTENCODING_ASCII_US);
+ }
+
+ aTmpStr += String("<frms>", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += lcl_AnchoredFrames(rNode);
+ aTmpStr += String("</frms>", RTL_TEXTENCODING_ASCII_US);
+
+ if (bDbgOutPrintAttrSet)
+ {
+ aTmpStr += String("<attrs>", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += lcl_dbg_out(pTxtNode->GetSwAttrSet());
+ aTmpStr += String("</attrs>", RTL_TEXTENCODING_ASCII_US);
+ }
+ }
+ else if (rNode.IsStartNode())
+ {
+ aTmpStr += String("<start end=\"", RTL_TEXTENCODING_ASCII_US);
+
+ const SwStartNode * pStartNode = dynamic_cast<const SwStartNode *> (&rNode);
+ if (pStartNode != NULL)
+ aTmpStr += String::CreateFromInt32(pStartNode->EndOfSectionNode()->GetIndex());
+
+ aTmpStr += String("\"/>", RTL_TEXTENCODING_ASCII_US);
+ }
+ else if (rNode.IsEndNode())
+ aTmpStr += String("<end/>", RTL_TEXTENCODING_ASCII_US);
+
+ aTmpStr += String("</node>", RTL_TEXTENCODING_ASCII_US);
+
+ return aTmpStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwNode & rNode)
+{
+ return dbg_out(lcl_dbg_out(rNode));
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwNode * pNode)
+{
+ if (NULL != pNode)
+ return dbg_out(*pNode);
+ else
+ return NULL;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwCntntNode * pNode)
+{
+ if (NULL != pNode)
+ return dbg_out(*pNode);
+ else
+ return NULL;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwTxtNode * pNode)
+{
+ if (NULL != pNode)
+ return dbg_out(*pNode);
+ else
+ return NULL;
+}
+
+sal_Bool lcl_dbg_add_node(const SwNodePtr & pNode, void * pArgs)
+{
+ if (pNode)
+ {
+ (*((String *) pArgs)) += lcl_dbg_out(*pNode);
+ (*((String *) pArgs)) += String("\n", RTL_TEXTENCODING_ASCII_US);
+ }
+
+ //MBA: this code didn't compile, needed to add a return value
+ return sal_True;
+}
+
+void lcl_dbg_nodes_inner(String & aStr, SwNodes & rNodes, sal_uLong & nIndex)
+{
+ SwNode * pNode = rNodes[nIndex];
+ SwStartNode * pStartNode = dynamic_cast<SwStartNode *> (pNode);
+
+ SwNode * pEndNode = NULL;
+ if (pStartNode != NULL)
+ pEndNode = pStartNode->EndOfSectionNode();
+
+ sal_uLong nCount = rNodes.Count();
+ sal_uLong nStartIndex = nIndex;
+
+ bool bDone = false;
+
+ String aTag;
+ if (pNode->IsTableNode())
+ aTag += String("table", RTL_TEXTENCODING_ASCII_US);
+ else if (pNode->IsSectionNode())
+ aTag += String("section", RTL_TEXTENCODING_ASCII_US);
+ else
+ aTag += String("nodes", RTL_TEXTENCODING_ASCII_US);
+
+ aStr += String("<", RTL_TEXTENCODING_ASCII_US);
+ aStr += aTag;
+ aStr += String(">", RTL_TEXTENCODING_ASCII_US);
+
+ while (! bDone)
+ {
+ if (pNode->IsStartNode() && nIndex != nStartIndex)
+ lcl_dbg_nodes_inner(aStr, rNodes, nIndex);
+ else
+ {
+ aStr += lcl_dbg_out(*pNode);
+ aStr += String("\n", RTL_TEXTENCODING_ASCII_US);
+
+ nIndex++;
+ }
+
+ if (pNode == pEndNode || nIndex >= nCount)
+ bDone = true;
+ else
+ pNode = rNodes[nIndex];
+ }
+
+ aStr += String("</", RTL_TEXTENCODING_ASCII_US);
+ aStr += aTag;
+ aStr += String(">\n", RTL_TEXTENCODING_ASCII_US);
+}
+
+String lcl_dbg_out(SwNodes & rNodes)
+{
+ String aStr("<nodes-array>", RTL_TEXTENCODING_ASCII_US);
+
+ sal_uLong nIndex = 0;
+ sal_uLong nCount = rNodes.Count();
+
+ while (nIndex < nCount)
+ {
+ lcl_dbg_nodes_inner(aStr, rNodes, nIndex);
+ }
+
+ aStr += String("</nodes-array>\n", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(SwNodes & rNodes)
+{
+ return dbg_out(lcl_dbg_out(rNodes));
+}
+
+String lcl_dbg_out(const SwUndo & rUndo)
+{
+ String aStr("[ ", RTL_TEXTENCODING_ASCII_US);
+
+ aStr += String::CreateFromInt32(
+ static_cast<SfxUndoAction const&>(rUndo).GetId());
+ aStr += String(": ", RTL_TEXTENCODING_ASCII_US);
+
+ aStr += rUndo.GetComment();
+ aStr += String(" ]", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwUndo & rUndo)
+{
+ return dbg_out(lcl_dbg_out(rUndo));
+}
+
+String lcl_dbg_out(SwOutlineNodes & rNodes)
+{
+ String aStr("[\n", RTL_TEXTENCODING_ASCII_US);
+
+ for (sal_uInt16 i = 0; i < rNodes.Count(); i++)
+ {
+ aStr += lcl_dbg_out(*rNodes[i]);
+ aStr += String("\n", RTL_TEXTENCODING_ASCII_US);
+ }
+
+ aStr += String("]\n", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(SwOutlineNodes & rNodes)
+{
+ return dbg_out(lcl_dbg_out(rNodes));
+}
+
+String lcl_dbg_out(const SwRewriter & rRewriter)
+{
+ (void) rRewriter;
+ String aResult;
+
+ //aResult = rRewriter.ToString();
+
+ return aResult;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwRewriter & rRewriter)
+{
+ return dbg_out(lcl_dbg_out(rRewriter));
+}
+
+String lcl_dbg_out(const SvxNumberFormat & rFmt)
+{
+ String aResult;
+
+ aResult = lcl_dbg_out_NumType(rFmt.GetNumberingType());
+
+ return aResult;
+}
+
+String lcl_dbg_out(const SwNumRule & rRule)
+{
+ String aResult("[ ", RTL_TEXTENCODING_ASCII_US);
+
+ aResult += rRule.GetName();
+ aResult += String(" [", RTL_TEXTENCODING_ASCII_US);
+
+ for (sal_uInt8 n = 0; n < MAXLEVEL; n++)
+ {
+ if (n > 0)
+ aResult += String(", ", RTL_TEXTENCODING_ASCII_US);
+
+ aResult += lcl_dbg_out(rRule.Get(n));
+ }
+
+ aResult += String("]", RTL_TEXTENCODING_ASCII_US);
+
+ aResult += String("]", RTL_TEXTENCODING_ASCII_US);
+
+ return aResult;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwNumRule & rRule)
+{
+ return dbg_out(lcl_dbg_out(rRule));
+}
+
+String lcl_dbg_out(const SwTxtFmtColl & rFmt)
+{
+ String aResult(rFmt.GetName());
+
+ aResult += String("(", RTL_TEXTENCODING_ASCII_US);
+ aResult += String::CreateFromInt32(rFmt.GetAttrOutlineLevel());
+ aResult += String(")", RTL_TEXTENCODING_ASCII_US);
+
+ return aResult;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwTxtFmtColl & rFmt)
+{
+ return dbg_out(lcl_dbg_out(rFmt));
+}
+
+String lcl_dbg_out(const SwFrmFmts & rFrmFmts)
+{
+ return lcl_dbg_out_SvPtrArr<SwFrmFmts>(rFrmFmts);
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwFrmFmts & rFrmFmts)
+{
+ return dbg_out(lcl_dbg_out(rFrmFmts));
+}
+
+String lcl_dbg_out(const SwNumRuleTbl & rTbl)
+{
+ String aResult("[", RTL_TEXTENCODING_ASCII_US);
+
+ for (sal_uInt16 n = 0; n < rTbl.Count(); n++)
+ {
+ if (n > 0)
+ aResult += String(", ", RTL_TEXTENCODING_ASCII_US);
+
+ aResult += rTbl[n]->GetName();
+
+ char sBuffer[256];
+ sprintf(sBuffer, "(%p)", rTbl[n]);
+ aResult += String(sBuffer, RTL_TEXTENCODING_ASCII_US);
+ }
+
+ aResult += String("]", RTL_TEXTENCODING_ASCII_US);
+
+ return aResult;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwNumRuleTbl & rTbl)
+{
+ return dbg_out(lcl_dbg_out(rTbl));
+}
+
+String lcl_TokenType2Str(FormTokenType nType)
+{
+ switch(nType)
+ {
+ case TOKEN_ENTRY_NO:
+ return String("NO", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_ENTRY_TEXT:
+ return String("ENTRY_TEXT", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_ENTRY:
+ return String("ENTRY", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_TAB_STOP:
+ return String("TAB_STOP", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_TEXT:
+ return String("TOKEN_TEXT", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_PAGE_NUMS:
+ return String("NUMS", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_CHAPTER_INFO:
+ return String("CHAPTER_INFO", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_LINK_START:
+ return String("LINK_START", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_LINK_END:
+ return String("LINK_END", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_AUTHORITY:
+ return String("AUTHORITY", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_END:
+ return String("END", RTL_TEXTENCODING_ASCII_US);
+ default:
+ return String("??", RTL_TEXTENCODING_ASCII_US);
+ }
+
+ ASSERT(false, "should not be reached");
+
+ return String("??", RTL_TEXTENCODING_ASCII_US);
+}
+
+String lcl_dbg_out(const SwFormToken & rToken)
+{
+ return rToken.GetString();
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwFormToken & rToken)
+{
+ return dbg_out(lcl_dbg_out(rToken));
+}
+
+String lcl_dbg_out(const SwFormTokens & rTokens)
+{
+ String aStr("[", RTL_TEXTENCODING_ASCII_US);
+
+ SwFormTokens::const_iterator aIt;
+
+ for (aIt = rTokens.begin(); aIt != rTokens.end(); aIt++)
+ {
+ if (aIt != rTokens.begin())
+ aStr += String(", ", RTL_TEXTENCODING_ASCII_US);
+
+ aStr += lcl_TokenType2Str(aIt->eTokenType);
+ aStr += String(": ", RTL_TEXTENCODING_ASCII_US);
+ aStr += lcl_dbg_out(*aIt);
+ }
+
+ aStr += String("]" , RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwFormTokens & rTokens)
+{
+ return dbg_out(lcl_dbg_out(rTokens));
+}
+
+String lcl_dbg_out(const SwNodeRange & rRange)
+{
+ String aStr("[", RTL_TEXTENCODING_ASCII_US);
+
+ aStr += lcl_dbg_out(SwPosition(rRange.aStart));
+ aStr += String(", ", RTL_TEXTENCODING_ASCII_US);
+ aStr += lcl_dbg_out(SwPosition(rRange.aEnd));
+
+ aStr += String("]" , RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwNodeRange & rRange)
+{
+ return dbg_out(lcl_dbg_out(rRange));
+}
+
+#endif // DEBUG
+
diff --git a/sw/source/core/doc/doc.cxx b/sw/source/core/doc/doc.cxx
new file mode 100644
index 000000000000..47dc02014aa7
--- /dev/null
+++ b/sw/source/core/doc/doc.cxx
@@ -0,0 +1,2836 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <doc.hxx>
+#include <UndoManager.hxx>
+#include <hintids.hxx>
+
+#include <tools/shl.hxx>
+#include <tools/globname.hxx>
+#include <svx/svxids.hrc>
+#include <com/sun/star/i18n/WordType.hdl>
+#include <com/sun/star/i18n/ForbiddenCharacters.hdl>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <comphelper/processfactory.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/poly.hxx>
+#include <tools/multisel.hxx>
+#include <rtl/ustring.hxx>
+#include <vcl/virdev.hxx>
+#include <svl/itemiter.hxx>
+#include <svl/poolitem.hxx>
+#include <unotools/syslocale.hxx>
+#include <sfx2/printer.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/cscoitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <editeng/forbiddencharacterstable.hxx>
+#include <svx/svdmodel.hxx>
+#include <editeng/pbinitem.hxx>
+#include <unotools/charclass.hxx>
+#include <unotools/localedatawrapper.hxx>
+
+#include <swatrset.hxx>
+#include <swmodule.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtanchr.hxx>
+#include <fmtrfmrk.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <dbfld.hxx>
+#include <txtinet.hxx>
+#include <txtrfmrk.hxx>
+#include <frmatr.hxx>
+#include <linkenum.hxx>
+#include <errhdl.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <swtable.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <UndoCore.hxx>
+#include <UndoInsert.hxx>
+#include <UndoSplitMove.hxx>
+#include <UndoTable.hxx>
+#include <pagedesc.hxx> //DTor
+#include <breakit.hxx>
+#include <ndole.hxx>
+#include <ndgrf.hxx>
+#include <rolbck.hxx> // Undo-Attr
+#include <doctxm.hxx> // fuer die Verzeichnisse
+#include <grfatr.hxx>
+#include <poolfmt.hxx> // PoolVorlagen-Id's
+#include <mvsave.hxx> // fuer Server-Funktionalitaet
+#include <SwGrammarMarkUp.hxx>
+#include <scriptinfo.hxx>
+#include <acorrect.hxx> // Autokorrektur
+#include <mdiexp.hxx> // Statusanzeige
+#include <docstat.hxx>
+#include <docary.hxx>
+#include <redline.hxx>
+#include <fldupde.hxx>
+#include <swbaslnk.hxx>
+#include <printdata.hxx>
+#include <cmdid.h> // fuer den dflt - Printer in SetJob
+#include <statstr.hrc> // StatLine-String
+#include <comcore.hrc>
+#include <SwUndoTOXChange.hxx>
+#include <SwUndoFmt.hxx>
+#include <unocrsr.hxx>
+#include <docsh.hxx>
+#include <docfld.hxx> // _SetGetExpFld
+#include <docufld.hxx> // SwPostItField
+#include <viewsh.hxx>
+#include <shellres.hxx>
+#include <txtfrm.hxx>
+#include <wdocsh.hxx> // SwWebDocShell
+#include <prtopt.hxx> // SwPrintOptions
+
+#include <vector>
+#include <map>
+
+#include <osl/diagnose.h>
+#include <osl/interlck.h>
+#include <vbahelper/vbaaccesshelper.hxx>
+
+/* @@@MAINTAINABILITY-HORROR@@@
+ Probably unwanted dependency on SwDocShell
+*/
+// --> OD 2005-08-29 #125370#
+#include <layouter.hxx>
+// <--
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+
+// Seiten-Deskriptoren
+SV_IMPL_PTRARR(SwPageDescs,SwPageDescPtr);
+// Verzeichnisse
+SV_IMPL_PTRARR( SwTOXTypes, SwTOXTypePtr )
+// FeldTypen
+SV_IMPL_PTRARR( SwFldTypes, SwFldTypePtr)
+
+/** IInterface
+*/
+sal_Int32 SwDoc::acquire()
+{
+ OSL_ASSERT(mReferenceCount >= 0 && "Negative reference count detected! This is a sign for unbalanced acquire/release calls.");
+ return osl_incrementInterlockedCount(&mReferenceCount);
+}
+
+sal_Int32 SwDoc::release()
+{
+ OSL_PRECOND(mReferenceCount >= 1, "Object is already released! Releasing it again leads to a negative reference count.");
+ return osl_decrementInterlockedCount(&mReferenceCount);
+}
+
+sal_Int32 SwDoc::getReferenceCount() const
+{
+ OSL_ASSERT(mReferenceCount >= 0 && "Negative reference count detected! This is a sign for unbalanced acquire/release calls.");
+ return mReferenceCount;
+}
+
+/** IDocumentSettingAccess
+*/
+bool SwDoc::get(/*[in]*/ DocumentSettingId id) const
+{
+ switch (id)
+ {
+ // COMPATIBILITY FLAGS START
+ case PARA_SPACE_MAX: return mbParaSpaceMax; //(n8Dummy1 & DUMMY_PARASPACEMAX);
+ case PARA_SPACE_MAX_AT_PAGES: return mbParaSpaceMaxAtPages; //(n8Dummy1 & DUMMY_PARASPACEMAX_AT_PAGES);
+ case TAB_COMPAT: return mbTabCompat; //(n8Dummy1 & DUMMY_TAB_COMPAT);
+ case ADD_FLY_OFFSETS: return mbAddFlyOffsets; //(n8Dummy2 & DUMMY_ADD_FLY_OFFSETS);
+ case ADD_EXT_LEADING: return mbAddExternalLeading; //(n8Dummy2 & DUMMY_ADD_EXTERNAL_LEADING);
+ case USE_VIRTUAL_DEVICE: return mbUseVirtualDevice; //(n8Dummy1 & DUMMY_USE_VIRTUAL_DEVICE);
+ case USE_HIRES_VIRTUAL_DEVICE: return mbUseHiResolutionVirtualDevice; //(n8Dummy2 & DUMMY_USE_HIRES_VIR_DEV);
+ case OLD_NUMBERING: return mbOldNumbering;
+ case OLD_LINE_SPACING: return mbOldLineSpacing;
+ case ADD_PARA_SPACING_TO_TABLE_CELLS: return mbAddParaSpacingToTableCells;
+ case USE_FORMER_OBJECT_POS: return mbUseFormerObjectPos;
+ case USE_FORMER_TEXT_WRAPPING: return mbUseFormerTextWrapping;
+ case CONSIDER_WRAP_ON_OBJECT_POSITION: return mbConsiderWrapOnObjPos;
+ case DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK: return mbDoNotJustifyLinesWithManualBreak;
+ case IGNORE_FIRST_LINE_INDENT_IN_NUMBERING: return mbIgnoreFirstLineIndentInNumbering;
+ case OUTLINE_LEVEL_YIELDS_OUTLINE_RULE: return mbOutlineLevelYieldsOutlineRule;
+ case TABLE_ROW_KEEP: return mbTableRowKeep;
+ case IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION: return mbIgnoreTabsAndBlanksForLineCalculation;
+ case DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE: return mbDoNotCaptureDrawObjsOnPage;
+ // --> OD 2006-08-25 #i68949#
+ case CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAME: return mbClipAsCharacterAnchoredWriterFlyFrames;
+ // <--
+ case UNIX_FORCE_ZERO_EXT_LEADING: return mbUnixForceZeroExtLeading;
+ case USE_OLD_PRINTER_METRICS: return mbOldPrinterMetrics;
+ case TABS_RELATIVE_TO_INDENT : return mbTabRelativeToIndent;
+ case PROTECT_FORM: return mbProtectForm;
+ // --> OD 2008-06-05 #i89181#
+ case TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST: return mbTabAtLeftIndentForParagraphsInList;
+ // <--
+ // COMPATIBILITY FLAGS END
+
+ case BROWSE_MODE: return mbBrowseMode;
+ case HTML_MODE: return mbHTMLMode;
+ case GLOBAL_DOCUMENT: return mbIsGlobalDoc;
+ case GLOBAL_DOCUMENT_SAVE_LINKS: return mbGlblDocSaveLinks;
+ case LABEL_DOCUMENT: return mbIsLabelDoc;
+ case PURGE_OLE: return mbPurgeOLE;
+ case KERN_ASIAN_PUNCTUATION: return mbKernAsianPunctuation;
+ case DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT: return mbDoNotResetParaAttrsForNumFont;
+ case MATH_BASELINE_ALIGNMENT: return mbMathBaselineAlignment;
+ default:
+ ASSERT(false, "Invalid setting id");
+ }
+ return false;
+}
+
+void SwDoc::set(/*[in]*/ DocumentSettingId id, /*[in]*/ bool value)
+{
+ switch (id)
+ {
+ // COMPATIBILITY FLAGS START
+ case PARA_SPACE_MAX:
+ mbParaSpaceMax = value;
+ break;
+ case PARA_SPACE_MAX_AT_PAGES:
+ mbParaSpaceMaxAtPages = value;
+ break;
+ case TAB_COMPAT:
+ mbTabCompat = value;
+ break;
+ case ADD_FLY_OFFSETS:
+ mbAddFlyOffsets = value;
+ break;
+ case ADD_EXT_LEADING:
+ mbAddExternalLeading = value;
+ break;
+ case USE_VIRTUAL_DEVICE:
+ mbUseVirtualDevice = value;
+ break;
+ case USE_HIRES_VIRTUAL_DEVICE:
+ mbUseHiResolutionVirtualDevice = value;
+ break;
+ case OLD_NUMBERING:
+ if (mbOldNumbering != value)
+ {
+ mbOldNumbering = value;
+
+ const SwNumRuleTbl& rNmTbl = GetNumRuleTbl();
+ for( sal_uInt16 n = 0; n < rNmTbl.Count(); ++n )
+ rNmTbl[n]->SetInvalidRule(sal_True);
+
+ UpdateNumRule();
+
+ if (pOutlineRule)
+ {
+ pOutlineRule->Validate();
+ // --> OD 2005-10-21 - counting of phantoms depends on <IsOldNumbering()>
+ pOutlineRule->SetCountPhantoms( !mbOldNumbering );
+ // <--
+ }
+ }
+ break;
+ case OLD_LINE_SPACING:
+ mbOldLineSpacing = value;
+ break;
+ case ADD_PARA_SPACING_TO_TABLE_CELLS:
+ mbAddParaSpacingToTableCells = value;
+ break;
+ case USE_FORMER_OBJECT_POS:
+ mbUseFormerObjectPos = value;
+ break;
+ case USE_FORMER_TEXT_WRAPPING:
+ mbUseFormerTextWrapping = value;
+ break;
+ case CONSIDER_WRAP_ON_OBJECT_POSITION:
+ mbConsiderWrapOnObjPos = value;
+ break;
+ case DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK:
+ mbDoNotJustifyLinesWithManualBreak = value;
+ break;
+ case IGNORE_FIRST_LINE_INDENT_IN_NUMBERING:
+ mbIgnoreFirstLineIndentInNumbering = value;
+ break;
+
+ case OUTLINE_LEVEL_YIELDS_OUTLINE_RULE:
+ mbOutlineLevelYieldsOutlineRule = value;
+ break;
+
+ case TABLE_ROW_KEEP:
+ mbTableRowKeep = value;
+ break;
+
+ case IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION:
+ mbIgnoreTabsAndBlanksForLineCalculation = value;
+ break;
+
+ case DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE:
+ mbDoNotCaptureDrawObjsOnPage = value;
+ break;
+
+ // --> OD 2006-08-25 #i68949#
+ case CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAME:
+ mbClipAsCharacterAnchoredWriterFlyFrames = value;
+ break;
+ // <--
+ case UNIX_FORCE_ZERO_EXT_LEADING:
+ mbUnixForceZeroExtLeading = value;
+ break;
+ case PROTECT_FORM:
+ mbProtectForm = value;
+ break;
+
+ case USE_OLD_PRINTER_METRICS:
+ mbOldPrinterMetrics = value;
+ break;
+ case TABS_RELATIVE_TO_INDENT:
+ mbTabRelativeToIndent = value;
+ break;
+ // --> OD 2008-06-05 #i89181#
+ case TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST:
+ mbTabAtLeftIndentForParagraphsInList = value;
+ break;
+ // <--
+ // COMPATIBILITY FLAGS END
+
+ case BROWSE_MODE:
+ mbBrowseMode = value;
+ break;
+ case HTML_MODE:
+ mbHTMLMode = value;
+ break;
+ case GLOBAL_DOCUMENT:
+ mbIsGlobalDoc = value;
+ break;
+ case GLOBAL_DOCUMENT_SAVE_LINKS:
+ mbGlblDocSaveLinks = value;
+ break;
+ case LABEL_DOCUMENT:
+ mbIsLabelDoc = value;
+ break;
+ case PURGE_OLE:
+ mbPurgeOLE = value;
+ break;
+ case KERN_ASIAN_PUNCTUATION:
+ mbKernAsianPunctuation = value;
+ break;
+ case DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT:
+ mbDoNotResetParaAttrsForNumFont = value;
+ break;
+ case MATH_BASELINE_ALIGNMENT:
+ mbMathBaselineAlignment = value;
+ break;
+ default:
+ ASSERT(false, "Invalid setting id");
+ }
+}
+
+const i18n::ForbiddenCharacters*
+ SwDoc::getForbiddenCharacters(/*[in]*/ sal_uInt16 nLang, /*[in]*/ bool bLocaleData ) const
+{
+ const i18n::ForbiddenCharacters* pRet = 0;
+ if( xForbiddenCharsTable.isValid() )
+ pRet = xForbiddenCharsTable->GetForbiddenCharacters( nLang, sal_False );
+ if( bLocaleData && !pRet && pBreakIt )
+ pRet = &pBreakIt->GetForbidden( (LanguageType)nLang );
+ return pRet;
+}
+
+void SwDoc::setForbiddenCharacters(/*[in]*/ sal_uInt16 nLang,
+ /*[in]*/ const i18n::ForbiddenCharacters& rFChars )
+{
+ if( !xForbiddenCharsTable.isValid() )
+ {
+ uno::Reference<
+ lang::XMultiServiceFactory > xMSF =
+ ::comphelper::getProcessServiceFactory();
+ xForbiddenCharsTable = new SvxForbiddenCharactersTable( xMSF );
+ }
+ xForbiddenCharsTable->SetForbiddenCharacters( nLang, rFChars );
+ if( pDrawModel )
+ {
+ pDrawModel->SetForbiddenCharsTable( xForbiddenCharsTable );
+ if( !mbInReading )
+ pDrawModel->ReformatAllTextObjects();
+ }
+
+ if( pLayout && !mbInReading )
+ {
+ pLayout->StartAllAction();
+ pLayout->InvalidateAllCntnt();
+ pLayout->EndAllAction();
+ }
+ SetModified();
+}
+
+vos::ORef<SvxForbiddenCharactersTable>& SwDoc::getForbiddenCharacterTable()
+{
+ if( !xForbiddenCharsTable.isValid() )
+ {
+ uno::Reference<
+ lang::XMultiServiceFactory > xMSF =
+ ::comphelper::getProcessServiceFactory();
+ xForbiddenCharsTable = new SvxForbiddenCharactersTable( xMSF );
+ }
+ return xForbiddenCharsTable;
+}
+
+const vos::ORef<SvxForbiddenCharactersTable>& SwDoc::getForbiddenCharacterTable() const
+{
+ return xForbiddenCharsTable;
+}
+
+sal_uInt16 SwDoc::getLinkUpdateMode( /*[in]*/bool bGlobalSettings ) const
+{
+ sal_uInt16 nRet = nLinkUpdMode;
+ if( bGlobalSettings && GLOBALSETTING == nRet )
+ nRet = SW_MOD()->GetLinkUpdMode(get(IDocumentSettingAccess::HTML_MODE));
+ return nRet;
+}
+
+void SwDoc::setLinkUpdateMode( /*[in]*/sal_uInt16 eMode )
+{
+ nLinkUpdMode = eMode;
+}
+
+SwFldUpdateFlags SwDoc::getFieldUpdateFlags( /*[in]*/bool bGlobalSettings ) const
+{
+ SwFldUpdateFlags eRet = eFldUpdMode;
+ if( bGlobalSettings && AUTOUPD_GLOBALSETTING == eRet )
+ eRet = SW_MOD()->GetFldUpdateFlags(get(IDocumentSettingAccess::HTML_MODE));
+ return eRet;
+}
+
+void SwDoc::setFieldUpdateFlags(/*[in]*/SwFldUpdateFlags eMode )
+{
+ eFldUpdMode = eMode;
+}
+
+SwCharCompressType SwDoc::getCharacterCompressionType() const
+{
+ return eChrCmprType;
+}
+
+void SwDoc::setCharacterCompressionType( /*[in]*/SwCharCompressType n )
+{
+ if( eChrCmprType != n )
+ {
+ eChrCmprType = n;
+ if( pDrawModel )
+ {
+ pDrawModel->SetCharCompressType( static_cast<sal_uInt16>(n) );
+ if( !mbInReading )
+ pDrawModel->ReformatAllTextObjects();
+ }
+
+ if( pLayout && !mbInReading )
+ {
+ pLayout->StartAllAction();
+ pLayout->InvalidateAllCntnt();
+ pLayout->EndAllAction();
+ }
+ SetModified();
+ }
+}
+
+/** IDocumentDeviceAccess
+*/
+SfxPrinter* SwDoc::getPrinter(/*[in]*/ bool bCreate ) const
+{
+ SfxPrinter* pRet = 0;
+ if ( !bCreate || pPrt )
+ pRet = pPrt;
+ else
+ pRet = &CreatePrinter_();
+
+ return pRet;
+}
+
+void SwDoc::setPrinter(/*[in]*/ SfxPrinter *pP,/*[in]*/ bool bDeleteOld,/*[in]*/ bool bCallPrtDataChanged )
+{
+ if ( pP != pPrt )
+ {
+ if ( bDeleteOld )
+ delete pPrt;
+ pPrt = pP;
+
+ // our printer should always use TWIP. Don't rely on this being set in ViewShell::InitPrt, there
+ // are situations where this isn't called.
+ // #i108712# / 2010-02-26 / frank.schoenheit@sun.com
+ if ( pPrt )
+ {
+ MapMode aMapMode( pPrt->GetMapMode() );
+ aMapMode.SetMapUnit( MAP_TWIP );
+ pPrt->SetMapMode( aMapMode );
+ }
+
+ if ( pDrawModel && !get( IDocumentSettingAccess::USE_VIRTUAL_DEVICE ) )
+ pDrawModel->SetRefDevice( pPrt );
+ }
+
+ if ( bCallPrtDataChanged &&
+ // --> FME 2005-01-21 #i41075# Do not call PrtDataChanged() if we do not
+ // use the printer for formatting:
+ !get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) )
+ // <--
+ PrtDataChanged();
+}
+
+VirtualDevice* SwDoc::getVirtualDevice(/*[in]*/ bool bCreate ) const
+{
+ VirtualDevice* pRet = 0;
+ if ( !bCreate || pVirDev )
+ pRet = pVirDev;
+ else
+ pRet = &CreateVirtualDevice_();
+
+ return pRet;
+}
+
+void SwDoc::setVirtualDevice(/*[in]*/ VirtualDevice* pVd,/*[in]*/ bool bDeleteOld, /*[in]*/ bool )
+{
+ if ( pVirDev != pVd )
+ {
+ if ( bDeleteOld )
+ delete pVirDev;
+ pVirDev = pVd;
+
+ if ( pDrawModel && get( IDocumentSettingAccess::USE_VIRTUAL_DEVICE ) )
+ pDrawModel->SetRefDevice( pVirDev );
+ }
+}
+
+OutputDevice* SwDoc::getReferenceDevice(/*[in]*/ bool bCreate ) const
+{
+ OutputDevice* pRet = 0;
+ if ( !get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) )
+ {
+ pRet = getPrinter( bCreate );
+
+ if ( bCreate && !pPrt->IsValid() )
+ {
+ pRet = getVirtualDevice( sal_True );
+ }
+ }
+ else
+ {
+ pRet = getVirtualDevice( bCreate );
+ }
+
+ return pRet;
+}
+
+void SwDoc::setReferenceDeviceType(/*[in]*/ bool bNewVirtual,/*[in]*/ bool bNewHiRes )
+{
+ if ( get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) != bNewVirtual ||
+ get(IDocumentSettingAccess::USE_HIRES_VIRTUAL_DEVICE) != bNewHiRes )
+ {
+ if ( bNewVirtual )
+ {
+ VirtualDevice* pMyVirDev = getVirtualDevice( true );
+ if ( !bNewHiRes )
+ pMyVirDev->SetReferenceDevice( VirtualDevice::REFDEV_MODE06 );
+ else
+ pMyVirDev->SetReferenceDevice( VirtualDevice::REFDEV_MODE_MSO1 );
+
+ if( pDrawModel )
+ pDrawModel->SetRefDevice( pMyVirDev );
+ }
+ else
+ {
+ // --> FME 2005-01-21 #i41075#
+ // We have to take care that a printer exists before calling
+ // PrtDataChanged() in order to prevent that PrtDataChanged()
+ // triggers this funny situation:
+ // getReferenceDevice()->getPrinter()->CreatePrinter_()
+ // ->setPrinter()-> PrtDataChanged()
+ SfxPrinter* pPrinter = getPrinter( true );
+ // <--
+ if( pDrawModel )
+ pDrawModel->SetRefDevice( pPrinter );
+ }
+
+ set(IDocumentSettingAccess::USE_VIRTUAL_DEVICE, bNewVirtual );
+ set(IDocumentSettingAccess::USE_HIRES_VIRTUAL_DEVICE, bNewHiRes );
+ PrtDataChanged();
+ SetModified();
+ }
+}
+
+const JobSetup* SwDoc::getJobsetup() const
+{
+ return pPrt ? &pPrt->GetJobSetup() : 0;
+}
+
+void SwDoc::setJobsetup(/*[in]*/ const JobSetup &rJobSetup )
+{
+ sal_Bool bCheckPageDescs = 0 == pPrt;
+ sal_Bool bDataChanged = sal_False;
+
+ if ( pPrt )
+ {
+ if ( pPrt->GetName() == rJobSetup.GetPrinterName() )
+ {
+ if ( pPrt->GetJobSetup() != rJobSetup )
+ {
+ pPrt->SetJobSetup( rJobSetup );
+ bDataChanged = sal_True;
+ }
+ }
+ else
+ delete pPrt, pPrt = 0;
+ }
+
+ if( !pPrt )
+ {
+ //Das ItemSet wird vom Sfx geloescht!
+ SfxItemSet *pSet = new SfxItemSet( GetAttrPool(),
+ FN_PARAM_ADDPRINTER, FN_PARAM_ADDPRINTER,
+ SID_HTML_MODE, SID_HTML_MODE,
+ SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
+ SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
+ 0 );
+ SfxPrinter *p = new SfxPrinter( pSet, rJobSetup );
+ if ( bCheckPageDescs )
+ setPrinter( p, true, true );
+ else
+ {
+ pPrt = p;
+ bDataChanged = sal_True;
+ }
+ }
+ if ( bDataChanged && !get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) )
+ PrtDataChanged();
+}
+
+const SwPrintData & SwDoc::getPrintData() const
+{
+ if(!pPrtData)
+ {
+ SwDoc * pThis = const_cast< SwDoc * >(this);
+ pThis->pPrtData = new SwPrintData;
+
+ // SwPrintData should be initialized from the configuration,
+ // the respective config item is implememted by SwPrintOptions which
+ // is also derived from SwPrintData
+ const SwDocShell *pDocSh = GetDocShell();
+ DBG_ASSERT( pDocSh, "pDocSh is 0, can't determine if this is a WebDoc or not" );
+ bool bWeb = 0 != dynamic_cast< const SwWebDocShell * >(pDocSh);
+ SwPrintOptions aPrintOptions( bWeb );
+ *pThis->pPrtData = aPrintOptions;
+ }
+ return *pPrtData;
+}
+
+void SwDoc::setPrintData(/*[in]*/ const SwPrintData& rPrtData )
+{
+ if(!pPrtData)
+ pPrtData = new SwPrintData;
+ *pPrtData = rPrtData;
+}
+
+/** Implementations the next Interface here
+*/
+
+/*
+ * Dokumenteditieren (Doc-SS) zum Fuellen des Dokuments
+ * durch den RTF Parser und fuer die EditShell.
+ */
+void SwDoc::ChgDBData(const SwDBData& rNewData)
+{
+ if( rNewData != aDBData )
+ {
+ aDBData = rNewData;
+ SetModified();
+ }
+ GetSysFldType(RES_DBNAMEFLD)->UpdateFlds();
+}
+
+bool SwDoc::SplitNode( const SwPosition &rPos, bool bChkTableStart )
+{
+ SwCntntNode *pNode = rPos.nNode.GetNode().GetCntntNode();
+ if(0 == pNode)
+ return false;
+
+ {
+ // Bug 26675: DataChanged vorm loeschen verschicken, dann bekommt
+ // man noch mit, welche Objecte sich im Bereich befinden.
+ // Danach koennen sie vor/hinter der Position befinden.
+ SwDataChanged aTmp( this, rPos, 0 );
+ }
+
+ SwUndoSplitNode* pUndo = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ // einfuegen vom Undo-Object, z.Z. nur beim TextNode
+ if( pNode->IsTxtNode() )
+ {
+ pUndo = new SwUndoSplitNode( this, rPos, bChkTableStart );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ }
+
+ //JP 28.01.97: Sonderfall fuer SplitNode am Tabellenanfang:
+ // steht die am Doc/Fly/Footer/..-Anfang oder direkt
+ // hinter einer Tabelle, dann fuege davor
+ // einen Absatz ein
+ if( bChkTableStart && !rPos.nContent.GetIndex() && pNode->IsTxtNode() )
+ {
+ sal_uLong nPrevPos = rPos.nNode.GetIndex() - 1;
+ const SwTableNode* pTblNd;
+ const SwNode* pNd = GetNodes()[ nPrevPos ];
+ if( pNd->IsStartNode() &&
+ SwTableBoxStartNode == ((SwStartNode*)pNd)->GetStartNodeType() &&
+ 0 != ( pTblNd = GetNodes()[ --nPrevPos ]->GetTableNode() ) &&
+ ((( pNd = GetNodes()[ --nPrevPos ])->IsStartNode() &&
+ SwTableBoxStartNode != ((SwStartNode*)pNd)->GetStartNodeType() )
+ || ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsTableNode() )
+ || pNd->IsCntntNode() ))
+ {
+ if( pNd->IsCntntNode() )
+ {
+ //JP 30.04.99 Bug 65660:
+ // ausserhalb des normalen BodyBereiches gibt es keine
+ // Seitenumbrueche, also ist das hier kein gueltige
+ // Bedingung fuers einfuegen eines Absatzes
+ if( nPrevPos < GetNodes().GetEndOfExtras().GetIndex() )
+ pNd = 0;
+ else
+ {
+ // Dann nur, wenn die Tabelle Umbrueche traegt!
+ const SwFrmFmt* pFrmFmt = pTblNd->GetTable().GetFrmFmt();
+ if( SFX_ITEM_SET != pFrmFmt->GetItemState(RES_PAGEDESC, sal_False) &&
+ SFX_ITEM_SET != pFrmFmt->GetItemState( RES_BREAK, sal_False ) )
+ pNd = 0;
+ }
+ }
+
+ if( pNd )
+ {
+ SwTxtNode* pTxtNd = GetNodes().MakeTxtNode(
+ SwNodeIndex( *pTblNd ),
+ GetTxtCollFromPool( RES_POOLCOLL_TEXT ));
+ if( pTxtNd )
+ {
+ ((SwPosition&)rPos).nNode = pTblNd->GetIndex()-1;
+ ((SwPosition&)rPos).nContent.Assign( pTxtNd, 0 );
+
+ // nur im BodyBereich den SeitenUmbruch/-Vorlage umhaengem
+ if( nPrevPos > GetNodes().GetEndOfExtras().GetIndex() )
+ {
+ SwFrmFmt* pFrmFmt = pTblNd->GetTable().GetFrmFmt();
+ const SfxPoolItem *pItem;
+ if( SFX_ITEM_SET == pFrmFmt->GetItemState( RES_PAGEDESC,
+ sal_False, &pItem ) )
+ {
+ pTxtNd->SetAttr( *pItem );
+ pFrmFmt->ResetFmtAttr( RES_PAGEDESC );
+ }
+ if( SFX_ITEM_SET == pFrmFmt->GetItemState( RES_BREAK,
+ sal_False, &pItem ) )
+ {
+ pTxtNd->SetAttr( *pItem );
+ pFrmFmt->ResetFmtAttr( RES_BREAK );
+ }
+ }
+
+ if( pUndo )
+ pUndo->SetTblFlag();
+ SetModified();
+ return true;
+ }
+ }
+ }
+ }
+
+ SvULongs aBkmkArr( 15, 15 );
+ _SaveCntntIdx( this, rPos.nNode.GetIndex(), rPos.nContent.GetIndex(),
+ aBkmkArr, SAVEFLY_SPLIT );
+ // FIXME: only SwTxtNode has a valid implementation of SplitCntntNode!
+ ASSERT(pNode->IsTxtNode(), "splitting non-text node?");
+ pNode = pNode->SplitCntntNode( rPos );
+ if (pNode)
+ {
+ // verschiebe noch alle Bookmarks/TOXMarks/FlyAtCnt
+ if( aBkmkArr.Count() )
+ _RestoreCntntIdx( this, aBkmkArr, rPos.nNode.GetIndex()-1, 0, sal_True );
+
+ if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() ))
+ {
+ SwPaM aPam( rPos );
+ aPam.SetMark();
+ aPam.Move( fnMoveBackward );
+ if( IsRedlineOn() )
+ AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
+ else
+ SplitRedline( aPam );
+ }
+ }
+
+ SetModified();
+ return true;
+}
+
+bool SwDoc::AppendTxtNode( SwPosition& rPos )
+{
+ // create new node before EndOfContent
+ SwTxtNode * pCurNode = rPos.nNode.GetNode().GetTxtNode();
+ if( !pCurNode )
+ {
+ // dann kann ja einer angelegt werden!
+ SwNodeIndex aIdx( rPos.nNode, 1 );
+ pCurNode = GetNodes().MakeTxtNode( aIdx,
+ GetTxtCollFromPool( RES_POOLCOLL_STANDARD ));
+ }
+ else
+ pCurNode = (SwTxtNode*)pCurNode->AppendNode( rPos );
+
+ rPos.nNode++;
+ rPos.nContent.Assign( pCurNode, 0 );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoInsert( rPos.nNode ) );
+ }
+
+ if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() ))
+ {
+ SwPaM aPam( rPos );
+ aPam.SetMark();
+ aPam.Move( fnMoveBackward );
+ if( IsRedlineOn() )
+ AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
+ else
+ SplitRedline( aPam );
+ }
+
+ SetModified();
+ return sal_True;
+}
+
+bool SwDoc::InsertString( const SwPaM &rRg, const String &rStr,
+ const enum InsertFlags nInsertMode )
+{
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo(); // AppendUndo not always called!
+ }
+
+ const SwPosition& rPos = *rRg.GetPoint();
+
+ if( pACEWord ) // Aufnahme in die Autokorrektur
+ {
+ if( 1 == rStr.Len() && pACEWord->IsDeleted() )
+ {
+ pACEWord->CheckChar( rPos, rStr.GetChar( 0 ) );
+ }
+ delete pACEWord, pACEWord = 0;
+ }
+
+ SwTxtNode *const pNode = rPos.nNode.GetNode().GetTxtNode();
+ if(!pNode)
+ {
+ return false;
+ }
+
+ SwDataChanged aTmp( rRg, 0 );
+
+ if (!GetIDocumentUndoRedo().DoesUndo() ||
+ !GetIDocumentUndoRedo().DoesGroupUndo())
+ {
+ pNode->InsertText( rStr, rPos.nContent, nInsertMode );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoInsert * const pUndo( new SwUndoInsert(
+ rPos.nNode, rPos.nContent.GetIndex(), rStr.Len(), nInsertMode));
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ }
+ else
+ { // ist Undo und Gruppierung eingeschaltet, ist alles anders !
+ SwUndoInsert * pUndo = NULL; // #111827#
+
+ // don't group the start if hints at the start should be expanded
+ if (!(nInsertMode & IDocumentContentOperations::INS_FORCEHINTEXPAND))
+ // -> #111827#
+ {
+ SwUndo *const pLastUndo = GetUndoManager().GetLastUndo();
+ SwUndoInsert *const pUndoInsert(
+ dynamic_cast<SwUndoInsert *>(pLastUndo) );
+ if (pUndoInsert && pUndoInsert->CanGrouping(rPos))
+ {
+ pUndo = pUndoInsert;
+ }
+ }
+ // <- #111827#
+
+ CharClass const& rCC = GetAppCharClass();
+ xub_StrLen nInsPos = rPos.nContent.GetIndex();
+
+ if (!pUndo)
+ {
+ pUndo = new SwUndoInsert( rPos.nNode, nInsPos, 0, nInsertMode,
+ !rCC.isLetterNumeric( rStr, 0 ) );
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+
+ pNode->InsertText( rStr, rPos.nContent, nInsertMode );
+
+ for( xub_StrLen i = 0; i < rStr.Len(); ++i )
+ {
+ nInsPos++;
+ // wenn CanGrouping() sal_True returnt, ist schon alles erledigt
+ if( !pUndo->CanGrouping( rStr.GetChar( i ) ))
+ {
+ pUndo = new SwUndoInsert( rPos.nNode, nInsPos, 1, nInsertMode,
+ !rCC.isLetterNumeric( rStr, i ) );
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ }
+ }
+
+ if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() ))
+ {
+ SwPaM aPam( rPos.nNode, aTmp.GetCntnt(),
+ rPos.nNode, rPos.nContent.GetIndex());
+ if( IsRedlineOn() )
+ {
+ AppendRedline(
+ new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
+ }
+ else
+ {
+ SplitRedline( aPam );
+ }
+ }
+
+ SetModified();
+ return true;
+}
+
+SwFlyFrmFmt* SwDoc::_InsNoTxtNode( const SwPosition& rPos, SwNoTxtNode* pNode,
+ const SfxItemSet* pFlyAttrSet,
+ const SfxItemSet* pGrfAttrSet,
+ SwFrmFmt* pFrmFmt)
+{
+ SwFlyFrmFmt *pFmt = 0;
+ if( pNode )
+ {
+ pFmt = _MakeFlySection( rPos, *pNode, FLY_AT_PARA,
+ pFlyAttrSet, pFrmFmt );
+ if( pGrfAttrSet )
+ pNode->SetAttr( *pGrfAttrSet );
+ }
+ return pFmt;
+}
+
+SwFlyFrmFmt* SwDoc::Insert( const SwPaM &rRg,
+ const String& rGrfName,
+ const String& rFltName,
+ const Graphic* pGraphic,
+ const SfxItemSet* pFlyAttrSet,
+ const SfxItemSet* pGrfAttrSet,
+ SwFrmFmt* pFrmFmt )
+{
+ if( !pFrmFmt )
+ pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_GRAPHIC );
+ return _InsNoTxtNode( *rRg.GetPoint(), GetNodes().MakeGrfNode(
+ SwNodeIndex( GetNodes().GetEndOfAutotext() ),
+ rGrfName, rFltName, pGraphic,
+ pDfltGrfFmtColl ),
+ pFlyAttrSet, pGrfAttrSet, pFrmFmt );
+}
+SwFlyFrmFmt* SwDoc::Insert( const SwPaM &rRg, const GraphicObject& rGrfObj,
+ const SfxItemSet* pFlyAttrSet,
+ const SfxItemSet* pGrfAttrSet,
+ SwFrmFmt* pFrmFmt )
+{
+ if( !pFrmFmt )
+ pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_GRAPHIC );
+ return _InsNoTxtNode( *rRg.GetPoint(), GetNodes().MakeGrfNode(
+ SwNodeIndex( GetNodes().GetEndOfAutotext() ),
+ rGrfObj, pDfltGrfFmtColl ),
+ pFlyAttrSet, pGrfAttrSet, pFrmFmt );
+}
+
+SwFlyFrmFmt* SwDoc::Insert(const SwPaM &rRg, const svt::EmbeddedObjectRef& xObj,
+ const SfxItemSet* pFlyAttrSet,
+ const SfxItemSet* pGrfAttrSet,
+ SwFrmFmt* pFrmFmt )
+{
+ if( !pFrmFmt )
+ {
+ sal_uInt16 nId = RES_POOLFRM_OLE;
+ SvGlobalName aClassName( xObj->getClassID() );
+ if (SotExchange::IsMath(aClassName))
+ nId = RES_POOLFRM_FORMEL;
+
+ pFrmFmt = GetFrmFmtFromPool( nId );
+ }
+ return _InsNoTxtNode( *rRg.GetPoint(), GetNodes().MakeOLENode(
+ SwNodeIndex( GetNodes().GetEndOfAutotext() ),
+ xObj,
+ pDfltGrfFmtColl ),
+ pFlyAttrSet, pGrfAttrSet,
+ pFrmFmt );
+}
+
+SwFlyFrmFmt* SwDoc::InsertOLE(const SwPaM &rRg, const String& rObjName,
+ sal_Int64 nAspect,
+ const SfxItemSet* pFlyAttrSet,
+ const SfxItemSet* pGrfAttrSet,
+ SwFrmFmt* pFrmFmt )
+{
+ if( !pFrmFmt )
+ pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_OLE );
+
+ return _InsNoTxtNode( *rRg.GetPoint(),
+ GetNodes().MakeOLENode(
+ SwNodeIndex( GetNodes().GetEndOfAutotext() ),
+ rObjName,
+ nAspect,
+ pDfltGrfFmtColl,
+ 0 ),
+ pFlyAttrSet, pGrfAttrSet,
+ pFrmFmt );
+}
+
+/*************************************************************************
+|* SwDoc::GetFldType()
+|* Beschreibung: liefert den am Doc eingerichteten Feldtypen zurueck
+*************************************************************************/
+
+SwFieldType *SwDoc::GetSysFldType( const sal_uInt16 eWhich ) const
+{
+ for( sal_uInt16 i = 0; i < INIT_FLDTYPES; ++i )
+ if( eWhich == (*pFldTypes)[i]->Which() )
+ return (*pFldTypes)[i];
+ return 0;
+}
+/*************************************************************************
+ * void SetDocStat( const SwDocStat& rStat );
+ *************************************************************************/
+
+void SwDoc::SetDocStat( const SwDocStat& rStat )
+{
+ *pDocStat = rStat;
+}
+
+const SwDocStat& SwDoc::GetDocStat() const
+{
+ return *pDocStat;
+}
+
+/*************************************************************************/
+
+
+struct _PostItFld : public _SetGetExpFld
+{
+ _PostItFld( const SwNodeIndex& rNdIdx, const SwTxtFld* pFld, const SwIndex* pIdx = 0 )
+ : _SetGetExpFld( rNdIdx, pFld, pIdx ) {}
+
+ sal_uInt16 GetPageNo( const StringRangeEnumerator &rRangeEnum,
+ const std::set< sal_Int32 > &rPossiblePages,
+ sal_uInt16& rVirtPgNo, sal_uInt16& rLineNo );
+
+ SwPostItField* GetPostIt() const
+ {
+ return (SwPostItField*) GetFld()->GetFld().GetFld();
+ }
+};
+
+
+sal_uInt16 _PostItFld::GetPageNo(
+ const StringRangeEnumerator &rRangeEnum,
+ const std::set< sal_Int32 > &rPossiblePages,
+ /* out */ sal_uInt16& rVirtPgNo, /* out */ sal_uInt16& rLineNo )
+{
+ //Problem: Wenn ein PostItFld in einem Node steht, der von mehr als
+ //einer Layout-Instanz repraesentiert wird, steht die Frage im Raum,
+ //ob das PostIt nur ein- oder n-mal gedruck werden soll.
+ //Wahrscheinlich nur einmal, als Seitennummer soll hier keine Zufaellige
+ //sondern die des ersten Auftretens des PostIts innerhalb des selektierten
+ //Bereichs ermittelt werden.
+ rVirtPgNo = 0;
+ sal_uInt16 nPos = GetCntnt();
+ SwClientIter aIter( (SwModify &)GetFld()->GetTxtNode() );
+ for( SwTxtFrm* pFrm = (SwTxtFrm*)aIter.First( TYPE( SwFrm ));
+ pFrm; pFrm = (SwTxtFrm*)aIter.Next() )
+ {
+ if( pFrm->GetOfst() > nPos ||
+ (pFrm->HasFollow() && pFrm->GetFollow()->GetOfst() <= nPos) )
+ continue;
+ sal_uInt16 nPgNo = pFrm->GetPhyPageNum();
+ if( rRangeEnum.hasValue( nPgNo, &rPossiblePages ))
+ {
+ rLineNo = (sal_uInt16)(pFrm->GetLineCount( nPos ) +
+ pFrm->GetAllLines() - pFrm->GetThisLines());
+ rVirtPgNo = pFrm->GetVirtPageNum();
+ return nPgNo;
+ }
+ }
+ return 0;
+}
+
+
+bool lcl_GetPostIts(
+ IDocumentFieldsAccess* pIDFA,
+ _SetGetExpFlds * pSrtLst )
+{
+ bool bHasPostIts = false;
+
+ SwFieldType* pFldType = pIDFA->GetSysFldType( RES_POSTITFLD );
+ DBG_ASSERT( pFldType, "kein PostItType ? ");
+
+ if( pFldType->GetDepends() )
+ {
+ // Modify-Object gefunden, trage alle Felder ins Array ein
+ SwClientIter aIter( *pFldType );
+ SwClient* pLast;
+ const SwTxtFld* pTxtFld;
+
+ for( pLast = aIter.First( TYPE(SwFmtFld)); pLast; pLast = aIter.Next() )
+ {
+ if( 0 != ( pTxtFld = ((SwFmtFld*)pLast)->GetTxtFld() ) &&
+ pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
+ {
+ bHasPostIts = true;
+ if (pSrtLst)
+ {
+ SwNodeIndex aIdx( pTxtFld->GetTxtNode() );
+ _PostItFld* pNew = new _PostItFld( aIdx, pTxtFld );
+ pSrtLst->Insert( pNew );
+ }
+ else
+ break; // we just wanted to check for the existence of postits ...
+ }
+ }
+ }
+
+ return bHasPostIts;
+}
+
+
+static void lcl_FormatPostIt(
+ IDocumentContentOperations* pIDCO,
+ SwPaM& aPam,
+ SwPostItField* pField,
+ bool bNewPage, bool bIsFirstPostIt,
+ sal_uInt16 nPageNo, sal_uInt16 nLineNo )
+{
+ static char __READONLY_DATA sTmp[] = " : ";
+
+ DBG_ASSERT( ViewShell::GetShellRes(), "missing ShellRes" );
+
+ if (bNewPage)
+ {
+ pIDCO->InsertPoolItem( aPam, SvxFmtBreakItem( SVX_BREAK_PAGE_AFTER, RES_BREAK ), 0 );
+ pIDCO->SplitNode( *aPam.GetPoint(), false );
+ }
+ else if (!bIsFirstPostIt)
+ {
+ // add an empty line between different notes
+ pIDCO->SplitNode( *aPam.GetPoint(), false );
+ pIDCO->SplitNode( *aPam.GetPoint(), false );
+ }
+
+ String aStr( ViewShell::GetShellRes()->aPostItPage );
+ aStr.AppendAscii(sTmp);
+
+ aStr += XubString::CreateFromInt32( nPageNo );
+ aStr += ' ';
+ if( nLineNo )
+ {
+ aStr += ViewShell::GetShellRes()->aPostItLine;
+ aStr.AppendAscii(sTmp);
+ aStr += XubString::CreateFromInt32( nLineNo );
+ aStr += ' ';
+ }
+ aStr += ViewShell::GetShellRes()->aPostItAuthor;
+ aStr.AppendAscii(sTmp);
+ aStr += pField->GetPar1();
+ aStr += ' ';
+ SvtSysLocale aSysLocale;
+ aStr += /*(LocaleDataWrapper&)*/aSysLocale.GetLocaleData().getDate( pField->GetDate() );
+ pIDCO->InsertString( aPam, aStr );
+
+ pIDCO->SplitNode( *aPam.GetPoint(), false );
+ aStr = pField->GetPar2();
+#if defined( WNT ) || defined( PM2 )
+ // Bei Windows und Co alle CR rausschmeissen
+ aStr.EraseAllChars( '\r' );
+#endif
+ pIDCO->InsertString( aPam, aStr );
+}
+
+
+// provide the paper tray to use according to the page style in use,
+// but do that only if the respective item is NOT just the default item
+static sal_Int32 lcl_GetPaperBin( const SwPageFrm *pStartFrm )
+{
+ sal_Int32 nRes = -1;
+
+ const SwFrmFmt &rFmt = pStartFrm->GetPageDesc()->GetMaster();
+ const SfxPoolItem *pItem = NULL;
+ SfxItemState eState = rFmt.GetItemState( RES_PAPER_BIN, sal_False, &pItem );
+ const SvxPaperBinItem *pPaperBinItem = dynamic_cast< const SvxPaperBinItem * >(pItem);
+ if (eState > SFX_ITEM_DEFAULT && pPaperBinItem)
+ nRes = pPaperBinItem->GetValue();
+
+ return nRes;
+}
+
+
+void SwDoc::CalculatePagesForPrinting(
+ /* out */ SwRenderData &rData,
+ const SwPrintUIOptions &rOptions,
+ bool bIsPDFExport,
+ sal_Int32 nDocPageCount )
+{
+ DBG_ASSERT( pLayout, "no layout present" );
+ if (!pLayout)
+ return;
+
+ const sal_Int32 nContent = rOptions.getIntValue( "PrintContent", 0 );
+ const bool bPrintSelection = nContent == 2;
+
+ // properties to take into account when calcualting the set of pages
+ // (PDF export UI does not allow for selecting left or right pages only)
+ bool bPrintLeftPages = bIsPDFExport ? true : rOptions.IsPrintLeftPages();
+ bool bPrintRightPages = bIsPDFExport ? true : rOptions.IsPrintRightPages();
+ // #i103700# printing selections should not allow for automatic inserting empty pages
+ bool bPrintEmptyPages = bPrintSelection ? false : rOptions.IsPrintEmptyPages( bIsPDFExport );
+
+ Range aPages( 1, nDocPageCount );
+
+ MultiSelection aMulti( aPages );
+ aMulti.SetTotalRange( Range( 0, RANGE_MAX ) );
+ aMulti.Select( aPages );
+
+ const SwPageFrm *pStPage = (SwPageFrm*)pLayout->Lower();
+ const SwFrm *pEndPage = pStPage;
+
+ sal_uInt16 nFirstPageNo = 0;
+ sal_uInt16 nLastPageNo = 0;
+ sal_uInt16 nPageNo = 1;
+
+ for( sal_uInt16 i = 1; i <= (sal_uInt16)aPages.Max(); ++i )
+ {
+ if( i < (sal_uInt16)aPages.Min() )
+ {
+ if( !pStPage->GetNext() )
+ break;
+ pStPage = (SwPageFrm*)pStPage->GetNext();
+ pEndPage= pStPage;
+ }
+ else if( i == (sal_uInt16)aPages.Min() )
+ {
+ nFirstPageNo = i;
+ nLastPageNo = nFirstPageNo;
+ if( !pStPage->GetNext() || (i == (sal_uInt16)aPages.Max()) )
+ break;
+ pEndPage = pStPage->GetNext();
+ }
+ else if( i > (sal_uInt16)aPages.Min() )
+ {
+ nLastPageNo = i;
+ if( !pEndPage->GetNext() || (i == (sal_uInt16)aPages.Max()) )
+ break;
+ pEndPage = pEndPage->GetNext();
+ }
+ }
+
+ DBG_ASSERT( nFirstPageNo, "first page not found! Should not happen!" );
+ if (nFirstPageNo)
+ {
+// HACK: Hier muss von der MultiSelection noch eine akzeptable Moeglichkeit
+// geschaffen werden, alle Seiten von Seite x an zu deselektieren.
+// Z.B. durch SetTotalRange ....
+
+// aMulti.Select( Range( nLastPageNo+1, SELECTION_MAX ), sal_False );
+ MultiSelection aTmpMulti( Range( 1, nLastPageNo ) );
+ long nTmpIdx = aMulti.FirstSelected();
+ static long nEndOfSelection = SFX_ENDOFSELECTION;
+ while ( nEndOfSelection != nTmpIdx && nTmpIdx <= long(nLastPageNo) )
+ {
+ aTmpMulti.Select( nTmpIdx );
+ nTmpIdx = aMulti.NextSelected();
+ }
+ aMulti = aTmpMulti;
+// Ende des HACKs
+
+ nPageNo = nFirstPageNo;
+
+ std::map< sal_Int32, sal_Int32 > &rPrinterPaperTrays = rData.GetPrinterPaperTrays();
+ std::set< sal_Int32 > &rValidPages = rData.GetValidPagesSet();
+ std::map< sal_Int32, const SwPageFrm * > &rValidStartFrms = rData.GetValidStartFrames();
+ rValidPages.clear();
+ rValidStartFrms.clear();
+ while ( pStPage )
+ {
+ const sal_Bool bRightPg = pStPage->OnRightPage();
+ if ( aMulti.IsSelected( nPageNo ) &&
+ ( (bRightPg && bPrintRightPages) ||
+ (!bRightPg && bPrintLeftPages) ) )
+ {
+ // --> FME 2005-12-12 #b6354161# Feature - Print empty pages
+ if ( bPrintEmptyPages || pStPage->Frm().Height() )
+ // <--
+ {
+ rValidPages.insert( nPageNo );
+ rValidStartFrms[ nPageNo ] = pStPage;
+
+ rPrinterPaperTrays[ nPageNo ] = lcl_GetPaperBin( pStPage );
+ }
+ }
+
+ if ( pStPage == pEndPage )
+ {
+ pStPage = 0;
+ }
+ else
+ { ++nPageNo;
+ pStPage = (SwPageFrm*)pStPage->GetNext();
+ }
+ }
+ }
+
+
+ //
+ // now that we have identified the valid pages for printing according
+ // to the print settings we need to get the PageRange to use and
+ // use both results to get the actual pages to be printed
+ // (post-it settings need to be taken into account later on!)
+ //
+
+ // get PageRange value to use
+ OUString aPageRange;
+ // --> PL, OD #i116085# - adjusting fix for i113919
+// if (bIsPDFExport)
+// {
+// aPageRange = rOptions.getStringValue( "PageRange", OUString() );
+// }
+// else
+ if ( !bIsPDFExport )
+ // <--
+ {
+ // PageContent :
+ // 0 -> print all pages (default if aPageRange is empty)
+ // 1 -> print range according to PageRange
+ // 2 -> print selection
+ if (1 == nContent)
+ aPageRange = rOptions.getStringValue( "PageRange", OUString() );
+ if (2 == nContent)
+ {
+ // note that printing selections is actually implemented by copying
+ // the selection to a new temporary document and printing all of that one.
+ // Thus for Writer "PrintContent" must never be 2.
+ // See SwXTextDocument::GetRenderDoc for evaluating if a selection is to be
+ // printed and for creating the temporary document.
+ }
+
+ // please note
+ }
+ if (aPageRange.getLength() == 0) // empty string -> print all
+ {
+ // set page range to print to 'all pages'
+ aPageRange = OUString::valueOf( (sal_Int32)1 );
+ aPageRange += OUString::valueOf( (sal_Unicode)'-');
+ aPageRange += OUString::valueOf( nDocPageCount );
+ }
+ rData.SetPageRange( aPageRange );
+
+ // get vector of pages to print according to PageRange and valid pages set from above
+ // (result may be an empty vector, for example if the range string is not correct)
+ StringRangeEnumerator::getRangesFromString(
+ aPageRange, rData.GetPagesToPrint(),
+ 1, nDocPageCount, 0, &rData.GetValidPagesSet() );
+}
+
+
+void SwDoc::UpdatePagesForPrintingWithPostItData(
+ /* out */ SwRenderData &rData,
+ const SwPrintUIOptions &rOptions,
+ bool /*bIsPDFExport*/,
+ sal_Int32 nDocPageCount )
+{
+
+ sal_Int16 nPostItMode = (sal_Int16) rOptions.getIntValue( "PrintAnnotationMode", 0 );
+ DBG_ASSERT(nPostItMode == POSTITS_NONE || rData.HasPostItData(),
+ "print post-its without post-it data?" );
+ const sal_uInt16 nPostItCount = rData.HasPostItData() ? rData.m_pPostItFields->Count() : 0;
+ if (nPostItMode != POSTITS_NONE && nPostItCount > 0)
+ {
+ SET_CURR_SHELL( rData.m_pPostItShell );
+
+ // clear document and move to end of it
+ SwPaM aPam( rData.m_pPostItDoc->GetNodes().GetEndOfContent() );
+ aPam.Move( fnMoveBackward, fnGoDoc );
+ aPam.SetMark();
+ aPam.Move( fnMoveForward, fnGoDoc );
+ rData.m_pPostItDoc->DeleteRange( aPam );
+
+ const StringRangeEnumerator aRangeEnum( rData.GetPageRange(), 1, nDocPageCount, 0 );
+
+ // For mode POSTITS_ENDPAGE:
+ // maps a physical page number to the page number in post-it document that holds
+ // the first post-it for that physical page . Needed to relate the correct start frames
+ // from the post-it doc to the physical page of the document
+ std::map< sal_Int32, sal_Int32 > aPostItLastStartPageNum;
+
+ // add all post-its on valid pages within the the page range to the
+ // temporary post-it document.
+ // Since the array of post-it fileds is sorted by page and line number we will
+ // already get them in the correct order
+ sal_uInt16 nVirtPg = 0, nLineNo = 0, nLastPageNum = 0, nPhyPageNum = 0;
+ bool bIsFirstPostIt = true;
+ for (sal_uInt16 i = 0; i < nPostItCount; ++i)
+ {
+ _PostItFld& rPostIt = (_PostItFld&)*(*rData.m_pPostItFields)[ i ];
+ nLastPageNum = nPhyPageNum;
+ nPhyPageNum = rPostIt.GetPageNo(
+ aRangeEnum, rData.GetValidPagesSet(), nVirtPg, nLineNo );
+ if (nPhyPageNum)
+ {
+ // need to insert a page break?
+ // In POSTITS_ENDPAGE mode for each document page the following
+ // post-it page needs to start on a new page
+ const bool bNewPage = nPostItMode == POSTITS_ENDPAGE &&
+ !bIsFirstPostIt && nPhyPageNum != nLastPageNum;
+
+ lcl_FormatPostIt( rData.m_pPostItShell->GetDoc(), aPam,
+ rPostIt.GetPostIt(), bNewPage, bIsFirstPostIt, nVirtPg, nLineNo );
+ bIsFirstPostIt = false;
+
+ if (nPostItMode == POSTITS_ENDPAGE)
+ {
+ // get the correct number of current pages for the post-it document
+ rData.m_pPostItShell->CalcLayout();
+ const sal_Int32 nPages = rData.m_pPostItDoc->GetPageCount();
+ aPostItLastStartPageNum[ nPhyPageNum ] = nPages;
+ }
+ }
+ }
+
+ // format post-it doc to get correct number of pages
+ rData.m_pPostItShell->CalcLayout();
+ const sal_Int32 nPostItDocPageCount = rData.m_pPostItDoc->GetPageCount();
+
+ if (nPostItMode == POSTITS_ONLY || nPostItMode == POSTITS_ENDDOC)
+ {
+ // now add those post-it pages to the vector of pages to print
+ // or replace them if only post-its should be printed
+
+ rData.GetPostItStartFrames().clear();
+ if (nPostItMode == POSTITS_ENDDOC)
+ {
+ // set all values up to number of pages to print currently known to NULL,
+ // meaning none of the pages currently in the vector is from the
+ // post-it document, they are the documents pages.
+ rData.GetPostItStartFrames().resize( rData.GetPagesToPrint().size() );
+ }
+ else if (nPostItMode == POSTITS_ONLY)
+ {
+ // no document page to be printed
+ rData.GetPagesToPrint().clear();
+ }
+
+ // now we just need to add the post-it pages to be printed to the end
+ // of the vector of pages to print and keep the GetValidStartFrames
+ // data conform with it
+ sal_Int32 nPageNum = 0;
+ const SwPageFrm * pPageFrm = (SwPageFrm*)rData.m_pPostItShell->GetLayout()->Lower();
+ while( pPageFrm && nPageNum < nPostItDocPageCount )
+ {
+ DBG_ASSERT( pPageFrm, "Empty page frame. How are we going to print this?" );
+ ++nPageNum;
+ rData.GetPagesToPrint().push_back( 0 ); // a page number of 0 indicates this page is from the post-it doc
+ DBG_ASSERT( pPageFrm, "pPageFrm is NULL!" );
+ rData.GetPostItStartFrames().push_back( pPageFrm );
+ pPageFrm = (SwPageFrm*)pPageFrm->GetNext();
+ }
+ DBG_ASSERT( nPageNum == nPostItDocPageCount, "unexpected number of pages" );
+ }
+ else if (nPostItMode == POSTITS_ENDPAGE)
+ {
+ // the next step is to find all the start frames from the post-it
+ // document that should be printed for a given physical page of the document
+ std::map< sal_Int32, std::vector< const SwPageFrm * > > aPhysPageToPostItFrames;
+
+ // ... thus, first collect all post-it doc start frames in a vector
+ sal_Int32 nPostItPageNum = 0;
+ std::vector< const SwPageFrm * > aAllPostItStartFrames;
+ const SwPageFrm * pPageFrm = (SwPageFrm*)rData.m_pPostItShell->GetLayout()->Lower();
+ while( pPageFrm && sal_Int32(aAllPostItStartFrames.size()) < nPostItDocPageCount )
+ {
+ DBG_ASSERT( pPageFrm, "Empty page frame. How are we going to print this?" );
+ ++nPostItPageNum;
+ aAllPostItStartFrames.push_back( pPageFrm );
+ pPageFrm = (SwPageFrm*)pPageFrm->GetNext();
+ }
+ DBG_ASSERT( sal_Int32(aAllPostItStartFrames.size()) == nPostItDocPageCount,
+ "unexpected number of frames; does not match number of pages" );
+
+ // get a map that holds all post-it frames to be printed for a
+ // given physical page from the document
+ sal_Int32 nLastStartPageNum = 0;
+ std::map< sal_Int32, sal_Int32 >::const_iterator aIt;
+ for (aIt = aPostItLastStartPageNum.begin(); aIt != aPostItLastStartPageNum.end(); ++aIt)
+ {
+ const sal_Int32 nFrames = aIt->second - nLastStartPageNum;
+ const sal_Int32 nFirstStartPageNum = aIt == aPostItLastStartPageNum.begin() ?
+ 1 : aIt->second - nFrames + 1;
+ DBG_ASSERT( 1 <= nFirstStartPageNum && nFirstStartPageNum <= nPostItDocPageCount,
+ "page number for first frame out of range" );
+ std::vector< const SwPageFrm * > aStartFrames;
+ for (sal_Int32 i = 0; i < nFrames; ++i)
+ {
+ const sal_Int32 nIdx = nFirstStartPageNum - 1 + i; // -1 because lowest page num is 1
+ DBG_ASSERT( 0 <= nIdx && nIdx < sal_Int32(aAllPostItStartFrames.size()),
+ "index out of range" );
+ aStartFrames.push_back( aAllPostItStartFrames[ nIdx ] );
+ }
+ aPhysPageToPostItFrames[ aIt->first /* phys page num */ ] = aStartFrames;
+ nLastStartPageNum = aIt->second;
+ }
+
+
+ // ok, now that aPhysPageToPostItFrames can give the start frames for all
+ // post-it pages to be printed we need to merge those at the correct
+ // position into the GetPagesToPrint vector and build and maintain the
+ // GetValidStartFrames vector as well.
+ // Since inserting a larger number of entries in the middle of a vector
+ // isn't that efficient we will create new vectors by copying the required data
+ std::vector< sal_Int32 > aTmpPagesToPrint;
+ std::vector< const SwPageFrm * > aTmpPostItStartFrames;
+ const size_t nNum = rData.GetPagesToPrint().size();
+ for (size_t i = 0 ; i < nNum; ++i)
+ {
+ // add the physical page to print from the document
+ const sal_Int32 nPhysPage = rData.GetPagesToPrint()[i];
+ aTmpPagesToPrint.push_back( nPhysPage );
+ aTmpPostItStartFrames.push_back( NULL );
+
+ // add the post-it document pages to print, i.e those
+ // post-it pages that have the data for the above physical page
+ const std::vector< const SwPageFrm * > &rPostItFrames = aPhysPageToPostItFrames[ nPhysPage ];
+ const size_t nPostItFrames = rPostItFrames.size();
+ for (size_t k = 0; k < nPostItFrames; ++k)
+ {
+ aTmpPagesToPrint.push_back( 0 );
+ aTmpPostItStartFrames.push_back( rPostItFrames[k] );
+ }
+ }
+
+ // finally we need to assign those vectors to the resulting ones.
+ // swapping the data should be more efficient than assigning since
+ // we won't need the temporary vectors anymore
+ rData.GetPagesToPrint().swap( aTmpPagesToPrint );
+ rData.GetPostItStartFrames().swap( aTmpPostItStartFrames );
+ }
+ }
+}
+
+
+void SwDoc::CalculatePagePairsForProspectPrinting(
+ /* out */ SwRenderData &rData,
+ const SwPrintUIOptions &rOptions,
+ sal_Int32 nDocPageCount )
+{
+ std::map< sal_Int32, sal_Int32 > &rPrinterPaperTrays = rData.GetPrinterPaperTrays();
+ std::set< sal_Int32 > &rValidPagesSet = rData.GetValidPagesSet();
+ std::map< sal_Int32, const SwPageFrm * > &rValidStartFrms = rData.GetValidStartFrames();
+ std::vector< std::pair< sal_Int32, sal_Int32 > > &rPagePairs = rData.GetPagePairsForProspectPrinting();
+
+ rPagePairs.clear();
+ rValidPagesSet.clear();
+ rValidStartFrms.clear();
+
+ rtl::OUString aPageRange = rOptions.getStringValue( "PageRange", rtl::OUString() );
+ // PageContent :
+ // 0 -> print all pages (default if aPageRange is empty)
+ // 1 -> print range according to PageRange
+ // 2 -> print selection
+ const sal_Int32 nContent = rOptions.getIntValue( "PrintContent", 0 );
+ if (0 == nContent)
+ {
+ // set page range to print to 'all pages'
+ aPageRange = OUString::valueOf( (sal_Int32)1 );
+ aPageRange += OUString::valueOf( (sal_Unicode)'-');
+ aPageRange += OUString::valueOf( nDocPageCount );
+ }
+ StringRangeEnumerator aRange( aPageRange, 1, nDocPageCount, 0 );
+
+ DBG_ASSERT( pLayout, "no layout present" );
+ if (!pLayout || aRange.size() <= 0)
+ return;
+
+ const SwPageFrm *pStPage = (SwPageFrm*)pLayout->Lower();
+ sal_Int32 i = 0;
+ for ( i = 1; pStPage && i < nDocPageCount; ++i )
+ pStPage = (SwPageFrm*)pStPage->GetNext();
+ if ( !pStPage ) // dann wars das
+ return;
+
+ // currently for prospect printing all pages are valid to be printed
+ // thus we add them all to the respective map and set for later use
+ sal_Int32 nPageNum = 0;
+ const SwPageFrm *pPageFrm = (SwPageFrm*)pLayout->Lower();
+ while( pPageFrm && nPageNum < nDocPageCount )
+ {
+ DBG_ASSERT( pPageFrm, "Empty page frame. How are we going to print this?" );
+ ++nPageNum;
+ rValidPagesSet.insert( nPageNum );
+ rValidStartFrms[ nPageNum ] = pPageFrm;
+ pPageFrm = (SwPageFrm*)pPageFrm->GetNext();
+
+ rPrinterPaperTrays[ nPageNum ] = lcl_GetPaperBin( pStPage );
+ }
+ DBG_ASSERT( nPageNum == nDocPageCount, "unexpected number of pages" );
+
+ // properties to take into account when calcualting the set of pages
+ // Note: here bPrintLeftPages and bPrintRightPages refer to the (virtual) resulting pages
+ // of the prospect!
+ bool bPrintLeftPages = rOptions.IsPrintLeftPages();
+ bool bPrintRightPages = rOptions.IsPrintRightPages();
+ bool bPrintProspectRTL = rOptions.getIntValue( "PrintProspectRTL", 0 ) ? true : false;
+
+ // get pages for prospect printing according to the 'PageRange'
+ // (duplicates and any order allowed!)
+ std::vector< sal_Int32 > aPagesToPrint;
+ StringRangeEnumerator::getRangesFromString(
+ aPageRange, aPagesToPrint, 1, nDocPageCount, 0 );
+
+ // now fill the vector for calculating the page pairs with the start frames
+ // from the above obtained vector
+ std::vector< const SwPageFrm * > aVec;
+ for ( i = 0; i < sal_Int32(aPagesToPrint.size()); ++i)
+ {
+ const sal_Int32 nPage = aPagesToPrint[i];
+ const SwPageFrm *pFrm = rValidStartFrms[ nPage ];
+ aVec.push_back( pFrm );
+ }
+
+ // just one page is special ...
+ if ( 1 == aVec.size() )
+ aVec.insert( aVec.begin() + 1, 0 ); // insert a second empty page
+ else
+ {
+ // now extend the number of pages to fit a multiple of 4
+ // (4 'normal' pages are needed for a single prospect paper
+ // with back and front)
+ while( aVec.size() & 3 )
+ aVec.push_back( 0 );
+ }
+
+ // dann sorge mal dafuer, das alle Seiten in der richtigen
+ // Reihenfolge stehen:
+ sal_uInt16 nSPg = 0, nEPg = aVec.size(), nStep = 1;
+ if ( 0 == (nEPg & 1 )) // ungerade gibt es nicht!
+ --nEPg;
+
+ if ( !bPrintLeftPages )
+ ++nStep;
+ else if ( !bPrintRightPages )
+ {
+ ++nStep;
+ ++nSPg, --nEPg;
+ }
+
+ // the number of 'virtual' pages to be printed
+ sal_Int32 nCntPage = (( nEPg - nSPg ) / ( 2 * nStep )) + 1;
+
+ for ( sal_uInt16 nPrintCount = 0; nSPg < nEPg &&
+ nPrintCount < nCntPage; ++nPrintCount )
+ {
+ pStPage = aVec[ nSPg ];
+ const SwPageFrm* pNxtPage = nEPg < aVec.size() ? aVec[ nEPg ] : 0;
+
+ short nRtlOfs = bPrintProspectRTL ? 1 : 0;
+ if ( 0 == (( nSPg + nRtlOfs) & 1 ) ) // switch for odd number in LTR, even number in RTL
+ {
+ const SwPageFrm* pTmp = pStPage;
+ pStPage = pNxtPage;
+ pNxtPage = pTmp;
+ }
+
+ sal_Int32 nFirst = -1, nSecond = -1;
+ for ( int nC = 0; nC < 2; ++nC )
+ {
+ sal_Int32 nPage = -1;
+ if ( pStPage )
+ nPage = pStPage->GetPhyPageNum();
+ if (nC == 0)
+ nFirst = nPage;
+ else
+ nSecond = nPage;
+
+ pStPage = pNxtPage;
+ }
+ rPagePairs.push_back( std::pair< sal_Int32, sal_Int32 >(nFirst, nSecond) );
+
+ nSPg = nSPg + nStep;
+ nEPg = nEPg - nStep;
+ }
+ DBG_ASSERT( size_t(nCntPage) == rPagePairs.size(), "size mismatch for number of page pairs" );
+
+ // luckily prospect printing does not make use of post-its so far,
+ // thus we are done here.
+}
+
+
+sal_uInt16 SwDoc::GetPageCount() const
+{
+ return GetRootFrm() ? GetRootFrm()->GetPageNum() : 0;
+}
+
+const Size SwDoc::GetPageSize( sal_uInt16 nPageNum, bool bSkipEmptyPages ) const
+{
+ Size aSize;
+ if ( GetRootFrm() && nPageNum )
+ {
+ const SwPageFrm* pPage = static_cast<const SwPageFrm*>
+ (GetRootFrm()->Lower());
+
+ while ( --nPageNum && pPage->GetNext() )
+ {
+ pPage = static_cast<const SwPageFrm*>( pPage->GetNext() );
+ }
+
+ // switch to next page for an empty page, if empty pages are not skipped
+ // in order to get a sensible page size for an empty page - e.g. for printing.
+ if ( !bSkipEmptyPages && pPage->IsEmptyPage() && pPage->GetNext() )
+ {
+ pPage = static_cast<const SwPageFrm*>( pPage->GetNext() );
+ }
+
+ aSize = pPage->Frm().SSize();
+ }
+ return aSize;
+}
+
+
+/*************************************************************************
+ * void UpdateDocStat( const SwDocStat& rStat );
+ *************************************************************************/
+
+void SwDoc::UpdateDocStat( SwDocStat& rStat )
+{
+ if( rStat.bModified )
+ {
+ rStat.Reset();
+ rStat.nPara = 0; // Default ist auf 1 !!
+ SwNode* pNd;
+
+ for( sal_uLong i = GetNodes().Count(); i; )
+ {
+ switch( ( pNd = GetNodes()[ --i ])->GetNodeType() )
+ {
+ case ND_TEXTNODE:
+ ((SwTxtNode*)pNd)->CountWords( rStat, 0, ((SwTxtNode*)pNd)->GetTxt().Len() );
+ break;
+ case ND_TABLENODE: ++rStat.nTbl; break;
+ case ND_GRFNODE: ++rStat.nGrf; break;
+ case ND_OLENODE: ++rStat.nOLE; break;
+ case ND_SECTIONNODE: break;
+ }
+ }
+
+ // #i93174#: notes contain paragraphs that are not nodes
+ {
+ SwFieldType * const pPostits( GetSysFldType(RES_POSTITFLD) );
+ SwClientIter aIter(*pPostits);
+ SwFmtFld const * pFmtFld =
+ static_cast<SwFmtFld const*>(aIter.First( TYPE(SwFmtFld) ));
+ while (pFmtFld)
+ {
+ if (pFmtFld->IsFldInDoc())
+ {
+ SwPostItField const * const pField(
+ static_cast<SwPostItField const*>(pFmtFld->GetFld()));
+ rStat.nAllPara += pField->GetNumberOfParagraphs();
+ }
+ pFmtFld = static_cast<SwFmtFld const*>(aIter.Next());
+ }
+ }
+
+ rStat.nPage = GetRootFrm() ? GetRootFrm()->GetPageNum() : 0;
+ rStat.bModified = sal_False;
+ SetDocStat( rStat );
+
+ com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aStat( rStat.nPage ? 7 : 6);
+ sal_Int32 n=0;
+ aStat[n].Name = ::rtl::OUString::createFromAscii("TableCount");
+ aStat[n++].Value <<= (sal_Int32)rStat.nTbl;
+ aStat[n].Name = ::rtl::OUString::createFromAscii("ImageCount");
+ aStat[n++].Value <<= (sal_Int32)rStat.nGrf;
+ aStat[n].Name = ::rtl::OUString::createFromAscii("ObjectCount");
+ aStat[n++].Value <<= (sal_Int32)rStat.nOLE;
+ if ( rStat.nPage )
+ {
+ aStat[n].Name = ::rtl::OUString::createFromAscii("PageCount");
+ aStat[n++].Value <<= (sal_Int32)rStat.nPage;
+ }
+ aStat[n].Name = ::rtl::OUString::createFromAscii("ParagraphCount");
+ aStat[n++].Value <<= (sal_Int32)rStat.nPara;
+ aStat[n].Name = ::rtl::OUString::createFromAscii("WordCount");
+ aStat[n++].Value <<= (sal_Int32)rStat.nWord;
+ aStat[n].Name = ::rtl::OUString::createFromAscii("CharacterCount");
+ aStat[n++].Value <<= (sal_Int32)rStat.nChar;
+
+ // For e.g. autotext documents there is no pSwgInfo (#i79945)
+ SfxObjectShell * const pObjShell( GetDocShell() );
+ if (pObjShell)
+ {
+ const uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ pObjShell->GetModel(), uno::UNO_QUERY_THROW);
+ const uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties());
+ // #i96786#: do not set modified flag when updating statistics
+ const bool bDocWasModified( IsModified() );
+ const ModifyBlocker_Impl b(pObjShell);
+ xDocProps->setDocumentStatistics(aStat);
+ if (!bDocWasModified)
+ {
+ ResetModified();
+ }
+ }
+
+ // event. Stat. Felder Updaten
+ SwFieldType *pType = GetSysFldType(RES_DOCSTATFLD);
+ pType->UpdateFlds();
+ }
+}
+
+
+// Dokument - Info
+
+void SwDoc::DocInfoChgd( )
+{
+ GetSysFldType( RES_DOCINFOFLD )->UpdateFlds();
+ GetSysFldType( RES_TEMPLNAMEFLD )->UpdateFlds();
+ SetModified();
+}
+
+ // returne zum Namen die im Doc gesetzte Referenz
+const SwFmtRefMark* SwDoc::GetRefMark( const String& rName ) const
+{
+ const SfxPoolItem* pItem;
+ sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_REFMARK );
+ for( sal_uInt32 n = 0; n < nMaxItems; ++n )
+ {
+ if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_REFMARK, n ) ))
+ continue;
+
+ const SwFmtRefMark* pFmtRef = (SwFmtRefMark*)pItem;
+ const SwTxtRefMark* pTxtRef = pFmtRef->GetTxtRefMark();
+ if( pTxtRef && &pTxtRef->GetTxtNode().GetNodes() == &GetNodes() &&
+ rName.Equals( pFmtRef->GetRefName() ) )
+ return pFmtRef;
+ }
+ return 0;
+}
+
+ // returne die RefMark per Index - fuer Uno
+const SwFmtRefMark* SwDoc::GetRefMark( sal_uInt16 nIndex ) const
+{
+ const SfxPoolItem* pItem;
+ const SwTxtRefMark* pTxtRef;
+ const SwFmtRefMark* pRet = 0;
+
+ sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_REFMARK );
+ sal_uInt32 nCount = 0;
+ for( sal_uInt32 n = 0; n < nMaxItems; ++n )
+ if( 0 != (pItem = GetAttrPool().GetItem2( RES_TXTATR_REFMARK, n )) &&
+ 0 != (pTxtRef = ((SwFmtRefMark*)pItem)->GetTxtRefMark()) &&
+ &pTxtRef->GetTxtNode().GetNodes() == &GetNodes() )
+ {
+ if(nCount == nIndex)
+ {
+ pRet = (SwFmtRefMark*)pItem;
+ break;
+ }
+ nCount++;
+ }
+ return pRet;
+}
+
+ // returne die Namen aller im Doc gesetzten Referenzen
+ //JP 24.06.96: Ist der ArrayPointer 0 dann returne nur, ob im Doc. eine
+ // RefMark gesetzt ist
+ // OS 25.06.96: ab jetzt wird immer die Anzahl der Referenzen returnt
+sal_uInt16 SwDoc::GetRefMarks( SvStringsDtor* pNames ) const
+{
+ const SfxPoolItem* pItem;
+ const SwTxtRefMark* pTxtRef;
+
+ sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_REFMARK );
+ sal_uInt32 nCount = 0;
+ for( sal_uInt32 n = 0; n < nMaxItems; ++n )
+ if( 0 != (pItem = GetAttrPool().GetItem2( RES_TXTATR_REFMARK, n )) &&
+ 0 != (pTxtRef = ((SwFmtRefMark*)pItem)->GetTxtRefMark()) &&
+ &pTxtRef->GetTxtNode().GetNodes() == &GetNodes() )
+ {
+ if( pNames )
+ {
+ String* pTmp = new String( ((SwFmtRefMark*)pItem)->GetRefName() );
+ pNames->Insert( pTmp, nCount );
+ }
+ nCount ++;
+ }
+
+ return nCount;
+}
+
+bool SwDoc::IsLoaded() const
+{
+ return mbLoaded;
+}
+
+bool SwDoc::IsUpdateExpFld() const
+{
+ return mbUpdateExpFld;
+}
+
+bool SwDoc::IsNewDoc() const
+{
+ return mbNewDoc;
+}
+
+bool SwDoc::IsPageNums() const
+{
+ return mbPageNums;
+}
+
+void SwDoc::SetPageNums(bool b)
+{
+ mbPageNums = b;
+}
+
+void SwDoc::SetNewDoc(bool b)
+{
+ mbNewDoc = b;
+}
+
+void SwDoc::SetUpdateExpFldStat(bool b)
+{
+ mbUpdateExpFld = b;
+}
+
+void SwDoc::SetLoaded(bool b)
+{
+ mbLoaded = b;
+}
+
+bool SwDoc::IsModified() const
+{
+ return mbModified;
+}
+
+void SwDoc::SetModified()
+{
+ // --> OD 2005-08-29 #125370#
+ SwLayouter::ClearMovedFwdFrms( *this );
+ SwLayouter::ClearObjsTmpConsiderWrapInfluence( *this );
+ SwLayouter::ClearFrmsNotToWrap( *this );
+ // <--
+ // --> OD 2006-05-10 #i65250#
+ SwLayouter::ClearMoveBwdLayoutInfo( *this );
+ // <--
+ // dem Link wird der Status returnt, wie die Flags waren und werden
+ // Bit 0: -> alter Zustand
+ // Bit 1: -> neuer Zustand
+ long nCall = mbModified ? 3 : 2;
+ mbModified = sal_True;
+ pDocStat->bModified = sal_True;
+ if( aOle2Link.IsSet() )
+ {
+ mbInCallModified = sal_True;
+ aOle2Link.Call( (void*)nCall );
+ mbInCallModified = sal_False;
+ }
+
+ if( pACEWord && !pACEWord->IsDeleted() )
+ delete pACEWord, pACEWord = 0;
+}
+
+void SwDoc::ResetModified()
+{
+ // dem Link wird der Status returnt, wie die Flags waren und werden
+ // Bit 0: -> alter Zustand
+ // Bit 1: -> neuer Zustand
+ long nCall = mbModified ? 1 : 0;
+ mbModified = sal_False;
+ // If there is already a document statistic, we assume that
+ // it is correct. In this case we reset the modified flag.
+ if ( 0 != pDocStat->nChar )
+ pDocStat->bModified = sal_False;
+ GetIDocumentUndoRedo().SetUndoNoModifiedPosition();
+ if( nCall && aOle2Link.IsSet() )
+ {
+ mbInCallModified = sal_True;
+ aOle2Link.Call( (void*)nCall );
+ mbInCallModified = sal_False;
+ }
+}
+
+
+void SwDoc::ReRead( SwPaM& rPam, const String& rGrfName,
+ const String& rFltName, const Graphic* pGraphic,
+ const GraphicObject* pGrafObj )
+{
+ SwGrfNode *pGrfNd;
+ if( ( !rPam.HasMark()
+ || rPam.GetPoint()->nNode.GetIndex() == rPam.GetMark()->nNode.GetIndex() )
+ && 0 != ( pGrfNd = rPam.GetPoint()->nNode.GetNode().GetGrfNode() ) )
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(new SwUndoReRead(rPam, *pGrfNd));
+ }
+
+ // Weil nicht bekannt ist, ob sich die Grafik spiegeln laesst,
+ // immer das SpiegelungsAttribut zuruecksetzen
+ if( RES_MIRROR_GRAPH_DONT != pGrfNd->GetSwAttrSet().
+ GetMirrorGrf().GetValue() )
+ pGrfNd->SetAttr( SwMirrorGrf() );
+
+ pGrfNd->ReRead( rGrfName, rFltName, pGraphic, pGrafObj, sal_True );
+ SetModified();
+ }
+}
+
+sal_Bool lcl_SpellAndGrammarAgain( const SwNodePtr& rpNd, void* pArgs )
+{
+ SwTxtNode *pTxtNode = (SwTxtNode*)rpNd->GetTxtNode();
+ sal_Bool bOnlyWrong = *(sal_Bool*)pArgs;
+ if( pTxtNode )
+ {
+ if( bOnlyWrong )
+ {
+ if( pTxtNode->GetWrong() &&
+ pTxtNode->GetWrong()->InvalidateWrong() )
+ pTxtNode->SetWrongDirty( true );
+ if( pTxtNode->GetGrammarCheck() &&
+ pTxtNode->GetGrammarCheck()->InvalidateWrong() )
+ pTxtNode->SetGrammarCheckDirty( true );
+ }
+ else
+ {
+ pTxtNode->SetWrongDirty( true );
+ if( pTxtNode->GetWrong() )
+ pTxtNode->GetWrong()->SetInvalid( 0, STRING_LEN );
+ pTxtNode->SetGrammarCheckDirty( true );
+ if( pTxtNode->GetGrammarCheck() )
+ pTxtNode->GetGrammarCheck()->SetInvalid( 0, STRING_LEN );
+ }
+ }
+ return sal_True;
+}
+
+sal_Bool lcl_CheckSmartTagsAgain( const SwNodePtr& rpNd, void* )
+{
+ SwTxtNode *pTxtNode = (SwTxtNode*)rpNd->GetTxtNode();
+// sal_Bool bOnlyWrong = *(sal_Bool*)pArgs;
+ if( pTxtNode )
+ {
+ pTxtNode->SetSmartTagDirty( true );
+ if( pTxtNode->GetSmartTags() )
+ {
+// if ( bOnlyWrong ) // only some smart tag types have been enabled or disabled
+// pTxtNode->GetSmartTags()->SetInvalid( 0, STRING_LEN );
+// else // smart tags all have been enabled or disabled
+ pTxtNode->SetSmartTags( NULL );
+ }
+ }
+ return sal_True;
+}
+
+
+/*************************************************************************
+ * SwDoc::SpellItAgainSam( sal_Bool bInvalid, sal_Bool bOnlyWrong )
+ *
+ * stoesst das Spelling im Idle-Handler wieder an.
+ * Wird bInvalid als sal_True uebergeben, so werden zusaetzlich die WrongListen
+ * an allen Nodes invalidiert und auf allen Seiten das SpellInvalid-Flag
+ * gesetzt.
+ * Mit bOnlyWrong kann man dann steuern, ob nur die Bereiche mit falschen
+ * Woertern oder die kompletten Bereiche neu ueberprueft werden muessen.
+ ************************************************************************/
+
+void SwDoc::SpellItAgainSam( sal_Bool bInvalid, sal_Bool bOnlyWrong, sal_Bool bSmartTags )
+{
+ ASSERT( GetRootFrm(), "SpellAgain: Where's my RootFrm?" );
+ if( bInvalid )
+ {
+ SwPageFrm *pPage = (SwPageFrm*)GetRootFrm()->Lower();
+ while ( pPage )
+ {
+ if ( bSmartTags )
+ pPage->InvalidateSmartTags();
+
+ pPage->InvalidateSpelling();
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+ GetRootFrm()->SetNeedGrammarCheck( true );
+
+ if ( bSmartTags )
+ GetNodes().ForEach( lcl_CheckSmartTagsAgain, &bOnlyWrong );
+
+ GetNodes().ForEach( lcl_SpellAndGrammarAgain, &bOnlyWrong );
+ }
+
+ GetRootFrm()->SetIdleFlags();
+}
+
+void SwDoc::InvalidateAutoCompleteFlag()
+{
+ if( GetRootFrm() )
+ {
+ SwPageFrm *pPage = (SwPageFrm*)GetRootFrm()->Lower();
+ while ( pPage )
+ {
+ pPage->InvalidateAutoCompleteWords();
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+ for( sal_uLong nNd = 1, nCnt = GetNodes().Count(); nNd < nCnt; ++nNd )
+ {
+ SwTxtNode* pTxtNode = GetNodes()[ nNd ]->GetTxtNode();
+ if ( pTxtNode ) pTxtNode->SetAutoCompleteWordDirty( true );
+ }
+ GetRootFrm()->SetIdleFlags();
+ }
+}
+
+const SwFmtINetFmt* SwDoc::FindINetAttr( const String& rName ) const
+{
+ const SwFmtINetFmt* pItem;
+ const SwTxtINetFmt* pTxtAttr;
+ const SwTxtNode* pTxtNd;
+ sal_uInt32 n, nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_INETFMT );
+ for( n = 0; n < nMaxItems; ++n )
+ if( 0 != (pItem = (SwFmtINetFmt*)GetAttrPool().GetItem2(
+ RES_TXTATR_INETFMT, n ) ) &&
+ pItem->GetName().Equals( rName ) &&
+ 0 != ( pTxtAttr = pItem->GetTxtINetFmt()) &&
+ 0 != ( pTxtNd = pTxtAttr->GetpTxtNode() ) &&
+ &pTxtNd->GetNodes() == &GetNodes() )
+ {
+ return pItem;
+ }
+
+ return 0;
+}
+
+void SwDoc::Summary( SwDoc* pExtDoc, sal_uInt8 nLevel, sal_uInt8 nPara, sal_Bool bImpress )
+{
+ const SwOutlineNodes& rOutNds = GetNodes().GetOutLineNds();
+ if( pExtDoc && rOutNds.Count() )
+ {
+ sal_uInt16 i;
+ ::StartProgress( STR_STATSTR_SUMMARY, 0, rOutNds.Count(), GetDocShell() );
+ SwNodeIndex aEndOfDoc( pExtDoc->GetNodes().GetEndOfContent(), -1 );
+ for( i = 0; i < rOutNds.Count(); ++i )
+ {
+ ::SetProgressState( i, GetDocShell() );
+ const sal_uLong nIndex = rOutNds[ i ]->GetIndex();
+ //sal_uInt8 nLvl = ((SwTxtNode*)GetNodes()[ nIndex ])->GetTxtColl()//#outline level,zhaojianwei
+ // ->GetOutlineLevel();
+ const int nLvl = ((SwTxtNode*)GetNodes()[ nIndex ])->GetAttrOutlineLevel()-1;//<-end,zhaojianwei
+ if( nLvl > nLevel )
+ continue;
+ sal_uInt16 nEndOfs = 1;
+ sal_uInt8 nWish = nPara;
+ sal_uLong nNextOutNd = i + 1 < rOutNds.Count() ?
+ rOutNds[ i + 1 ]->GetIndex() : GetNodes().Count();
+ sal_Bool bKeep = sal_False;
+ while( ( nWish || bKeep ) && nIndex + nEndOfs < nNextOutNd &&
+ GetNodes()[ nIndex + nEndOfs ]->IsTxtNode() )
+ {
+ SwTxtNode* pTxtNode = (SwTxtNode*)GetNodes()[ nIndex+nEndOfs ];
+ if( pTxtNode->GetTxt().Len() && nWish )
+ --nWish;
+ bKeep = pTxtNode->GetSwAttrSet().GetKeep().GetValue();
+ ++nEndOfs;
+ }
+
+ SwNodeRange aRange( *rOutNds[ i ], 0, *rOutNds[ i ], nEndOfs );
+ GetNodes()._Copy( aRange, aEndOfDoc );
+ }
+ const SwTxtFmtColls *pColl = pExtDoc->GetTxtFmtColls();
+ for( i = 0; i < pColl->Count(); ++i )
+ (*pColl)[ i ]->ResetFmtAttr( RES_PAGEDESC, RES_BREAK );
+ SwNodeIndex aIndx( pExtDoc->GetNodes().GetEndOfExtras() );
+ ++aEndOfDoc;
+ while( aIndx < aEndOfDoc )
+ {
+ SwNode *pNode;
+ sal_Bool bDelete = sal_False;
+ if( (pNode = &aIndx.GetNode())->IsTxtNode() )
+ {
+ SwTxtNode *pNd = (SwTxtNode*)pNode;
+ if( pNd->HasSwAttrSet() )
+ pNd->ResetAttr( RES_PAGEDESC, RES_BREAK );
+ if( bImpress )
+ {
+ SwTxtFmtColl* pMyColl = pNd->GetTxtColl();
+ //sal_uInt16 nHeadLine = static_cast<sal_uInt16>(pMyColl->GetOutlineLevel()==NO_NUMBERING ?//#outlinelevel,zhaojianwei
+ const sal_uInt16 nHeadLine = static_cast<sal_uInt16>(
+ !pMyColl->IsAssignedToListLevelOfOutlineStyle() //<-end,zhaojianwei
+ ? RES_POOLCOLL_HEADLINE2
+ : RES_POOLCOLL_HEADLINE1 );
+ pMyColl = pExtDoc->GetTxtCollFromPool( nHeadLine );
+ pNd->ChgFmtColl( pMyColl );
+ }
+ if( !pNd->Len() &&
+ pNd->StartOfSectionIndex()+2 < pNd->EndOfSectionIndex() )
+ {
+ bDelete = sal_True;
+ pExtDoc->GetNodes().Delete( aIndx );
+ }
+ }
+ if( !bDelete )
+ ++aIndx;
+ }
+ ::EndProgress( GetDocShell() );
+ }
+}
+
+ // loesche den nicht sichtbaren Content aus dem Document, wie z.B.:
+ // versteckte Bereiche, versteckte Absaetze
+bool SwDoc::RemoveInvisibleContent()
+{
+ sal_Bool bRet = sal_False;
+ GetIDocumentUndoRedo().StartUndo( UNDO_UI_DELETE_INVISIBLECNTNT, NULL );
+
+ {
+ SwTxtNode* pTxtNd;
+ SwClientIter aIter( *GetSysFldType( RES_HIDDENPARAFLD ) );
+ for( SwFmtFld* pFmtFld = (SwFmtFld*)aIter.First( TYPE( SwFmtFld ));
+ pFmtFld; pFmtFld = (SwFmtFld*)aIter.Next() )
+ {
+ if( pFmtFld->GetTxtFld() &&
+ 0 != ( pTxtNd = (SwTxtNode*)pFmtFld->GetTxtFld()->GetpTxtNode() ) &&
+ pTxtNd->GetpSwpHints() && pTxtNd->HasHiddenParaField() &&
+ &pTxtNd->GetNodes() == &GetNodes() )
+ {
+ bRet = sal_True;
+ SwPaM aPam( *pTxtNd, 0, *pTxtNd, pTxtNd->GetTxt().Len() );
+
+ // Remove hidden paragraph or delete contents:
+ // Delete contents if
+ // 1. removing the paragraph would result in an empty section or
+ // 2. if the paragraph is the last paragraph in the section and
+ // there is no paragraph in front of the paragraph:
+ if ( ( 2 == pTxtNd->EndOfSectionIndex() - pTxtNd->StartOfSectionIndex() ) ||
+ ( 1 == pTxtNd->EndOfSectionIndex() - pTxtNd->GetIndex() &&
+ !GetNodes()[ pTxtNd->GetIndex() - 1 ]->GetTxtNode() ) )
+ {
+ DeleteRange( aPam );
+ }
+ else
+ {
+ aPam.DeleteMark();
+ DelFullPara( aPam );
+ }
+ }
+ }
+ }
+
+ //
+ // Remove any hidden paragraph (hidden text attribute)
+ //
+ for( sal_uLong n = GetNodes().Count(); n; )
+ {
+ SwTxtNode* pTxtNd = GetNodes()[ --n ]->GetTxtNode();
+ if ( pTxtNd )
+ {
+ bool bRemoved = false;
+ SwPaM aPam( *pTxtNd, 0, *pTxtNd, pTxtNd->GetTxt().Len() );
+ if ( pTxtNd->HasHiddenCharAttribute( true ) )
+ {
+ bRemoved = sal_True;
+ bRet = sal_True;
+
+ // Remove hidden paragraph or delete contents:
+ // Delete contents if
+ // 1. removing the paragraph would result in an empty section or
+ // 2. if the paragraph is the last paragraph in the section and
+ // there is no paragraph in front of the paragraph:
+
+ if ( ( 2 == pTxtNd->EndOfSectionIndex() - pTxtNd->StartOfSectionIndex() ) ||
+ ( 1 == pTxtNd->EndOfSectionIndex() - pTxtNd->GetIndex() &&
+ !GetNodes()[ pTxtNd->GetIndex() - 1 ]->GetTxtNode() ) )
+ {
+ DeleteRange( aPam );
+ }
+ else
+ {
+ aPam.DeleteMark();
+ DelFullPara( aPam );
+ }
+ }
+ else if ( pTxtNd->HasHiddenCharAttribute( false ) )
+ {
+ bRemoved = sal_True;
+ bRet = sal_True;
+ SwScriptInfo::DeleteHiddenRanges( *pTxtNd );
+ }
+
+ // --> FME 2006-01-11 #120473#
+ // Footnotes/Frames may have been removed, therefore we have
+ // to reset n:
+ if ( bRemoved )
+ n = aPam.GetPoint()->nNode.GetIndex();
+ // <--
+ }
+ }
+
+ {
+ // dann noch alle versteckten Bereiche loeschen/leeren
+ SwSectionFmts aSectFmts;
+ SwSectionFmts& rSectFmts = GetSections();
+ sal_uInt16 n;
+
+ for( n = rSectFmts.Count(); n; )
+ {
+ SwSectionFmt* pSectFmt = rSectFmts[ --n ];
+ // don't add sections in Undo/Redo
+ if( !pSectFmt->IsInNodesArr())
+ continue;
+ SwSection* pSect = pSectFmt->GetSection();
+ if( pSect->CalcHiddenFlag() )
+ {
+ SwSection* pParent = pSect, *pTmp;
+ while( 0 != (pTmp = pParent->GetParent() ))
+ {
+ if( pTmp->IsHiddenFlag() )
+ pSect = pTmp;
+ pParent = pTmp;
+ }
+
+ if( USHRT_MAX == aSectFmts.GetPos( pSect->GetFmt() ) )
+ aSectFmts.Insert( pSect->GetFmt(), 0 );
+ }
+ if( pSect->GetCondition().Len() )
+ {
+ SwSectionData aSectionData( *pSect );
+ aSectionData.SetCondition( aEmptyStr );
+ aSectionData.SetHidden( false );
+ UpdateSection( n, aSectionData );
+ }
+ }
+
+ if( 0 != ( n = aSectFmts.Count() ))
+ {
+ while( n )
+ {
+ SwSectionFmt* pSectFmt = aSectFmts[ --n ];
+ SwSectionNode* pSectNd = pSectFmt->GetSectionNode();
+ if( pSectNd )
+ {
+ bRet = sal_True;
+ SwPaM aPam( *pSectNd );
+
+ if( pSectNd->StartOfSectionNode()->StartOfSectionIndex() ==
+ pSectNd->GetIndex() - 1 &&
+ pSectNd->StartOfSectionNode()->EndOfSectionIndex() ==
+ pSectNd->EndOfSectionIndex() + 1 )
+ {
+ // nur den Inhalt loeschen
+ SwCntntNode* pCNd = GetNodes().GoNext(
+ &aPam.GetPoint()->nNode );
+ aPam.GetPoint()->nContent.Assign( pCNd, 0 );
+ aPam.SetMark();
+ aPam.GetPoint()->nNode = *pSectNd->EndOfSectionNode();
+ pCNd = GetNodes().GoPrevious(
+ &aPam.GetPoint()->nNode );
+ aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+
+ DeleteRange( aPam );
+ }
+ else
+ {
+ // die gesamte Section loeschen
+ aPam.SetMark();
+ aPam.GetPoint()->nNode = *pSectNd->EndOfSectionNode();
+ DelFullPara( aPam );
+ }
+
+ }
+ }
+ aSectFmts.Remove( 0, aSectFmts.Count() );
+ }
+ }
+
+ if( bRet )
+ SetModified();
+ GetIDocumentUndoRedo().EndUndo( UNDO_UI_DELETE_INVISIBLECNTNT, NULL );
+ return bRet;
+}
+/*-- 25.08.2010 14:18:12---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+bool SwDoc::HasInvisibleContent() const
+{
+ sal_Bool bRet = sal_False;
+
+ SwClientIter aIter( *GetSysFldType( RES_HIDDENPARAFLD ) );
+ if( aIter.First( TYPE( SwFmtFld ) ) )
+ bRet = sal_True;
+
+ //
+ // Search for any hidden paragraph (hidden text attribute)
+ //
+ if( ! bRet )
+ {
+ for( sal_uLong n = GetNodes().Count(); !bRet && (n > 0); )
+ {
+ SwTxtNode* pTxtNd = GetNodes()[ --n ]->GetTxtNode();
+ if ( pTxtNd )
+ {
+ SwPaM aPam( *pTxtNd, 0, *pTxtNd, pTxtNd->GetTxt().Len() );
+ if( pTxtNd->HasHiddenCharAttribute( true ) || ( pTxtNd->HasHiddenCharAttribute( false ) ) )
+ {
+ bRet = sal_True;
+ }
+ }
+ }
+ }
+
+ if( ! bRet )
+ {
+ const SwSectionFmts& rSectFmts = GetSections();
+ sal_uInt16 n;
+
+ for( n = rSectFmts.Count(); !bRet && (n > 0); )
+ {
+ SwSectionFmt* pSectFmt = rSectFmts[ --n ];
+ // don't add sections in Undo/Redo
+ if( !pSectFmt->IsInNodesArr())
+ continue;
+ SwSection* pSect = pSectFmt->GetSection();
+ if( pSect->IsHidden() )
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+bool SwDoc::RestoreInvisibleContent()
+{
+ bool bRet = false;
+ SwUndoId nLastUndoId(UNDO_EMPTY);
+ if (GetIDocumentUndoRedo().GetLastUndoInfo(0, & nLastUndoId)
+ && (UNDO_UI_DELETE_INVISIBLECNTNT == nLastUndoId))
+ {
+ GetIDocumentUndoRedo().Undo();
+ GetIDocumentUndoRedo().ClearRedo();
+ bRet = true;
+ }
+ return bRet;
+}
+
+/*-- 11.06.2004 08:34:04---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+sal_Bool SwDoc::ConvertFieldsToText()
+{
+ sal_Bool bRet = sal_False;
+ LockExpFlds();
+ GetIDocumentUndoRedo().StartUndo( UNDO_UI_REPLACE, NULL );
+
+ const SwFldTypes* pMyFldTypes = GetFldTypes();
+ sal_uInt16 nCount = pMyFldTypes->Count();
+ //go backward, field types are removed
+ for(sal_uInt16 nType = nCount; nType > 0; --nType)
+ {
+ const SwFieldType *pCurType = pMyFldTypes->GetObject(nType - 1);
+
+ if ( RES_POSTITFLD == pCurType->Which() )
+ continue;
+
+ SwClientIter aIter( *(SwFieldType*)pCurType );
+ const SwFmtFld* pCurFldFmt = (SwFmtFld*)aIter.First( TYPE( SwFmtFld ));
+ ::std::vector<const SwFmtFld*> aFieldFmts;
+ while (pCurFldFmt)
+ {
+ aFieldFmts.push_back(pCurFldFmt);
+ pCurFldFmt = (SwFmtFld*)aIter.Next();
+ }
+ ::std::vector<const SwFmtFld*>::iterator aBegin = aFieldFmts.begin();
+ ::std::vector<const SwFmtFld*>::iterator aEnd = aFieldFmts.end();
+ while(aBegin != aEnd)
+ {
+ const SwTxtFld *pTxtFld = (*aBegin)->GetTxtFld();
+ // skip fields that are currently not in the document
+ // e.g. fields in undo or redo array
+
+ sal_Bool bSkip = !pTxtFld ||
+ !pTxtFld->GetpTxtNode()->GetNodes().IsDocNodes();
+
+ if (!bSkip)
+ {
+ sal_Bool bInHeaderFooter = IsInHeaderFooter(SwNodeIndex(*pTxtFld->GetpTxtNode()));
+ const SwFmtFld& rFmtFld = pTxtFld->GetFld();
+ const SwField* pField = rFmtFld.GetFld();
+
+ //#i55595# some fields have to be excluded in headers/footers
+ sal_uInt16 nWhich = pField->GetTyp()->Which();
+ if(!bInHeaderFooter ||
+ (nWhich != RES_PAGENUMBERFLD &&
+ nWhich != RES_CHAPTERFLD &&
+ nWhich != RES_GETEXPFLD&&
+ nWhich != RES_SETEXPFLD&&
+ nWhich != RES_INPUTFLD&&
+ nWhich != RES_REFPAGEGETFLD&&
+ nWhich != RES_REFPAGESETFLD))
+ {
+ String sText = pField->ExpandField(true);
+ //database fields should not convert their command into text
+ if( RES_DBFLD == pCurType->Which() && !static_cast<const SwDBField*>(pField)->IsInitialized())
+ sText.Erase();
+
+ //now remove the field and insert the string
+ SwPaM aPam1(*pTxtFld->GetpTxtNode(), *pTxtFld->GetStart());
+ aPam1.Move();
+ //insert first to keep the field's attributes
+ InsertString( aPam1, sText );
+ SwPaM aPam2(*pTxtFld->GetpTxtNode(), *pTxtFld->GetStart());
+ aPam2.SetMark();
+ aPam2.Move();
+ DeleteAndJoin(aPam2);//remove the field
+ }
+ }
+ ++aBegin;
+ }
+ }
+
+ if( bRet )
+ SetModified();
+ GetIDocumentUndoRedo().EndUndo( UNDO_UI_REPLACE, NULL );
+ UnlockExpFlds();
+ return bRet;
+
+}
+
+bool SwDoc::IsVisibleLinks() const
+{
+ return mbVisibleLinks;
+}
+
+void SwDoc::SetVisibleLinks(bool bFlag)
+{
+ mbVisibleLinks = bFlag;
+}
+
+sfx2::LinkManager& SwDoc::GetLinkManager()
+{
+ return *pLinkMgr;
+}
+
+const sfx2::LinkManager& SwDoc::GetLinkManager() const
+{
+ return *pLinkMgr;
+}
+
+void SwDoc::SetLinksUpdated(const bool bNewLinksUpdated)
+{
+ mbLinksUpdated = bNewLinksUpdated;
+}
+
+bool SwDoc::LinksUpdated() const
+{
+ return mbLinksUpdated;
+}
+
+ // embedded alle lokalen Links (Bereiche/Grafiken)
+::sfx2::SvBaseLink* lcl_FindNextRemovableLink( const ::sfx2::SvBaseLinks& rLinks, sfx2::LinkManager& rLnkMgr )
+{
+ for( sal_uInt16 n = 0; n < rLinks.Count(); ++n )
+ {
+ ::sfx2::SvBaseLink* pLnk = &(*rLinks[ n ]);
+ if( pLnk &&
+ ( OBJECT_CLIENT_GRF == pLnk->GetObjType() ||
+ OBJECT_CLIENT_FILE == pLnk->GetObjType() ) &&
+ pLnk->ISA( SwBaseLink ) )
+ {
+ ::sfx2::SvBaseLinkRef xLink = pLnk;
+
+ String sFName;
+ rLnkMgr.GetDisplayNames( xLink, 0, &sFName, 0, 0 );
+
+ INetURLObject aURL( sFName );
+ if( INET_PROT_FILE == aURL.GetProtocol() ||
+ INET_PROT_CID == aURL.GetProtocol() )
+ return pLnk;
+ }
+ }
+ return 0;
+}
+bool SwDoc::EmbedAllLinks()
+{
+ sal_Bool bRet = sal_False;
+ sfx2::LinkManager& rLnkMgr = GetLinkManager();
+ const ::sfx2::SvBaseLinks& rLinks = rLnkMgr.GetLinks();
+ if( rLinks.Count() )
+ {
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ ::sfx2::SvBaseLink* pLnk = 0;
+ while( 0 != (pLnk = lcl_FindNextRemovableLink( rLinks, rLnkMgr ) ) )
+ {
+ ::sfx2::SvBaseLinkRef xLink = pLnk;
+ // dem Link sagen, das er aufgeloest wird!
+ xLink->Closed();
+
+ // falls einer vergessen hat sich auszutragen
+ if( xLink.Is() )
+ rLnkMgr.Remove( xLink );
+
+ bRet = sal_True;
+ }
+
+ GetIDocumentUndoRedo().DelAllUndoObj();
+ SetModified();
+ }
+ return bRet;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung:
+ --------------------------------------------------------------------*/
+
+sal_Bool SwDoc::IsInsTblFormatNum() const
+{
+ return SW_MOD()->IsInsTblFormatNum(get(IDocumentSettingAccess::HTML_MODE));
+}
+
+sal_Bool SwDoc::IsInsTblChangeNumFormat() const
+{
+ return SW_MOD()->IsInsTblChangeNumFormat(get(IDocumentSettingAccess::HTML_MODE));
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung:
+ --------------------------------------------------------------------*/
+
+sal_Bool SwDoc::IsInsTblAlignNum() const
+{
+ return SW_MOD()->IsInsTblAlignNum(get(IDocumentSettingAccess::HTML_MODE));
+}
+
+ // setze das InsertDB als Tabelle Undo auf:
+void SwDoc::AppendUndoForInsertFromDB( const SwPaM& rPam, sal_Bool bIsTable )
+{
+ if( bIsTable )
+ {
+ const SwTableNode* pTblNd = rPam.GetPoint()->nNode.GetNode().FindTableNode();
+ if( pTblNd )
+ {
+ SwUndoCpyTbl* pUndo = new SwUndoCpyTbl;
+ pUndo->SetTableSttIdx( pTblNd->GetIndex() );
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ }
+ else if( rPam.HasMark() )
+ {
+ SwUndoCpyDoc* pUndo = new SwUndoCpyDoc( rPam );
+ pUndo->SetInsertRange( rPam, sal_False );
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+}
+
+void SwDoc::ChgTOX(SwTOXBase & rTOX, const SwTOXBase & rNew)
+{
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().DelAllUndoObj();
+
+ SwUndo * pUndo = new SwUndoTOXChange(&rTOX, rNew);
+
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ rTOX = rNew;
+
+ if (rTOX.ISA(SwTOXBaseSection))
+ {
+ static_cast<SwTOXBaseSection &>(rTOX).Update();
+ static_cast<SwTOXBaseSection &>(rTOX).UpdatePageNum();
+ }
+}
+
+// #111827#
+String SwDoc::GetPaMDescr(const SwPaM & rPam) const
+{
+ String aResult;
+ bool bOK = false;
+
+ if (rPam.GetNode(sal_True) == rPam.GetNode(sal_False))
+ {
+ SwTxtNode * pTxtNode = rPam.GetNode(sal_True)->GetTxtNode();
+
+ if (0 != pTxtNode)
+ {
+ xub_StrLen nStart = rPam.Start()->nContent.GetIndex();
+ xub_StrLen nEnd = rPam.End()->nContent.GetIndex();
+
+ aResult += String(SW_RES(STR_START_QUOTE));
+ aResult += ShortenString(pTxtNode->GetTxt().
+ Copy(nStart, nEnd - nStart),
+ nUndoStringLength,
+ String(SW_RES(STR_LDOTS)));
+ aResult += String(SW_RES(STR_END_QUOTE));
+
+ bOK = true;
+ }
+ }
+ else if (0 != rPam.GetNode(sal_True))
+ {
+ if (0 != rPam.GetNode(sal_False))
+ aResult += String(SW_RES(STR_PARAGRAPHS));
+
+ bOK = true;
+ }
+
+ if (! bOK)
+ aResult += String("??", RTL_TEXTENCODING_ASCII_US);
+
+ return aResult;
+}
+
+// -> #111840#
+SwField * SwDoc::GetField(const SwPosition & rPos)
+{
+ SwTxtFld * const pAttr = GetTxtFld(rPos);
+
+ return (pAttr) ? const_cast<SwField *>( pAttr->GetFld().GetFld() ) : 0;
+}
+
+SwTxtFld * SwDoc::GetTxtFld(const SwPosition & rPos)
+{
+ SwTxtNode * const pNode = rPos.nNode.GetNode().GetTxtNode();
+
+ return (pNode)
+ ? static_cast<SwTxtFld*>( pNode->GetTxtAttrForCharAt(
+ rPos.nContent.GetIndex(), RES_TXTATR_FIELD) )
+ : 0;
+}
+// <- #111840#
+
+bool SwDoc::ContainsHiddenChars() const
+{
+ for( sal_uLong n = GetNodes().Count(); n; )
+ {
+ SwNode* pNd = GetNodes()[ --n ];
+ if ( ND_TEXTNODE == pNd->GetNodeType() &&
+ ((SwTxtNode*)pNd)->HasHiddenCharAttribute( false ) )
+ return true;
+ }
+
+ return false;
+}
+
+SwUnoCrsr* SwDoc::CreateUnoCrsr( const SwPosition& rPos, sal_Bool bTblCrsr )
+{
+ SwUnoCrsr* pNew;
+ if( bTblCrsr )
+ pNew = new SwUnoTableCrsr( rPos );
+ else
+ pNew = new SwUnoCrsr( rPos );
+
+ pUnoCrsrTbl->Insert( pNew, pUnoCrsrTbl->Count() );
+ return pNew;
+}
+
+void SwDoc::ChkCondColls()
+{
+ for (sal_uInt16 n = 0; n < pTxtFmtCollTbl->Count(); n++)
+ {
+ SwTxtFmtColl *pColl = (*pTxtFmtCollTbl)[n];
+
+ if (RES_CONDTXTFMTCOLL == pColl->Which())
+ {
+ SwClientIter aIter(*pColl);
+
+ SwClient * pClient = aIter.First(TYPE(SwTxtNode));
+ while (pClient)
+ {
+ SwTxtNode * pTxtNode = static_cast<SwTxtNode *>(pClient);
+
+ pTxtNode->ChkCondColl();
+
+ pClient = aIter.Next();
+ }
+ }
+ }
+}
+
+#ifdef FUTURE_VBA
+uno::Reference< script::vba::XVBAEventProcessor >
+SwDoc::GetVbaEventProcessor()
+{
+ if( !mxVbaEvents.is() && pDocShell && ooo::vba::isAlienWordDoc( *pDocShell ) )
+ {
+ try
+ {
+ uno::Reference< frame::XModel > xModel( pDocShell->GetModel(), uno::UNO_SET_THROW );
+ uno::Sequence< uno::Any > aArgs(1);
+ aArgs[0] <<= xModel;
+ mxVbaEvents.set( ooo::vba::createVBAUnoAPIServiceWithArgs( pDocShell, "com.sun.star.script.vba.VBATextEventProcessor" , aArgs ), uno::UNO_QUERY_THROW );
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+ return mxVbaEvents;
+}
+#endif
+
+void SwDoc::setExternalData(::sw::tExternalDataType eType,
+ ::sw::tExternalDataPointer pPayload)
+{
+ m_externalData[eType] = pPayload;
+}
+
+::sw::tExternalDataPointer SwDoc::getExternalData(::sw::tExternalDataType eType)
+{
+ return m_externalData[eType];
+}
diff --git a/sw/source/core/doc/docbasic.cxx b/sw/source/core/doc/docbasic.cxx
new file mode 100644
index 000000000000..77665e55fbce
--- /dev/null
+++ b/sw/source/core/doc/docbasic.cxx
@@ -0,0 +1,276 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#ifndef _RTL_USTRING_HXX //autogen
+#include <rtl/ustring.hxx>
+#endif
+#include <svtools/imap.hxx>
+#include <svtools/imapobj.hxx>
+#include <basic/sbx.hxx>
+#include <frmfmt.hxx>
+#include <fmtinfmt.hxx>
+#include <fmturl.hxx>
+#include <frmatr.hxx>
+#include <docary.hxx>
+#include <doc.hxx>
+#ifndef _DOCSH_HXX
+#include <docsh.hxx>
+#endif
+#include <swevent.hxx>
+
+using namespace ::com::sun::star::uno;
+using ::rtl::OUString;
+
+static Sequence<Any> *lcl_docbasic_convertArgs( SbxArray& rArgs )
+{
+ Sequence<Any> *pRet = 0;
+
+ sal_uInt16 nCount = rArgs.Count();
+ if( nCount > 1 )
+ {
+ nCount--;
+ pRet = new Sequence<Any>( nCount );
+ Any *pUnoArgs = pRet->getArray();
+ for( sal_uInt16 i=0; i<nCount; i++ )
+ {
+ SbxVariable *pVar = rArgs.Get( i+1 );
+ switch( pVar->GetType() )
+ {
+ case SbxSTRING:
+ pUnoArgs[i] <<= OUString( pVar->GetString() );
+ break;
+ case SbxCHAR:
+ pUnoArgs[i] <<= (sal_Int16)pVar->GetChar() ;
+ break;
+ case SbxUSHORT:
+ pUnoArgs[i] <<= (sal_Int16)pVar->GetUShort();
+ break;
+ case SbxLONG:
+ pUnoArgs[i] <<= (sal_Int32)pVar->GetLong();
+ break;
+ default:
+ pUnoArgs[i].setValue(0, ::getVoidCppuType());
+ break;
+ }
+ }
+ }
+
+ return pRet;
+}
+
+sal_Bool SwDoc::ExecMacro( const SvxMacro& rMacro, String* pRet, SbxArray* pArgs )
+{
+ ErrCode eErr = 0;
+ switch( rMacro.GetScriptType() )
+ {
+ case STARBASIC:
+ {
+ SbxBaseRef aRef;
+ SbxValue* pRetValue = new SbxValue;
+ aRef = pRetValue;
+ eErr = pDocShell->CallBasic( rMacro.GetMacName(),
+ rMacro.GetLibName(),
+ pArgs, pRet ? pRetValue : 0 );
+
+ if( pRet && SbxNULL < pRetValue->GetType() &&
+ SbxVOID != pRetValue->GetType() )
+ // gueltiger Wert, also setzen
+ *pRet = pRetValue->GetString();
+ }
+ break;
+ case JAVASCRIPT:
+ // ignore JavaScript calls
+ break;
+ case EXTENDED_STYPE:
+ {
+ Sequence<Any> *pUnoArgs = 0;
+ if( pArgs )
+ {
+ // better to rename the local function to lcl_translateBasic2Uno and
+ // a much shorter routine can be found in sfx2/source/doc/objmisc.cxx
+ pUnoArgs = lcl_docbasic_convertArgs( *pArgs );
+ }
+
+ if (!pUnoArgs)
+ {
+ pUnoArgs = new Sequence< Any > (0);
+ }
+
+ // TODO - return value is not handled
+ Any aRet;
+ Sequence< sal_Int16 > aOutArgsIndex;
+ Sequence< Any > aOutArgs;
+
+ OSL_TRACE( "SwDoc::ExecMacro URL is %s", ByteString( rMacro.GetMacName(),
+ RTL_TEXTENCODING_UTF8).GetBuffer() );
+
+ eErr = pDocShell->CallXScript(
+ rMacro.GetMacName(), *pUnoArgs, aRet, aOutArgsIndex, aOutArgs);
+
+ //*pRet = pRetValue->GetString();
+ // use the AnyConverter to return a String if appropriate?
+
+ // need to call something like lcl_translateUno2Basic
+ // pArgs = lcl_translateUno2Basic( pUnoArgs );
+
+ delete pUnoArgs;
+ break;
+ }
+ }
+
+ return 0 == eErr;
+}
+
+
+
+sal_uInt16 SwDoc::CallEvent( sal_uInt16 nEvent, const SwCallMouseEvent& rCallEvent,
+ sal_Bool bCheckPtr, SbxArray* pArgs, const Link* )
+{
+ if( !pDocShell ) // ohne DocShell geht das nicht!
+ return 0;
+
+ sal_uInt16 nRet = 0;
+ const SvxMacroTableDtor* pTbl = 0;
+ switch( rCallEvent.eType )
+ {
+ case EVENT_OBJECT_INETATTR:
+ if( bCheckPtr )
+ {
+ const SfxPoolItem* pItem;
+ sal_uInt32 n, nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_INETFMT );
+ for( n = 0; n < nMaxItems; ++n )
+ if( 0 != (pItem = GetAttrPool().GetItem2( RES_TXTATR_INETFMT, n ) )
+ && rCallEvent.PTR.pINetAttr == pItem )
+ {
+ bCheckPtr = sal_False; // als Flag missbrauchen
+ break;
+ }
+ }
+ if( !bCheckPtr )
+ pTbl = rCallEvent.PTR.pINetAttr->GetMacroTbl();
+ break;
+
+ case EVENT_OBJECT_URLITEM:
+ case EVENT_OBJECT_IMAGE:
+ {
+ const SwFrmFmtPtr pFmt = (SwFrmFmtPtr)rCallEvent.PTR.pFmt;
+ if( bCheckPtr )
+ {
+ sal_uInt16 nPos = GetSpzFrmFmts()->GetPos( pFmt );
+ if( USHRT_MAX != nPos )
+ bCheckPtr = sal_False; // als Flag missbrauchen
+ }
+ if( !bCheckPtr )
+ pTbl = &pFmt->GetMacro().GetMacroTable();
+ }
+ break;
+
+ case EVENT_OBJECT_IMAGEMAP:
+ {
+ const IMapObject* pIMapObj = rCallEvent.PTR.IMAP.pIMapObj;
+ if( bCheckPtr )
+ {
+ const SwFrmFmtPtr pFmt = (SwFrmFmtPtr)rCallEvent.PTR.IMAP.pFmt;
+ sal_uInt16 nPos = GetSpzFrmFmts()->GetPos( pFmt );
+ const ImageMap* pIMap;
+ if( USHRT_MAX != nPos &&
+ 0 != (pIMap = pFmt->GetURL().GetMap()) )
+ {
+ for( nPos = pIMap->GetIMapObjectCount(); nPos; )
+ if( pIMapObj == pIMap->GetIMapObject( --nPos ))
+ {
+ bCheckPtr = sal_False; // als Flag missbrauchen
+ break;
+ }
+ }
+ }
+ if( !bCheckPtr )
+ pTbl = &pIMapObj->GetMacroTable();
+ }
+ break;
+ default:
+ break;
+ }
+
+ if( pTbl )
+ {
+ nRet = 0x1;
+ if( pTbl->IsKeyValid( nEvent ) )
+ {
+ const SvxMacro& rMacro = *pTbl->Get( nEvent );
+ if( STARBASIC == rMacro.GetScriptType() )
+ {
+ nRet += 0 == pDocShell->CallBasic( rMacro.GetMacName(),
+ rMacro.GetLibName(), pArgs ) ? 1 : 0;
+ }
+ else if( EXTENDED_STYPE == rMacro.GetScriptType() )
+ {
+ Sequence<Any> *pUnoArgs = 0;
+
+ if( pArgs )
+ {
+ pUnoArgs = lcl_docbasic_convertArgs( *pArgs );
+ }
+
+ if (!pUnoArgs)
+ {
+ pUnoArgs = new Sequence <Any> (0);
+ }
+
+ Any aRet;
+ Sequence< sal_Int16 > aOutArgsIndex;
+ Sequence< Any > aOutArgs;
+
+ OSL_TRACE( "SwDoc::CallEvent URL is %s", ByteString(
+ rMacro.GetMacName(), RTL_TEXTENCODING_UTF8).GetBuffer() );
+
+ nRet += 0 == pDocShell->CallXScript(
+ rMacro.GetMacName(), *pUnoArgs,aRet, aOutArgsIndex, aOutArgs) ? 1 : 0;
+
+ //*pRet = pRetValue->GetString();
+ // use the AnyConverter to return a String if appropriate?
+
+ // need to call something like lcl_translateUno2Basic
+ // pArgs = lcl_translateUno2Basic( pUnoArgs );
+
+ delete pUnoArgs;
+ }
+ // JavaScript calls are ignored
+ }
+ }
+ return nRet;
+}
+
+
+
+
diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
new file mode 100644
index 000000000000..50fb0e7b98f7
--- /dev/null
+++ b/sw/source/core/doc/docbm.cxx
@@ -0,0 +1,1746 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <MarkManager.hxx>
+#include <bookmrk.hxx>
+#include <boost/bind.hpp>
+#include <cntfrm.hxx>
+#include <crossrefbookmark.hxx>
+#include <dcontact.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <xmloff/odffields.hxx>
+#include <editsh.hxx>
+#include <errhdl.hxx>
+#include <fmtanchr.hxx>
+#include <frmfmt.hxx>
+#include <functional>
+#include <hintids.hxx>
+#include <mvsave.hxx>
+#include <ndtxt.hxx>
+#include <node.hxx>
+#include <pam.hxx>
+#include <redline.hxx>
+#include <rolbck.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+#include <sortedobjs.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <swserv.hxx>
+#include <swundo.hxx>
+#include <tools/pstm.hxx>
+#include <unocrsr.hxx>
+#include <viscrs.hxx>
+#include <stdio.h>
+
+
+using namespace ::std;
+using namespace ::boost;
+using namespace ::sw::mark;
+
+namespace
+{
+ static bool lcl_GreaterThan( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
+ {
+ return pIdx ? ( rPos.nNode > rNdIdx || ( rPos.nNode == rNdIdx && rPos.nContent >= pIdx->GetIndex() )) : rPos.nNode >= rNdIdx;
+ }
+
+ static bool lcl_Lower( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
+ {
+ return rPos.nNode < rNdIdx || ( pIdx && rPos.nNode == rNdIdx && rPos.nContent < pIdx->GetIndex() );
+ }
+
+ static bool lcl_MarkOrderingByStart(const IDocumentMarkAccess::pMark_t& rpFirst,
+ const IDocumentMarkAccess::pMark_t& rpSecond)
+ {
+ return rpFirst->GetMarkStart() < rpSecond->GetMarkStart();
+ }
+
+ static bool lcl_MarkOrderingByEnd(const IDocumentMarkAccess::pMark_t& rpFirst,
+ const IDocumentMarkAccess::pMark_t& rpSecond)
+ {
+ return rpFirst->GetMarkEnd() < rpSecond->GetMarkEnd();
+ }
+
+ static void lcl_InsertMarkSorted(IDocumentMarkAccess::container_t& io_vMarks,
+ const IDocumentMarkAccess::pMark_t& pMark)
+ {
+ io_vMarks.insert(
+ lower_bound(
+ io_vMarks.begin(),
+ io_vMarks.end(),
+ pMark,
+ &lcl_MarkOrderingByStart),
+ pMark);
+ }
+
+ static inline auto_ptr<SwPosition> lcl_PositionFromCntntNode(SwCntntNode * const pCntntNode, const bool bAtEnd=false)
+ {
+ auto_ptr<SwPosition> pResult(new SwPosition(*pCntntNode));
+ pResult->nContent.Assign(pCntntNode, bAtEnd ? pCntntNode->Len() : 0);
+ return pResult;
+ }
+
+ // return a position at the begin of rEnd, if it is a CntntNode
+ // else set it to the begin of the Node after rEnd, if there is one
+ // else set it to the end of the node before rStt
+ // else set it to the CntntNode of the Pos outside the Range
+ static inline auto_ptr<SwPosition> lcl_FindExpelPosition(const SwNodeIndex& rStt,
+ const SwNodeIndex& rEnd,
+ const SwPosition& rOtherPosition)
+ {
+ SwCntntNode * pNode = rEnd.GetNode().GetCntntNode();
+ SwNodeIndex aStt = SwNodeIndex(rStt);
+ SwNodeIndex aEnd = SwNodeIndex(rEnd);
+ bool bAtEnd = false;
+ if(!pNode)
+ pNode = rEnd.GetNodes().GoNext(&aEnd), bAtEnd = false;
+ if(!pNode)
+ pNode = rStt.GetNodes().GoPrevious(&aStt), bAtEnd = true;
+ if(pNode)
+ return lcl_PositionFromCntntNode(pNode, bAtEnd);
+ return auto_ptr<SwPosition>(new SwPosition(rOtherPosition));
+ };
+
+ static IMark* lcl_getMarkAfter(const IDocumentMarkAccess::container_t& rMarks, const SwPosition& rPos)
+ {
+ IDocumentMarkAccess::const_iterator_t pMarkAfter = upper_bound(
+ rMarks.begin(),
+ rMarks.end(),
+ rPos,
+ bind(&IMark::StartsAfter, _2, _1)); // finds the first that is starting after
+ if(pMarkAfter == rMarks.end()) return NULL;
+ return pMarkAfter->get();
+ };
+
+ static IMark* lcl_getMarkBefore(const IDocumentMarkAccess::container_t& rMarks, const SwPosition& rPos)
+ {
+ // candidates from which to choose the mark before
+ IDocumentMarkAccess::container_t vCandidates;
+ // no need to consider marks starting after rPos
+ IDocumentMarkAccess::const_iterator_t pCandidatesEnd = upper_bound(
+ rMarks.begin(),
+ rMarks.end(),
+ rPos,
+ bind(&IMark::StartsAfter, _2, _1));
+ vCandidates.reserve(pCandidatesEnd - rMarks.begin());
+ // only marks ending before are candidates
+ remove_copy_if(
+ rMarks.begin(),
+ pCandidatesEnd,
+ back_inserter(vCandidates),
+ bind(logical_not<bool>(), bind(&IMark::EndsBefore, _1, rPos)));
+ // no candidate left => we are in front of the first mark or there are none
+ if(!vCandidates.size()) return NULL;
+ // return the highest (last) candidate using mark end ordering
+ return max_element(vCandidates.begin(), vCandidates.end(), &lcl_MarkOrderingByEnd)->get();
+ }
+
+ static bool lcl_FixCorrectedMark(bool bChangedPos, bool bChangedOPos, MarkBase* io_pMark)
+ {
+ if( (bChangedPos || bChangedOPos) && io_pMark->IsExpanded() &&
+ io_pMark->GetOtherMarkPos().nNode.GetNode().FindTableBoxStartNode() !=
+ io_pMark->GetMarkPos().nNode.GetNode().FindTableBoxStartNode() )
+ {
+ if(!bChangedOPos)
+ io_pMark->SetMarkPos(io_pMark->GetOtherMarkPos());
+ io_pMark->ClearOtherMarkPos();
+ DdeBookmark * const pDdeBkmk = dynamic_cast< DdeBookmark*>(io_pMark);
+ if(pDdeBkmk && pDdeBkmk->IsServer())
+ pDdeBkmk->SetRefObject(NULL);
+ return true;
+ }
+ return false;
+ }
+
+ static IDocumentMarkAccess::iterator_t lcl_FindMark(
+ IDocumentMarkAccess::container_t& rMarks,
+ const IDocumentMarkAccess::pMark_t& rpMarkToFind)
+ {
+ IDocumentMarkAccess::iterator_t ppCurrentMark = lower_bound(
+ rMarks.begin(), rMarks.end(),
+ rpMarkToFind, &lcl_MarkOrderingByStart);
+ // since there are usually not too many marks on the same start
+ // position, we are not doing a bisect search for the upper bound
+ // but instead start to iterate from pMarkLow directly
+ while(ppCurrentMark != rMarks.end() && **ppCurrentMark == *rpMarkToFind)
+ {
+ if(ppCurrentMark->get() == rpMarkToFind.get())
+ {
+ //OSL_TRACE("found mark named '%s'",
+ // ::rtl::OUStringToOString(ppCurrentMark->get()->GetName(), RTL_TEXTENCODING_UTF8).getStr());
+ return ppCurrentMark;
+ }
+ ++ppCurrentMark;
+ }
+ // reached a mark starting on a later start pos or the end of the
+ // vector => not found
+ return rMarks.end();
+ };
+
+ static IDocumentMarkAccess::iterator_t lcl_FindMarkAtPos(
+ IDocumentMarkAccess::container_t& rMarks,
+ const SwPosition& rPos,
+ const IDocumentMarkAccess::MarkType eType)
+ {
+ for(IDocumentMarkAccess::iterator_t ppCurrentMark = lower_bound(
+ rMarks.begin(), rMarks.end(),
+ rPos,
+ bind(&IMark::StartsBefore, _1, _2));
+ ppCurrentMark != rMarks.end();
+ ++ppCurrentMark)
+ {
+ // Once we reach a mark starting after the target pos
+ // we do not need to continue
+ if(ppCurrentMark->get()->StartsAfter(rPos))
+ break;
+ if(IDocumentMarkAccess::GetType(**ppCurrentMark) == eType)
+ {
+ //OSL_TRACE("found mark named '%s'",
+ // ::rtl::OUStringToOString(ppCurrentMark->get()->GetName(), RTL_TEXTENCODING_UTF8).getStr());
+ return ppCurrentMark;
+ }
+ }
+ // reached a mark starting on a later start pos or the end of the
+ // vector => not found
+ return rMarks.end();
+ };
+
+ static IDocumentMarkAccess::const_iterator_t lcl_FindMarkByName(
+ const ::rtl::OUString& rName,
+ IDocumentMarkAccess::const_iterator_t ppMarksBegin,
+ IDocumentMarkAccess::const_iterator_t ppMarksEnd)
+ {
+ return find_if(
+ ppMarksBegin,
+ ppMarksEnd,
+ bind(&::rtl::OUString::equals, bind(&IMark::GetName, _1), rName));
+ }
+
+#if 0
+ static void lcl_DebugMarks(IDocumentMarkAccess::container_t vMarks)
+ {
+ OSL_TRACE("%d Marks", vMarks.size());
+ for(IDocumentMarkAccess::iterator_t ppMark = vMarks.begin();
+ ppMark != vMarks.end();
+ ppMark++)
+ {
+ IMark* pMark = ppMark->get();
+ ::rtl::OString sName = ::rtl::OUStringToOString(pMark->GetName(), RTL_TEXTENCODING_UTF8);
+ const SwPosition* const pStPos = &pMark->GetMarkStart();
+ const SwPosition* const pEndPos = &pMark->GetMarkEnd();
+ OSL_TRACE("%s %s %d,%d %d,%d",
+ typeid(*pMark).name(),
+ sName.getStr(),
+ pStPos->nNode.GetIndex(),
+ pStPos->nContent.GetIndex(),
+ pEndPos->nNode.GetIndex(),
+ pEndPos->nContent.GetIndex());
+ }
+ };
+#endif
+}
+
+IDocumentMarkAccess::MarkType IDocumentMarkAccess::GetType(const IMark& rBkmk)
+{
+ const std::type_info* const pMarkTypeInfo = &typeid(rBkmk);
+ // not using dynamic_cast<> here for performance
+ if(*pMarkTypeInfo == typeid(UnoMark))
+ return UNO_BOOKMARK;
+ else if(*pMarkTypeInfo == typeid(DdeBookmark))
+ return DDE_BOOKMARK;
+ else if(*pMarkTypeInfo == typeid(Bookmark))
+ return BOOKMARK;
+ else if(*pMarkTypeInfo == typeid(CrossRefHeadingBookmark))
+ return CROSSREF_HEADING_BOOKMARK;
+ else if(*pMarkTypeInfo == typeid(CrossRefNumItemBookmark))
+ return CROSSREF_NUMITEM_BOOKMARK;
+ else if(*pMarkTypeInfo == typeid(TextFieldmark))
+ return TEXT_FIELDMARK;
+ else if(*pMarkTypeInfo == typeid(CheckboxFieldmark))
+ return CHECKBOX_FIELDMARK;
+ else if(*pMarkTypeInfo == typeid(NavigatorReminder))
+ return NAVIGATOR_REMINDER;
+ else
+ {
+ OSL_ENSURE(false,
+ "IDocumentMarkAccess::GetType(..)"
+ " - unknown MarkType. This needs to be fixed!");
+ return UNO_BOOKMARK;
+ }
+}
+
+namespace sw { namespace mark
+{
+ MarkManager::MarkManager(SwDoc& rDoc)
+ : m_pDoc(&rDoc)
+ { }
+#if OSL_DEBUG_LEVEL > 1
+ void MarkManager::dumpFieldmarks( ) const
+ {
+ const_iterator_t pIt = m_vFieldmarks.begin();
+ for (; pIt != m_vFieldmarks.end( ); pIt++)
+ {
+ rtl::OUString str = (*pIt)->ToString();
+ OSL_TRACE("%s\n",
+ ::rtl::OUStringToOString(str, RTL_TEXTENCODING_UTF8).getStr());
+ }
+ }
+#endif
+ ::sw::mark::IMark* MarkManager::makeMark(const SwPaM& rPaM,
+ const ::rtl::OUString& rName,
+ const IDocumentMarkAccess::MarkType eType)
+ {
+#if 0
+ {
+ ::rtl::OString sName = ::rtl::OUStringToOString(rName, RTL_TEXTENCODING_UTF8);
+ const SwPosition* const pPos1 = rPaM.GetPoint();
+ const SwPosition* pPos2 = pPos1;
+ if(rPaM.HasMark())
+ pPos2 = rPaM.GetMark();
+ OSL_TRACE("%s %d,%d %d,%d",
+ sName.getStr(),
+ pPos1->nNode.GetIndex(),
+ pPos1->nContent.GetIndex(),
+ pPos2->nNode.GetIndex(),
+ pPos2->nContent.GetIndex());
+ }
+#endif
+ // see for example _SaveCntntIdx, Shells
+ OSL_PRECOND(m_vMarks.size() < USHRT_MAX,
+ "MarkManager::makeMark(..)"
+ " - more than USHRT_MAX marks are not supported correctly");
+ // There should only be one CrossRefBookmark per Textnode per Type
+ OSL_PRECOND(
+ (eType != CROSSREF_NUMITEM_BOOKMARK && eType != CROSSREF_HEADING_BOOKMARK)
+ || (lcl_FindMarkAtPos(m_vBookmarks, *rPaM.GetPoint(), eType) == m_vBookmarks.end()),
+ "MarkManager::makeMark(..)"
+ " - creating duplicate CrossRefBookmark");
+
+ // create mark
+ pMark_t pMark;
+ switch(eType)
+ {
+ case IDocumentMarkAccess::TEXT_FIELDMARK:
+ pMark = shared_ptr<IMark>(new TextFieldmark(rPaM));
+ break;
+ case IDocumentMarkAccess::CHECKBOX_FIELDMARK:
+ pMark = shared_ptr<IMark>(new CheckboxFieldmark(rPaM));
+ break;
+ case IDocumentMarkAccess::NAVIGATOR_REMINDER:
+ pMark = shared_ptr<IMark>(new NavigatorReminder(rPaM));
+ break;
+ case IDocumentMarkAccess::BOOKMARK:
+ pMark = shared_ptr<IMark>(new Bookmark(rPaM, KeyCode(), rName, ::rtl::OUString()));
+ break;
+ case IDocumentMarkAccess::DDE_BOOKMARK:
+ pMark = shared_ptr<IMark>(new DdeBookmark(rPaM));
+ break;
+ case IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK:
+ pMark = shared_ptr<IMark>(new CrossRefHeadingBookmark(rPaM, KeyCode(), rName, ::rtl::OUString()));
+ break;
+ case IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK:
+ pMark = shared_ptr<IMark>(new CrossRefNumItemBookmark(rPaM, KeyCode(), rName, ::rtl::OUString()));
+ break;
+ case IDocumentMarkAccess::UNO_BOOKMARK:
+ pMark = shared_ptr<IMark>(new UnoMark(rPaM));
+ break;
+ }
+ OSL_ENSURE(pMark.get(),
+ "MarkManager::makeMark(..)"
+ " - Mark was not created.");
+ MarkBase* pMarkBase = dynamic_cast<MarkBase*>(pMark.get());
+
+ if(pMark->GetMarkPos() != pMark->GetMarkStart())
+ pMarkBase->Swap();
+
+ // for performance reasons, we trust UnoMarks to have a (generated) unique name
+ if(eType != IDocumentMarkAccess::UNO_BOOKMARK)
+ pMarkBase->SetName(getUniqueMarkName(pMarkBase->GetName()));
+
+ // register mark
+ lcl_InsertMarkSorted(m_vMarks, pMark);
+ switch(eType)
+ {
+ case IDocumentMarkAccess::BOOKMARK:
+ case IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK:
+ case IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK:
+ // if(dynamic_cast<IBookmark*>)
+ lcl_InsertMarkSorted(m_vBookmarks, pMark);
+ break;
+ case IDocumentMarkAccess::TEXT_FIELDMARK:
+ case IDocumentMarkAccess::CHECKBOX_FIELDMARK:
+ // if(dynamic_cast<IFieldmark*>
+ lcl_InsertMarkSorted(m_vFieldmarks, pMark);
+ break;
+ case IDocumentMarkAccess::NAVIGATOR_REMINDER:
+ case IDocumentMarkAccess::DDE_BOOKMARK:
+ case IDocumentMarkAccess::UNO_BOOKMARK:
+ // no special array for these
+ break;
+ }
+ pMarkBase->InitDoc(m_pDoc);
+#if 0
+ OSL_TRACE("--- makeType ---");
+ OSL_TRACE("Marks");
+ lcl_DebugMarks(m_vMarks);
+ OSL_TRACE("Bookmarks");
+ lcl_DebugMarks(m_vBookmarks);
+ OSL_TRACE("Fieldmarks");
+ lcl_DebugMarks(m_vFieldmarks);
+#endif
+ return pMark.get();
+ }
+
+ ::sw::mark::IFieldmark* MarkManager::makeFieldBookmark( const SwPaM& rPaM,
+ const rtl::OUString& rName,
+ const rtl::OUString& rType )
+ {
+ sw::mark::IMark* pMark = makeMark( rPaM, rName,
+ IDocumentMarkAccess::TEXT_FIELDMARK );
+ sw::mark::IFieldmark* pFieldMark = dynamic_cast<sw::mark::IFieldmark*>( pMark );
+ pFieldMark->SetFieldname( rType );
+
+ return pFieldMark;
+ }
+
+ ::sw::mark::IFieldmark* MarkManager::makeNoTextFieldBookmark( const SwPaM& rPaM,
+ const rtl::OUString& rName,
+ const rtl::OUString& rType)
+ {
+ sw::mark::IMark* pMark = makeMark( rPaM, rName,
+ IDocumentMarkAccess::CHECKBOX_FIELDMARK );
+ sw::mark::IFieldmark* pFieldMark = dynamic_cast<sw::mark::IFieldmark*>( pMark );
+ pFieldMark->SetFieldname( rType );
+
+ return pFieldMark;
+ }
+
+ ::sw::mark::IMark* MarkManager::getMarkForTxtNode(const SwTxtNode& rTxtNode,
+ const IDocumentMarkAccess::MarkType eType)
+ {
+ SwPosition aPos(rTxtNode);
+ aPos.nContent.Assign(&(const_cast<SwTxtNode&>(rTxtNode)), 0);
+ const iterator_t ppExistingMark = lcl_FindMarkAtPos(m_vBookmarks, aPos, eType);
+ if(ppExistingMark != m_vBookmarks.end())
+ return ppExistingMark->get();
+ const SwPaM aPaM(aPos);
+ return makeMark(aPaM, ::rtl::OUString(), eType);
+ }
+
+ void MarkManager::repositionMark( ::sw::mark::IMark* const io_pMark,
+ const SwPaM& rPaM)
+ {
+ OSL_PRECOND(io_pMark->GetMarkPos().GetDoc() == m_pDoc,
+ "<MarkManager::repositionMark(..)>"
+ " - Mark is not in my doc.");
+ MarkBase* const pMarkBase = dynamic_cast< MarkBase* >(io_pMark);
+ pMarkBase->SetMarkPos(*(rPaM.GetPoint()));
+ if(rPaM.HasMark())
+ pMarkBase->SetOtherMarkPos(*(rPaM.GetMark()));
+ else
+ pMarkBase->ClearOtherMarkPos();
+
+ if(pMarkBase->GetMarkPos() != pMarkBase->GetMarkStart())
+ pMarkBase->Swap();
+
+ sortMarks();
+ }
+
+ bool MarkManager::renameMark(::sw::mark::IMark* io_pMark, const ::rtl::OUString& rNewName)
+ {
+ OSL_PRECOND(io_pMark->GetMarkPos().GetDoc() == m_pDoc,
+ "<MarkManager::repositionMark(..)>"
+ " - Mark is not in my doc.");
+ if(io_pMark->GetName() == rNewName)
+ return true;
+ if(findMark(rNewName) != getMarksEnd())
+ return false;
+ dynamic_cast< ::sw::mark::MarkBase* >(io_pMark)->SetName(rNewName);
+ return true;
+ }
+
+ void MarkManager::correctMarksAbsolute(const SwNodeIndex& rOldNode, const SwPosition& rNewPos, const xub_StrLen nOffset)
+ {
+ const SwNode* const pOldNode = &rOldNode.GetNode();
+ SwPosition aNewPos(rNewPos);
+ aNewPos.nContent += nOffset;
+ bool isSortingNeeded = false;
+ for(iterator_t ppMark = m_vMarks.begin();
+ ppMark != m_vMarks.end();
+ ppMark++)
+ {
+ // is on position ??
+ bool bChangedPos = false, bChangedOPos = false;
+ ::sw::mark::MarkBase* pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
+ if(&pMark->GetMarkPos().nNode.GetNode() == pOldNode)
+ {
+ pMark->SetMarkPos(aNewPos);
+ bChangedPos = true;
+ }
+ if (pMark->IsExpanded() &&
+ &pMark->GetOtherMarkPos().nNode.GetNode() == pOldNode)
+ {
+ pMark->SetMarkPos(aNewPos);
+ bChangedOPos= true;
+ }
+ // illegal selection? collapse the mark and restore sorting later
+ isSortingNeeded |= lcl_FixCorrectedMark(bChangedPos, bChangedOPos, pMark);
+ }
+ // restore sorting if needed
+ if(isSortingNeeded)
+ sortMarks();
+#if 0
+ OSL_TRACE("correctMarksAbsolute");
+ lcl_DebugMarks(m_vMarks);
+#endif
+ }
+
+ void MarkManager::correctMarksRelative(const SwNodeIndex& rOldNode, const SwPosition& rNewPos, const xub_StrLen nOffset)
+ {
+ const SwNode* const pOldNode = &rOldNode.GetNode();
+ SwPosition aNewPos(rNewPos);
+ aNewPos.nContent += nOffset;
+ bool isSortingNeeded = false;
+ for(iterator_t ppMark = m_vMarks.begin();
+ ppMark != m_vMarks.end();
+ ppMark++)
+ {
+ // is on position ??
+ bool bChangedPos = false, bChangedOPos = false;
+ ::sw::mark::MarkBase* const pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
+ if(&pMark->GetMarkPos().nNode.GetNode() == pOldNode)
+ {
+ SwPosition aNewPosRel(aNewPos);
+ aNewPosRel.nContent += pMark->GetMarkPos().nContent.GetIndex();
+ pMark->SetMarkPos(aNewPosRel);
+ bChangedPos = true;
+ }
+ if(pMark->IsExpanded() &&
+ &pMark->GetOtherMarkPos().nNode.GetNode() == pOldNode)
+ {
+ SwPosition aNewPosRel(aNewPos);
+ aNewPosRel.nContent += pMark->GetOtherMarkPos().nContent.GetIndex();
+ pMark->SetOtherMarkPos(aNewPosRel);
+ bChangedOPos = true;
+ }
+ // illegal selection? collapse the mark and restore sorting later
+ isSortingNeeded |= lcl_FixCorrectedMark(bChangedPos, bChangedOPos, pMark);
+ }
+ // restore sorting if needed
+ if(isSortingNeeded)
+ sortMarks();
+#if 0
+ OSL_TRACE("correctMarksRelative");
+ lcl_DebugMarks(m_vMarks);
+#endif
+ }
+
+ void MarkManager::deleteMarks(
+ const SwNodeIndex& rStt,
+ const SwNodeIndex& rEnd,
+ ::std::vector<SaveBookmark>* pSaveBkmk,
+ const SwIndex* pSttIdx,
+ const SwIndex* pEndIdx )
+ {
+ vector<const_iterator_t> vMarksToDelete;
+ bool isSortingNeeded = false;
+ // copy all bookmarks in the move area to a vector storing all position data as offset
+ // reassignment is performed after the move
+ for(iterator_t ppMark = m_vMarks.begin();
+ ppMark != m_vMarks.end();
+ ppMark++)
+ {
+ // navigator marks should not be moved
+ // TODO: Check if this might make them invalid
+ if(IDocumentMarkAccess::GetType(**ppMark) == NAVIGATOR_REMINDER)
+ continue;
+
+ ::sw::mark::MarkBase* pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
+ // on position ??
+ bool isPosInRange = (lcl_GreaterThan(pMark->GetMarkPos(), rStt, pSttIdx) &&
+ lcl_Lower(pMark->GetMarkPos(), rEnd, pEndIdx));
+ bool isOtherPosInRange = (pMark->IsExpanded() &&
+ lcl_GreaterThan(pMark->GetOtherMarkPos(), rStt, pSttIdx) &&
+ lcl_Lower(pMark->GetOtherMarkPos(), rEnd, pEndIdx));
+ // special case: completely in range, touching the end?
+ if(pEndIdx &&
+ ((isOtherPosInRange
+ && pMark->GetMarkPos().nNode == rEnd
+ && pMark->GetMarkPos().nContent == *pEndIdx)
+ || (isPosInRange
+ && pMark->IsExpanded()
+ && pMark->GetOtherMarkPos().nNode == rEnd
+ && pMark->GetOtherMarkPos().nContent == *pEndIdx)))
+ {
+ isPosInRange = true, isOtherPosInRange = true;
+ }
+
+ if(isPosInRange && (isOtherPosInRange || !pMark->IsExpanded()))
+ {
+ // completely in range
+
+ // --> OD 2009-08-07 #i92125#
+ bool bKeepCrossRefBkmk( false );
+ {
+ if ( rStt == rEnd &&
+ ( IDocumentMarkAccess::GetType(*pMark) ==
+ IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK ||
+ IDocumentMarkAccess::GetType(*pMark) ==
+ IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK ) )
+ {
+ bKeepCrossRefBkmk = true;
+ }
+ }
+ if ( !bKeepCrossRefBkmk )
+ {
+ if(pSaveBkmk)
+ pSaveBkmk->push_back(SaveBookmark(true, true, *pMark, rStt, pSttIdx));
+ vMarksToDelete.push_back(ppMark);
+ }
+ // <--
+ }
+ else if(isPosInRange ^ isOtherPosInRange)
+ {
+ // the bookmark is partitially in the range
+ // move position of that is in the range out of it
+ auto_ptr<SwPosition> pNewPos;
+ if(pEndIdx)
+ pNewPos = auto_ptr<SwPosition>(new SwPosition(
+ rEnd,
+ *pEndIdx));
+ else
+ pNewPos = lcl_FindExpelPosition(
+ rStt,
+ rEnd,
+ isPosInRange ? pMark->GetOtherMarkPos() : pMark->GetMarkPos());
+
+ // --> OD 2009-08-06 #i92125#
+ // no move of position for cross-reference bookmarks,
+ // if move occurs inside a certain node
+ if ( ( IDocumentMarkAccess::GetType(*pMark) !=
+ IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK &&
+ IDocumentMarkAccess::GetType(*pMark) !=
+ IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK ) ||
+ pMark->GetMarkPos().nNode != pNewPos->nNode )
+ {
+ if(isPosInRange)
+ pMark->SetMarkPos(*pNewPos);
+ else
+ pMark->SetOtherMarkPos(*pNewPos);
+
+ // illegal selection? collapse the mark and restore sorting later
+ isSortingNeeded |= lcl_FixCorrectedMark(isPosInRange, isOtherPosInRange, pMark);
+ }
+ // <--
+ }
+ }
+
+ // we just remembered the iterators to delete, so we do not need to search
+ // for the shared_ptr<> (the entry in m_vMarks) again
+ // reverse iteration, since erasing an entry invalidates iterators
+ // behind it (the iterators in vMarksToDelete are sorted)
+ for(vector<const_iterator_t>::reverse_iterator pppMark = vMarksToDelete.rbegin();
+ pppMark != vMarksToDelete.rend();
+ pppMark++)
+ {
+ deleteMark(*pppMark);
+ }
+ if(isSortingNeeded)
+ sortMarks();
+#if 0
+ OSL_TRACE("deleteMarks");
+ lcl_DebugMarks(m_vMarks);
+#endif
+ }
+
+ void MarkManager::deleteMark(const const_iterator_t ppMark)
+ {
+ if(ppMark == m_vMarks.end()) return;
+
+ switch(IDocumentMarkAccess::GetType(**ppMark))
+ {
+ case IDocumentMarkAccess::BOOKMARK:
+ case IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK:
+ case IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK:
+ // if(dynamic_cast<IBookmark*>)
+ {
+ IDocumentMarkAccess::iterator_t ppBookmark = lcl_FindMark(m_vBookmarks, *ppMark);
+ OSL_ENSURE(ppBookmark != m_vBookmarks.end(),
+ "<MarkManager::deleteMark(..)>"
+ " - Bookmark not found.");
+ m_vBookmarks.erase(ppBookmark);
+ break;
+ }
+ case IDocumentMarkAccess::TEXT_FIELDMARK:
+ case IDocumentMarkAccess::CHECKBOX_FIELDMARK:
+ // if(dynamic_cast<IFieldmark*>
+ {
+ IDocumentMarkAccess::iterator_t ppFieldmark = lcl_FindMark(m_vFieldmarks, *ppMark);
+ OSL_ENSURE(ppFieldmark != m_vFieldmarks.end(),
+ "<MarkManager::deleteMark(..)>"
+ " - Bookmark not found.");
+ m_vFieldmarks.erase(ppFieldmark);
+ break;
+ }
+ case IDocumentMarkAccess::NAVIGATOR_REMINDER:
+ case IDocumentMarkAccess::DDE_BOOKMARK:
+ case IDocumentMarkAccess::UNO_BOOKMARK:
+ // no special array for these
+ break;
+ }
+ DdeBookmark* const pDdeBookmark = dynamic_cast<DdeBookmark*>(ppMark->get());
+ if(pDdeBookmark)
+ pDdeBookmark->DeregisterFromDoc(m_pDoc);
+ m_vMarks.erase(m_vMarks.begin() + (ppMark - m_vMarks.begin())); // clumsy const-cast
+ }
+
+ void MarkManager::deleteMark(const IMark* const pMark)
+ {
+ OSL_PRECOND(pMark->GetMarkPos().GetDoc() == m_pDoc,
+ "<MarkManager::repositionMark(..)>"
+ " - Mark is not in my doc.");
+ // finds the last Mark that is starting before pMark
+ // (pMarkLow < pMark)
+ iterator_t pMarkLow = lower_bound(
+ m_vMarks.begin(), m_vMarks.end(),
+ pMark->GetMarkStart(),
+ bind(&IMark::StartsBefore, _1, _2));
+ // finds the first Mark that pMark is starting before
+ // (pMark < pMarkHigh)
+ //iterator_t pMarkHigh = upper_bound(
+ // pMarkLow, m_vMarks.end(),
+ // pMark->GetMarkStart(),
+ // bind(&IMark::StartsBefore, _2, _1));
+ // since it should be rare that pMark isnt found at all
+ // we skip the bisect search on the upper bound
+ iterator_t pMarkHigh = m_vMarks.end();
+ iterator_t pMarkFound = find_if(
+ pMarkLow, pMarkHigh,
+ bind(equal_to<const IMark*>(), bind(&shared_ptr<IMark>::get, _1), pMark));
+ if(pMarkFound != pMarkHigh)
+ deleteMark(pMarkFound);
+ }
+
+ void MarkManager::clearAllMarks()
+ {
+ m_vFieldmarks.clear();
+ m_vBookmarks.clear();
+#ifdef DEBUG
+ for(iterator_t pBkmk = m_vMarks.begin();
+ pBkmk != m_vMarks.end();
+ ++pBkmk)
+ OSL_ENSURE(pBkmk->unique(),
+ "<MarkManager::clearAllMarks(..)>"
+ " - a Bookmark is still in use.");
+#endif
+ m_vMarks.clear();
+ }
+
+ IDocumentMarkAccess::const_iterator_t MarkManager::findMark(const ::rtl::OUString& rName) const
+ {
+ return lcl_FindMarkByName(rName, m_vMarks.begin(), m_vMarks.end());
+ }
+
+ IDocumentMarkAccess::const_iterator_t MarkManager::findBookmark(const ::rtl::OUString& rName) const
+ {
+ return lcl_FindMarkByName(rName, m_vBookmarks.begin(), m_vBookmarks.end());
+ }
+
+ IDocumentMarkAccess::const_iterator_t MarkManager::getMarksBegin() const
+ { return m_vMarks.begin(); }
+
+ IDocumentMarkAccess::const_iterator_t MarkManager::getMarksEnd() const
+ { return m_vMarks.end(); }
+
+ sal_Int32 MarkManager::getMarksCount() const
+ { return m_vMarks.size(); }
+
+ IDocumentMarkAccess::const_iterator_t MarkManager::getBookmarksBegin() const
+ { return m_vBookmarks.begin(); }
+
+ IDocumentMarkAccess::const_iterator_t MarkManager::getBookmarksEnd() const
+ { return m_vBookmarks.end(); }
+
+ sal_Int32 MarkManager::getBookmarksCount() const
+ { return m_vBookmarks.size(); }
+
+ IFieldmark* MarkManager::getFieldmarkFor(const SwPosition& rPos) const
+ {
+ const_iterator_t pFieldmark = find_if(
+ m_vFieldmarks.begin(),
+ m_vFieldmarks.end( ),
+ bind(&IMark::IsCoveringPosition, _1, rPos));
+ if(pFieldmark == m_vFieldmarks.end()) return NULL;
+ return dynamic_cast<IFieldmark*>(pFieldmark->get());
+ }
+
+ IFieldmark* MarkManager::getFieldmarkAfter(const SwPosition& rPos) const
+ { return dynamic_cast<IFieldmark*>(lcl_getMarkAfter(m_vFieldmarks, rPos)); }
+
+ IFieldmark* MarkManager::getFieldmarkBefore(const SwPosition& rPos) const
+ { return dynamic_cast<IFieldmark*>(lcl_getMarkBefore(m_vFieldmarks, rPos)); }
+
+ ::rtl::OUString MarkManager::getUniqueMarkName(const ::rtl::OUString& rName) const
+ {
+ OSL_ENSURE(rName.getLength(),
+ "<MarkManager::getUniqueMarkName(..)>"
+ " - a name should be proposed");
+ if(findMark(rName) == getMarksEnd()) return rName;
+ ::rtl::OUStringBuffer sBuf;
+ ::rtl::OUString sTmp;
+ for(sal_Int32 nCnt = 1; nCnt < SAL_MAX_INT32; nCnt++)
+ {
+ sTmp = sBuf.append(rName).append(nCnt).makeStringAndClear();
+ if(findMark(sTmp) == getMarksEnd()) break;
+ }
+ return sTmp;
+ }
+
+ void MarkManager::sortMarks()
+ {
+ sort(m_vMarks.begin(), m_vMarks.end(), &lcl_MarkOrderingByStart);
+ sort(m_vBookmarks.begin(), m_vBookmarks.end(), &lcl_MarkOrderingByStart);
+ sort(m_vFieldmarks.begin(), m_vFieldmarks.end(), &lcl_MarkOrderingByStart);
+ }
+
+}} // namespace ::sw::mark
+
+
+// old implementation
+
+//SV_IMPL_OP_PTRARR_SORT(SwBookmarks, SwBookmarkPtr)
+
+#define PCURCRSR (_pCurrCrsr)
+#define FOREACHPAM_START(pSttCrsr) \
+ {\
+ SwPaM *_pStartCrsr = pSttCrsr, *_pCurrCrsr = pSttCrsr; \
+ do {
+
+#define FOREACHPAM_END() \
+ } while( (_pCurrCrsr=(SwPaM *)_pCurrCrsr->GetNext()) != _pStartCrsr ); \
+ }
+#define PCURSH ((SwCrsrShell*)_pStartShell)
+#define FOREACHSHELL_START( pEShell ) \
+ {\
+ ViewShell *_pStartShell = pEShell; \
+ do { \
+ if( _pStartShell->IsA( TYPE( SwCrsrShell )) ) \
+ {
+
+#define FOREACHSHELL_END( pEShell ) \
+ } \
+ } while((_pStartShell=(ViewShell*)_pStartShell->GetNext())!= pEShell ); \
+ }
+
+namespace
+{
+ // Aufbau vom Array: 2 longs,
+ // 1. Long enthaelt Type und Position im DocArray,
+ // 2. die ContentPosition
+ //
+ // CntntType --
+ // 0x8000 = Bookmark Pos1
+ // 0x8001 = Bookmark Pos2
+ // 0x2000 = Absatzgebundener Rahmen
+ // 0x2001 = Auto-Absatzgebundener Rahmen, der umgehaengt werden soll
+ // 0x1000 = Redline Mark
+ // 0x1001 = Redline Point
+ // 0x0800 = Crsr aus der CrsrShell Mark
+ // 0x0801 = Crsr aus der CrsrShell Point
+ // 0x0400 = UnoCrsr Mark
+ // 0x0401 = UnoCrsr Point
+ //
+
+ class _SwSaveTypeCountContent
+ {
+ union {
+ struct { sal_uInt16 nType, nCount; } TC;
+ sal_uLong nTypeCount;
+ } TYPECOUNT;
+ xub_StrLen nContent;
+
+ public:
+ _SwSaveTypeCountContent() { TYPECOUNT.nTypeCount = 0; nContent = 0; }
+ _SwSaveTypeCountContent( sal_uInt16 nType )
+ {
+ SetTypeAndCount( nType, 0 );
+ nContent = 0;
+ }
+ _SwSaveTypeCountContent( const SvULongs& rArr, sal_uInt16& rPos )
+ {
+ TYPECOUNT.nTypeCount = rArr[ rPos++ ];
+ nContent = static_cast<xub_StrLen>(rArr[ rPos++ ]);
+ }
+ void Add( SvULongs& rArr )
+ {
+ rArr.Insert( TYPECOUNT.nTypeCount, rArr.Count() );
+ rArr.Insert( nContent, rArr.Count() );
+ }
+
+ void SetType( sal_uInt16 n ) { TYPECOUNT.TC.nType = n; }
+ sal_uInt16 GetType() const { return TYPECOUNT.TC.nType; }
+ void IncType() { ++TYPECOUNT.TC.nType; }
+ void DecType() { --TYPECOUNT.TC.nType; }
+
+ void SetCount( sal_uInt16 n ) { TYPECOUNT.TC.nCount = n; }
+ sal_uInt16 GetCount() const { return TYPECOUNT.TC.nCount; }
+ sal_uInt16 IncCount() { return ++TYPECOUNT.TC.nCount; }
+ sal_uInt16 DecCount() { return --TYPECOUNT.TC.nCount; }
+
+ void SetTypeAndCount( sal_uInt16 nT, sal_uInt16 nC )
+ { TYPECOUNT.TC.nCount = nC; TYPECOUNT.TC.nType = nT; }
+
+ void SetContent( xub_StrLen n ) { nContent = n; }
+ xub_StrLen GetContent() const { return nContent; }
+ };
+
+ // #i59534: If a paragraph will be splitted we have to restore some redline positions
+ // This help function checks a position compared with a node and an content index
+
+ static const int BEFORE_NODE = 0; // Position before the given node index
+ static const int BEFORE_SAME_NODE = 1; // Same node index but content index before given content index
+ static const int SAME_POSITION = 2; // Same node index and samecontent index
+ static const int BEHIND_SAME_NODE = 3; // Same node index but content index behind given content index
+ static const int BEHIND_NODE = 4; // Position behind the given node index
+
+ static int lcl_RelativePosition( const SwPosition& rPos, sal_uLong nNode, xub_StrLen nCntnt )
+ {
+ sal_uLong nIndex = rPos.nNode.GetIndex();
+ int nReturn = BEFORE_NODE;
+ if( nIndex == nNode )
+ {
+ xub_StrLen nCntIdx = rPos.nContent.GetIndex();
+ if( nCntIdx < nCntnt )
+ nReturn = BEFORE_SAME_NODE;
+ else if( nCntIdx == nCntnt )
+ nReturn = SAME_POSITION;
+ else
+ nReturn = BEHIND_SAME_NODE;
+ }
+ else if( nIndex > nNode )
+ nReturn = BEHIND_NODE;
+ return nReturn;
+ }
+
+
+ static inline int lcl_Greater( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
+ {
+ return rPos.nNode > rNdIdx || ( pIdx && rPos.nNode == rNdIdx && rPos.nContent > pIdx->GetIndex() );
+ }
+
+ static void lcl_ChkPaM( SvULongs& rSaveArr, sal_uLong nNode, xub_StrLen nCntnt,
+ const SwPaM& rPam, _SwSaveTypeCountContent& rSave,
+ sal_Bool bChkSelDirection )
+ {
+ // SelektionsRichtung beachten
+ bool bBound1IsStart = !bChkSelDirection ? sal_True :
+ ( *rPam.GetPoint() < *rPam.GetMark()
+ ? rPam.GetPoint() == &rPam.GetBound()
+ : rPam.GetMark() == &rPam.GetBound());
+
+ const SwPosition* pPos = &rPam.GetBound( sal_True );
+ if( pPos->nNode.GetIndex() == nNode &&
+ ( bBound1IsStart ? pPos->nContent.GetIndex() < nCntnt
+ : pPos->nContent.GetIndex() <= nCntnt ))
+ {
+ rSave.SetContent( pPos->nContent.GetIndex() );
+ rSave.Add( rSaveArr );
+ }
+
+ pPos = &rPam.GetBound( sal_False );
+ if( pPos->nNode.GetIndex() == nNode &&
+ ( (bBound1IsStart && bChkSelDirection)
+ ? pPos->nContent.GetIndex() <= nCntnt
+ : pPos->nContent.GetIndex() < nCntnt ))
+ {
+ rSave.SetContent( pPos->nContent.GetIndex() );
+ rSave.IncType();
+ rSave.Add( rSaveArr );
+ rSave.DecType();
+ }
+ }
+
+}
+
+
+// IDocumentMarkAccess for SwDoc
+
+IDocumentMarkAccess* SwDoc::getIDocumentMarkAccess()
+ { return static_cast< IDocumentMarkAccess* >(pMarkManager.get()); }
+
+const IDocumentMarkAccess* SwDoc::getIDocumentMarkAccess() const
+ { return static_cast< IDocumentMarkAccess* >(pMarkManager.get()); }
+
+// SaveBookmark
+
+SaveBookmark::SaveBookmark(
+ bool bSavePos,
+ bool bSaveOtherPos,
+ const IMark& rBkmk,
+ const SwNodeIndex & rMvPos,
+ const SwIndex* pIdx)
+ : m_aName(rBkmk.GetName())
+ , m_aShortName()
+ , m_aCode()
+ , m_bSavePos(bSavePos)
+ , m_bSaveOtherPos(bSaveOtherPos)
+ , m_eOrigBkmType(IDocumentMarkAccess::GetType(rBkmk))
+{
+ const IBookmark* const pBookmark = dynamic_cast< const IBookmark* >(&rBkmk);
+ if(pBookmark)
+ {
+ m_aShortName = pBookmark->GetShortName();
+ m_aCode = pBookmark->GetKeyCode();
+
+ ::sfx2::Metadatable const*const pMetadatable(
+ dynamic_cast< ::sfx2::Metadatable const* >(pBookmark));
+ if (pMetadatable)
+ {
+ m_pMetadataUndo = pMetadatable->CreateUndo();
+ }
+ }
+ m_nNode1 = rBkmk.GetMarkPos().nNode.GetIndex();
+ m_nCntnt1 = rBkmk.GetMarkPos().nContent.GetIndex();
+
+ if(m_bSavePos)
+ {
+ m_nNode1 -= rMvPos.GetIndex();
+ if(pIdx && !m_nNode1)
+ m_nCntnt1 -= pIdx->GetIndex();
+ }
+
+ if(rBkmk.IsExpanded())
+ {
+ m_nNode2 = rBkmk.GetOtherMarkPos().nNode.GetIndex();
+ m_nCntnt2 = rBkmk.GetOtherMarkPos().nContent.GetIndex();
+
+ if(m_bSaveOtherPos)
+ {
+ m_nNode2 -= rMvPos.GetIndex();
+ if(pIdx && !m_nNode2)
+ m_nCntnt2 -= pIdx->GetIndex();
+ }
+ }
+ else
+ m_nNode2 = ULONG_MAX, m_nCntnt2 = STRING_NOTFOUND;
+}
+
+void SaveBookmark::SetInDoc(
+ SwDoc* pDoc,
+ const SwNodeIndex& rNewPos,
+ const SwIndex* pIdx)
+{
+ SwPaM aPam(rNewPos.GetNode());
+ if(pIdx)
+ aPam.GetPoint()->nContent = *pIdx;
+
+ if(ULONG_MAX != m_nNode2)
+ {
+ aPam.SetMark();
+
+ if(m_bSaveOtherPos)
+ {
+ aPam.GetMark()->nNode += m_nNode2;
+ if(pIdx && !m_nNode2)
+ aPam.GetMark()->nContent += m_nCntnt2;
+ else
+ aPam.GetMark()->nContent.Assign(aPam.GetCntntNode(sal_False), m_nCntnt2);
+ }
+ else
+ {
+ aPam.GetMark()->nNode = m_nNode2;
+ aPam.GetMark()->nContent.Assign(aPam.GetCntntNode(sal_False), m_nCntnt2);
+ }
+ }
+
+ if(m_bSavePos)
+ {
+ aPam.GetPoint()->nNode += m_nNode1;
+
+ if(pIdx && !m_nNode1)
+ aPam.GetPoint()->nContent += m_nCntnt1;
+ else
+ aPam.GetPoint()->nContent.Assign(aPam.GetCntntNode(), m_nCntnt1);
+ }
+ else
+ {
+ aPam.GetPoint()->nNode = m_nNode1;
+ aPam.GetPoint()->nContent.Assign(aPam.GetCntntNode(), m_nCntnt1);
+ }
+
+ if(!aPam.HasMark()
+ || CheckNodesRange(aPam.GetPoint()->nNode, aPam.GetMark()->nNode, sal_True))
+ {
+ ::sw::mark::IBookmark* const pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(pDoc->getIDocumentMarkAccess()->makeMark(aPam, m_aName, m_eOrigBkmType));
+ if(pBookmark)
+ {
+ pBookmark->SetKeyCode(m_aCode);
+ pBookmark->SetShortName(m_aShortName);
+ if (m_pMetadataUndo)
+ {
+ ::sfx2::Metadatable * const pMeta(
+ dynamic_cast< ::sfx2::Metadatable* >(pBookmark));
+ OSL_ENSURE(pMeta, "metadata undo, but not metadatable?");
+ if (pMeta)
+ {
+ pMeta->RestoreMetadata(m_pMetadataUndo);
+ }
+ }
+ }
+ }
+}
+
+// _DelBookmarks, _{Save,Restore}CntntIdx
+
+void _DelBookmarks(
+ const SwNodeIndex& rStt,
+ const SwNodeIndex& rEnd,
+ ::std::vector<SaveBookmark> * pSaveBkmk,
+ const SwIndex* pSttIdx,
+ const SwIndex* pEndIdx)
+{
+ // illegal range ??
+ if(rStt.GetIndex() > rEnd.GetIndex()
+ || (rStt == rEnd && (!pSttIdx || pSttIdx->GetIndex() >= pEndIdx->GetIndex())))
+ return;
+ SwDoc* const pDoc = rStt.GetNode().GetDoc();
+
+ pDoc->getIDocumentMarkAccess()->deleteMarks(rStt, rEnd, pSaveBkmk, pSttIdx, pEndIdx);
+
+ // kopiere alle Redlines, die im Move Bereich stehen in ein
+ // Array, das alle Angaben auf die Position als Offset speichert.
+ // Die neue Zuordung erfolgt nach dem Moven.
+ SwRedlineTbl& rTbl = (SwRedlineTbl&)pDoc->GetRedlineTbl();
+ for(sal_uInt16 nCnt = 0; nCnt < rTbl.Count(); ++nCnt )
+ {
+ // liegt auf der Position ??
+ SwRedline* pRedl = rTbl[ nCnt ];
+
+ SwPosition *pRStt = &pRedl->GetBound(sal_True),
+ *pREnd = &pRedl->GetBound(sal_False);
+ if( *pRStt > *pREnd )
+ {
+ SwPosition *pTmp = pRStt; pRStt = pREnd, pREnd = pTmp;
+ }
+
+ if( lcl_Greater( *pRStt, rStt, pSttIdx ) && lcl_Lower( *pRStt, rEnd, pEndIdx ))
+ {
+ pRStt->nNode = rEnd;
+ if( pEndIdx )
+ pRStt->nContent = *pEndIdx;
+ else
+ {
+ sal_Bool bStt = sal_True;
+ SwCntntNode* pCNd = pRStt->nNode.GetNode().GetCntntNode();
+ if( !pCNd && 0 == ( pCNd = pDoc->GetNodes().GoNext( &pRStt->nNode )) )
+ {
+ bStt = sal_False;
+ pRStt->nNode = rStt;
+ if( 0 == ( pCNd = pDoc->GetNodes().GoPrevious( &pRStt->nNode )) )
+ {
+ pRStt->nNode = pREnd->nNode;
+ pCNd = pRStt->nNode.GetNode().GetCntntNode();
+ }
+ }
+ xub_StrLen nTmp = bStt ? 0 : pCNd->Len();
+ pRStt->nContent.Assign( pCNd, nTmp );
+ }
+ }
+ if( lcl_Greater( *pREnd, rStt, pSttIdx ) && lcl_Lower( *pREnd, rEnd, pEndIdx ))
+ {
+ pREnd->nNode = rStt;
+ if( pSttIdx )
+ pREnd->nContent = *pSttIdx;
+ else
+ {
+ sal_Bool bStt = sal_False;
+ SwCntntNode* pCNd = pREnd->nNode.GetNode().GetCntntNode();
+ if( !pCNd && 0 == ( pCNd = pDoc->GetNodes().GoPrevious( &pREnd->nNode )) )
+ {
+ bStt = sal_True;
+ pREnd->nNode = rEnd;
+ if( 0 == ( pCNd = pDoc->GetNodes().GoNext( &pREnd->nNode )) )
+ {
+ pREnd->nNode = pRStt->nNode;
+ pCNd = pREnd->nNode.GetNode().GetCntntNode();
+ }
+ }
+ xub_StrLen nTmp = bStt ? 0 : pCNd->Len();
+ pREnd->nContent.Assign( pCNd, nTmp );
+ }
+ }
+ }
+}
+
+void _SaveCntntIdx(SwDoc* pDoc,
+ sal_uLong nNode,
+ xub_StrLen nCntnt,
+ SvULongs& rSaveArr,
+ sal_uInt8 nSaveFly)
+{
+ // 1. Bookmarks
+ _SwSaveTypeCountContent aSave;
+ aSave.SetTypeAndCount( 0x8000, 0 );
+
+ IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ const sal_Int32 nBkmks = pMarkAccess->getMarksCount();
+ for(; aSave.GetCount() < nBkmks; aSave.IncCount())
+ {
+ bool bEqual = false;
+ bool bLower = false;
+ const ::sw::mark::IMark* pBkmk = (pMarkAccess->getMarksBegin() + aSave.GetCount())->get();
+ if(pBkmk->GetMarkPos().nNode.GetIndex() == nNode
+ && pBkmk->GetMarkPos().nContent.GetIndex() <= nCntnt)
+ {
+ if(pBkmk->GetMarkPos().nContent.GetIndex() < nCntnt)
+ {
+ bLower = true; // a hint for the other position...
+ aSave.SetContent(pBkmk->GetMarkPos().nContent.GetIndex());
+ aSave.Add(rSaveArr);
+ }
+ else // if a bookmark position is equal nCntnt, the other position
+ bEqual = true; // has to decide if it is added to the array
+ }
+
+ if(pBkmk->IsExpanded()
+ && pBkmk->GetOtherMarkPos().nNode.GetIndex() == nNode
+ && pBkmk->GetOtherMarkPos().nContent.GetIndex() <= nCntnt)
+ {
+ if(bLower || pBkmk->GetOtherMarkPos().nContent.GetIndex() < nCntnt)
+ {
+ if(bEqual)
+ { // the other position is before, the (main) position is equal
+ aSave.SetContent(pBkmk->GetMarkPos().nContent.GetIndex());
+ aSave.Add(rSaveArr);
+ }
+ aSave.SetContent(pBkmk->GetOtherMarkPos().nContent.GetIndex());
+ aSave.IncType();
+ aSave.Add(rSaveArr);
+ aSave.DecType();
+ }
+ }
+ }
+
+ // 2. Redlines
+ aSave.SetTypeAndCount( 0x1000, 0 );
+ const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
+ for( ; aSave.GetCount() < rRedlTbl.Count(); aSave.IncCount() )
+ {
+ const SwRedline* pRdl = rRedlTbl[ aSave.GetCount() ];
+ int nPointPos = lcl_RelativePosition( *pRdl->GetPoint(), nNode, nCntnt );
+ int nMarkPos = pRdl->HasMark() ? lcl_RelativePosition( *pRdl->GetMark(), nNode, nCntnt ) :
+ nPointPos;
+ // #i59534: We have to store the positions inside the same node before the insert position
+ // and the one at the insert position if the corresponding Point/Mark position is before
+ // the insert position.
+ if( nPointPos == BEFORE_SAME_NODE ||
+ ( nPointPos == SAME_POSITION && nMarkPos < SAME_POSITION ) )
+ {
+ aSave.SetContent( pRdl->GetPoint()->nContent.GetIndex() );
+ aSave.IncType();
+ aSave.Add( rSaveArr );
+ aSave.DecType();
+ }
+ if( pRdl->HasMark() && ( nMarkPos == BEFORE_SAME_NODE ||
+ ( nMarkPos == SAME_POSITION && nPointPos < SAME_POSITION ) ) )
+ {
+ aSave.SetContent( pRdl->GetMark()->nContent.GetIndex() );
+ aSave.Add( rSaveArr );
+ }
+ }
+
+ // 4. Absatzgebundene Objekte
+ {
+ SwCntntNode *pNode = pDoc->GetNodes()[nNode]->GetCntntNode();
+ if( pNode )
+ {
+
+ SwFrm* pFrm = pNode->GetFrm();
+#if OSL_DEBUG_LEVEL > 1
+ static sal_Bool bViaDoc = sal_False;
+ if( bViaDoc )
+ pFrm = NULL;
+#endif
+ if( pFrm ) // gibt es ein Layout? Dann ist etwas billiger...
+ {
+ if( pFrm->GetDrawObjs() )
+ {
+ const SwSortedObjs& rDObj = *pFrm->GetDrawObjs();
+ for( sal_uInt32 n = rDObj.Count(); n; )
+ {
+ SwAnchoredObject* pObj = rDObj[ --n ];
+ const SwFrmFmt& rFmt = pObj->GetFrmFmt();
+ const SwFmtAnchor& rAnchor = rFmt.GetAnchor();
+ SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
+ if ( pAPos &&
+ ( ( nSaveFly &&
+ FLY_AT_PARA == rAnchor.GetAnchorId() ) ||
+ ( FLY_AT_CHAR == rAnchor.GetAnchorId() ) ) )
+ {
+ aSave.SetType( 0x2000 );
+ aSave.SetContent( pAPos->nContent.GetIndex() );
+
+ OSL_ENSURE( nNode == pAPos->nNode.GetIndex(),
+ "_SaveCntntIdx: Wrong Node-Index" );
+ if ( FLY_AT_CHAR == rAnchor.GetAnchorId() )
+ {
+ if( nCntnt <= aSave.GetContent() )
+ {
+ if( SAVEFLY_SPLIT == nSaveFly )
+ aSave.IncType(); // = 0x2001;
+ else
+ continue;
+ }
+ }
+ aSave.SetCount( pDoc->GetSpzFrmFmts()->Count() );
+ while( aSave.GetCount() &&
+ &rFmt != (*pDoc->GetSpzFrmFmts())[
+ aSave.DecCount() ] )
+ ; // nothing
+ OSL_ENSURE( &rFmt == (*pDoc->GetSpzFrmFmts())[
+ aSave.GetCount() ],
+ "_SaveCntntIdx: Lost FrameFormat" );
+ aSave.Add( rSaveArr );
+ }
+ }
+ }
+ }
+ else // Schade, kein Layout, dann ist es eben etwas teurer...
+ {
+ for( aSave.SetCount( pDoc->GetSpzFrmFmts()->Count() );
+ aSave.GetCount() ; )
+ {
+ SwFrmFmt* pFrmFmt = (*pDoc->GetSpzFrmFmts())[
+ aSave.DecCount() ];
+ if ( RES_FLYFRMFMT != pFrmFmt->Which() &&
+ RES_DRAWFRMFMT != pFrmFmt->Which() )
+ continue;
+
+ const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
+ SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
+ if ( pAPos && ( nNode == pAPos->nNode.GetIndex() ) &&
+ ( FLY_AT_PARA == rAnchor.GetAnchorId() ||
+ FLY_AT_CHAR == rAnchor.GetAnchorId() ) )
+ {
+ aSave.SetType( 0x2000 );
+ aSave.SetContent( pAPos->nContent.GetIndex() );
+ if ( FLY_AT_CHAR == rAnchor.GetAnchorId() )
+ {
+ if( nCntnt <= aSave.GetContent() )
+ {
+ if( SAVEFLY_SPLIT == nSaveFly )
+ aSave.IncType(); // = 0x2001;
+ else
+ continue;
+ }
+ }
+ aSave.Add( rSaveArr );
+ }
+ }
+ }
+ }
+ }
+ // 5. CrsrShell
+ {
+ SwCrsrShell* pShell = pDoc->GetEditShell();
+ if( pShell )
+ {
+ aSave.SetTypeAndCount( 0x800, 0 );
+ FOREACHSHELL_START( pShell )
+ SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
+ if( _pStkCrsr )
+ do {
+ lcl_ChkPaM( rSaveArr, nNode, nCntnt, *_pStkCrsr,
+ aSave, sal_False );
+ aSave.IncCount();
+ } while ( (_pStkCrsr != 0 ) &&
+ ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
+
+ FOREACHPAM_START( PCURSH->_GetCrsr() )
+ lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR,
+ aSave, sal_False );
+ aSave.IncCount();
+ FOREACHPAM_END()
+
+ FOREACHSHELL_END( pShell )
+ }
+ }
+ // 6. UnoCrsr
+ {
+ aSave.SetTypeAndCount( 0x400, 0 );
+ const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ FOREACHPAM_START( rTbl[ n ] )
+ lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR, aSave, sal_False );
+ aSave.IncCount();
+ FOREACHPAM_END()
+
+ SwUnoTableCrsr* pUnoTblCrsr =
+ dynamic_cast<SwUnoTableCrsr*>(rTbl[ n ]);
+ if( pUnoTblCrsr )
+ {
+ FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
+ lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR, aSave, sal_False );
+ aSave.IncCount();
+ FOREACHPAM_END()
+ }
+ }
+ }
+}
+
+
+void _RestoreCntntIdx(SwDoc* pDoc,
+ SvULongs& rSaveArr,
+ sal_uLong nNode,
+ xub_StrLen nOffset,
+ sal_Bool bAuto)
+{
+ SwCntntNode* pCNd = pDoc->GetNodes()[ nNode ]->GetCntntNode();
+ const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
+ SwSpzFrmFmts* pSpz = pDoc->GetSpzFrmFmts();
+ IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ sal_uInt16 n = 0;
+ while( n < rSaveArr.Count() )
+ {
+ _SwSaveTypeCountContent aSave( rSaveArr, n );
+ SwPosition* pPos = 0;
+ switch( aSave.GetType() )
+ {
+ case 0x8000:
+ {
+ MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
+ SwPosition aNewPos(pMark->GetMarkPos());
+ aNewPos.nNode = *pCNd;
+ aNewPos.nContent.Assign(pCNd, aSave.GetContent() + nOffset);
+ pMark->SetMarkPos(aNewPos);
+ }
+ break;
+ case 0x8001:
+ {
+ MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
+ SwPosition aNewPos(pMark->GetOtherMarkPos());
+ aNewPos.nNode = *pCNd;
+ aNewPos.nContent.Assign(pCNd, aSave.GetContent() + nOffset);
+ pMark->SetOtherMarkPos(aNewPos);
+ }
+ break;
+ case 0x1001:
+ pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetPoint();
+ break;
+ case 0x1000:
+ pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetMark();
+ break;
+ case 0x2000:
+ {
+ SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
+ const SwFmtAnchor& rFlyAnchor = pFrmFmt->GetAnchor();
+ if( rFlyAnchor.GetCntntAnchor() )
+ {
+ SwFmtAnchor aNew( rFlyAnchor );
+ SwPosition aNewPos( *rFlyAnchor.GetCntntAnchor() );
+ aNewPos.nNode = *pCNd;
+ if ( FLY_AT_CHAR == rFlyAnchor.GetAnchorId() )
+ {
+ aNewPos.nContent.Assign( pCNd,
+ aSave.GetContent() + nOffset );
+ }
+ else
+ {
+ aNewPos.nContent.Assign( 0, 0 );
+ }
+ aNew.SetAnchor( &aNewPos );
+ pFrmFmt->SetFmtAttr( aNew );
+ }
+ }
+ break;
+ case 0x2001:
+ if( bAuto )
+ {
+ SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
+ SfxPoolItem *pAnchor = (SfxPoolItem*)&pFrmFmt->GetAnchor();
+ pFrmFmt->SwModify::Modify( pAnchor, pAnchor );
+ }
+ break;
+
+ case 0x0800:
+ case 0x0801:
+ {
+ sal_uInt16 nCnt = 0;
+ SwCrsrShell* pShell = pDoc->GetEditShell();
+ if( pShell )
+ {
+ FOREACHSHELL_START( pShell )
+ SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
+ if( _pStkCrsr )
+ do {
+ if( aSave.GetCount() == nCnt )
+ {
+ pPos = &_pStkCrsr->GetBound( 0x0800 ==
+ aSave.GetType() );
+ break;
+ }
+ ++nCnt;
+ } while ( (_pStkCrsr != 0 ) &&
+ ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
+
+ if( pPos )
+ break;
+
+ FOREACHPAM_START( PCURSH->_GetCrsr() )
+ if( aSave.GetCount() == nCnt )
+ {
+ pPos = &PCURCRSR->GetBound( 0x0800 ==
+ aSave.GetType() );
+ break;
+ }
+ ++nCnt;
+ FOREACHPAM_END()
+ if( pPos )
+ break;
+
+ FOREACHSHELL_END( pShell )
+ }
+ }
+ break;
+
+ case 0x0400:
+ case 0x0401:
+ {
+ sal_uInt16 nCnt = 0;
+ const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
+ for( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
+ {
+ FOREACHPAM_START( rTbl[ i ] )
+ if( aSave.GetCount() == nCnt )
+ {
+ pPos = &PCURCRSR->GetBound( 0x0400 ==
+ aSave.GetType() );
+ break;
+ }
+ ++nCnt;
+ FOREACHPAM_END()
+ if( pPos )
+ break;
+
+ SwUnoTableCrsr* pUnoTblCrsr =
+ dynamic_cast<SwUnoTableCrsr*>(rTbl[ i ]);
+ if ( pUnoTblCrsr )
+ {
+ FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
+ if( aSave.GetCount() == nCnt )
+ {
+ pPos = &PCURCRSR->GetBound( 0x0400 ==
+ aSave.GetType() );
+ break;
+ }
+ ++nCnt;
+ FOREACHPAM_END()
+ }
+ if ( pPos )
+ break;
+ }
+ }
+ break;
+ }
+
+ if( pPos )
+ {
+ pPos->nNode = *pCNd;
+ pPos->nContent.Assign( pCNd, aSave.GetContent() + nOffset );
+ }
+ }
+}
+
+void _RestoreCntntIdx(SvULongs& rSaveArr,
+ const SwNode& rNd,
+ xub_StrLen nLen,
+ xub_StrLen nChkLen)
+{
+ const SwDoc* pDoc = rNd.GetDoc();
+ const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
+ const SwSpzFrmFmts* pSpz = pDoc->GetSpzFrmFmts();
+ const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ SwCntntNode* pCNd = (SwCntntNode*)rNd.GetCntntNode();
+
+ sal_uInt16 n = 0;
+ while( n < rSaveArr.Count() )
+ {
+ _SwSaveTypeCountContent aSave( rSaveArr, n );
+ if( aSave.GetContent() >= nChkLen )
+ rSaveArr[ n-1 ] -= nChkLen;
+ else
+ {
+ SwPosition* pPos = 0;
+ switch( aSave.GetType() )
+ {
+ case 0x8000:
+ {
+ MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
+ SwPosition aNewPos(pMark->GetMarkPos());
+ aNewPos.nNode = rNd;
+ aNewPos.nContent.Assign(pCNd, Min(aSave.GetContent(), nLen));
+ pMark->SetMarkPos(aNewPos);
+ }
+ break;
+ case 0x8001:
+ {
+ MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
+ SwPosition aNewPos(pMark->GetOtherMarkPos());
+ aNewPos.nNode = rNd;
+ aNewPos.nContent.Assign(pCNd, Min(aSave.GetContent(), nLen));
+ pMark->SetOtherMarkPos(aNewPos);
+ }
+ break;
+ case 0x1001:
+ pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetPoint();
+ break;
+ case 0x1000:
+ pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetMark();
+ break;
+ case 0x2000:
+ case 0x2001:
+ {
+ SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
+ const SwFmtAnchor& rFlyAnchor = pFrmFmt->GetAnchor();
+ if( rFlyAnchor.GetCntntAnchor() )
+ {
+ SwFmtAnchor aNew( rFlyAnchor );
+ SwPosition aNewPos( *rFlyAnchor.GetCntntAnchor() );
+ aNewPos.nNode = rNd;
+ if ( FLY_AT_CHAR == rFlyAnchor.GetAnchorId() )
+ {
+ aNewPos.nContent.Assign( pCNd, Min(
+ aSave.GetContent(), nLen ) );
+ }
+ else
+ {
+ aNewPos.nContent.Assign( 0, 0 );
+ }
+ aNew.SetAnchor( &aNewPos );
+ pFrmFmt->SetFmtAttr( aNew );
+ }
+ }
+ break;
+
+ case 0x0800:
+ case 0x0801:
+ {
+ sal_uInt16 nCnt = 0;
+ SwCrsrShell* pShell = pDoc->GetEditShell();
+ if( pShell )
+ {
+ FOREACHSHELL_START( pShell )
+ SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
+ if( _pStkCrsr )
+ do {
+ if( aSave.GetCount() == nCnt )
+ {
+ pPos = &_pStkCrsr->GetBound( 0x0800 ==
+ aSave.GetType() );
+ break;
+ }
+ ++nCnt;
+ } while ( (_pStkCrsr != 0 ) &&
+ ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
+
+ if( pPos )
+ break;
+
+ FOREACHPAM_START( PCURSH->_GetCrsr() )
+ if( aSave.GetCount() == nCnt )
+ {
+ pPos = &PCURCRSR->GetBound( 0x0800 ==
+ aSave.GetType() );
+ break;
+ }
+ ++nCnt;
+ FOREACHPAM_END()
+ if( pPos )
+ break;
+
+ FOREACHSHELL_END( pShell )
+ }
+ }
+ break;
+
+ case 0x0400:
+ case 0x0401:
+ {
+ sal_uInt16 nCnt = 0;
+ const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
+ for( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
+ {
+ FOREACHPAM_START( rTbl[ i ] )
+ if( aSave.GetCount() == nCnt )
+ {
+ pPos = &PCURCRSR->GetBound( 0x0400 ==
+ aSave.GetType() );
+ break;
+ }
+ ++nCnt;
+ FOREACHPAM_END()
+ if( pPos )
+ break;
+
+ SwUnoTableCrsr* pUnoTblCrsr =
+ dynamic_cast<SwUnoTableCrsr*>(rTbl[ i ]);
+ if ( pUnoTblCrsr )
+ {
+ FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
+ if( aSave.GetCount() == nCnt )
+ {
+ pPos = &PCURCRSR->GetBound( 0x0400 ==
+ aSave.GetType() );
+ break;
+ }
+ ++nCnt;
+ FOREACHPAM_END()
+ }
+ if ( pPos )
+ break;
+ }
+ }
+ break;
+ }
+
+ if( pPos )
+ {
+ pPos->nNode = rNd;
+ pPos->nContent.Assign( pCNd, Min( aSave.GetContent(), nLen ) );
+ }
+ n -= 2;
+ rSaveArr.Remove( n, 2 );
+ }
+ }
+}
diff --git a/sw/source/core/doc/docchart.cxx b/sw/source/core/doc/docchart.cxx
new file mode 100644
index 000000000000..1d1890521acf
--- /dev/null
+++ b/sw/source/core/doc/docchart.cxx
@@ -0,0 +1,277 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <com/sun/star/frame/XModel.hpp>
+
+#include <com/sun/star/chart2/XChartDocument.hpp>
+
+#include <float.h>
+#include <hintids.hxx>
+#include <vcl/window.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <ndindex.hxx>
+#include <swtable.hxx>
+#include <ndtxt.hxx>
+#include <ndole.hxx>
+#include <calc.hxx>
+#include <frmfmt.hxx>
+#include <cellfml.hxx>
+#include <viewsh.hxx>
+#include <ndole.hxx>
+#include <calbck.hxx>
+#include <cntfrm.hxx>
+#include <swtblfmt.hxx>
+#include <tblsel.hxx>
+#include <cellatr.hxx>
+#include <vos/mutex.hxx>
+#include <vcl/svapp.hxx>
+
+#include <unochart.hxx>
+
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+
+
+void SwTable::UpdateCharts() const
+{
+ GetFrmFmt()->GetDoc()->UpdateCharts( GetFrmFmt()->GetName() );
+}
+
+sal_Bool SwTable::IsTblComplexForChart( const String& rSelection,
+ SwChartLines* pGetCLines ) const
+{
+ const SwTableBox* pSttBox, *pEndBox;
+ if( 2 < rSelection.Len() )
+ {
+ // spitze Klammern am Anfang & Ende enfernen
+ String sBox( rSelection );
+ if( '<' == sBox.GetChar( 0 ) ) sBox.Erase( 0, 1 );
+ if( '>' == sBox.GetChar( sBox.Len()-1 ) ) sBox.Erase( sBox.Len()-1 );
+
+ xub_StrLen nTrenner = sBox.Search( ':' );
+ ASSERT( STRING_NOTFOUND != nTrenner, "keine gueltige Selektion" );
+
+ pSttBox = GetTblBox( sBox.Copy( 0, nTrenner ));
+ pEndBox = GetTblBox( sBox.Copy( nTrenner+1 ));
+ }
+ else
+ {
+ const SwTableLines* pLns = &GetTabLines();
+ pSttBox = (*pLns)[ 0 ]->GetTabBoxes()[ 0 ];
+ while( !pSttBox->GetSttNd() )
+ // bis zur Content Box!
+ pSttBox = pSttBox->GetTabLines()[ 0 ]->GetTabBoxes()[ 0 ];
+
+ const SwTableBoxes* pBoxes = &(*pLns)[ pLns->Count()-1 ]->GetTabBoxes();
+ pEndBox = (*pBoxes)[ pBoxes->Count()-1 ];
+ while( !pEndBox->GetSttNd() )
+ {
+ // bis zur Content Box!
+ pLns = &pEndBox->GetTabLines();
+ pBoxes = &(*pLns)[ pLns->Count()-1 ]->GetTabBoxes();
+ pEndBox = (*pBoxes)[ pBoxes->Count()-1 ];
+ }
+ }
+
+ return !pSttBox || !pEndBox || !::ChkChartSel( *pSttBox->GetSttNd(),
+ *pEndBox->GetSttNd(), pGetCLines );
+}
+
+
+
+IMPL_LINK( SwDoc, DoUpdateAllCharts, Timer *, EMPTYARG )
+{
+ ViewShell* pVSh;
+ GetEditShell( &pVSh );
+ if( pVSh )
+ {
+ const SwFrmFmts& rTblFmts = *GetTblFrmFmts();
+ for( sal_uInt16 n = 0; n < rTblFmts.Count(); ++n )
+ {
+ SwTable* pTmpTbl;
+ const SwTableNode* pTblNd;
+ SwFrmFmt* pFmt = rTblFmts[ n ];
+
+ if( 0 != ( pTmpTbl = SwTable::FindTable( pFmt ) ) &&
+ 0 != ( pTblNd = pTmpTbl->GetTableNode() ) &&
+ pTblNd->GetNodes().IsDocNodes() )
+ {
+ _UpdateCharts( *pTmpTbl, *pVSh );
+ }
+ }
+ }
+ return 0;
+}
+
+void SwDoc::_UpdateCharts( const SwTable& rTbl, ViewShell& /*rVSh*/ ) const
+{
+ String aName( rTbl.GetFrmFmt()->GetName() );
+ SwOLENode *pONd;
+ SwStartNode *pStNd;
+ SwNodeIndex aIdx( *GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 );
+ while( 0 != (pStNd = aIdx.GetNode().GetStartNode()) )
+ {
+ aIdx++;
+ SwFrm* pFrm;
+ if( 0 != ( pONd = aIdx.GetNode().GetOLENode() ) &&
+ aName.Equals( pONd->GetChartTblName() ) &&
+ 0 != ( pFrm = pONd->GetFrm() ) )
+ {
+ SwChartDataProvider *pPCD = GetChartDataProvider();
+ if (pPCD)
+ pPCD->InvalidateTable( &rTbl );
+ // following this the framework will now take care of repainting
+ // the chart or it's replacement image...
+ }
+ aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 );
+ }
+}
+
+void SwDoc::UpdateCharts( const String &rName ) const
+{
+ SwTable* pTmpTbl = SwTable::FindTable( FindTblFmtByName( rName ) );
+ if( pTmpTbl )
+ {
+ ViewShell* pVSh;
+ GetEditShell( &pVSh );
+
+ if( pVSh )
+ _UpdateCharts( *pTmpTbl, *pVSh );
+ }
+}
+
+void SwDoc::SetTableName( SwFrmFmt& rTblFmt, const String &rNewName )
+{
+// sal_Bool bStop = 1;
+
+ const String aOldName( rTblFmt.GetName() );
+
+ sal_Bool bNameFound = 0 == rNewName.Len();
+ if( !bNameFound )
+ {
+ SwFrmFmt* pFmt;
+ const SwFrmFmts& rTbl = *GetTblFrmFmts();
+ for( sal_uInt16 i = rTbl.Count(); i; )
+ if( !( pFmt = rTbl[ --i ] )->IsDefault() &&
+ pFmt->GetName() == rNewName && IsUsed( *pFmt ) )
+ {
+ bNameFound = sal_True;
+ break;
+ }
+ }
+
+ if( !bNameFound )
+ rTblFmt.SetName( rNewName, sal_True );
+ else
+ rTblFmt.SetName( GetUniqueTblName(), sal_True );
+
+ SwStartNode *pStNd;
+ SwNodeIndex aIdx( *GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 );
+ while ( 0 != (pStNd = aIdx.GetNode().GetStartNode()) )
+ {
+ aIdx++;
+ SwOLENode *pNd = aIdx.GetNode().GetOLENode();
+ if( pNd && aOldName == pNd->GetChartTblName() )
+ {
+ pNd->SetChartTblName( rNewName );
+
+ ViewShell* pVSh;
+ GetEditShell( &pVSh );
+
+ SwTable* pTable = SwTable::FindTable( &rTblFmt );
+ SwChartDataProvider *pPCD = GetChartDataProvider();
+ if (pPCD)
+ pPCD->InvalidateTable( pTable );
+ // following this the framework will now take care of repainting
+ // the chart or it's replacement image...
+ }
+ aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 );
+ }
+ SetModified();
+}
+
+
+SwChartDataProvider * SwDoc::GetChartDataProvider( bool bCreate ) const
+{
+ // since there must be only one instance of this object per document
+ // we need a mutex here
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+
+ if (bCreate && !aChartDataProviderImplRef.get())
+ {
+ aChartDataProviderImplRef = comphelper::ImplementationReference< SwChartDataProvider
+ , chart2::data::XDataProvider >( new SwChartDataProvider( this ) );
+ }
+ return aChartDataProviderImplRef.get();
+}
+
+
+void SwDoc::CreateChartInternalDataProviders( const SwTable *pTable )
+{
+ if (pTable)
+ {
+ String aName( pTable->GetFrmFmt()->GetName() );
+ SwOLENode *pONd;
+ SwStartNode *pStNd;
+ SwNodeIndex aIdx( *GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 );
+ while (0 != (pStNd = aIdx.GetNode().GetStartNode()))
+ {
+ aIdx++;
+ if( 0 != ( pONd = aIdx.GetNode().GetOLENode() ) &&
+ aName.Equals( pONd->GetChartTblName() ) /* OLE node is chart? */ &&
+ 0 != (pONd->GetFrm()) /* chart frame is not hidden */ )
+ {
+ uno::Reference < embed::XEmbeddedObject > xIP = pONd->GetOLEObj().GetOleRef();
+ if ( svt::EmbeddedObjectRef::TryRunningState( xIP ) )
+ {
+ uno::Reference< chart2::XChartDocument > xChart( xIP->getComponent(), UNO_QUERY );
+ if (xChart.is())
+ xChart->createInternalDataProvider( sal_True );
+
+ // there may be more than one chart for each table thus we need to continue the loop...
+ }
+ }
+ aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 );
+ }
+ }
+}
+
+
+SwChartLockController_Helper & SwDoc::GetChartControllerHelper()
+{
+ if (!pChartControllerHelper)
+ {
+ pChartControllerHelper = new SwChartLockController_Helper( this );
+ }
+ return *pChartControllerHelper;
+}
+
diff --git a/sw/source/core/doc/doccomp.cxx b/sw/source/core/doc/doccomp.cxx
new file mode 100644
index 000000000000..e0c550dff020
--- /dev/null
+++ b/sw/source/core/doc/doccomp.cxx
@@ -0,0 +1,1883 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <tools/list.hxx>
+#include <vcl/vclenum.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <redline.hxx>
+#include <UndoRedline.hxx>
+#include <section.hxx>
+#include <tox.hxx>
+#include <docsh.hxx>
+
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+
+using namespace ::com::sun::star;
+
+
+class CompareLine
+{
+public:
+ CompareLine() {}
+ virtual ~CompareLine();
+
+ virtual sal_uLong GetHashValue() const = 0;
+ virtual sal_Bool Compare( const CompareLine& rLine ) const = 0;
+};
+
+DECLARE_LIST( CompareList, CompareLine* )
+
+class CompareData
+{
+ sal_uLong* pIndex;
+ sal_Bool* pChangedFlag;
+
+protected:
+ CompareList aLines;
+ sal_uLong nSttLineNum;
+
+ // Anfang und Ende beschneiden und alle anderen in das
+ // LinesArray setzen
+ virtual void CheckRanges( CompareData& ) = 0;
+
+public:
+ CompareData();
+ virtual ~CompareData();
+
+ // gibt es unterschiede?
+ sal_Bool HasDiffs( const CompareData& rData ) const;
+
+ // startet das Vergleichen und Erzeugen der Unterschiede zweier
+ // Dokumente
+ void CompareLines( CompareData& rData );
+ // lasse die Unterschiede anzeigen - ruft die beiden Methoden
+ // ShowInsert / ShowDelete. Diese bekommen die Start und EndLine-Nummer
+ // uebergeben. Die Abbildung auf den tatsaechline Inhalt muss die
+ // Ableitung uebernehmen!
+ sal_uLong ShowDiffs( const CompareData& rData );
+
+ virtual void ShowInsert( sal_uLong nStt, sal_uLong nEnd );
+ virtual void ShowDelete( const CompareData& rData, sal_uLong nStt,
+ sal_uLong nEnd, sal_uLong nInsPos );
+ virtual void CheckForChangesInLine( const CompareData& rData,
+ sal_uLong& nStt, sal_uLong& nEnd,
+ sal_uLong& nThisStt, sal_uLong& nThisEnd );
+
+ // Eindeutigen Index fuer eine Line setzen. Gleiche Lines haben den
+ // selben Index; auch in den anderen CompareData!
+ void SetIndex( sal_uLong nLine, sal_uLong nIndex );
+ sal_uLong GetIndex( sal_uLong nLine ) const
+ { return nLine < aLines.Count() ? pIndex[ nLine ] : 0; }
+
+ // setze/erfrage ob eine Zeile veraendert ist
+ void SetChanged( sal_uLong nLine, sal_Bool bFlag = sal_True );
+ sal_Bool GetChanged( sal_uLong nLine ) const
+ {
+ return (pChangedFlag && nLine < aLines.Count())
+ ? pChangedFlag[ nLine ]
+ : 0;
+ }
+
+ sal_uLong GetLineCount() const { return aLines.Count(); }
+ sal_uLong GetLineOffset() const { return nSttLineNum; }
+ const CompareLine* GetLine( sal_uLong nLine ) const
+ { return aLines.GetObject( nLine ); }
+ void InsertLine( CompareLine* pLine )
+ { aLines.Insert( pLine, LIST_APPEND ); }
+};
+
+class Hash
+{
+ struct _HashData
+ {
+ sal_uLong nNext, nHash;
+ const CompareLine* pLine;
+
+ _HashData()
+ : nNext( 0 ), nHash( 0 ), pLine(0) {}
+ };
+
+ sal_uLong* pHashArr;
+ _HashData* pDataArr;
+ sal_uLong nCount, nPrime;
+
+public:
+ Hash( sal_uLong nSize );
+ ~Hash();
+
+ void CalcHashValue( CompareData& rData );
+
+ sal_uLong GetCount() const { return nCount; }
+};
+
+class Compare
+{
+public:
+ class MovedData
+ {
+ sal_uLong* pIndex;
+ sal_uLong* pLineNum;
+ sal_uLong nCount;
+
+ public:
+ MovedData( CompareData& rData, sal_Char* pDiscard );
+ ~MovedData();
+
+ sal_uLong GetIndex( sal_uLong n ) const { return pIndex[ n ]; }
+ sal_uLong GetLineNum( sal_uLong n ) const { return pLineNum[ n ]; }
+ sal_uLong GetCount() const { return nCount; }
+ };
+
+private:
+ // Suche die verschobenen Lines
+ class CompareSequence
+ {
+ CompareData &rData1, &rData2;
+ const MovedData &rMoved1, &rMoved2;
+ long *pMemory, *pFDiag, *pBDiag;
+
+ void Compare( sal_uLong nStt1, sal_uLong nEnd1, sal_uLong nStt2, sal_uLong nEnd2 );
+ sal_uLong CheckDiag( sal_uLong nStt1, sal_uLong nEnd1,
+ sal_uLong nStt2, sal_uLong nEnd2, sal_uLong* pCost );
+ public:
+ CompareSequence( CompareData& rData1, CompareData& rData2,
+ const MovedData& rD1, const MovedData& rD2 );
+ ~CompareSequence();
+ };
+
+
+ static void CountDifference( const CompareData& rData, sal_uLong* pCounts );
+ static void SetDiscard( const CompareData& rData,
+ sal_Char* pDiscard, sal_uLong* pCounts );
+ static void CheckDiscard( sal_uLong nLen, sal_Char* pDiscard );
+ static sal_uLong SetChangedFlag( CompareData& rData, sal_Char* pDiscard, int bFirst );
+ static void ShiftBoundaries( CompareData& rData1, CompareData& rData2 );
+
+public:
+ Compare( sal_uLong nDiff, CompareData& rData1, CompareData& rData2 );
+};
+
+// ====================================================================
+
+CompareLine::~CompareLine() {}
+
+// ----------------------------------------------------------------------
+
+CompareData::CompareData()
+ : pIndex( 0 ), pChangedFlag( 0 ), nSttLineNum( 0 )
+{
+}
+
+CompareData::~CompareData()
+{
+ delete[] pIndex;
+ delete[] pChangedFlag;
+}
+
+void CompareData::SetIndex( sal_uLong nLine, sal_uLong nIndex )
+{
+ if( !pIndex )
+ {
+ pIndex = new sal_uLong[ aLines.Count() ];
+ memset( pIndex, 0, aLines.Count() * sizeof( sal_uLong ) );
+ }
+ if( nLine < aLines.Count() )
+ pIndex[ nLine ] = nIndex;
+}
+
+void CompareData::SetChanged( sal_uLong nLine, sal_Bool bFlag )
+{
+ if( !pChangedFlag )
+ {
+ pChangedFlag = new sal_Bool[ aLines.Count() +1 ];
+ memset( pChangedFlag, 0, aLines.Count() +1 * sizeof( sal_Bool ) );
+ }
+ if( nLine < aLines.Count() )
+ pChangedFlag[ nLine ] = bFlag;
+}
+
+void CompareData::CompareLines( CompareData& rData )
+{
+ CheckRanges( rData );
+
+ sal_uLong nDifferent;
+ {
+ Hash aH( GetLineCount() + rData.GetLineCount() + 1 );
+ aH.CalcHashValue( *this );
+ aH.CalcHashValue( rData );
+ nDifferent = aH.GetCount();
+ }
+ {
+ Compare aComp( nDifferent, *this, rData );
+ }
+}
+
+sal_uLong CompareData::ShowDiffs( const CompareData& rData )
+{
+ sal_uLong nLen1 = rData.GetLineCount(), nLen2 = GetLineCount();
+ sal_uLong nStt1 = 0, nStt2 = 0;
+ sal_uLong nCnt = 0;
+
+ while( nStt1 < nLen1 || nStt2 < nLen2 )
+ {
+ if( rData.GetChanged( nStt1 ) || GetChanged( nStt2 ) )
+ {
+ sal_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;
+ }
+ ++nStt1, ++nStt2;
+ }
+ return nCnt;
+}
+
+sal_Bool CompareData::HasDiffs( const CompareData& rData ) const
+{
+ sal_Bool bRet = sal_False;
+ sal_uLong nLen1 = rData.GetLineCount(), nLen2 = GetLineCount();
+ sal_uLong nStt1 = 0, nStt2 = 0;
+
+ while( nStt1 < nLen1 || nStt2 < nLen2 )
+ {
+ if( rData.GetChanged( nStt1 ) || GetChanged( nStt2 ) )
+ {
+ bRet = sal_True;
+ break;
+ }
+ ++nStt1, ++nStt2;
+ }
+ return bRet;
+}
+
+void CompareData::ShowInsert( sal_uLong, sal_uLong )
+{
+}
+
+void CompareData::ShowDelete( const CompareData&, sal_uLong, sal_uLong, sal_uLong )
+{
+}
+
+void CompareData::CheckForChangesInLine( const CompareData& ,
+ sal_uLong&, sal_uLong&, sal_uLong&, sal_uLong& )
+{
+}
+
+// ----------------------------------------------------------------------
+
+Hash::Hash( sal_uLong nSize )
+ : nCount( 1 )
+{
+
+static const sal_uLong primes[] =
+{
+ 509,
+ 1021,
+ 2039,
+ 4093,
+ 8191,
+ 16381,
+ 32749,
+ 65521,
+ 131071,
+ 262139,
+ 524287,
+ 1048573,
+ 2097143,
+ 4194301,
+ 8388593,
+ 16777213,
+ 33554393,
+ 67108859, /* Preposterously large . . . */
+ 134217689,
+ 268435399,
+ 536870909,
+ 1073741789,
+ 2147483647,
+ 0
+};
+ int i;
+
+ pDataArr = new _HashData[ nSize ];
+ pDataArr[0].nNext = 0;
+ pDataArr[0].nHash = 0,
+ pDataArr[0].pLine = 0;
+
+ for( i = 0; primes[i] < nSize / 3; i++)
+ if( !primes[i] )
+ {
+ pHashArr = 0;
+ return;
+ }
+ nPrime = primes[ i ];
+ pHashArr = new sal_uLong[ nPrime ];
+ memset( pHashArr, 0, nPrime * sizeof( sal_uLong ) );
+}
+
+Hash::~Hash()
+{
+ delete[] pHashArr;
+ delete[] pDataArr;
+}
+
+void Hash::CalcHashValue( CompareData& rData )
+{
+ if( pHashArr )
+ {
+ for( sal_uLong n = 0; n < rData.GetLineCount(); ++n )
+ {
+ const CompareLine* pLine = rData.GetLine( n );
+ ASSERT( pLine, "wo ist die Line?" );
+ sal_uLong nH = pLine->GetHashValue();
+
+ sal_uLong* pFound = &pHashArr[ nH % nPrime ];
+ sal_uLong i;
+ for( i = *pFound; ; i = pDataArr[i].nNext )
+ if( !i )
+ {
+ i = nCount++;
+ pDataArr[i].nNext = *pFound;
+ pDataArr[i].nHash = nH;
+ pDataArr[i].pLine = pLine;
+ *pFound = i;
+ break;
+ }
+ else if( pDataArr[i].nHash == nH &&
+ pDataArr[i].pLine->Compare( *pLine ))
+ break;
+
+ rData.SetIndex( n, i );
+ }
+ }
+}
+
+// ----------------------------------------------------------------------
+
+Compare::Compare( sal_uLong nDiff, CompareData& rData1, CompareData& rData2 )
+{
+ MovedData *pMD1, *pMD2;
+ // Suche die unterschiedlichen Lines
+ {
+ sal_Char* pDiscard1 = new sal_Char[ rData1.GetLineCount() ];
+ sal_Char* pDiscard2 = new sal_Char[ rData2.GetLineCount() ];
+
+ sal_uLong* pCount1 = new sal_uLong[ nDiff ];
+ sal_uLong* pCount2 = new sal_uLong[ nDiff ];
+ memset( pCount1, 0, nDiff * sizeof( sal_uLong ));
+ memset( pCount2, 0, nDiff * sizeof( sal_uLong ));
+
+ // stelle fest, welche Indizies in den CompareData mehrfach vergeben wurden
+ CountDifference( rData1, pCount1 );
+ CountDifference( rData2, pCount2 );
+
+ // alle die jetzt nur einmal vorhanden sind, sind eingefuegt oder
+ // geloescht worden. Alle die im anderen auch vorhanden sind, sind
+ // verschoben worden
+ SetDiscard( rData1, pDiscard1, pCount2 );
+ SetDiscard( rData2, pDiscard2, pCount1 );
+
+ // die Arrays koennen wir wieder vergessen
+ delete [] pCount1; delete [] pCount2;
+
+ CheckDiscard( rData1.GetLineCount(), pDiscard1 );
+ CheckDiscard( rData2.GetLineCount(), pDiscard2 );
+
+ pMD1 = new MovedData( rData1, pDiscard1 );
+ pMD2 = new MovedData( rData2, pDiscard2 );
+
+ // die Arrays koennen wir wieder vergessen
+ delete [] pDiscard1; delete [] pDiscard2;
+ }
+
+ {
+ CompareSequence aTmp( rData1, rData2, *pMD1, *pMD2 );
+ }
+
+ ShiftBoundaries( rData1, rData2 );
+
+ delete pMD1;
+ delete pMD2;
+}
+
+
+
+void Compare::CountDifference( const CompareData& rData, sal_uLong* pCounts )
+{
+ sal_uLong nLen = rData.GetLineCount();
+ for( sal_uLong n = 0; n < nLen; ++n )
+ {
+ sal_uLong nIdx = rData.GetIndex( n );
+ ++pCounts[ nIdx ];
+ }
+}
+
+void Compare::SetDiscard( const CompareData& rData,
+ sal_Char* pDiscard, sal_uLong* pCounts )
+{
+ sal_uLong nLen = rData.GetLineCount();
+
+ // berechne Max in Abhanegigkeit zur LineAnzahl
+ sal_uInt16 nMax = 5;
+ sal_uLong n;
+
+ for( n = nLen / 64; ( n = n >> 2 ) > 0; )
+ nMax <<= 1;
+
+ for( n = 0; n < nLen; ++n )
+ {
+ sal_uLong nIdx = rData.GetIndex( n );
+ if( nIdx )
+ {
+ nIdx = pCounts[ nIdx ];
+ pDiscard[ n ] = !nIdx ? 1 : nIdx > nMax ? 2 : 0;
+ }
+ else
+ pDiscard[ n ] = 0;
+ }
+}
+
+void Compare::CheckDiscard( sal_uLong nLen, sal_Char* pDiscard )
+{
+ for( sal_uLong n = 0; n < nLen; ++n )
+ {
+ if( 2 == pDiscard[ n ] )
+ pDiscard[n] = 0;
+ else if( pDiscard[ n ] )
+ {
+ sal_uLong j;
+ sal_uLong length;
+ sal_uLong provisional = 0;
+
+ /* Find end of this run of discardable lines.
+ Count how many are provisionally discardable. */
+ for (j = n; j < nLen; j++)
+ {
+ if( !pDiscard[j] )
+ break;
+ if( 2 == pDiscard[j] )
+ ++provisional;
+ }
+
+ /* Cancel provisional discards at end, and shrink the run. */
+ while( j > n && 2 == pDiscard[j - 1] )
+ pDiscard[ --j ] = 0, --provisional;
+
+ /* Now we have the length of a run of discardable lines
+ whose first and last are not provisional. */
+ length = j - n;
+
+ /* If 1/4 of the lines in the run are provisional,
+ cancel discarding of all provisional lines in the run. */
+ if (provisional * 4 > length)
+ {
+ while (j > n)
+ if (pDiscard[--j] == 2)
+ pDiscard[j] = 0;
+ }
+ else
+ {
+ sal_uLong consec;
+ sal_uLong minimum = 1;
+ sal_uLong tem = length / 4;
+
+ /* MINIMUM is approximate square root of LENGTH/4.
+ A subrun of two or more provisionals can stand
+ when LENGTH is at least 16.
+ A subrun of 4 or more can stand when LENGTH >= 64. */
+ while ((tem = tem >> 2) > 0)
+ minimum *= 2;
+ minimum++;
+
+ /* Cancel any subrun of MINIMUM or more provisionals
+ within the larger run. */
+ for (j = 0, consec = 0; j < length; j++)
+ if (pDiscard[n + j] != 2)
+ consec = 0;
+ else if (minimum == ++consec)
+ /* Back up to start of subrun, to cancel it all. */
+ j -= consec;
+ else if (minimum < consec)
+ pDiscard[n + j] = 0;
+
+ /* Scan from beginning of run
+ until we find 3 or more nonprovisionals in a row
+ or until the first nonprovisional at least 8 lines in.
+ Until that point, cancel any provisionals. */
+ for (j = 0, consec = 0; j < length; j++)
+ {
+ if (j >= 8 && pDiscard[n + j] == 1)
+ break;
+ if (pDiscard[n + j] == 2)
+ consec = 0, pDiscard[n + j] = 0;
+ else if (pDiscard[n + j] == 0)
+ consec = 0;
+ else
+ consec++;
+ if (consec == 3)
+ break;
+ }
+
+ /* I advances to the last line of the run. */
+ n += length - 1;
+
+ /* Same thing, from end. */
+ for (j = 0, consec = 0; j < length; j++)
+ {
+ if (j >= 8 && pDiscard[n - j] == 1)
+ break;
+ if (pDiscard[n - j] == 2)
+ consec = 0, pDiscard[n - j] = 0;
+ else if (pDiscard[n - j] == 0)
+ consec = 0;
+ else
+ consec++;
+ if (consec == 3)
+ break;
+ }
+ }
+ }
+ }
+}
+
+// ----------------------------------------------------------------------
+
+Compare::MovedData::MovedData( CompareData& rData, sal_Char* pDiscard )
+ : pIndex( 0 ), pLineNum( 0 ), nCount( 0 )
+{
+ sal_uLong nLen = rData.GetLineCount();
+ sal_uLong n;
+
+ for( n = 0; n < nLen; ++n )
+ if( pDiscard[ n ] )
+ rData.SetChanged( n );
+ else
+ ++nCount;
+
+ if( nCount )
+ {
+ pIndex = new sal_uLong[ nCount ];
+ pLineNum = new sal_uLong[ nCount ];
+
+ for( n = 0, nCount = 0; n < nLen; ++n )
+ if( !pDiscard[ n ] )
+ {
+ pIndex[ nCount ] = rData.GetIndex( n );
+ pLineNum[ nCount++ ] = n;
+ }
+ }
+}
+
+Compare::MovedData::~MovedData()
+{
+ delete pIndex;
+ delete pLineNum;
+}
+
+// ----------------------------------------------------------------------
+
+ // Suche die verschobenen Lines
+Compare::CompareSequence::CompareSequence(
+ CompareData& rD1, CompareData& rD2,
+ const MovedData& rMD1, const MovedData& rMD2 )
+ : rData1( rD1 ), rData2( rD2 ), rMoved1( rMD1 ), rMoved2( rMD2 )
+{
+ sal_uLong nSize = rMD1.GetCount() + rMD2.GetCount() + 3;
+ pMemory = new long[ nSize * 2 ];
+ pFDiag = pMemory + ( rMD2.GetCount() + 1 );
+ pBDiag = pMemory + ( nSize + rMD2.GetCount() + 1 );
+
+ Compare( 0, rMD1.GetCount(), 0, rMD2.GetCount() );
+}
+
+Compare::CompareSequence::~CompareSequence()
+{
+ delete pMemory;
+}
+
+void Compare::CompareSequence::Compare( sal_uLong nStt1, sal_uLong nEnd1,
+ sal_uLong nStt2, sal_uLong nEnd2 )
+{
+ /* Slide down the bottom initial diagonal. */
+ while( nStt1 < nEnd1 && nStt2 < nEnd2 &&
+ rMoved1.GetIndex( nStt1 ) == rMoved2.GetIndex( nStt2 ))
+ ++nStt1, ++nStt2;
+
+ /* Slide up the top initial diagonal. */
+ while( nEnd1 > nStt1 && nEnd2 > nStt2 &&
+ rMoved1.GetIndex( nEnd1 - 1 ) == rMoved2.GetIndex( nEnd2 - 1 ))
+ --nEnd1, --nEnd2;
+
+ /* Handle simple cases. */
+ if( nStt1 == nEnd1 )
+ while( nStt2 < nEnd2 )
+ rData2.SetChanged( rMoved2.GetLineNum( nStt2++ ));
+
+ else if (nStt2 == nEnd2)
+ while (nStt1 < nEnd1)
+ rData1.SetChanged( rMoved1.GetLineNum( nStt1++ ));
+
+ else
+ {
+ sal_uLong c, d, b;
+
+ /* Find a point of correspondence in the middle of the files. */
+
+ d = CheckDiag( nStt1, nEnd1, nStt2, nEnd2, &c );
+ b = pBDiag[ d ];
+
+ if( 1 != c )
+ {
+ /* Use that point to split this problem into two subproblems. */
+ Compare( nStt1, b, nStt2, b - d );
+ /* This used to use f instead of b,
+ but that is incorrect!
+ It is not necessarily the case that diagonal d
+ has a snake from b to f. */
+ Compare( b, nEnd1, b - d, nEnd2 );
+ }
+ }
+}
+
+sal_uLong Compare::CompareSequence::CheckDiag( sal_uLong nStt1, sal_uLong nEnd1,
+ sal_uLong nStt2, sal_uLong nEnd2, sal_uLong* pCost )
+{
+ const long dmin = nStt1 - nEnd2; /* Minimum valid diagonal. */
+ const long dmax = nEnd1 - nStt2; /* Maximum valid diagonal. */
+ const long fmid = nStt1 - nStt2; /* Center diagonal of top-down search. */
+ const long bmid = nEnd1 - nEnd2; /* Center diagonal of bottom-up search. */
+
+ long fmin = fmid, fmax = fmid; /* Limits of top-down search. */
+ long bmin = bmid, bmax = bmid; /* Limits of bottom-up search. */
+
+ long c; /* Cost. */
+ long odd = (fmid - bmid) & 1; /* True if southeast corner is on an odd
+ diagonal with respect to the northwest. */
+
+ pFDiag[fmid] = nStt1;
+ pBDiag[bmid] = nEnd1;
+
+ for (c = 1;; ++c)
+ {
+ long d; /* Active diagonal. */
+ long big_snake = 0;
+
+ /* Extend the top-down search by an edit step in each diagonal. */
+ fmin > dmin ? pFDiag[--fmin - 1] = -1 : ++fmin;
+ fmax < dmax ? pFDiag[++fmax + 1] = -1 : --fmax;
+ for (d = fmax; d >= fmin; d -= 2)
+ {
+ long x, y, oldx, tlo = pFDiag[d - 1], thi = pFDiag[d + 1];
+
+ if (tlo >= thi)
+ x = tlo + 1;
+ else
+ x = thi;
+ oldx = x;
+ y = x - d;
+ while( sal_uLong(x) < nEnd1 && sal_uLong(y) < nEnd2 &&
+ rMoved1.GetIndex( x ) == rMoved2.GetIndex( y ))
+ ++x, ++y;
+ if (x - oldx > 20)
+ big_snake = 1;
+ pFDiag[d] = x;
+ if( odd && bmin <= d && d <= bmax && pBDiag[d] <= pFDiag[d] )
+ {
+ *pCost = 2 * c - 1;
+ return d;
+ }
+ }
+
+ /* Similar extend the bottom-up search. */
+ bmin > dmin ? pBDiag[--bmin - 1] = INT_MAX : ++bmin;
+ bmax < dmax ? pBDiag[++bmax + 1] = INT_MAX : --bmax;
+ for (d = bmax; d >= bmin; d -= 2)
+ {
+ long x, y, oldx, tlo = pBDiag[d - 1], thi = pBDiag[d + 1];
+
+ if (tlo < thi)
+ x = tlo;
+ else
+ x = thi - 1;
+ oldx = x;
+ y = x - d;
+ while( sal_uLong(x) > nStt1 && sal_uLong(y) > nStt2 &&
+ rMoved1.GetIndex( x - 1 ) == rMoved2.GetIndex( y - 1 ))
+ --x, --y;
+ if (oldx - x > 20)
+ big_snake = 1;
+ pBDiag[d] = x;
+ if (!odd && fmin <= d && d <= fmax && pBDiag[d] <= pFDiag[d])
+ {
+ *pCost = 2 * c;
+ return d;
+ }
+ }
+ }
+}
+
+void Compare::ShiftBoundaries( CompareData& rData1, CompareData& rData2 )
+{
+ for( int iz = 0; iz < 2; ++iz )
+ {
+ CompareData* pData = &rData1;
+ CompareData* pOtherData = &rData2;
+
+ sal_uLong i = 0;
+ sal_uLong j = 0;
+ sal_uLong i_end = pData->GetLineCount();
+ sal_uLong preceding = ULONG_MAX;
+ sal_uLong other_preceding = ULONG_MAX;
+
+ while (1)
+ {
+ sal_uLong start, other_start;
+
+ /* Scan forwards to find beginning of another run of changes.
+ Also keep track of the corresponding point in the other file. */
+
+ while( i < i_end && !pData->GetChanged( i ) )
+ {
+ while( pOtherData->GetChanged( j++ ))
+ /* Non-corresponding lines in the other file
+ will count as the preceding batch of changes. */
+ other_preceding = j;
+ i++;
+ }
+
+ if (i == i_end)
+ break;
+
+ start = i;
+ other_start = j;
+
+ while (1)
+ {
+ /* Now find the end of this run of changes. */
+
+ while( pData->GetChanged( ++i ))
+ ;
+
+ /* If the first changed line matches the following unchanged one,
+ and this run does not follow right after a previous run,
+ and there are no lines deleted from the other file here,
+ then classify the first changed line as unchanged
+ and the following line as changed in its place. */
+
+ /* You might ask, how could this run follow right after another?
+ Only because the previous run was shifted here. */
+
+ if( i != i_end &&
+ pData->GetIndex( start ) == pData->GetIndex( i ) &&
+ !pOtherData->GetChanged( j ) &&
+ !( start == preceding || other_start == other_preceding ))
+ {
+ pData->SetChanged( start++, 0 );
+ pData->SetChanged( i );
+ /* Since one line-that-matches is now before this run
+ instead of after, we must advance in the other file
+ to keep in synch. */
+ ++j;
+ }
+ else
+ break;
+ }
+
+ preceding = i;
+ other_preceding = j;
+ }
+
+ pData = &rData2;
+ pOtherData = &rData1;
+ }
+}
+
+/* */
+
+class SwCompareLine : public CompareLine
+{
+ const SwNode& rNode;
+public:
+ SwCompareLine( const SwNode& rNd );
+ virtual ~SwCompareLine();
+
+ virtual sal_uLong GetHashValue() const;
+ virtual sal_Bool Compare( const CompareLine& rLine ) const;
+
+ static sal_uLong GetTxtNodeHashValue( const SwTxtNode& rNd, sal_uLong nVal );
+ static sal_Bool CompareNode( const SwNode& rDstNd, const SwNode& rSrcNd );
+ static sal_Bool CompareTxtNd( const SwTxtNode& rDstNd,
+ const SwTxtNode& rSrcNd );
+
+ sal_Bool ChangesInLine( const SwCompareLine& rLine,
+ SwPaM *& rpInsRing, SwPaM*& rpDelRing ) const;
+
+ const SwNode& GetNode() const { return rNode; }
+
+ const SwNode& GetEndNode() const;
+
+ // fuers Debugging!
+ String GetText() const;
+};
+
+class SwCompareData : public CompareData
+{
+ SwDoc& rDoc;
+ SwPaM *pInsRing, *pDelRing;
+
+ sal_uLong PrevIdx( const SwNode* pNd );
+ sal_uLong NextIdx( const SwNode* pNd );
+
+ virtual void CheckRanges( CompareData& );
+ virtual void ShowInsert( sal_uLong nStt, sal_uLong nEnd );
+ virtual void ShowDelete( const CompareData& rData, sal_uLong nStt,
+ sal_uLong nEnd, sal_uLong nInsPos );
+
+ virtual void CheckForChangesInLine( const CompareData& rData,
+ sal_uLong& nStt, sal_uLong& nEnd,
+ sal_uLong& nThisStt, sal_uLong& nThisEnd );
+
+public:
+ SwCompareData( SwDoc& rD ) : rDoc( rD ), pInsRing(0), pDelRing(0) {}
+ virtual ~SwCompareData();
+
+ void SetRedlinesToDoc( sal_Bool bUseDocInfo );
+};
+
+// ----------------------------------------------------------------
+
+SwCompareLine::SwCompareLine( const SwNode& rNd )
+ : rNode( rNd )
+{
+}
+
+SwCompareLine::~SwCompareLine()
+{
+}
+
+sal_uLong SwCompareLine::GetHashValue() const
+{
+ sal_uLong nRet = 0;
+ switch( rNode.GetNodeType() )
+ {
+ case ND_TEXTNODE:
+ nRet = GetTxtNodeHashValue( (SwTxtNode&)rNode, nRet );
+ break;
+
+ case ND_TABLENODE:
+ {
+ const SwNode* pEndNd = rNode.EndOfSectionNode();
+ SwNodeIndex aIdx( rNode );
+ while( &aIdx.GetNode() != pEndNd )
+ {
+ if( aIdx.GetNode().IsTxtNode() )
+ nRet = GetTxtNodeHashValue( (SwTxtNode&)aIdx.GetNode(), nRet );
+ aIdx++;
+ }
+ }
+ break;
+
+ case ND_SECTIONNODE:
+ {
+ String sStr( GetText() );
+ for( xub_StrLen n = 0; n < sStr.Len(); ++n )
+ ( nRet <<= 1 ) += sStr.GetChar( n );
+ }
+ break;
+
+ case ND_GRFNODE:
+ case ND_OLENODE:
+ // feste Id ? sollte aber nie auftauchen
+ break;
+ }
+ return nRet;
+}
+
+const SwNode& SwCompareLine::GetEndNode() const
+{
+ const SwNode* pNd = &rNode;
+ switch( rNode.GetNodeType() )
+ {
+ case ND_TABLENODE:
+ pNd = rNode.EndOfSectionNode();
+ break;
+
+ case ND_SECTIONNODE:
+ {
+ const SwSectionNode& rSNd = (SwSectionNode&)rNode;
+ const SwSection& rSect = rSNd.GetSection();
+ if( CONTENT_SECTION != rSect.GetType() || rSect.IsProtect() )
+ pNd = rNode.EndOfSectionNode();
+ }
+ break;
+ }
+ return *pNd;
+}
+
+sal_Bool SwCompareLine::Compare( const CompareLine& rLine ) const
+{
+ return CompareNode( rNode, ((SwCompareLine&)rLine).rNode );
+}
+
+namespace
+{
+ static String SimpleTableToText(const SwNode &rNode)
+ {
+ String sRet;
+ const SwNode* pEndNd = rNode.EndOfSectionNode();
+ SwNodeIndex aIdx( rNode );
+ while (&aIdx.GetNode() != pEndNd)
+ {
+ if (aIdx.GetNode().IsTxtNode())
+ {
+ if (sRet.Len())
+ {
+ sRet.Append( '\n' );
+ }
+ sRet.Append( aIdx.GetNode().GetTxtNode()->GetExpandTxt() );
+ }
+ aIdx++;
+ }
+ return sRet;
+ }
+}
+
+sal_Bool SwCompareLine::CompareNode( const SwNode& rDstNd, const SwNode& rSrcNd )
+{
+ if( rSrcNd.GetNodeType() != rDstNd.GetNodeType() )
+ return sal_False;
+
+ sal_Bool bRet = sal_False;
+
+ switch( rDstNd.GetNodeType() )
+ {
+ case ND_TEXTNODE:
+ bRet = CompareTxtNd( (SwTxtNode&)rDstNd, (SwTxtNode&)rSrcNd );
+ break;
+
+ case ND_TABLENODE:
+ {
+ const SwTableNode& rTSrcNd = (SwTableNode&)rSrcNd;
+ const SwTableNode& rTDstNd = (SwTableNode&)rDstNd;
+
+ bRet = ( rTSrcNd.EndOfSectionIndex() - rTSrcNd.GetIndex() ) ==
+ ( rTDstNd.EndOfSectionIndex() - rTDstNd.GetIndex() );
+
+ // --> #i107826#: compare actual table content
+ if (bRet)
+ {
+ bRet = (SimpleTableToText(rSrcNd) == SimpleTableToText(rDstNd));
+ }
+ // <--
+ }
+ break;
+
+ case ND_SECTIONNODE:
+ {
+ const SwSectionNode& rSSrcNd = (SwSectionNode&)rSrcNd,
+ & rSDstNd = (SwSectionNode&)rDstNd;
+ const SwSection& rSrcSect = rSSrcNd.GetSection(),
+ & rDstSect = rSDstNd.GetSection();
+ SectionType eSrcSectType = rSrcSect.GetType(),
+ eDstSectType = rDstSect.GetType();
+ switch( eSrcSectType )
+ {
+ case CONTENT_SECTION:
+ bRet = CONTENT_SECTION == eDstSectType &&
+ rSrcSect.IsProtect() == rDstSect.IsProtect();
+ if( bRet && rSrcSect.IsProtect() )
+ {
+ // the only have they both the same size
+ bRet = ( rSSrcNd.EndOfSectionIndex() - rSSrcNd.GetIndex() ) ==
+ ( rSDstNd.EndOfSectionIndex() - rSDstNd.GetIndex() );
+ }
+ break;
+
+ case TOX_HEADER_SECTION:
+ case TOX_CONTENT_SECTION:
+ if( TOX_HEADER_SECTION == eDstSectType ||
+ TOX_CONTENT_SECTION == eDstSectType )
+ {
+ // the same type of TOX?
+ const SwTOXBase* pSrcTOX = rSrcSect.GetTOXBase();
+ const SwTOXBase* pDstTOX = rDstSect.GetTOXBase();
+ bRet = pSrcTOX && pDstTOX
+ && pSrcTOX->GetType() == pDstTOX->GetType()
+ && pSrcTOX->GetTitle() == pDstTOX->GetTitle()
+ && pSrcTOX->GetTypeName() == pDstTOX->GetTypeName()
+// && pSrcTOX->GetTOXName() == pDstTOX->GetTOXName()
+ ;
+ }
+ break;
+
+ case DDE_LINK_SECTION:
+ case FILE_LINK_SECTION:
+ bRet = eSrcSectType == eDstSectType &&
+ rSrcSect.GetLinkFileName() ==
+ rDstSect.GetLinkFileName();
+ break;
+ }
+ }
+ break;
+
+ case ND_ENDNODE:
+ bRet = rSrcNd.StartOfSectionNode()->GetNodeType() ==
+ rDstNd.StartOfSectionNode()->GetNodeType();
+
+ // --> #i107826#: compare actual table content
+ if (bRet && rSrcNd.StartOfSectionNode()->GetNodeType() == ND_TABLENODE)
+ {
+ bRet = CompareNode(
+ *rSrcNd.StartOfSectionNode(), *rDstNd.StartOfSectionNode());
+ }
+ // <--
+
+ break;
+ }
+ return bRet;
+}
+
+String SwCompareLine::GetText() const
+{
+ String sRet;
+ switch( rNode.GetNodeType() )
+ {
+ case ND_TEXTNODE:
+ sRet = ((SwTxtNode&)rNode).GetExpandTxt();
+ break;
+
+ case ND_TABLENODE:
+ {
+ sRet = SimpleTableToText(rNode);
+ sRet.InsertAscii( "Tabelle: ", 0 );
+ }
+ break;
+
+ case ND_SECTIONNODE:
+ {
+ sRet.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "Section - Node:" ));
+
+ const SwSectionNode& rSNd = (SwSectionNode&)rNode;
+ const SwSection& rSect = rSNd.GetSection();
+ switch( rSect.GetType() )
+ {
+ case CONTENT_SECTION:
+ if( rSect.IsProtect() )
+ sRet.Append( String::CreateFromInt32(
+ rSNd.EndOfSectionIndex() - rSNd.GetIndex() ));
+ break;
+
+ case TOX_HEADER_SECTION:
+ case TOX_CONTENT_SECTION:
+ {
+ const SwTOXBase* pTOX = rSect.GetTOXBase();
+ if( pTOX )
+ sRet.Append( pTOX->GetTitle() )
+ .Append( pTOX->GetTypeName() )
+// .Append( pTOX->GetTOXName() )
+ .Append( String::CreateFromInt32( pTOX->GetType() ));
+ }
+ break;
+
+ case DDE_LINK_SECTION:
+ case FILE_LINK_SECTION:
+ sRet += rSect.GetLinkFileName();
+ break;
+ }
+ }
+ break;
+
+ case ND_GRFNODE:
+ sRet.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "Grafik - Node:" ));
+ break;
+ case ND_OLENODE:
+ sRet.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "OLE - Node:" ));
+ break;
+ }
+ return sRet;
+}
+
+sal_uLong SwCompareLine::GetTxtNodeHashValue( const SwTxtNode& rNd, sal_uLong nVal )
+{
+ String sStr( rNd.GetExpandTxt() );
+ for( xub_StrLen n = 0; n < sStr.Len(); ++n )
+ ( nVal <<= 1 ) += sStr.GetChar( n );
+ return nVal;
+}
+
+sal_Bool SwCompareLine::CompareTxtNd( const SwTxtNode& rDstNd,
+ const SwTxtNode& rSrcNd )
+{
+ sal_Bool bRet = sal_False;
+ // erstmal ganz einfach!
+ if( rDstNd.GetTxt() == rSrcNd.GetTxt() )
+ {
+ // der Text ist gleich, aber sind die "Sonderattribute" (0xFF) auch
+ // dieselben??
+ bRet = sal_True;
+ }
+ return bRet;
+}
+
+sal_Bool SwCompareLine::ChangesInLine( const SwCompareLine& rLine,
+ SwPaM *& rpInsRing, SwPaM*& rpDelRing ) const
+{
+ sal_Bool bRet = sal_False;
+ if( ND_TEXTNODE == rNode.GetNodeType() &&
+ ND_TEXTNODE == rLine.GetNode().GetNodeType() )
+ {
+ SwTxtNode& rDestNd = *(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 )
+ {
+ --nDEnd, --nSEnd;
+ if( rDestNd.GetTxt().GetChar( nDEnd ) !=
+ rSrcNd.GetTxt().GetChar( nSEnd ) )
+ {
+ ++nDEnd, ++nSEnd;
+ break;
+ }
+ }
+
+ if( nStt || !nDEnd || !nSEnd || nDEnd < rDestNd.GetTxt().Len() ||
+ nSEnd < rSrcNd.GetTxt().Len() )
+ {
+ // 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 )
+ {
+ SwPaM* pTmp = new SwPaM( *aPam.GetPoint(), rpInsRing );
+ if( !rpInsRing )
+ rpInsRing = pTmp;
+
+ pTmp->SetMark();
+ pTmp->GetMark()->nContent = nStt;
+ }
+
+ if( nStt != nSEnd )
+ {
+ {
+ ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
+ SwPaM aCpyPam( rSrcNd, nStt );
+ aCpyPam.SetMark();
+ aCpyPam.GetPoint()->nContent = nSEnd;
+ aCpyPam.GetDoc()->CopyRange( aCpyPam, *aPam.GetPoint(),
+ false );
+ }
+
+ SwPaM* pTmp = new SwPaM( *aPam.GetPoint(), rpDelRing );
+ if( !rpDelRing )
+ rpDelRing = pTmp;
+
+ pTmp->SetMark();
+ pTmp->GetMark()->nContent = nDEnd;
+
+ if( rpInsRing )
+ {
+ SwPaM* pCorr = (SwPaM*)rpInsRing->GetPrev();
+ if( *pCorr->GetPoint() == *pTmp->GetPoint() )
+ *pCorr->GetPoint() = *pTmp->GetMark();
+ }
+ }
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+// ----------------------------------------------------------------
+
+SwCompareData::~SwCompareData()
+{
+ if( pDelRing )
+ {
+ while( pDelRing->GetNext() != pDelRing )
+ delete pDelRing->GetNext();
+ delete pDelRing;
+ }
+ if( pInsRing )
+ {
+ while( pInsRing->GetNext() != pInsRing )
+ delete pInsRing->GetNext();
+ delete pInsRing;
+ }
+}
+
+sal_uLong SwCompareData::NextIdx( const SwNode* pNd )
+{
+ if( pNd->IsStartNode() )
+ {
+ const SwSectionNode* pSNd;
+ if( pNd->IsTableNode() ||
+ ( 0 != (pSNd = pNd->GetSectionNode() ) &&
+ ( CONTENT_SECTION != pSNd->GetSection().GetType() ||
+ pSNd->GetSection().IsProtect() ) ) )
+ pNd = pNd->EndOfSectionNode();
+ }
+ return pNd->GetIndex() + 1;
+}
+
+sal_uLong SwCompareData::PrevIdx( const SwNode* pNd )
+{
+ if( pNd->IsEndNode() )
+ {
+ const SwSectionNode* pSNd;
+ if( pNd->StartOfSectionNode()->IsTableNode() ||
+ ( 0 != (pSNd = pNd->StartOfSectionNode()->GetSectionNode() ) &&
+ ( CONTENT_SECTION != pSNd->GetSection().GetType() ||
+ pSNd->GetSection().IsProtect() ) ) )
+ pNd = pNd->StartOfSectionNode();
+ }
+ return pNd->GetIndex() - 1;
+}
+
+
+void SwCompareData::CheckRanges( CompareData& rData )
+{
+ const SwNodes& rSrcNds = ((SwCompareData&)rData).rDoc.GetNodes();
+ const SwNodes& rDstNds = rDoc.GetNodes();
+
+ const SwNode& rSrcEndNd = rSrcNds.GetEndOfContent();
+ const SwNode& rDstEndNd = rDstNds.GetEndOfContent();
+
+ sal_uLong nSrcSttIdx = NextIdx( rSrcEndNd.StartOfSectionNode() );
+ sal_uLong nSrcEndIdx = rSrcEndNd.GetIndex();
+
+ sal_uLong nDstSttIdx = NextIdx( rDstEndNd.StartOfSectionNode() );
+ sal_uLong nDstEndIdx = rDstEndNd.GetIndex();
+
+ while( nSrcSttIdx < nSrcEndIdx && nDstSttIdx < nDstEndIdx )
+ {
+ const SwNode* pSrcNd = rSrcNds[ nSrcSttIdx ];
+ const SwNode* pDstNd = rDstNds[ nDstSttIdx ];
+ if( !SwCompareLine::CompareNode( *pSrcNd, *pDstNd ))
+ break;
+
+ nSrcSttIdx = NextIdx( pSrcNd );
+ nDstSttIdx = NextIdx( pDstNd );
+ }
+
+ nSrcEndIdx = PrevIdx( &rSrcEndNd );
+ nDstEndIdx = PrevIdx( &rDstEndNd );
+ while( nSrcSttIdx < nSrcEndIdx && nDstSttIdx < nDstEndIdx )
+ {
+ const SwNode* pSrcNd = rSrcNds[ nSrcEndIdx ];
+ const SwNode* pDstNd = rDstNds[ nDstEndIdx ];
+ if( !SwCompareLine::CompareNode( *pSrcNd, *pDstNd ))
+ break;
+
+ nSrcEndIdx = PrevIdx( pSrcNd );
+ nDstEndIdx = PrevIdx( pDstNd );
+ }
+
+ while( nSrcSttIdx <= nSrcEndIdx )
+ {
+ const SwNode* pNd = rSrcNds[ nSrcSttIdx ];
+ rData.InsertLine( new SwCompareLine( *pNd ) );
+ nSrcSttIdx = NextIdx( pNd );
+ }
+
+ while( nDstSttIdx <= nDstEndIdx )
+ {
+ const SwNode* pNd = rDstNds[ nDstSttIdx ];
+ InsertLine( new SwCompareLine( *pNd ) );
+ nDstSttIdx = NextIdx( pNd );
+ }
+}
+
+
+void SwCompareData::ShowInsert( sal_uLong nStt, sal_uLong nEnd )
+{
+ SwPaM* pTmp = new SwPaM( ((SwCompareLine*)GetLine( nStt ))->GetNode(), 0,
+ ((SwCompareLine*)GetLine( nEnd-1 ))->GetEndNode(), 0,
+ pInsRing );
+ if( !pInsRing )
+ pInsRing = pTmp;
+
+ // #i65201#: These SwPaMs are calculated smaller than needed, see comment below
+
+}
+
+void SwCompareData::ShowDelete( const CompareData& rData, sal_uLong nStt,
+ sal_uLong nEnd, sal_uLong nInsPos )
+{
+ SwNodeRange aRg(
+ ((SwCompareLine*)rData.GetLine( nStt ))->GetNode(), 0,
+ ((SwCompareLine*)rData.GetLine( nEnd-1 ))->GetEndNode(), 1 );
+
+ sal_uInt16 nOffset = 0;
+ const CompareLine* pLine;
+ if( GetLineCount() == nInsPos )
+ {
+ pLine = GetLine( nInsPos-1 );
+ nOffset = 1;
+ }
+ else
+ pLine = GetLine( nInsPos );
+
+ const SwNode* pLineNd;
+ if( pLine )
+ {
+ if( nOffset )
+ pLineNd = &((SwCompareLine*)pLine)->GetEndNode();
+ else
+ pLineNd = &((SwCompareLine*)pLine)->GetNode();
+ }
+ else
+ {
+ pLineNd = &rDoc.GetNodes().GetEndOfContent();
+ nOffset = 0;
+ }
+
+ SwNodeIndex aInsPos( *pLineNd, nOffset );
+ SwNodeIndex aSavePos( aInsPos, -1 );
+
+ ((SwCompareData&)rData).rDoc.CopyWithFlyInFly( aRg, 0, aInsPos );
+ rDoc.SetModified();
+ aSavePos++;
+
+ // #i65201#: These SwPaMs are calculated when the (old) delete-redlines are hidden,
+ // they will be inserted when the delete-redlines are shown again.
+ // To avoid unwanted insertions of delete-redlines into these new redlines, what happens
+ // especially at the end of the document, I reduce the SwPaM by one node.
+ // Before the new redlines are inserted, they have to expand again.
+ SwPaM* pTmp = new SwPaM( aSavePos.GetNode(), aInsPos.GetNode(), 0, -1, pDelRing );
+ if( !pDelRing )
+ pDelRing = pTmp;
+
+ if( pInsRing )
+ {
+ SwPaM* pCorr = (SwPaM*)pInsRing->GetPrev();
+ if( *pCorr->GetPoint() == *pTmp->GetPoint() )
+ {
+ SwNodeIndex aTmpPos( pTmp->GetMark()->nNode, -1 );
+ *pCorr->GetPoint() = SwPosition( aTmpPos );
+ }
+ }
+}
+
+void SwCompareData::CheckForChangesInLine( const CompareData& rData,
+ sal_uLong& rStt, sal_uLong& rEnd,
+ sal_uLong& rThisStt, sal_uLong& rThisEnd )
+{
+ while( rStt < rEnd && rThisStt < rThisEnd )
+ {
+ SwCompareLine* pDstLn = (SwCompareLine*)GetLine( rThisStt );
+ SwCompareLine* pSrcLn = (SwCompareLine*)rData.GetLine( rStt );
+ if( !pDstLn->ChangesInLine( *pSrcLn, pInsRing, pDelRing ) )
+ break;
+
+ ++rStt;
+ ++rThisStt;
+ }
+}
+
+void SwCompareData::SetRedlinesToDoc( sal_Bool bUseDocInfo )
+{
+ SwPaM* pTmp = pDelRing;
+
+ // Bug #83296#: get the Author / TimeStamp from the "other"
+ // document info
+ sal_uInt16 nAuthor = rDoc.GetRedlineAuthor();
+ DateTime aTimeStamp;
+ SwDocShell *pDocShell(rDoc.GetDocShell());
+ DBG_ASSERT(pDocShell, "no SwDocShell");
+ if (pDocShell) {
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ pDocShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties());
+ DBG_ASSERT(xDocProps.is(), "Doc has no DocumentProperties");
+
+ if( bUseDocInfo && xDocProps.is() ) {
+ String aTmp( 1 == xDocProps->getEditingCycles()
+ ? xDocProps->getAuthor()
+ : xDocProps->getModifiedBy() );
+ util::DateTime uDT( 1 == xDocProps->getEditingCycles()
+ ? xDocProps->getCreationDate()
+ : xDocProps->getModificationDate() );
+ Date d(uDT.Day, uDT.Month, uDT.Year);
+ Time t(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
+ DateTime aDT(d,t);
+
+ if( aTmp.Len() )
+ {
+ nAuthor = rDoc.InsertRedlineAuthor( aTmp );
+ aTimeStamp = aDT;
+ }
+ }
+ }
+
+ if( pTmp )
+ {
+ SwRedlineData aRedlnData( nsRedlineType_t::REDLINE_DELETE, nAuthor, aTimeStamp,
+ aEmptyStr, 0, 0 );
+ do {
+ // #i65201#: Expand again, see comment above.
+ if( pTmp->GetPoint()->nContent == 0 )
+ {
+ pTmp->GetPoint()->nNode++;
+ pTmp->GetPoint()->nContent.Assign( pTmp->GetCntntNode(), 0 );
+ }
+ // --> mst 2010-05-17 #i101009#
+ // prevent redlines that end on structural end node
+ if (& rDoc.GetNodes().GetEndOfContent() ==
+ & pTmp->GetPoint()->nNode.GetNode())
+ {
+ pTmp->GetPoint()->nNode--;
+ SwCntntNode *const pContentNode( pTmp->GetCntntNode() );
+ pTmp->GetPoint()->nContent.Assign( pContentNode,
+ (pContentNode) ? pContentNode->Len() : 0 );
+ }
+ // <--
+
+ rDoc.DeleteRedline( *pTmp, false, USHRT_MAX );
+
+ if (rDoc.GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo(new SwUndoCompDoc( *pTmp, sal_False )) ;
+ rDoc.GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ rDoc.AppendRedline( new SwRedline( aRedlnData, *pTmp ), true );
+
+ } while( pDelRing != ( pTmp = (SwPaM*)pTmp->GetNext() ));
+ }
+
+ pTmp = pInsRing;
+ if( pTmp )
+ {
+ do {
+ if( pTmp->GetPoint()->nContent == 0 )
+ {
+ pTmp->GetPoint()->nNode++;
+ pTmp->GetPoint()->nContent.Assign( pTmp->GetCntntNode(), 0 );
+ }
+ // --> mst 2010-05-17 #i101009#
+ // prevent redlines that end on structural end node
+ if (& rDoc.GetNodes().GetEndOfContent() ==
+ & pTmp->GetPoint()->nNode.GetNode())
+ {
+ pTmp->GetPoint()->nNode--;
+ SwCntntNode *const pContentNode( pTmp->GetCntntNode() );
+ pTmp->GetPoint()->nContent.Assign( pContentNode,
+ (pContentNode) ? pContentNode->Len() : 0 );
+ }
+ // <--
+ } while( pInsRing != ( pTmp = (SwPaM*)pTmp->GetNext() ));
+ SwRedlineData aRedlnData( nsRedlineType_t::REDLINE_INSERT, nAuthor, aTimeStamp,
+ aEmptyStr, 0, 0 );
+
+ // zusammenhaengende zusammenfassen
+ if( pTmp->GetNext() != pInsRing )
+ {
+ const SwCntntNode* pCNd;
+ do {
+ SwPosition& rSttEnd = *pTmp->End(),
+ & rEndStt = *((SwPaM*)pTmp->GetNext())->Start();
+ if( rSttEnd == rEndStt ||
+ (!rEndStt.nContent.GetIndex() &&
+ rEndStt.nNode.GetIndex() - 1 == rSttEnd.nNode.GetIndex() &&
+ 0 != ( pCNd = rSttEnd.nNode.GetNode().GetCntntNode() )
+ ? rSttEnd.nContent.GetIndex() == pCNd->Len()
+ : 0 ))
+ {
+ if( pTmp->GetNext() == pInsRing )
+ {
+ // liegen hintereinander also zusammen fassen
+ rEndStt = *pTmp->Start();
+ delete pTmp;
+ pTmp = pInsRing;
+ }
+ else
+ {
+ // liegen hintereinander also zusammen fassen
+ rSttEnd = *((SwPaM*)pTmp->GetNext())->End();
+ delete pTmp->GetNext();
+ }
+ }
+ else
+ pTmp = (SwPaM*)pTmp->GetNext();
+ } while( pInsRing != pTmp );
+ }
+
+ do {
+ if( rDoc.AppendRedline( new SwRedline( aRedlnData, *pTmp ), true) &&
+ rDoc.GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo(new SwUndoCompDoc( *pTmp, sal_True ));
+ rDoc.GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ } while( pInsRing != ( pTmp = (SwPaM*)pTmp->GetNext() ));
+ }
+}
+
+/* */
+
+
+
+ // returnt (?die Anzahl der Unterschiede?) ob etwas unterschiedlich ist
+long SwDoc::CompareDoc( const SwDoc& rDoc )
+{
+ if( &rDoc == this )
+ return 0;
+
+ long nRet = 0;
+
+ GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+ sal_Bool bDocWasModified = IsModified();
+ SwDoc& rSrcDoc = (SwDoc&)rDoc;
+ sal_Bool bSrcModified = rSrcDoc.IsModified();
+
+ RedlineMode_t eSrcRedlMode = rSrcDoc.GetRedlineMode();
+ rSrcDoc.SetRedlineMode( nsRedlineMode_t::REDLINE_SHOW_INSERT );
+ SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT));
+
+ SwCompareData aD0( rSrcDoc );
+ SwCompareData aD1( *this );
+
+ aD1.CompareLines( aD0 );
+
+ nRet = aD1.ShowDiffs( aD0 );
+
+ if( nRet )
+ {
+ SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_ON |
+ nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE));
+
+ aD1.SetRedlinesToDoc( !bDocWasModified );
+ SetModified();
+ }
+
+ rSrcDoc.SetRedlineMode( eSrcRedlMode );
+ SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE));
+
+ if( !bSrcModified )
+ rSrcDoc.ResetModified();
+
+ GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+
+ return nRet;
+}
+
+
+class _SaveMergeRedlines : public Ring
+{
+ const SwRedline* pSrcRedl;
+ SwRedline* pDestRedl;
+public:
+ _SaveMergeRedlines( const SwNode& rDstNd,
+ const SwRedline& rSrcRedl, Ring* pRing );
+ sal_uInt16 InsertRedline();
+
+ SwRedline* GetDestRedline() { return pDestRedl; }
+};
+
+_SaveMergeRedlines::_SaveMergeRedlines( const SwNode& rDstNd,
+ const SwRedline& rSrcRedl, Ring* pRing )
+ : Ring( pRing ), pSrcRedl( &rSrcRedl )
+{
+ SwPosition aPos( rDstNd );
+
+ const SwPosition* pStt = rSrcRedl.Start();
+ if( rDstNd.IsCntntNode() )
+ aPos.nContent.Assign( ((SwCntntNode*)&rDstNd), pStt->nContent.GetIndex() );
+ pDestRedl = new SwRedline( rSrcRedl.GetRedlineData(), aPos );
+
+ if( nsRedlineType_t::REDLINE_DELETE == pDestRedl->GetType() )
+ {
+ // den Bereich als geloescht kennzeichnen
+ const SwPosition* pEnd = pStt == rSrcRedl.GetPoint()
+ ? rSrcRedl.GetMark()
+ : rSrcRedl.GetPoint();
+
+ pDestRedl->SetMark();
+ pDestRedl->GetPoint()->nNode += pEnd->nNode.GetIndex() -
+ pStt->nNode.GetIndex();
+ pDestRedl->GetPoint()->nContent.Assign( pDestRedl->GetCntntNode(),
+ pEnd->nContent.GetIndex() );
+ }
+}
+
+sal_uInt16 _SaveMergeRedlines::InsertRedline()
+{
+ sal_uInt16 nIns = 0;
+ SwDoc* pDoc = pDestRedl->GetDoc();
+
+ if( nsRedlineType_t::REDLINE_INSERT == pDestRedl->GetType() )
+ {
+ // der Teil wurde eingefuegt, also kopiere ihn aus dem SourceDoc
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ SwNodeIndex aSaveNd( pDestRedl->GetPoint()->nNode, -1 );
+ xub_StrLen nSaveCnt = pDestRedl->GetPoint()->nContent.GetIndex();
+
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
+
+ pSrcRedl->GetDoc()->CopyRange(
+ *const_cast<SwPaM*>(static_cast<const SwPaM*>(pSrcRedl)),
+ *pDestRedl->GetPoint(), false );
+
+ pDoc->SetRedlineMode_intern( eOld );
+
+ pDestRedl->SetMark();
+ aSaveNd++;
+ pDestRedl->GetMark()->nNode = aSaveNd;
+ pDestRedl->GetMark()->nContent.Assign( aSaveNd.GetNode().GetCntntNode(),
+ nSaveCnt );
+
+ if( GetPrev() != this )
+ {
+ SwPaM* pTmpPrev = ((_SaveMergeRedlines*)GetPrev())->pDestRedl;
+ if( pTmpPrev && *pTmpPrev->GetPoint() == *pDestRedl->GetPoint() )
+ *pTmpPrev->GetPoint() = *pDestRedl->GetMark();
+ }
+ }
+ else
+ {
+ //JP 21.09.98: Bug 55909
+ // falls im Doc auf gleicher Pos aber schon ein geloeschter oder
+ // eingefuegter ist, dann muss dieser gesplittet werden!
+ SwPosition* pDStt = pDestRedl->GetMark(),
+ * pDEnd = pDestRedl->GetPoint();
+ sal_uInt16 n = 0;
+
+ // zur StartPos das erste Redline suchen
+ if( !pDoc->GetRedline( *pDStt, &n ) && n )
+ --n;
+
+ const SwRedlineTbl& rRedlineTbl = pDoc->GetRedlineTbl();
+ for( ; n < rRedlineTbl.Count(); ++n )
+ {
+ SwRedline* pRedl = rRedlineTbl[ n ];
+ SwPosition* pRStt = pRedl->Start(),
+ * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark()
+ : pRedl->GetPoint();
+ if( nsRedlineType_t::REDLINE_DELETE == pRedl->GetType() ||
+ nsRedlineType_t::REDLINE_INSERT == pRedl->GetType() )
+ {
+ SwComparePosition eCmpPos = ComparePosition( *pDStt, *pDEnd, *pRStt, *pREnd );
+ switch( eCmpPos )
+ {
+ case POS_COLLIDE_START:
+ case POS_BEHIND:
+ break;
+
+ case POS_INSIDE:
+ case POS_EQUAL:
+ delete pDestRedl, pDestRedl = 0;
+ // break; -> kein break !!!!
+
+ case POS_COLLIDE_END:
+ case POS_BEFORE:
+ n = rRedlineTbl.Count();
+ break;
+
+ case POS_OUTSIDE:
+ {
+ SwRedline* pCpyRedl = new SwRedline(
+ pDestRedl->GetRedlineData(), *pDStt );
+ pCpyRedl->SetMark();
+ *pCpyRedl->GetPoint() = *pRStt;
+
+ SwUndoCompDoc *const pUndo =
+ (pDoc->GetIDocumentUndoRedo().DoesUndo())
+ ? new SwUndoCompDoc( *pCpyRedl ) : 0;
+
+ // now modify doc: append redline, undo (and count)
+ pDoc->AppendRedline( pCpyRedl, true );
+ if( pUndo )
+ {
+ pDoc->GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ ++nIns;
+
+ *pDStt = *pREnd;
+
+ // dann solle man neu anfangen
+ n = USHRT_MAX;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ *pDEnd = *pRStt;
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ *pDStt = *pREnd;
+ break;
+ }
+ }
+ else if( *pDEnd <= *pRStt )
+ break;
+ }
+
+ }
+
+ if( pDestRedl )
+ {
+ SwUndoCompDoc *const pUndo = (pDoc->GetIDocumentUndoRedo().DoesUndo())
+ ? new SwUndoCompDoc( *pDestRedl ) : 0;
+
+ // now modify doc: append redline, undo (and count)
+ bool bRedlineAccepted = pDoc->AppendRedline( pDestRedl, true );
+ if( pUndo )
+ {
+ pDoc->GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ ++nIns;
+
+ // if AppendRedline has deleted our redline, we may not keep a
+ // reference to it
+ if( ! bRedlineAccepted )
+ pDestRedl = NULL;
+ }
+ return nIns;
+}
+
+// merge zweier Dokumente
+long SwDoc::MergeDoc( const SwDoc& rDoc )
+{
+ if( &rDoc == this )
+ return 0;
+
+ long nRet = 0;
+
+ GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+
+ SwDoc& rSrcDoc = (SwDoc&)rDoc;
+ sal_Bool bSrcModified = rSrcDoc.IsModified();
+
+ RedlineMode_t eSrcRedlMode = rSrcDoc.GetRedlineMode();
+ rSrcDoc.SetRedlineMode( nsRedlineMode_t::REDLINE_SHOW_DELETE );
+ SetRedlineMode( nsRedlineMode_t::REDLINE_SHOW_DELETE );
+
+ SwCompareData aD0( rSrcDoc );
+ SwCompareData aD1( *this );
+
+ aD1.CompareLines( aD0 );
+
+ if( !aD1.HasDiffs( aD0 ) )
+ {
+ // jetzt wollen wir alle Redlines aus dem SourceDoc zu uns bekommen
+
+ // suche alle Insert - Redlines aus dem SourceDoc und bestimme
+ // deren Position im DestDoc
+ _SaveMergeRedlines* pRing = 0;
+ const SwRedlineTbl& rSrcRedlTbl = rSrcDoc.GetRedlineTbl();
+ sal_uLong nEndOfExtra = rSrcDoc.GetNodes().GetEndOfExtras().GetIndex();
+ sal_uLong nMyEndOfExtra = GetNodes().GetEndOfExtras().GetIndex();
+ for( sal_uInt16 n = 0; n < rSrcRedlTbl.Count(); ++n )
+ {
+ const SwRedline* pRedl = rSrcRedlTbl[ n ];
+ sal_uLong nNd = pRedl->GetPoint()->nNode.GetIndex();
+ RedlineType_t eType = pRedl->GetType();
+ if( nEndOfExtra < nNd &&
+ ( nsRedlineType_t::REDLINE_INSERT == eType || nsRedlineType_t::REDLINE_DELETE == eType ))
+ {
+ const SwNode* pDstNd = GetNodes()[
+ nMyEndOfExtra + nNd - nEndOfExtra ];
+
+ // Position gefunden. Dann muss im DestDoc auch
+ // in der Line das Redline eingefuegt werden
+ _SaveMergeRedlines* pTmp = new _SaveMergeRedlines(
+ *pDstNd, *pRedl, pRing );
+ if( !pRing )
+ pRing = pTmp;
+ }
+ }
+
+ if( pRing )
+ {
+ // dann alle ins DestDoc ueber nehmen
+ rSrcDoc.SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE));
+
+ SetRedlineMode((RedlineMode_t)(
+ nsRedlineMode_t::REDLINE_ON |
+ nsRedlineMode_t::REDLINE_SHOW_INSERT |
+ nsRedlineMode_t::REDLINE_SHOW_DELETE));
+
+ _SaveMergeRedlines* pTmp = pRing;
+
+ do {
+ nRet += pTmp->InsertRedline();
+ } while( pRing != ( pTmp = (_SaveMergeRedlines*)pTmp->GetNext() ));
+
+ while( pRing != pRing->GetNext() )
+ delete pRing->GetNext();
+ delete pRing;
+ }
+ }
+
+ rSrcDoc.SetRedlineMode( eSrcRedlMode );
+ if( !bSrcModified )
+ rSrcDoc.ResetModified();
+
+ SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE));
+
+ GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+
+ return nRet;
+}
+
+
diff --git a/sw/source/core/doc/doccorr.cxx b/sw/source/core/doc/doccorr.cxx
new file mode 100644
index 000000000000..3477619fba33
--- /dev/null
+++ b/sw/source/core/doc/doccorr.cxx
@@ -0,0 +1,360 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <doc.hxx>
+#include <node.hxx>
+#include <rootfrm.hxx>
+#include <editsh.hxx>
+#include <viscrs.hxx>
+#include <IMark.hxx>
+#include <bookmrk.hxx>
+#include <redline.hxx>
+#include <mvsave.hxx>
+#include <docary.hxx>
+#include <unocrsr.hxx>
+#include <swundo.hxx>
+#include <hints.hxx>
+
+/* */
+
+/*
+ * MACROS um ueber alle CrsrShells zu iterieren
+ */
+#define PCURSH ((SwCrsrShell*)_pStartShell)
+#define FOREACHSHELL_START( pEShell ) \
+ {\
+ ViewShell *_pStartShell = pEShell; \
+ do { \
+ if( _pStartShell->IsA( TYPE( SwCrsrShell )) ) \
+ {
+
+#define FOREACHSHELL_END( pEShell ) \
+ } \
+ } while((_pStartShell=(ViewShell*)_pStartShell->GetNext())!= pEShell ); \
+ }
+
+#define PCURCRSR (_pCurrCrsr)
+#define FOREACHPAM_START(pSttCrsr) \
+ {\
+ SwPaM *_pStartCrsr = pSttCrsr, *_pCurrCrsr = pSttCrsr; \
+ do {
+
+#define FOREACHPAM_END() \
+ } while( (_pCurrCrsr=(SwPaM *)_pCurrCrsr->GetNext()) != _pStartCrsr ); \
+ }
+
+namespace
+{
+ // find the relevant section in which the SwUnoCrsr may wander.
+ // returns NULL if no restrictions apply
+ static const SwStartNode* lcl_FindUnoCrsrSection( const SwNode& rNode )
+ {
+ const SwStartNode* pStartNode = rNode.StartOfSectionNode();
+ while( ( pStartNode != NULL ) &&
+ ( pStartNode->StartOfSectionNode() != pStartNode ) &&
+ ( pStartNode->GetStartNodeType() == SwNormalStartNode ) )
+ pStartNode = pStartNode->StartOfSectionNode();
+
+ return pStartNode;
+ }
+
+ static inline bool lcl_PosCorrAbs(SwPosition & rPos,
+ const SwPosition& rStart,
+ const SwPosition& rEnd,
+ const SwPosition& rNewPos)
+ {
+ if ((rStart <= rPos) && (rPos <= rEnd))
+ {
+ rPos = rNewPos;
+ return true;
+ }
+ return false;
+ };
+
+ static inline bool lcl_PaMCorrAbs(SwPaM & rPam,
+ const SwPosition& rStart,
+ const SwPosition& rEnd,
+ const SwPosition& rNewPos)
+ {
+ bool bRet = false;
+ bRet |= lcl_PosCorrAbs(rPam.GetBound(true ), rStart, rEnd, rNewPos);
+ bRet |= lcl_PosCorrAbs(rPam.GetBound(false), rStart, rEnd, rNewPos);
+ return bRet;
+ };
+
+ static inline void lcl_PaMCorrRel1(SwPaM * pPam,
+ SwNode const * const pOldNode,
+ const SwPosition& rNewPos,
+ const xub_StrLen nCntIdx)
+ {
+ for(int nb = 0; nb < 2; ++nb)
+ if(&((pPam)->GetBound(sal_Bool(nb)).nNode.GetNode()) == pOldNode)
+ {
+ (pPam)->GetBound(sal_Bool(nb)).nNode = rNewPos.nNode;
+ (pPam)->GetBound(sal_Bool(nb)).nContent.Assign(
+ const_cast<SwIndexReg*>(rNewPos.nContent.GetIdxReg()),
+ nCntIdx + (pPam)->GetBound(sal_Bool(nb)).nContent.GetIndex());
+ }
+ }
+}
+
+
+void PaMCorrAbs( const SwPaM& rRange,
+ const SwPosition& rNewPos )
+{
+ SwPosition const aStart( *rRange.Start() );
+ SwPosition const aEnd( *rRange.End() );
+ SwPosition const aNewPos( rNewPos );
+ SwDoc *const pDoc = aStart.nNode.GetNode().GetDoc();
+ SwCrsrShell *const pShell = pDoc->GetEditShell();
+
+ if( pShell )
+ {
+ FOREACHSHELL_START( pShell )
+ SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
+ if( _pStkCrsr )
+ do {
+ lcl_PaMCorrAbs( *_pStkCrsr, aStart, aEnd, aNewPos );
+ } while ( (_pStkCrsr != 0 ) &&
+ ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
+
+ FOREACHPAM_START( PCURSH->_GetCrsr() )
+ lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
+ FOREACHPAM_END()
+
+ if( PCURSH->IsTableMode() )
+ lcl_PaMCorrAbs( *PCURSH->GetTblCrs(), aStart, aEnd, aNewPos );
+
+ FOREACHSHELL_END( pShell )
+ }
+ {
+ SwUnoCrsrTbl& rTbl = const_cast<SwUnoCrsrTbl&>(pDoc->GetUnoCrsrTbl());
+
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ SwUnoCrsr *const pUnoCursor = rTbl[ n ];
+
+ bool bChange = false; // has the UNO cursor been corrected?
+
+ // determine whether the UNO cursor will leave it's designated
+ // section
+ bool const bLeaveSection =
+ pUnoCursor->IsRemainInSection() &&
+ ( lcl_FindUnoCrsrSection( aNewPos.nNode.GetNode() ) !=
+ lcl_FindUnoCrsrSection(
+ pUnoCursor->GetPoint()->nNode.GetNode() ) );
+
+ FOREACHPAM_START( pUnoCursor )
+ bChange |= lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
+ FOREACHPAM_END()
+
+ SwUnoTableCrsr *const pUnoTblCrsr =
+ dynamic_cast<SwUnoTableCrsr *>(rTbl[ n ]);
+ if( pUnoTblCrsr )
+ {
+ FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
+ bChange |=
+ lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
+ FOREACHPAM_END()
+ }
+
+ // if a UNO cursor leaves its designated section, we must inform
+ // (and invalidate) said cursor
+ if (bChange && bLeaveSection)
+ {
+ // the UNO cursor has left its section. We need to notify it!
+ SwMsgPoolItem aHint( RES_UNOCURSOR_LEAVES_SECTION );
+ pUnoCursor->Modify( &aHint, NULL );
+ }
+ }
+ }
+}
+
+void SwDoc::CorrAbs(const SwNodeIndex& rOldNode,
+ const SwPosition& rNewPos,
+ const xub_StrLen nOffset,
+ sal_Bool bMoveCrsr)
+{
+ SwCntntNode *const pCntntNode( rOldNode.GetNode().GetCntntNode() );
+ SwPaM const aPam(rOldNode, 0,
+ rOldNode, (pCntntNode) ? pCntntNode->Len() : 0);
+ SwPosition aNewPos(rNewPos);
+ aNewPos.nContent += nOffset;
+
+ getIDocumentMarkAccess()->correctMarksAbsolute(rOldNode, rNewPos, nOffset);
+ { // fix redlines
+ SwRedlineTbl& rTbl = *pRedlineTbl;
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ // is on position ??
+ lcl_PaMCorrAbs(*rTbl[ n ], *aPam.Start(), *aPam.End(), aNewPos);
+ }
+ }
+
+ if(bMoveCrsr)
+ {
+ ::PaMCorrAbs(aPam, aNewPos);
+ }
+}
+
+void SwDoc::CorrAbs(const SwPaM& rRange,
+ const SwPosition& rNewPos,
+ sal_Bool bMoveCrsr)
+{
+ SwPosition aStart(*rRange.Start());
+ SwPosition aEnd(*rRange.End());
+ SwPosition aNewPos(rNewPos);
+
+ _DelBookmarks(aStart.nNode, aEnd.nNode, NULL,
+ &aStart.nContent, &aEnd.nContent);
+ if(bMoveCrsr)
+ ::PaMCorrAbs(rRange, rNewPos);
+}
+
+void SwDoc::CorrAbs(const SwNodeIndex& rStartNode,
+ const SwNodeIndex& rEndNode,
+ const SwPosition& rNewPos,
+ sal_Bool bMoveCrsr)
+{
+ _DelBookmarks(rStartNode, rEndNode);
+
+ if(bMoveCrsr)
+ {
+ SwCntntNode *const pCntntNode( rEndNode.GetNode().GetCntntNode() );
+ SwPaM const aPam(rStartNode, 0,
+ rEndNode, (pCntntNode) ? pCntntNode->Len() : 0);
+ ::PaMCorrAbs(aPam, rNewPos);
+ }
+}
+
+
+
+
+
+void PaMCorrRel( const SwNodeIndex &rOldNode,
+ const SwPosition &rNewPos,
+ const xub_StrLen nOffset )
+{
+ const SwNode* pOldNode = &rOldNode.GetNode();
+ SwPosition aNewPos( rNewPos );
+ const SwDoc* pDoc = pOldNode->GetDoc();
+
+ xub_StrLen nCntIdx = rNewPos.nContent.GetIndex() + nOffset;
+
+ SwCrsrShell* pShell = pDoc->GetEditShell();
+ if( pShell )
+ {
+ FOREACHSHELL_START( pShell )
+ SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
+ if( _pStkCrsr )
+ do {
+ lcl_PaMCorrRel1( _pStkCrsr, pOldNode, aNewPos, nCntIdx );
+ } while ( (_pStkCrsr != 0 ) &&
+ ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
+
+ FOREACHPAM_START( PCURSH->_GetCrsr() )
+ lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx);
+ FOREACHPAM_END()
+
+ if( PCURSH->IsTableMode() )
+ lcl_PaMCorrRel1( PCURSH->GetTblCrs(), pOldNode, aNewPos, nCntIdx );
+
+ FOREACHSHELL_END( pShell )
+ }
+ {
+ SwUnoCrsrTbl& rTbl = (SwUnoCrsrTbl&)pDoc->GetUnoCrsrTbl();
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ FOREACHPAM_START( rTbl[ n ] )
+ lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx );
+ FOREACHPAM_END()
+
+ SwUnoTableCrsr* pUnoTblCrsr =
+ dynamic_cast<SwUnoTableCrsr*>(rTbl[ n ]);
+ if( pUnoTblCrsr )
+ {
+ FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
+ lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx );
+ FOREACHPAM_END()
+ }
+ }
+ }
+}
+
+void SwDoc::CorrRel(const SwNodeIndex& rOldNode,
+ const SwPosition& rNewPos,
+ const xub_StrLen nOffset,
+ sal_Bool bMoveCrsr)
+{
+ getIDocumentMarkAccess()->correctMarksRelative(rOldNode, rNewPos, nOffset);
+
+ { // dann die Redlines korrigieren
+ SwRedlineTbl& rTbl = *pRedlineTbl;
+ SwPosition aNewPos(rNewPos);
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ // liegt auf der Position ??
+ lcl_PaMCorrRel1( rTbl[ n ], &rOldNode.GetNode(), aNewPos, aNewPos.nContent.GetIndex() + nOffset );
+ }
+ }
+
+ if(bMoveCrsr)
+ ::PaMCorrRel(rOldNode, rNewPos, nOffset);
+}
+
+
+SwEditShell* SwDoc::GetEditShell( ViewShell** ppSh ) const
+{
+ // Layout und OLE-Shells sollten vorhanden sein!
+ if( pLayout && pLayout->GetCurrShell() )
+ {
+ ViewShell *pSh = pLayout->GetCurrShell(), *pVSh = pSh;
+ if( ppSh )
+ *ppSh = pSh;
+
+ // wir suchen uns eine EditShell, falls diese existiert
+ do {
+ if( pSh->IsA( TYPE( SwEditShell ) ) )
+ return (SwEditShell*)pSh;
+
+ } while( pVSh != ( pSh = (ViewShell*)pSh->GetNext() ));
+ }
+ else if( ppSh )
+ *ppSh = 0;
+
+ return 0;
+}
+
+::sw::IShellCursorSupplier * SwDoc::GetIShellCursorSupplier()
+{
+ return GetEditShell(0);
+}
+
diff --git a/sw/source/core/doc/docdde.cxx b/sw/source/core/doc/docdde.cxx
new file mode 100644
index 000000000000..bef9ea1f254f
--- /dev/null
+++ b/sw/source/core/doc/docdde.cxx
@@ -0,0 +1,418 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#include <stdlib.h>
+
+#ifndef _APP_HXX
+#include <vcl/svapp.hxx>
+#endif
+#include <tools/urlobj.hxx>
+
+#define _SVSTDARR_STRINGS
+#include <svl/svstdarr.hxx>
+#include <sfx2/linkmgr.hxx> // LinkManager
+#include <unotools/charclass.hxx>
+#include <fmtcntnt.hxx>
+#include <doc.hxx>
+#include <swserv.hxx> // fuer Server-Funktionalitaet
+#include <IMark.hxx>
+#include <bookmrk.hxx>
+#include <section.hxx> // fuer SwSectionFmt
+#include <swtable.hxx> // fuer SwTable
+#include <node.hxx>
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <docary.hxx>
+#include <MarkManager.hxx>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+
+ static ::sw::mark::DdeBookmark* lcl_FindDdeBookmark(const IDocumentMarkAccess& rMarkAccess, const String& rName, bool bCaseSensitive)
+ {
+ //Iterating over all bookmarks, checking DdeBookmarks
+ const ::rtl::OUString sNameLc = bCaseSensitive ? rName : GetAppCharClass().lower(rName);
+ for(IDocumentMarkAccess::const_iterator_t ppMark = rMarkAccess.getMarksBegin();
+ ppMark != rMarkAccess.getMarksEnd();
+ ppMark++)
+ {
+ if (::sw::mark::DdeBookmark* const pBkmk = dynamic_cast< ::sw::mark::DdeBookmark*>(ppMark->get()))
+ {
+ if (
+ (bCaseSensitive && (pBkmk->GetName() == sNameLc)) ||
+ (!bCaseSensitive && GetAppCharClass().lower(pBkmk->GetName()) == String(sNameLc))
+ )
+ {
+ return pBkmk;
+ }
+ }
+ }
+ return NULL;
+ }
+}
+
+struct _FindItem
+{
+ const String m_Item;
+ SwTableNode* pTblNd;
+ SwSectionNode* pSectNd;
+
+ _FindItem(const String& rS)
+ : m_Item(rS), pTblNd(0), pSectNd(0)
+ {}
+};
+
+sal_Bool lcl_FindSection( const SwSectionFmtPtr& rpSectFmt, void* pArgs, bool bCaseSensitive )
+{
+ _FindItem * const pItem( static_cast<_FindItem*>(pArgs) );
+ SwSection* pSect = rpSectFmt->GetSection();
+ if( pSect )
+ {
+ String sNm( (bCaseSensitive)
+ ? pSect->GetSectionName()
+ : GetAppCharClass().lower( pSect->GetSectionName() ));
+ String sCompare( (bCaseSensitive)
+ ? pItem->m_Item
+ : GetAppCharClass().lower( pItem->m_Item ) );
+ if( sNm == sCompare )
+ {
+ // gefunden, als erfrage die Daten
+ const SwNodeIndex* pIdx;
+ if( 0 != (pIdx = rpSectFmt->GetCntnt().GetCntntIdx() ) &&
+ &rpSectFmt->GetDoc()->GetNodes() == &pIdx->GetNodes() )
+ {
+ // eine Tabelle im normalen NodesArr
+ pItem->pSectNd = pIdx->GetNode().GetSectionNode();
+ return sal_False;
+ }
+//nein!! // sollte der Namen schon passen, der Rest aber nicht, dann haben wir
+ // sie nicht. Die Namen sind immer eindeutig.
+ }
+ }
+ return sal_True; // dann weiter
+}
+sal_Bool lcl_FindSectionCaseSensitive( const SwSectionFmtPtr& rpSectFmt, void* pArgs )
+{
+ return lcl_FindSection( rpSectFmt, pArgs, true );
+}
+sal_Bool lcl_FindSectionCaseInsensitive( const SwSectionFmtPtr& rpSectFmt, void* pArgs )
+{
+ return lcl_FindSection( rpSectFmt, pArgs, false );
+}
+
+
+
+sal_Bool lcl_FindTable( const SwFrmFmtPtr& rpTableFmt, void* pArgs )
+{
+ _FindItem * const pItem( static_cast<_FindItem*>(pArgs) );
+ String sNm( GetAppCharClass().lower( rpTableFmt->GetName() ));
+ if (sNm.Equals( pItem->m_Item ))
+ {
+ SwTable* pTmpTbl;
+ SwTableBox* pFBox;
+ if( 0 != ( pTmpTbl = SwTable::FindTable( rpTableFmt ) ) &&
+ 0 != ( pFBox = pTmpTbl->GetTabSortBoxes()[0] ) &&
+ pFBox->GetSttNd() &&
+ &rpTableFmt->GetDoc()->GetNodes() == &pFBox->GetSttNd()->GetNodes() )
+ {
+ // eine Tabelle im normalen NodesArr
+ pItem->pTblNd = (SwTableNode*)
+ pFBox->GetSttNd()->FindTableNode();
+ return sal_False;
+ }
+//nein! // sollte der Namen schon passen, der Rest aber nicht, dann haben wir
+ // sie nicht. Die Namen sind immer eindeutig.
+ }
+ return sal_True; // dann weiter
+}
+
+
+
+bool SwDoc::GetData( const String& rItem, const String& rMimeType,
+ uno::Any & rValue ) const
+{
+ //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive
+ bool bCaseSensitive = true;
+ while( true )
+ {
+ ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive);
+ if(pBkmk)
+ return SwServerObject(*pBkmk).GetData(rValue, rMimeType);
+
+ // haben wir ueberhaupt das Item vorraetig?
+ String sItem( bCaseSensitive ? rItem : GetAppCharClass().lower(rItem));
+ _FindItem aPara( sItem );
+ ((SwSectionFmts&)*pSectionFmtTbl).ForEach( 0, pSectionFmtTbl->Count(),
+ bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara );
+ if( aPara.pSectNd )
+ {
+ // gefunden, als erfrage die Daten
+ return SwServerObject( *aPara.pSectNd ).GetData( rValue, rMimeType );
+ }
+ if( !bCaseSensitive )
+ break;
+ bCaseSensitive = false;
+ }
+
+ _FindItem aPara( GetAppCharClass().lower( rItem ));
+ ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach( 0, pTblFrmFmtTbl->Count(),
+ lcl_FindTable, &aPara );
+ if( aPara.pTblNd )
+ {
+ return SwServerObject( *aPara.pTblNd ).GetData( rValue, rMimeType );
+ }
+
+ return sal_False;
+}
+
+
+
+bool SwDoc::SetData( const String& rItem, const String& rMimeType,
+ const uno::Any & rValue )
+{
+ //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive
+ bool bCaseSensitive = true;
+ while( true )
+ {
+ ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive);
+ if(pBkmk)
+ return SwServerObject(*pBkmk).SetData(rMimeType, rValue);
+
+ // haben wir ueberhaupt das Item vorraetig?
+ String sItem( bCaseSensitive ? rItem : GetAppCharClass().lower(rItem));
+ _FindItem aPara( sItem );
+ pSectionFmtTbl->ForEach( 0, pSectionFmtTbl->Count(), bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara );
+ if( aPara.pSectNd )
+ {
+ // gefunden, als erfrage die Daten
+ return SwServerObject( *aPara.pSectNd ).SetData( rMimeType, rValue );
+ }
+ if( !bCaseSensitive )
+ break;
+ bCaseSensitive = false;
+ }
+
+ String sItem(GetAppCharClass().lower(rItem));
+ _FindItem aPara( sItem );
+ pTblFrmFmtTbl->ForEach( 0, pTblFrmFmtTbl->Count(), lcl_FindTable, &aPara );
+ if( aPara.pTblNd )
+ {
+ return SwServerObject( *aPara.pTblNd ).SetData( rMimeType, rValue );
+ }
+
+ return sal_False;
+}
+
+
+
+::sfx2::SvLinkSource* SwDoc::CreateLinkSource(const String& rItem)
+{
+ SwServerObject* pObj = NULL;
+
+ //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive
+ bool bCaseSensitive = true;
+ while( true )
+ {
+ // bookmarks
+ ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive);
+ if(pBkmk && pBkmk->IsExpanded()
+ && (0 == (pObj = pBkmk->GetRefObject())))
+ {
+ // mark found, but no link yet -> create hotlink
+ pObj = new SwServerObject(*pBkmk);
+ pBkmk->SetRefObject(pObj);
+ GetLinkManager().InsertServer(pObj);
+ }
+ if(pObj)
+ return pObj;
+
+ _FindItem aPara(bCaseSensitive ? rItem : GetAppCharClass().lower(rItem));
+ // sections
+ ((SwSectionFmts&)*pSectionFmtTbl).ForEach(0, pSectionFmtTbl->Count(), bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara);
+ if(aPara.pSectNd
+ && (0 == (pObj = aPara.pSectNd->GetSection().GetObject())))
+ {
+ // section found, but no link yet -> create hotlink
+ pObj = new SwServerObject( *aPara.pSectNd );
+ aPara.pSectNd->GetSection().SetRefObject( pObj );
+ GetLinkManager().InsertServer(pObj);
+ }
+ if(pObj)
+ return pObj;
+ if( !bCaseSensitive )
+ break;
+ bCaseSensitive = false;
+ }
+
+ _FindItem aPara( GetAppCharClass().lower(rItem) );
+ // tables
+ ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach(0, pTblFrmFmtTbl->Count(), lcl_FindTable, &aPara);
+ if(aPara.pTblNd
+ && (0 == (pObj = aPara.pTblNd->GetTable().GetObject())))
+ {
+ // table found, but no link yet -> create hotlink
+ pObj = new SwServerObject(*aPara.pTblNd);
+ aPara.pTblNd->GetTable().SetRefObject(pObj);
+ GetLinkManager().InsertServer(pObj);
+ }
+ return pObj;
+}
+
+sal_Bool SwDoc::SelectServerObj( const String& rStr, SwPaM*& rpPam,
+ SwNodeRange*& rpRange ) const
+{
+ // haben wir ueberhaupt das Item vorraetig?
+ rpPam = 0;
+ rpRange = 0;
+
+ String sItem( INetURLObject::decode( rStr, INET_HEX_ESCAPE,
+ INetURLObject::DECODE_WITH_CHARSET,
+ RTL_TEXTENCODING_UTF8 ));
+
+ xub_StrLen nPos = sItem.Search( cMarkSeperator );
+
+ const CharClass& rCC = GetAppCharClass();
+
+ // Erweiterung fuer die Bereiche, nicht nur Bookmarks/Bereiche linken,
+ // sondern auch Rahmen(Text!), Tabellen, Gliederungen:
+ if( STRING_NOTFOUND != nPos )
+ {
+ sal_Bool bWeiter = sal_False;
+ String sName( sItem.Copy( 0, nPos ) );
+ String sCmp( sItem.Copy( nPos + 1 ));
+ rCC.toLower( sItem );
+
+ _FindItem aPara( sName );
+
+ if( sCmp.EqualsAscii( pMarkToTable ) )
+ {
+ rCC.toLower( sName );
+ ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach( 0, pTblFrmFmtTbl->Count(),
+ lcl_FindTable, &aPara );
+ if( aPara.pTblNd )
+ {
+ rpRange = new SwNodeRange( *aPara.pTblNd, 0,
+ *aPara.pTblNd->EndOfSectionNode(), 1 );
+ return sal_True;
+ }
+ }
+ else if( sCmp.EqualsAscii( pMarkToFrame ) )
+ {
+ SwNodeIndex* pIdx;
+ SwNode* pNd;
+ const SwFlyFrmFmt* pFlyFmt = FindFlyByName( sName );
+ if( pFlyFmt &&
+ 0 != ( pIdx = (SwNodeIndex*)pFlyFmt->GetCntnt().GetCntntIdx() ) &&
+ !( pNd = &pIdx->GetNode())->IsNoTxtNode() )
+ {
+ rpRange = new SwNodeRange( *pNd, 1, *pNd->EndOfSectionNode() );
+ return sal_True;
+ }
+ }
+ else if( sCmp.EqualsAscii( pMarkToRegion ) )
+ {
+ sItem = sName; // wird unten behandelt !
+ bWeiter = sal_True;
+ }
+ else if( sCmp.EqualsAscii( pMarkToOutline ) )
+ {
+ SwPosition aPos( SwNodeIndex( (SwNodes&)GetNodes() ));
+ if( GotoOutline( aPos, sName ))
+ {
+ SwNode* pNd = &aPos.nNode.GetNode();
+ //sal_uInt8 nLvl = pNd->GetTxtNode()->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
+ const int nLvl = pNd->GetTxtNode()->GetAttrOutlineLevel()-1;//<-end,zhaojianwei
+
+ const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
+ sal_uInt16 nTmpPos;
+ rOutlNds.Seek_Entry( pNd, &nTmpPos );
+ rpRange = new SwNodeRange( aPos.nNode, 0, aPos.nNode );
+
+ // dann suche jetzt noch das Ende vom Bereich
+ for( ++nTmpPos;
+ nTmpPos < rOutlNds.Count() &&
+ nLvl < rOutlNds[ nTmpPos ]->GetTxtNode()->
+ //GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
+ GetAttrOutlineLevel()-1;//<-end,zhaojianwei
+ ++nTmpPos )
+ ; // es gibt keinen Block
+
+ if( nTmpPos < rOutlNds.Count() )
+ rpRange->aEnd = *rOutlNds[ nTmpPos ];
+ else
+ rpRange->aEnd = GetNodes().GetEndOfContent();
+ return sal_True;
+ }
+ }
+
+ if( !bWeiter )
+ return sal_False;
+ }
+
+ //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive
+ bool bCaseSensitive = true;
+ while( true )
+ {
+ ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, sItem, bCaseSensitive);
+ if(pBkmk)
+ {
+ if(pBkmk->IsExpanded())
+ rpPam = new SwPaM(
+ pBkmk->GetMarkPos(),
+ pBkmk->GetOtherMarkPos());
+ return static_cast<bool>(rpPam);
+ }
+
+ //
+ _FindItem aPara( bCaseSensitive ? sItem : rCC.lower( sItem ) );
+
+ if( pSectionFmtTbl->Count() )
+ {
+ ((SwSectionFmts&)*pSectionFmtTbl).ForEach( 0, pSectionFmtTbl->Count(),
+ bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara );
+ if( aPara.pSectNd )
+ {
+ rpRange = new SwNodeRange( *aPara.pSectNd, 1,
+ *aPara.pSectNd->EndOfSectionNode() );
+ return sal_True;
+
+ }
+ }
+ if( !bCaseSensitive )
+ break;
+ bCaseSensitive = false;
+ }
+ return sal_False;
+}
+
diff --git a/sw/source/core/doc/docdesc.cxx b/sw/source/core/doc/docdesc.cxx
new file mode 100644
index 000000000000..463e15bf6b6e
--- /dev/null
+++ b/sw/source/core/doc/docdesc.cxx
@@ -0,0 +1,1018 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <vcl/virdev.hxx>
+#include <svx/svdmodel.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/paperinf.hxx>
+#include "editeng/frmdiritem.hxx"
+#include <tools/urlobj.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/printer.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <com/sun/star/document/PrinterIndependentLayout.hpp>
+#include <fmtfsize.hxx>
+#include <fmthdft.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtpdsc.hxx>
+#include <ftninfo.hxx>
+#include <fesh.hxx>
+#include <ndole.hxx>
+#include <mdiexp.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <pagefrm.hxx> //Fuer DelPageDesc
+#include <rootfrm.hxx> //Fuer DelPageDesc
+#include <ndtxt.hxx>
+#include <frmtool.hxx>
+#include <pagedesc.hxx>
+#include <poolfmt.hxx>
+#include <docsh.hxx>
+#include <ndindex.hxx>
+#include <ftnidx.hxx>
+#include <fmtftn.hxx>
+#include <txtftn.hxx>
+#include <fntcache.hxx>
+#include <viewsh.hxx>
+#include <viewopt.hxx>
+#include <fldbas.hxx>
+#include <swwait.hxx>
+#include <GetMetricVal.hxx>
+#include <unotools/syslocale.hxx>
+#include <statstr.hrc>
+#include <hints.hxx>
+
+#include <SwUndoPageDesc.hxx>
+
+#include <tgrditem.hxx>
+
+using namespace com::sun::star;
+
+static void lcl_DefaultPageFmt( sal_uInt16 nPoolFmtId,
+ SwFrmFmt &rFmt1,
+ SwFrmFmt &rFmt2 )
+{
+ // --> FME 2005-01-21 #i41075# Printer on demand
+ // This function does not require a printer anymore.
+ // The default page size is obtained from the application
+ //locale
+ // <--
+
+ SwFmtFrmSize aFrmSize( ATT_FIX_SIZE );
+ const Size aPhysSize = SvxPaperInfo::GetDefaultPaperSize();
+ aFrmSize.SetSize( aPhysSize );
+
+ //Auf Default-Raender vorbereiten.
+ //Raender haben eine defaultmaessige Mindestgroesse.
+ //wenn der Drucker einen groesseren Rand vorgibt, so
+ //ist mir dass auch recht.
+ // MIB 06/25/2002, #99397#: The HTML page desc had A4 as page size
+ // always. This has been changed to take the page size from the printer.
+ // Unfortunately, the margins of the HTML page desc are smaller than
+ // the margins used here in general, so one extra case is required.
+ // In the long term, this needs to be changed to always keep the
+ // margins from the page desc.
+ sal_Int32 nMinTop, nMinBottom, nMinLeft, nMinRight;
+ if( RES_POOLPAGE_HTML == nPoolFmtId )
+ {
+ nMinRight = nMinTop = nMinBottom = GetMetricVal( CM_1 );
+ nMinLeft = nMinRight * 2;
+ }
+ else if( MEASURE_METRIC == SvtSysLocale().GetLocaleData().getMeasurementSystemEnum() )
+ {
+ nMinTop = nMinBottom = nMinLeft = nMinRight = 1134; //2 Zentimeter
+ }
+ else
+ {
+ nMinTop = nMinBottom = 1440; //al la WW: 1Inch
+ nMinLeft = nMinRight = 1800; // 1,25 Inch
+ }
+
+ //Raender einstellen.
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ SvxULSpaceItem aUL( RES_UL_SPACE );
+
+ aUL.SetUpper( (sal_uInt16)nMinTop );
+ aUL.SetLower( (sal_uInt16)nMinBottom );
+ aLR.SetRight( nMinRight );
+ aLR.SetLeft( nMinLeft );
+
+ rFmt1.SetFmtAttr( aFrmSize );
+ rFmt1.SetFmtAttr( aLR );
+ rFmt1.SetFmtAttr( aUL );
+
+ rFmt2.SetFmtAttr( aFrmSize );
+ rFmt2.SetFmtAttr( aLR );
+ rFmt2.SetFmtAttr( aUL );
+}
+
+/*************************************************************************
+|*
+|* SwDoc::ChgPageDesc()
+|*
+|* Ersterstellung MA 25. Jan. 93
+|* Letzte Aenderung MA 01. Mar. 95
+|*
+|*************************************************************************/
+
+void lcl_DescSetAttr( const SwFrmFmt &rSource, SwFrmFmt &rDest,
+ const sal_Bool bPage = sal_True )
+{
+/////////////// !!!!!!!!!!!!!!!!
+//JP 03.03.99:
+// eigentlich sollte hier das Intersect von ItemSet benutzt werden, aber das
+// funktioniert nicht richtig, wenn man unterschiedliche WhichRanges hat.
+/////////////// !!!!!!!!!!!!!!!!
+ //Die interressanten Attribute uebernehmen.
+ sal_uInt16 __READONLY_DATA aIdArr[] = { RES_FRM_SIZE, RES_UL_SPACE,
+ RES_BACKGROUND, RES_SHADOW,
+ RES_COL, RES_COL,
+ RES_FRAMEDIR, RES_FRAMEDIR,
+ RES_TEXTGRID, RES_TEXTGRID,
+ // --> FME 2005-04-18 #i45539#
+ RES_HEADER_FOOTER_EAT_SPACING,
+ RES_HEADER_FOOTER_EAT_SPACING,
+ // <--
+ RES_UNKNOWNATR_CONTAINER,
+ RES_UNKNOWNATR_CONTAINER,
+ 0 };
+
+ const SfxPoolItem* pItem;
+ for( sal_uInt16 n = 0; aIdArr[ n ]; n += 2 )
+ {
+ for( sal_uInt16 nId = aIdArr[ n ]; nId <= aIdArr[ n+1]; ++nId )
+ {
+ // --> FME 2005-04-18 #i45539#
+ // bPage == true:
+ // All in aIdArr except from RES_HEADER_FOOTER_EAT_SPACING
+ // bPage == false:
+ // All in aIdArr except from RES_COL and RES_PAPER_BIN:
+ // <--
+ if( ( bPage && RES_HEADER_FOOTER_EAT_SPACING != nId ) ||
+ ( !bPage && RES_COL != nId && RES_PAPER_BIN != nId ))
+ {
+ if( SFX_ITEM_SET == rSource.GetItemState( nId, sal_False, &pItem ))
+ rDest.SetFmtAttr( *pItem );
+ else
+ rDest.ResetFmtAttr( nId );
+ }
+ }
+ }
+
+ // auch Pool-, Hilfe-Id's uebertragen
+ rDest.SetPoolFmtId( rSource.GetPoolFmtId() );
+ rDest.SetPoolHelpId( rSource.GetPoolHelpId() );
+ rDest.SetPoolHlpFileId( rSource.GetPoolHlpFileId() );
+}
+
+
+void SwDoc::ChgPageDesc( sal_uInt16 i, const SwPageDesc &rChged )
+{
+ ASSERT( i < aPageDescs.Count(), "PageDescs ueberindiziert." );
+
+ SwPageDesc *pDesc = aPageDescs[i];
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo(new SwUndoPageDesc(*pDesc, rChged, this));
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ //Als erstes wird ggf. gespiegelt.
+ if ( rChged.GetUseOn() == nsUseOnPage::PD_MIRROR )
+ ((SwPageDesc&)rChged).Mirror();
+ else
+ //sonst Werte aus Master nach Left uebertragen.
+ ::lcl_DescSetAttr( ((SwPageDesc&)rChged).GetMaster(),
+ ((SwPageDesc&)rChged).GetLeft() );
+
+ //NumType uebernehmen.
+ if( rChged.GetNumType().GetNumberingType() != pDesc->GetNumType().GetNumberingType() )
+ {
+ pDesc->SetNumType( rChged.GetNumType() );
+ // JP 30.03.99: Bug 64121 - den Seitennummernfeldern bescheid sagen,
+ // das sich das Num-Format geaendert hat
+ GetSysFldType( RES_PAGENUMBERFLD )->UpdateFlds();
+ GetSysFldType( RES_REFPAGEGETFLD )->UpdateFlds();
+
+ // Wenn sich die Numerierungsart geaendert hat, koennte es QuoVadis/
+ // ErgoSum-Texte geben, die sich auf eine geaenderte Seite beziehen,
+ // deshalb werden die Fussnoten invalidiert
+ SwFtnIdxs& rFtnIdxs = GetFtnIdxs();
+ for( sal_uInt16 nPos = 0; nPos < rFtnIdxs.Count(); ++nPos )
+ {
+ SwTxtFtn *pTxtFtn = rFtnIdxs[ nPos ];
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ pTxtFtn->SetNumber( rFtn.GetNumber(), &rFtn.GetNumStr());
+ }
+ }
+
+ //Orientierung uebernehmen
+ pDesc->SetLandscape( rChged.GetLandscape() );
+
+ // #i46909# no undo if header or footer changed
+ bool bHeaderFooterChanged = false;
+
+ //Header abgleichen.
+ const SwFmtHeader &rHead = rChged.GetMaster().GetHeader();
+ if (undoGuard.UndoWasEnabled())
+ {
+ // #i46909# no undo if header or footer changed
+ // hat sich an den Nodes etwas veraendert ?
+ const SwFmtHeader &rOldHead = pDesc->GetMaster().GetHeader();
+ bHeaderFooterChanged |=
+ ( rHead.IsActive() != rOldHead.IsActive() ||
+ rChged.IsHeaderShared() != pDesc->IsHeaderShared() );
+ }
+ pDesc->GetMaster().SetFmtAttr( rHead );
+ if ( rChged.IsHeaderShared() || !rHead.IsActive() )
+ {
+ //Left teilt sich den Header mit dem Master.
+ pDesc->GetLeft().SetFmtAttr( pDesc->GetMaster().GetHeader() );
+ }
+ else if ( rHead.IsActive() )
+ { //Left bekommt einen eigenen Header verpasst wenn das Format nicht
+ //bereits einen hat.
+ //Wenn er bereits einen hat und dieser auf die gleiche Section
+ //wie der Rechte zeigt, so muss er einen eigenen bekommen. Der
+ //Inhalt wird sinnigerweise kopiert.
+ const SwFmtHeader &rLeftHead = pDesc->GetLeft().GetHeader();
+ if ( !rLeftHead.IsActive() )
+ {
+ SwFmtHeader aHead( MakeLayoutFmt( RND_STD_HEADERL, 0 ) );
+ pDesc->GetLeft().SetFmtAttr( aHead );
+ //Weitere Attribute (Raender, Umrandung...) uebernehmen.
+ ::lcl_DescSetAttr( *rHead.GetHeaderFmt(), *aHead.GetHeaderFmt(), sal_False);
+ }
+ else
+ {
+ const SwFrmFmt *pRight = rHead.GetHeaderFmt();
+ const SwFmtCntnt &aRCnt = pRight->GetCntnt();
+ const SwFmtCntnt &aLCnt = rLeftHead.GetHeaderFmt()->GetCntnt();
+ if( !aLCnt.GetCntntIdx() )
+ pDesc->GetLeft().SetFmtAttr( rChged.GetLeft().GetHeader() );
+ else if( (*aRCnt.GetCntntIdx()) == (*aLCnt.GetCntntIdx()) )
+ {
+ SwFrmFmt *pFmt = new SwFrmFmt( GetAttrPool(), "Header",
+ GetDfltFrmFmt() );
+ ::lcl_DescSetAttr( *pRight, *pFmt, sal_False );
+ //Der Bereich auf den das rechte Kopfattribut zeigt wird
+ //kopiert und der Index auf den StartNode in das linke
+ //Kopfattribut gehaengt.
+ SwNodeIndex aTmp( GetNodes().GetEndOfAutotext() );
+ SwStartNode* pSttNd = GetNodes().MakeEmptySection( aTmp, SwHeaderStartNode );
+ SwNodeRange aRange( aRCnt.GetCntntIdx()->GetNode(), 0,
+ *aRCnt.GetCntntIdx()->GetNode().EndOfSectionNode() );
+ aTmp = *pSttNd->EndOfSectionNode();
+ GetNodes()._Copy( aRange, aTmp, sal_False );
+
+ pFmt->SetFmtAttr( SwFmtCntnt( pSttNd ) );
+ pDesc->GetLeft().SetFmtAttr( SwFmtHeader( pFmt ) );
+ }
+ else
+ ::lcl_DescSetAttr( *pRight,
+ *(SwFrmFmt*)rLeftHead.GetHeaderFmt(), sal_False );
+
+ }
+ }
+ pDesc->ChgHeaderShare( rChged.IsHeaderShared() );
+
+ //Footer abgleichen.
+ const SwFmtFooter &rFoot = rChged.GetMaster().GetFooter();
+ if (undoGuard.UndoWasEnabled())
+ {
+ // #i46909# no undo if header or footer changed
+ // hat sich an den Nodes etwas veraendert ?
+ const SwFmtFooter &rOldFoot = pDesc->GetMaster().GetFooter();
+ bHeaderFooterChanged |=
+ ( rFoot.IsActive() != rOldFoot.IsActive() ||
+ rChged.IsFooterShared() != pDesc->IsFooterShared() );
+ }
+ pDesc->GetMaster().SetFmtAttr( rFoot );
+ if ( rChged.IsFooterShared() || !rFoot.IsActive() )
+ //Left teilt sich den Header mit dem Master.
+ pDesc->GetLeft().SetFmtAttr( pDesc->GetMaster().GetFooter() );
+ else if ( rFoot.IsActive() )
+ { //Left bekommt einen eigenen Footer verpasst wenn das Format nicht
+ //bereits einen hat.
+ //Wenn er bereits einen hat und dieser auf die gleiche Section
+ //wie der Rechte zeigt, so muss er einen eigenen bekommen. Der
+ //Inhalt wird sinnigerweise kopiert.
+ const SwFmtFooter &rLeftFoot = pDesc->GetLeft().GetFooter();
+ if ( !rLeftFoot.IsActive() )
+ {
+ SwFmtFooter aFoot( MakeLayoutFmt( RND_STD_FOOTER, 0 ) );
+ pDesc->GetLeft().SetFmtAttr( aFoot );
+ //Weitere Attribute (Raender, Umrandung...) uebernehmen.
+ ::lcl_DescSetAttr( *rFoot.GetFooterFmt(), *aFoot.GetFooterFmt(), sal_False);
+ }
+ else
+ {
+ const SwFrmFmt *pRight = rFoot.GetFooterFmt();
+ const SwFmtCntnt &aRCnt = pRight->GetCntnt();
+ const SwFmtCntnt &aLCnt = rLeftFoot.GetFooterFmt()->GetCntnt();
+ if( !aLCnt.GetCntntIdx() )
+ pDesc->GetLeft().SetFmtAttr( rChged.GetLeft().GetFooter() );
+ else if( (*aRCnt.GetCntntIdx()) == (*aLCnt.GetCntntIdx()) )
+ {
+ SwFrmFmt *pFmt = new SwFrmFmt( GetAttrPool(), "Footer",
+ GetDfltFrmFmt() );
+ ::lcl_DescSetAttr( *pRight, *pFmt, sal_False );
+ //Der Bereich auf den das rechte Kopfattribut zeigt wird
+ //kopiert und der Index auf den StartNode in das linke
+ //Kopfattribut gehaengt.
+ SwNodeIndex aTmp( GetNodes().GetEndOfAutotext() );
+ SwStartNode* pSttNd = GetNodes().MakeEmptySection( aTmp, SwFooterStartNode );
+ SwNodeRange aRange( aRCnt.GetCntntIdx()->GetNode(), 0,
+ *aRCnt.GetCntntIdx()->GetNode().EndOfSectionNode() );
+ aTmp = *pSttNd->EndOfSectionNode();
+ GetNodes()._Copy( aRange, aTmp, sal_False );
+
+ pFmt->SetFmtAttr( SwFmtCntnt( pSttNd ) );
+ pDesc->GetLeft().SetFmtAttr( SwFmtFooter( pFmt ) );
+ }
+ else
+ ::lcl_DescSetAttr( *pRight,
+ *(SwFrmFmt*)rLeftFoot.GetFooterFmt(), sal_False );
+ }
+ }
+ pDesc->ChgFooterShare( rChged.IsFooterShared() );
+
+ if ( pDesc->GetName() != rChged.GetName() )
+ pDesc->SetName( rChged.GetName() );
+
+ // Dadurch wird ein RegisterChange ausgeloest, wenn notwendig
+ pDesc->SetRegisterFmtColl( rChged.GetRegisterFmtColl() );
+
+ //Wenn sich das UseOn oder der Follow aendern muessen die
+ //Absaetze das erfahren.
+ sal_Bool bUseOn = sal_False;
+ sal_Bool bFollow = sal_False;
+ if ( pDesc->GetUseOn() != rChged.GetUseOn() )
+ { pDesc->SetUseOn( rChged.GetUseOn() );
+ bUseOn = sal_True;
+ }
+ if ( pDesc->GetFollow() != rChged.GetFollow() )
+ { if ( rChged.GetFollow() == &rChged )
+ { if ( pDesc->GetFollow() != pDesc )
+ { pDesc->SetFollow( pDesc );
+ bFollow = sal_True;
+ }
+ }
+ else
+ { pDesc->SetFollow( rChged.pFollow );
+ bFollow = sal_True;
+ }
+ }
+
+ if ( (bUseOn || bFollow) && GetRootFrm() )
+ //Layot benachrichtigen!
+ GetRootFrm()->CheckPageDescs( (SwPageFrm*)GetRootFrm()->Lower() );
+
+ //Jetzt noch die Seiten-Attribute uebernehmen.
+ ::lcl_DescSetAttr( rChged.GetMaster(), pDesc->GetMaster() );
+ ::lcl_DescSetAttr( rChged.GetLeft(), pDesc->GetLeft() );
+
+ //Wenn sich FussnotenInfo veraendert, so werden die Seiten
+ //angetriggert.
+ if( !(pDesc->GetFtnInfo() == rChged.GetFtnInfo()) )
+ {
+ pDesc->SetFtnInfo( rChged.GetFtnInfo() );
+ SwMsgPoolItem aInfo( RES_PAGEDESC_FTNINFO );
+ {
+ SwClientIter aIter( pDesc->GetMaster() );
+ for( SwClient* pLast = aIter.First(TYPE(SwFrm)); pLast;
+ pLast = aIter.Next() )
+ pLast->Modify( &aInfo, 0 );
+ }
+ {
+ SwClientIter aIter( pDesc->GetLeft() );
+ for( SwClient* pLast = aIter.First(TYPE(SwFrm)); pLast;
+ pLast = aIter.Next() )
+ pLast->Modify( &aInfo, 0 );
+ }
+ }
+ SetModified();
+
+ // #i46909# no undo if header or footer changed
+ if( bHeaderFooterChanged )
+ {
+ GetIDocumentUndoRedo().DelAllUndoObj();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwDoc::DelPageDesc()
+|*
+|* Beschreibung Alle Descriptoren, deren Follow auf den zu loeschenden
+|* zeigen muessen angepasst werden.
+|* Ersterstellung MA 25. Jan. 93
+|* Letzte Aenderung JP 04.09.95
+|*
+|*************************************************************************/
+
+void lcl_RemoveFrms( SwFrmFmt& rFmt, sal_Bool& rbFtnsRemoved )
+{
+ SwClientIter aIter( rFmt );
+ SwFrm *pFrm;
+ for( pFrm = (SwFrm*)aIter.First(TYPE(SwFrm)); pFrm;
+ pFrm = (SwFrm*)aIter.Next() )
+ if ( !rbFtnsRemoved && pFrm->IsPageFrm() &&
+ ((SwPageFrm*)pFrm)->IsFtnPage() )
+ {
+ rFmt.getIDocumentLayoutAccess()->GetRootFrm()->RemoveFtns( 0, sal_False, sal_True );
+ rbFtnsRemoved = sal_True;
+ }
+ else
+ {
+ pFrm->Cut();
+ delete pFrm;
+ }
+}
+
+// #i7983#
+void SwDoc::PreDelPageDesc(SwPageDesc * pDel)
+{
+ if (0 == pDel)
+ return;
+
+ SwFmtPageDesc aDfltDesc( aPageDescs[0] );
+ SwClientIter aIter( *pDel );
+ SwClient* pLast;
+ while( 0 != ( pLast = aIter.GoRoot() ))
+ {
+ if( pLast->ISA( SwFmtPageDesc ) )
+ {
+ const SwModify* pMod = ((SwFmtPageDesc*)pLast)->GetDefinedIn();
+ if ( pMod )
+ {
+ if( pMod->ISA( SwCntntNode ) )
+ ((SwCntntNode*)pMod)->SetAttr( aDfltDesc );
+ else if( pMod->ISA( SwFmt ))
+ ((SwFmt*)pMod)->SetFmtAttr( aDfltDesc );
+ else
+ {
+ ASSERT( !this, "was ist das fuer ein Mofify-Obj?" );
+ aPageDescs[0]->Add( pLast );
+ }
+ }
+ else //Es kann noch eine Undo-Kopie existieren
+ aPageDescs[0]->Add( pLast );
+ }
+
+ sal_Bool bFtnInf = sal_False;
+ if ( sal_True == (bFtnInf = pLast == pFtnInfo->GetPageDescDep()) ||
+ pLast == pEndNoteInfo->GetPageDescDep() )
+ {
+ aPageDescs[0]->Add( pLast );
+ if ( GetRootFrm() )
+ GetRootFrm()->CheckFtnPageDescs( !bFtnInf );
+ }
+ }
+
+ for ( sal_uInt16 j = 0; j < aPageDescs.Count(); ++j )
+ {
+ if ( aPageDescs[j]->GetFollow() == pDel )
+ {
+ aPageDescs[j]->SetFollow( 0 );
+ //Clients des PageDesc sind die Attribute, denen sagen wir bescheid.
+ //die Attribute wiederum reichen die Meldung an die Absaetze weiter.
+
+ //Layot benachrichtigen!
+ if( GetRootFrm() ) // ist nicht immer vorhanden!! (Orginizer)
+ GetRootFrm()->CheckPageDescs( (SwPageFrm*)GetRootFrm()->Lower() );
+ }
+ }
+
+ if( GetRootFrm() ) // ist nicht immer vorhanden!! (Orginizer)
+ {
+ //Wenn jetzt noch irgendwelche Seiten auf die FrmFmt'e (Master und Left)
+ //Zeigen (z.B. irgendwelche Fussnotenseiten), so muessen die Seiten
+ //vernichtet werden.
+
+ // Wenn wir auf Endnotenseiten stossen, schmeissen wir alle Fussnoten weg,
+ // anders kann die Reihenfolge der Seiten (FollowsPageDescs usw.)
+ // nicht garantiert werden.
+ sal_Bool bFtnsRemoved = sal_False;
+
+ ::lcl_RemoveFrms( pDel->GetMaster(), bFtnsRemoved );
+ ::lcl_RemoveFrms( pDel->GetLeft(), bFtnsRemoved );
+ }
+}
+
+// #116530#
+void SwDoc::BroadcastStyleOperation(String rName, SfxStyleFamily eFamily,
+ sal_uInt16 nOp)
+{
+ if (pDocShell)
+ {
+ SfxStyleSheetBasePool * pPool = pDocShell->GetStyleSheetPool();
+
+ if (pPool)
+ {
+ pPool->SetSearchMask(eFamily, SFXSTYLEBIT_ALL );
+ SfxStyleSheetBase * pBase = pPool->Find(rName);
+
+ if (pBase != NULL)
+ pPool->Broadcast(SfxStyleSheetHint( nOp, *pBase ));
+ }
+ }
+}
+
+void SwDoc::DelPageDesc( sal_uInt16 i, sal_Bool bBroadcast )
+{
+ ASSERT( i < aPageDescs.Count(), "PageDescs ueberindiziert." );
+ ASSERT( i != 0, "Default Pagedesc loeschen is nicht." );
+ if ( i == 0 )
+ return;
+
+ SwPageDesc *pDel = aPageDescs[i];
+
+ // -> #116530#
+ if (bBroadcast)
+ BroadcastStyleOperation(pDel->GetName(), SFX_STYLE_FAMILY_PAGE,
+ SFX_STYLESHEET_ERASED);
+ // <- #116530#
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo(new SwUndoPageDescDelete(*pDel, this));
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ PreDelPageDesc(pDel); // #i7983#
+
+ aPageDescs.Remove( i );
+ delete pDel;
+ SetModified();
+}
+
+
+
+/*************************************************************************
+|*
+|* SwDoc::MakePageDesc()
+|*
+|* Ersterstellung MA 25. Jan. 93
+|* Letzte Aenderung MA 20. Aug. 93
+|*
+|*************************************************************************/
+
+sal_uInt16 SwDoc::MakePageDesc( const String &rName, const SwPageDesc *pCpy,
+ sal_Bool bRegardLanguage, sal_Bool bBroadcast) // #116530#
+{
+ SwPageDesc *pNew;
+ if( pCpy )
+ {
+ pNew = new SwPageDesc( *pCpy );
+ pNew->SetName( rName );
+ if( rName != pCpy->GetName() )
+ {
+ pNew->SetPoolFmtId( USHRT_MAX );
+ pNew->SetPoolHelpId( USHRT_MAX );
+ pNew->SetPoolHlpFileId( UCHAR_MAX );
+ }
+ }
+ else
+ {
+ pNew = new SwPageDesc( rName, GetDfltFrmFmt(), this );
+ //Default-Seitenformat einstellen.
+ lcl_DefaultPageFmt( USHRT_MAX, pNew->GetMaster(), pNew->GetLeft() );
+
+ SvxFrameDirection aFrameDirection = bRegardLanguage ?
+ GetDefaultFrameDirection(GetAppLanguage())
+ : FRMDIR_HORI_LEFT_TOP;
+
+ pNew->GetMaster().SetFmtAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) );
+ pNew->GetLeft().SetFmtAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) );
+ }
+ aPageDescs.Insert( pNew, aPageDescs.Count() );
+
+ // -> #116530#
+ if (bBroadcast)
+ BroadcastStyleOperation(rName, SFX_STYLE_FAMILY_PAGE,
+ SFX_STYLESHEET_CREATED);
+ // <- #116530#
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // #116530#
+ GetIDocumentUndoRedo().AppendUndo(new SwUndoPageDescCreate(pNew, this));
+ }
+
+ SetModified();
+ return (aPageDescs.Count()-1);
+}
+
+SwPageDesc* SwDoc::FindPageDescByName( const String& rName, sal_uInt16* pPos ) const
+{
+ SwPageDesc* pRet = 0;
+ if( pPos ) *pPos = USHRT_MAX;
+
+ for( sal_uInt16 n = 0, nEnd = aPageDescs.Count(); n < nEnd; ++n )
+ if( aPageDescs[ n ]->GetName() == rName )
+ {
+ pRet = aPageDescs[ n ];
+ if( pPos )
+ *pPos = n;
+ break;
+ }
+ return pRet;
+}
+
+/******************************************************************************
+ * Methode : void SwDoc::PrtDataChanged()
+ * Beschreibung:
+ * Erstellt : OK 27.10.94 10:20
+ * Aenderung : MA 26. Mar. 98
+ ******************************************************************************/
+
+void SwDoc::PrtDataChanged()
+{
+//!!!!!!!! Bei Aenderungen hier bitte ggf. InJobSetup im Sw3io mitpflegen
+
+ // --> FME 2005-01-21 #i41075#
+ ASSERT( get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) ||
+ 0 != getPrinter( sal_False ), "PrtDataChanged will be called recursive!" )
+ // <--
+
+ SwWait *pWait = 0;
+ sal_Bool bEndAction = sal_False;
+
+ if( GetDocShell() )
+ GetDocShell()->UpdateFontList();
+
+ sal_Bool bDraw = sal_True;
+ if ( GetRootFrm() )
+ {
+ ViewShell *pSh = GetRootFrm()->GetCurrShell();
+ if( !get(IDocumentSettingAccess::BROWSE_MODE) ||
+ ( pSh && pSh->GetViewOptions()->IsPrtFormat() ) )
+ {
+ if ( GetDocShell() )
+ pWait = new SwWait( *GetDocShell(), sal_True );
+
+ GetRootFrm()->StartAllAction();
+ bEndAction = sal_True;
+
+ bDraw = sal_False;
+ if( pDrawModel )
+ {
+ pDrawModel->SetAddExtLeading( get(IDocumentSettingAccess::ADD_EXT_LEADING) );
+ pDrawModel->SetRefDevice( getReferenceDevice( false ) );
+ }
+
+ pFntCache->Flush();
+ GetRootFrm()->InvalidateAllCntnt();
+
+ if ( pSh )
+ {
+ do
+ {
+ pSh->InitPrt( pPrt );
+ pSh = (ViewShell*)pSh->GetNext();
+ }
+ while ( pSh != GetRootFrm()->GetCurrShell() );
+ }
+
+ }
+ }
+ if ( bDraw && pDrawModel )
+ {
+ const sal_Bool bTmpAddExtLeading = get(IDocumentSettingAccess::ADD_EXT_LEADING);
+ if ( bTmpAddExtLeading != pDrawModel->IsAddExtLeading() )
+ pDrawModel->SetAddExtLeading( bTmpAddExtLeading );
+
+ OutputDevice* pOutDev = getReferenceDevice( false );
+ if ( pOutDev != pDrawModel->GetRefDevice() )
+ pDrawModel->SetRefDevice( pOutDev );
+ }
+
+ PrtOLENotify( sal_True );
+
+ if ( bEndAction )
+ GetRootFrm()->EndAllAction();
+ delete pWait;
+}
+
+//Zur Laufzeit sammeln wir die GlobalNames der Server, die keine
+//Benachrichtigung zu Druckerwechseln wuenschen. Dadurch sparen wir
+//das Laden vieler Objekte (gluecklicherweise werden obendrein alle
+//Fremdobjekte unter einer ID abgebuildet). Init und DeInit vom Array
+//ist in init.cxx zu finden.
+extern SvPtrarr *pGlobalOLEExcludeList;
+
+void SwDoc::PrtOLENotify( sal_Bool bAll )
+{
+ SwFEShell *pShell = 0;
+ if ( GetRootFrm() && GetRootFrm()->GetCurrShell() )
+ {
+ ViewShell *pSh = GetRootFrm()->GetCurrShell();
+ if ( !pSh->ISA(SwFEShell) )
+ do
+ { pSh = (ViewShell*)pSh->GetNext();
+ } while ( !pSh->ISA(SwFEShell) &&
+ pSh != GetRootFrm()->GetCurrShell() );
+
+ if ( pSh->ISA(SwFEShell) )
+ pShell = (SwFEShell*)pSh;
+ }
+ if ( !pShell )
+ {
+ //Das hat ohne Shell und damit ohne Client keinen Sinn, weil nur darueber
+ //die Kommunikation bezueglich der Groessenaenderung implementiert ist.
+ //Da wir keine Shell haben, merken wir uns diesen unguenstigen
+ //Zustand am Dokument, dies wird dann beim Erzeugen der ersten Shell
+ //nachgeholt.
+ mbOLEPrtNotifyPending = sal_True;
+ if ( bAll )
+ mbAllOLENotify = sal_True;
+ }
+ else
+ {
+ if ( mbAllOLENotify )
+ bAll = sal_True;
+
+ mbOLEPrtNotifyPending = mbAllOLENotify = sal_False;
+
+
+ SwOLENodes *pNodes = 0;
+ SwClientIter aIter( *(SwModify*)GetDfltGrfFmtColl() );
+ for( SwCntntNode* pNd = (SwCntntNode*)aIter.First( TYPE( SwCntntNode ) );
+ pNd;
+ pNd = (SwCntntNode*)aIter.Next() )
+ {
+ SwOLENode *pONd;
+ if ( 0 != (pONd = pNd->GetOLENode()) &&
+ (bAll || pONd->IsOLESizeInvalid()) )
+ {
+ if ( !pNodes )
+ pNodes = new SwOLENodes;
+ pNodes->Insert( pONd, pNodes->Count() );
+ }
+ }
+
+ if ( pNodes )
+ {
+ ::StartProgress( STR_STATSTR_SWGPRTOLENOTIFY,
+ 0, pNodes->Count(), GetDocShell());
+ GetRootFrm()->StartAllAction();
+
+ for( sal_uInt16 i = 0; i < pNodes->Count(); ++i )
+ {
+ ::SetProgressState( i, GetDocShell() );
+
+ SwOLENode* pOLENd = (*pNodes)[i];
+ pOLENd->SetOLESizeInvalid( sal_False );
+
+ //Ersteinmal die Infos laden und festellen ob das Teil nicht
+ //schon in der Exclude-Liste steht
+ SvGlobalName aName;
+
+ svt::EmbeddedObjectRef& xObj = pOLENd->GetOLEObj().GetObject();
+ if ( xObj.is() )
+ aName = SvGlobalName( xObj->getClassID() );
+ else //Noch nicht geladen
+ {
+ // TODO/LATER: retrieve ClassID of an unloaded object
+ // aName = ????
+ }
+
+ sal_Bool bFound = sal_False;
+ for ( sal_uInt16 j = 0;
+ j < pGlobalOLEExcludeList->Count() && !bFound;
+ ++j )
+ {
+ bFound = *(SvGlobalName*)(*pGlobalOLEExcludeList)[j] ==
+ aName;
+ }
+ if ( bFound )
+ continue;
+
+ //Kennen wir nicht, also muss das Objekt geladen werden.
+ //Wenn es keine Benachrichtigung wuenscht
+ if ( xObj.is() )
+ {
+ //TODO/LATER: needs MiscStatus for ResizeOnPrinterChange
+ /*
+ if ( SVOBJ_MISCSTATUS_RESIZEONPRINTERCHANGE & xRef->GetMiscStatus())
+ {
+ if ( pOLENd->GetFrm() )
+ {
+ xObj->OnDocumentPrinterChanged( pPrt );
+ pShell->CalcAndSetScale( xObj );//Client erzeugen lassen.
+ }
+ else
+ pOLENd->SetOLESizeInvalid( sal_True );
+ }
+ else */
+ pGlobalOLEExcludeList->Insert(
+ new SvGlobalName( aName ),
+ pGlobalOLEExcludeList->Count() );
+ }
+ }
+ delete pNodes;
+ GetRootFrm()->EndAllAction();
+ ::EndProgress( GetDocShell() );
+ }
+ }
+}
+
+IMPL_LINK( SwDoc, DoUpdateModifiedOLE, Timer *, )
+{
+ SwFEShell* pSh = (SwFEShell*)GetEditShell();
+ if( pSh )
+ {
+ mbOLEPrtNotifyPending = mbAllOLENotify = sal_False;
+
+ SwOLENodes aOLENodes;
+ SwClientIter aIter( *(SwModify*)GetDfltGrfFmtColl() );
+ for( SwCntntNode* pNd = (SwCntntNode*)aIter.First( TYPE( SwCntntNode ) );
+ pNd;
+ pNd = (SwCntntNode*)aIter.Next() )
+ {
+ SwOLENode *pONd = pNd->GetOLENode();
+ if( pONd && pONd->IsOLESizeInvalid() )
+ {
+ aOLENodes.Insert( pONd, aOLENodes.Count() );
+ }
+ }
+
+ if( aOLENodes.Count() )
+ {
+ ::StartProgress( STR_STATSTR_SWGPRTOLENOTIFY,
+ 0, aOLENodes.Count(), GetDocShell());
+ GetRootFrm()->StartAllAction();
+ SwMsgPoolItem aMsgHint( RES_UPDATE_ATTR );
+
+ for( sal_uInt16 i = 0; i < aOLENodes.Count(); ++i )
+ {
+ ::SetProgressState( i, GetDocShell() );
+
+ SwOLENode* pOLENd = aOLENodes[i];
+ pOLENd->SetOLESizeInvalid( sal_False );
+
+ //Kennen wir nicht, also muss das Objekt geladen werden.
+ //Wenn es keine Benachrichtigung wuenscht
+ if( pOLENd->GetOLEObj().GetOleRef().is() ) //Kaputt?
+ {
+ //TODO/LATER: needs MiscStatus for ResizeOnPrinterChange
+ /*
+ if( SVOBJ_MISCSTATUS_RESIZEONPRINTERCHANGE &
+ xRef->GetMiscStatus() )
+ {
+ if( pOLENd->GetFrm() )
+ {
+ xRef->OnDocumentPrinterChanged( pPrt );
+ pSh->CalcAndSetScale( xRef );//Client erzeugen lassen.
+ }
+ else
+ pOLENd->SetOLESizeInvalid( sal_True );
+ }*/
+ // repaint it
+ pOLENd->Modify( &aMsgHint, &aMsgHint );
+ }
+ }
+ GetRootFrm()->EndAllAction();
+ ::EndProgress( GetDocShell() );
+ }
+ }
+ return 0;
+}
+
+sal_Bool SwDoc::FindPageDesc( const String & rName, sal_uInt16 * pFound)
+{
+ sal_Bool bResult = sal_False;
+ sal_uInt16 nI;
+ for (nI = 0; nI < aPageDescs.Count(); nI++)
+ {
+ if (aPageDescs[nI]->GetName() == rName)
+ {
+ *pFound = nI;
+ bResult = sal_True;
+ break;
+ }
+ }
+
+ return bResult;
+}
+
+SwPageDesc * SwDoc::GetPageDesc( const String & rName )
+{
+ SwPageDesc * aResult = NULL;
+
+ sal_uInt16 nI;
+
+ if (FindPageDesc(rName, &nI))
+ aResult = aPageDescs[nI];
+
+ return aResult;
+}
+
+void SwDoc::DelPageDesc( const String & rName, sal_Bool bBroadcast ) // #116530#
+{
+ sal_uInt16 nI;
+
+ if (FindPageDesc(rName, &nI))
+ DelPageDesc(nI, bBroadcast); // #116530#
+}
+
+void SwDoc::ChgPageDesc( const String & rName, const SwPageDesc & rDesc)
+{
+ sal_uInt16 nI;
+
+ if (FindPageDesc(rName, &nI))
+ ChgPageDesc(nI, rDesc);
+}
+
+/*
+ * The HTML import cannot resist changing the page descriptions, I don't
+ * know why. This function is meant to check the page descriptors for invalid
+ * values.
+ */
+void SwDoc::CheckDefaultPageFmt()
+{
+ for ( sal_uInt16 i = 0; i < GetPageDescCnt(); ++i )
+ {
+ SwPageDesc& rDesc = _GetPageDesc( i );
+
+ SwFrmFmt& rMaster = rDesc.GetMaster();
+ SwFrmFmt& rLeft = rDesc.GetLeft();
+
+ const SwFmtFrmSize& rMasterSize = rMaster.GetFrmSize();
+ const SwFmtFrmSize& rLeftSize = rLeft.GetFrmSize();
+
+ const bool bSetSize = LONG_MAX == rMasterSize.GetWidth() ||
+ LONG_MAX == rMasterSize.GetHeight() ||
+ LONG_MAX == rLeftSize.GetWidth() ||
+ LONG_MAX == rLeftSize.GetHeight();
+
+ if ( bSetSize )
+ lcl_DefaultPageFmt( rDesc.GetPoolFmtId(), rDesc.GetMaster(), rDesc.GetLeft() );
+ }
+}
+
+void SwDoc::SetDefaultPageMode(bool bSquaredPageMode)
+{
+ if( !bSquaredPageMode == !IsSquaredPageMode() )
+ return;
+
+ const SwTextGridItem& rGrid =
+ (const SwTextGridItem&)GetDefault( RES_TEXTGRID );
+ SwTextGridItem aNewGrid = rGrid;
+ aNewGrid.SetSquaredMode(bSquaredPageMode);
+ aNewGrid.Init();
+ SetDefault(aNewGrid);
+
+ for ( sal_uInt16 i = 0; i < GetPageDescCnt(); ++i )
+ {
+ SwPageDesc& rDesc = _GetPageDesc( i );
+
+ SwFrmFmt& rMaster = rDesc.GetMaster();
+ SwFrmFmt& rLeft = rDesc.GetLeft();
+
+ SwTextGridItem aGrid((SwTextGridItem&)rMaster.GetFmtAttr(RES_TEXTGRID));
+ aGrid.SwitchPaperMode( bSquaredPageMode );
+ rMaster.SetFmtAttr(aGrid);
+ rLeft.SetFmtAttr(aGrid);
+ }
+}
+
+sal_Bool SwDoc::IsSquaredPageMode() const
+{
+ const SwTextGridItem& rGrid =
+ (const SwTextGridItem&)GetDefault( RES_TEXTGRID );
+ return rGrid.IsSquaredMode();
+}
diff --git a/sw/source/core/doc/docdraw.cxx b/sw/source/core/doc/docdraw.cxx
new file mode 100644
index 000000000000..91d99221e1fd
--- /dev/null
+++ b/sw/source/core/doc/docdraw.cxx
@@ -0,0 +1,1093 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <rtl/logfile.hxx>
+#include <vcl/outdev.hxx>
+#include <sfx2/printer.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/flditem.hxx>
+#include <editeng/editeng.hxx>
+#include <svx/svdoutl.hxx>
+#include <editeng/colritem.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdogrp.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/unolingu.hxx>
+#include <editeng/measfld.hxx>
+#include <svx/svdpool.hxx>
+#include <fmtanchr.hxx>
+#include <charatr.hxx>
+#include <frmfmt.hxx>
+#include <charfmt.hxx>
+#include <viewimp.hxx>
+#include <swhints.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docsh.hxx>
+#include <rootfrm.hxx> //Damit der RootDtor gerufen wird.
+#include <poolfmt.hxx>
+#include <viewsh.hxx> // fuer MakeDrawView
+#include <drawdoc.hxx>
+#include <UndoDraw.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <dcontact.hxx>
+#include <dview.hxx>
+#include <mvsave.hxx>
+#include <flyfrm.hxx>
+#include <dflyobj.hxx>
+#include <svx/svdetc.hxx>
+#include <editeng/fhgtitem.hxx>
+
+// OD 26.06.2003 #108784#
+#include <svx/svdpagv.hxx>
+// OD 2004-04-01 #i26791#
+#include <dcontact.hxx>
+#include <txtfrm.hxx>
+#include <frmfmt.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <fmtornt.hxx>
+// --> OD 2006-03-14 #i62875#
+#include <svx/svditer.hxx>
+// <--
+// --> OD 2006-11-01 #130889#
+#include <vector>
+// <--
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::linguistic2;
+
+
+SV_IMPL_VARARR_SORT( _ZSortFlys, _ZSortFly )
+
+/*************************************************************************
+|*
+|* SwDoc::GroupSelection / SwDoc::UnGroupSelection
+|*
+|* Ersterstellung JP 21.08.95
+|* Letzte Aenderung JP 21.08.95
+|*
+|*************************************************************************/
+// OD 2004-04-01 #i26791# - local method to determine positioning and
+// alignment attributes for a drawing object, which is newly connected to
+// the layout. Used for a newly formed group object <SwDoc::GroupSelection(..)>
+// and the members of a destroyed group <SwDoc::UnGroupSelection(..)>
+void lcl_AdjustPositioningAttr( SwDrawFrmFmt* _pFrmFmt,
+ const SdrObject& _rSdrObj )
+{
+ const SwContact* pContact = GetUserCall( &_rSdrObj );
+ ASSERT( pContact, "<lcl_AdjustPositioningAttr(..)> - missing contact object." );
+
+ // determine position of new group object relative to its anchor frame position
+ SwTwips nHoriRelPos = 0;
+ SwTwips nVertRelPos = 0;
+ {
+ const SwFrm* pAnchorFrm = pContact->GetAnchoredObj( &_rSdrObj )->GetAnchorFrm();
+ ASSERT( !pAnchorFrm ||
+ !pAnchorFrm->IsTxtFrm() ||
+ !static_cast<const SwTxtFrm*>(pAnchorFrm)->IsFollow(),
+ "<lcl_AdjustPositioningAttr(..)> - anchor frame is a follow. Please inform OD." );
+ bool bVert = false;
+ bool bR2L = false;
+ // --> OD 2005-05-10 #i45952# - use anchor position of
+ // anchor frame, if it exist.
+ Point aAnchorPos;
+ if ( pAnchorFrm )
+ {
+ // --> OD 2005-05-10 #i45952#
+ aAnchorPos = pAnchorFrm->GetFrmAnchorPos( ::HasWrap( &_rSdrObj ) );
+ // <--
+ bVert = pAnchorFrm->IsVertical();
+ bR2L = pAnchorFrm->IsRightToLeft();
+ }
+ else
+ {
+ // --> OD 2005-05-10 #i45952#
+ aAnchorPos = _rSdrObj.GetAnchorPos();
+ // <--
+ // If no anchor frame exist - e.g. because no layout exists - the
+ // default layout direction is taken.
+ const SvxFrameDirectionItem* pDirItem =
+ static_cast<const SvxFrameDirectionItem*>(&(_pFrmFmt->GetAttrSet().GetPool()->GetDefaultItem( RES_FRAMEDIR )));
+ switch ( pDirItem->GetValue() )
+ {
+ case FRMDIR_VERT_TOP_LEFT:
+ {
+ // vertical from left-to-right - Badaa: supported now!
+ bVert = true;
+ bR2L = true;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ //ASSERT( false, "<lcl_AdjustPositioningAttr(..)> - vertical from left-to-right not supported." );
+ //End
+ }
+ break;
+ case FRMDIR_VERT_TOP_RIGHT:
+ {
+ // vertical from right-to-left
+ bVert = true;
+ bR2L = false;
+ }
+ break;
+ case FRMDIR_HORI_RIGHT_TOP:
+ {
+ // horizontal from right-to-left
+ bVert = false;
+ bR2L = true;
+ }
+ break;
+ case FRMDIR_HORI_LEFT_TOP:
+ {
+ // horizontal from left-to-right
+ bVert = false;
+ bR2L = false;
+ }
+ break;
+ }
+
+ }
+ // use geometry of drawing object
+ const SwRect aObjRect = _rSdrObj.GetSnapRect();
+
+ if ( bVert )
+ {
+ if ( bR2L ) {
+ //FRMDIR_VERT_TOP_LEFT
+ nHoriRelPos = aObjRect.Left() - aAnchorPos.X();
+ nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
+ } else {
+ //FRMDIR_VERT_TOP_RIGHT
+ nHoriRelPos = aObjRect.Top() - aAnchorPos.Y();
+ nVertRelPos = aAnchorPos.X() - aObjRect.Right();
+ }
+ }
+ else if ( bR2L )
+ {
+ nHoriRelPos = aAnchorPos.X() - aObjRect.Right();
+ nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
+ }
+ else
+ {
+ nHoriRelPos = aObjRect.Left() - aAnchorPos.X();
+ nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
+ }
+ //End of SCMS
+ }
+
+ _pFrmFmt->SetFmtAttr( SwFmtHoriOrient( nHoriRelPos, text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
+ _pFrmFmt->SetFmtAttr( SwFmtVertOrient( nVertRelPos, text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
+ // --> OD 2005-03-11 #i44334#, #i44681# - positioning attributes already set
+ _pFrmFmt->PosAttrSet();
+ // <--
+ // --> OD 2004-10-01 #i34750# - keep current object rectangle for drawing
+ // objects. The object rectangle is used on events from the drawing layer
+ // to adjust the positioning attributes - see <SwDrawContact::_Changed(..)>.
+ {
+ const SwAnchoredObject* pAnchoredObj = pContact->GetAnchoredObj( &_rSdrObj );
+ if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
+ {
+ const SwAnchoredDrawObject* pAnchoredDrawObj =
+ static_cast<const SwAnchoredDrawObject*>(pAnchoredObj);
+ const SwRect aObjRect = _rSdrObj.GetSnapRect();
+ const_cast<SwAnchoredDrawObject*>(pAnchoredDrawObj)
+ ->SetLastObjRect( aObjRect.SVRect() );
+ }
+ }
+ // <--
+}
+
+SwDrawContact* SwDoc::GroupSelection( SdrView& rDrawView )
+{
+ // OD 30.06.2003 #108784# - replace marked 'virtual' drawing objects by
+ // the corresponding 'master' drawing objects.
+ SwDrawView::ReplaceMarkedDrawVirtObjs( rDrawView );
+
+ const SdrMarkList &rMrkList = rDrawView.GetMarkedObjectList();
+ SwDrawFrmFmt *pFmt = 0L;
+ SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+ sal_Bool bNoGroup = ( 0 == pObj->GetUpGroup() );
+ SwDrawContact* pNewContact = 0;
+ if( bNoGroup )
+ {
+ //Ankerattribut aufheben.
+ SwDrawContact *pMyContact = (SwDrawContact*)GetUserCall(pObj);
+ const SwFmtAnchor aAnch( pMyContact->GetFmt()->GetAnchor() );
+
+ SwUndoDrawGroup *const pUndo = (!GetIDocumentUndoRedo().DoesUndo())
+ ? 0
+ : new SwUndoDrawGroup( (sal_uInt16)rMrkList.GetMarkCount() );
+
+ // --> OD 2005-08-16 #i53320#
+ bool bGroupMembersNotPositioned( false );
+ {
+ SwAnchoredDrawObject* pAnchoredDrawObj =
+ static_cast<SwAnchoredDrawObject*>(pMyContact->GetAnchoredObj( pObj ));
+ bGroupMembersNotPositioned = pAnchoredDrawObj->NotYetPositioned();
+ }
+ // <--
+ //ContactObjekte und Formate vernichten.
+ for( sal_uInt16 i = 0; i < rMrkList.GetMarkCount(); ++i )
+ {
+ pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
+
+ // --> OD 2005-08-16 #i53320#
+#ifdef DBG_UTIL
+ SwAnchoredDrawObject* pAnchoredDrawObj =
+ static_cast<SwAnchoredDrawObject*>(pContact->GetAnchoredObj( pObj ));
+ ASSERT( bGroupMembersNotPositioned == pAnchoredDrawObj->NotYetPositioned(),
+ "<SwDoc::GroupSelection(..)> - group members have different positioning status!" );
+#endif
+ // <--
+
+ pFmt = (SwDrawFrmFmt*)pContact->GetFmt();
+ //loescht sich selbst!
+ pContact->Changed(*pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
+ pObj->SetUserCall( 0 );
+
+ if( pUndo )
+ pUndo->AddObj( i, pFmt, pObj );
+ else
+ DelFrmFmt( pFmt );
+
+ // --> OD 2005-05-10 #i45952# - re-introduce position
+ // normalization of group member objects, because its anchor position
+ // is cleared, when they are grouped.
+ Point aAnchorPos( pObj->GetAnchorPos() );
+ pObj->NbcSetAnchorPos( Point( 0, 0 ) );
+ pObj->NbcMove( Size( aAnchorPos.X(), aAnchorPos.Y() ) );
+ // <--
+ }
+
+ pFmt = MakeDrawFrmFmt( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "DrawObject" )),
+ GetDfltFrmFmt() );
+ pFmt->SetFmtAttr( aAnch );
+ // --> OD 2004-10-25 #i36010# - set layout direction of the position
+ pFmt->SetPositionLayoutDir(
+ text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
+ // <--
+
+ rDrawView.GroupMarked();
+ ASSERT( rMrkList.GetMarkCount() == 1, "GroupMarked more or none groups." );
+
+ SdrObject* pNewGroupObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+ pNewContact = new SwDrawContact( pFmt, pNewGroupObj );
+ // --> OD 2004-11-22 #i35635#
+ pNewContact->MoveObjToVisibleLayer( pNewGroupObj );
+ // <--
+ pNewContact->ConnectToLayout();
+ // --> OD 2005-08-16 #i53320# - No adjustment of the positioning and
+ // alignment attributes, if group members aren't positioned yet.
+ if ( !bGroupMembersNotPositioned )
+ {
+ // OD 2004-04-01 #i26791# - Adjust positioning and alignment attributes.
+ lcl_AdjustPositioningAttr( pFmt, *pNewGroupObj );
+ }
+ // <--
+
+ if( pUndo )
+ {
+ pUndo->SetGroupFmt( pFmt );
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ }
+ else
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ }
+
+ rDrawView.GroupMarked();
+ ASSERT( rMrkList.GetMarkCount() == 1, "GroupMarked more or none groups." );
+ }
+
+ return pNewContact;
+}
+
+
+void SwDoc::UnGroupSelection( SdrView& rDrawView )
+{
+ bool const bUndo = GetIDocumentUndoRedo().DoesUndo();
+ if( bUndo )
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ }
+
+ // OD 30.06.2003 #108784# - replace marked 'virtual' drawing objects by
+ // the corresponding 'master' drawing objects.
+ SwDrawView::ReplaceMarkedDrawVirtObjs( rDrawView );
+
+ const SdrMarkList &rMrkList = rDrawView.GetMarkedObjectList();
+ // --> OD 2006-11-01 #130889#
+ std::vector< std::pair< SwDrawFrmFmt*, SdrObject* > >* pFmtsAndObjs( 0L );
+ const sal_uInt32 nMarkCount( rMrkList.GetMarkCount() );
+ // <--
+ if ( nMarkCount )
+ {
+ // --> OD 2006-11-01 #130889#
+ pFmtsAndObjs = new std::vector< std::pair< SwDrawFrmFmt*, SdrObject* > >[nMarkCount];
+ // <--
+ SdrObject *pMyObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+ if( !pMyObj->GetUpGroup() )
+ {
+ String sDrwFmtNm( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM("DrawObject" )));
+ for ( sal_uInt16 i = 0; i < nMarkCount; ++i )
+ {
+ SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ if ( pObj->IsA( TYPE(SdrObjGroup) ) )
+ {
+ SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
+ SwFmtAnchor aAnch( pContact->GetFmt()->GetAnchor() );
+ SdrObjList *pLst = ((SdrObjGroup*)pObj)->GetSubList();
+
+ SwUndoDrawUnGroup* pUndo = 0;
+ if( bUndo )
+ {
+ pUndo = new SwUndoDrawUnGroup( (SdrObjGroup*)pObj );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ for ( sal_uInt16 i2 = 0; i2 < pLst->GetObjCount(); ++i2 )
+ {
+ SdrObject* pSubObj = pLst->GetObj( i2 );
+ SwDrawFrmFmt *pFmt = MakeDrawFrmFmt( sDrwFmtNm,
+ GetDfltFrmFmt() );
+ pFmt->SetFmtAttr( aAnch );
+ // --> OD 2004-10-25 #i36010# - set layout direction of the position
+ pFmt->SetPositionLayoutDir(
+ text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
+ // <--
+ // --> OD 2006-11-01 #130889#
+ // creation of <SwDrawContact> instances for the group
+ // members and its connection to the Writer layout is
+ // done after intrinsic ungrouping.
+// SwDrawContact* pContact = new SwDrawContact( pFmt, pSubObj );
+// // --> OD 2004-11-22 #i35635#
+// pContact->MoveObjToVisibleLayer( pSubObj );
+// // <--
+// pContact->ConnectToLayout();
+// // OD 2004-04-07 #i26791# - Adjust positioning and
+// // alignment attributes.
+// lcl_AdjustPositioningAttr( pFmt, *pSubObj );
+ pFmtsAndObjs[i].push_back( std::pair< SwDrawFrmFmt*, SdrObject* >( pFmt, pSubObj ) );
+ // <--
+
+ if( bUndo )
+ pUndo->AddObj( i2, pFmt );
+ }
+ }
+ }
+ }
+ }
+ rDrawView.UnGroupMarked();
+ // --> OD 2006-11-01 #130889#
+ // creation of <SwDrawContact> instances for the former group members and
+ // its connection to the Writer layout.
+ for ( sal_uInt32 i = 0; i < nMarkCount; ++i )
+ {
+ SwUndoDrawUnGroupConnectToLayout* pUndo = 0;
+ if( bUndo )
+ {
+ pUndo = new SwUndoDrawUnGroupConnectToLayout();
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ while ( pFmtsAndObjs[i].size() > 0 )
+ {
+ SwDrawFrmFmt* pFmt( pFmtsAndObjs[i].back().first );
+ SdrObject* pObj( pFmtsAndObjs[i].back().second );
+ pFmtsAndObjs[i].pop_back();
+
+ SwDrawContact* pContact = new SwDrawContact( pFmt, pObj );
+ pContact->MoveObjToVisibleLayer( pObj );
+ pContact->ConnectToLayout();
+ lcl_AdjustPositioningAttr( pFmt, *pObj );
+
+ if ( bUndo )
+ {
+ pUndo->AddFmtAndObj( pFmt, pObj );
+ }
+ }
+ }
+ delete [] pFmtsAndObjs;
+ // <--
+}
+
+/*************************************************************************
+|*
+|* SwDoc::DeleteSelection()
+|*
+|* Ersterstellung MA 14. Nov. 95
+|* Letzte Aenderung MA 14. Nov. 95
+|*
+|*************************************************************************/
+
+sal_Bool SwDoc::DeleteSelection( SwDrawView& rDrawView )
+{
+ sal_Bool bCallBase = sal_False;
+ const SdrMarkList &rMrkList = rDrawView.GetMarkedObjectList();
+ if( rMrkList.GetMarkCount() )
+ {
+ GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+ sal_uInt16 i;
+ sal_Bool bDelMarked = sal_True;
+
+ if( 1 == rMrkList.GetMarkCount() )
+ {
+ SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+ if( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ SwFlyFrmFmt* pFrmFmt = (SwFlyFrmFmt*)
+ ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->GetFmt();
+ if( pFrmFmt )
+ {
+ DelLayoutFmt( pFrmFmt );
+ bDelMarked = sal_False;
+ }
+ }
+ }
+
+ for( i = 0; i < rMrkList.GetMarkCount(); ++i )
+ {
+ SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ if( !pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ SwDrawContact *pC = (SwDrawContact*)GetUserCall(pObj);
+ SwDrawFrmFmt *pFrmFmt = (SwDrawFrmFmt*)pC->GetFmt();
+ if( pFrmFmt &&
+ FLY_AS_CHAR == pFrmFmt->GetAnchor().GetAnchorId() )
+ {
+ rDrawView.MarkObj( pObj, rDrawView.Imp().GetPageView(), sal_True );
+ --i;
+ DelLayoutFmt( pFrmFmt );
+ }
+ }
+ }
+
+ if( rMrkList.GetMarkCount() && bDelMarked )
+ {
+ SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+ if( !pObj->GetUpGroup() )
+ {
+ SwUndoDrawDelete *const pUndo =
+ (!GetIDocumentUndoRedo().DoesUndo())
+ ? 0
+ : new SwUndoDrawDelete( (sal_uInt16)rMrkList.GetMarkCount() );
+
+ //ContactObjekte vernichten, Formate sicherstellen.
+ for( i = 0; i < rMrkList.GetMarkCount(); ++i )
+ {
+ const SdrMark& rMark = *rMrkList.GetMark( i );
+ pObj = rMark.GetMarkedSdrObj();
+ SwDrawContact *pContact = (SwDrawContact*)pObj->GetUserCall();
+ if( pContact ) // natuerlich nicht bei gruppierten Objekten
+ {
+ SwDrawFrmFmt *pFmt = (SwDrawFrmFmt*)pContact->GetFmt();
+ // OD 18.06.2003 #108784# - before delete of selection
+ // is performed, marked <SwDrawVirtObj>-objects have to
+ // be replaced by its reference objects.
+ // Thus, assert, if a <SwDrawVirt>-object is found in the mark list.
+ if ( pObj->ISA(SwDrawVirtObj) )
+ {
+ ASSERT( false,
+ "<SwDrawVirtObj> is still marked for delete. application will crash!" );
+ }
+ //loescht sich selbst!
+ pContact->Changed(*pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
+ pObj->SetUserCall( 0 );
+
+ if( pUndo )
+ pUndo->AddObj( i, pFmt, rMark );
+ else
+ DelFrmFmt( pFmt );
+ }
+ }
+
+ if( pUndo )
+ {
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ }
+ bCallBase = sal_True;
+ }
+ SetModified();
+
+ GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+ }
+
+ return bCallBase;
+}
+
+/*************************************************************************
+|*
+|* SwDoc::DeleteSelection()
+|*
+|* Ersterstellung JP 11.01.96
+|* Letzte Aenderung JP 11.01.96
+|*
+|*************************************************************************/
+
+_ZSortFly::_ZSortFly( const SwFrmFmt* pFrmFmt, const SwFmtAnchor* pFlyAn,
+ sal_uInt32 nArrOrdNum )
+ : pFmt( pFrmFmt ), pAnchor( pFlyAn ), nOrdNum( nArrOrdNum )
+{
+ // #i11176#
+ // This also needs to work when no layout exists. Thus, for
+ // FlyFrames an alternative method is used now in that case.
+ SwClientIter aIter( (SwFmt&)*pFmt );
+
+ if( RES_FLYFRMFMT == pFmt->Which() )
+ {
+ if( pFmt->getIDocumentLayoutAccess()->GetRootFrm() )
+ {
+ // Schauen, ob es ein SdrObject dafuer gibt
+ if( aIter.First( TYPE( SwFlyFrm) ) )
+ nOrdNum = ((SwFlyFrm*)aIter())->GetVirtDrawObj()->GetOrdNum();
+ }
+ else
+ {
+ // Schauen, ob es ein SdrObject dafuer gibt
+ if( aIter.First( TYPE(SwFlyDrawContact) ) )
+ nOrdNum = ((SwFlyDrawContact*)aIter())->GetMaster()->GetOrdNum();
+ }
+ }
+ else if( RES_DRAWFRMFMT == pFmt->Which() )
+ {
+ // Schauen, ob es ein SdrObject dafuer gibt
+ if( aIter.First( TYPE(SwDrawContact) ) )
+ nOrdNum = ((SwDrawContact*)aIter())->GetMaster()->GetOrdNum();
+ }
+ else {
+ ASSERT( !this, "was ist das fuer ein Format?" );
+ }
+}
+
+/*************************************************************************/
+// Wird auch vom Sw3-Reader gerufen, wenn ein Fehler beim Einlesen
+// des Drawing Layers auftrat. In diesem Fall wird der Layer komplett
+// neu aufgebaut.
+
+// #75371#
+#include <svx/sxenditm.hxx>
+
+void SwDoc::InitDrawModel()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLog, "SW", "JP93722", "SwDoc::InitDrawModel" );
+
+ //!!Achtung im sw3-Reader (sw3imp.cxx) gibt es aehnlichen Code, der
+ //mitgepfelgt werden muss.
+ if ( pDrawModel )
+ ReleaseDrawModel();
+
+ //DrawPool und EditEnginePool anlegen, diese gehoeren uns und werden
+ //dem Drawing nur mitgegeben. Im ReleaseDrawModel werden die Pools wieder
+ //zerstoert.
+ // 17.2.99: for Bug 73110 - for loading the drawing items. This must
+ // be loaded without RefCounts!
+ SfxItemPool *pSdrPool = new SdrItemPool( &GetAttrPool() );
+ // #75371# change DefaultItems for the SdrEdgeObj distance items
+ // to TWIPS.
+ if(pSdrPool)
+ {
+ const long nDefEdgeDist = ((500 * 72) / 127); // 1/100th mm in twips
+ pSdrPool->SetPoolDefaultItem(SdrEdgeNode1HorzDistItem(nDefEdgeDist));
+ pSdrPool->SetPoolDefaultItem(SdrEdgeNode1VertDistItem(nDefEdgeDist));
+ pSdrPool->SetPoolDefaultItem(SdrEdgeNode2HorzDistItem(nDefEdgeDist));
+ pSdrPool->SetPoolDefaultItem(SdrEdgeNode2VertDistItem(nDefEdgeDist));
+
+ // #i33700#
+ // Set shadow distance defaults as PoolDefaultItems. Details see bug.
+ pSdrPool->SetPoolDefaultItem(SdrShadowXDistItem((300 * 72) / 127));
+ pSdrPool->SetPoolDefaultItem(SdrShadowYDistItem((300 * 72) / 127));
+ }
+ SfxItemPool *pEEgPool = EditEngine::CreatePool( sal_False );
+ pSdrPool->SetSecondaryPool( pEEgPool );
+ if ( !GetAttrPool().GetFrozenIdRanges () )
+ GetAttrPool().FreezeIdRanges();
+ else
+ pSdrPool->FreezeIdRanges();
+
+ // SJ: #95129# set FontHeight pool defaults without changing static SdrEngineDefaults
+ GetAttrPool().SetPoolDefaultItem(SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT ));
+
+ RTL_LOGFILE_CONTEXT_TRACE( aLog, "before create DrawDocument" );
+ //Das SdrModel gehoert dem Dokument, wir haben immer zwei Layer und eine
+ //Seite.
+ pDrawModel = new SwDrawDocument( this );
+
+ pDrawModel->EnableUndo( GetIDocumentUndoRedo().DoesUndo() );
+
+ String sLayerNm;
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("Hell" ));
+ nHell = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
+
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("Heaven" ));
+ nHeaven = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
+
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("Controls" ));
+ nControls = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
+
+ // OD 25.06.2003 #108784# - add invisible layers corresponding to the
+ // visible ones.
+ {
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleHell" ));
+ nInvisibleHell = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
+
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleHeaven" ));
+ nInvisibleHeaven = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
+
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleControls" ));
+ nInvisibleControls = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
+ }
+
+ pDrawModel->InsertPage( pDrawModel->AllocPage( sal_False ) );
+ RTL_LOGFILE_CONTEXT_TRACE( aLog, "after create DrawDocument" );
+
+ RTL_LOGFILE_CONTEXT_TRACE( aLog, "before create Spellchecker/Hyphenator" );
+ SdrOutliner& rOutliner = pDrawModel->GetDrawOutliner();
+ uno::Reference< XSpellChecker1 > xSpell = ::GetSpellChecker();
+ rOutliner.SetSpeller( xSpell );
+ uno::Reference<XHyphenator> xHyphenator( ::GetHyphenator() );
+ rOutliner.SetHyphenator( xHyphenator );
+ RTL_LOGFILE_CONTEXT_TRACE( aLog, "after create Spellchecker/Hyphenator" );
+
+ SetCalcFieldValueHdl(&rOutliner);
+ SetCalcFieldValueHdl(&pDrawModel->GetHitTestOutliner());
+
+ //JP 16.07.98: Bug 50193 - Linkmanager am Model setzen, damit
+ // dort ggfs. verlinkte Grafiken eingefuegt werden koennen
+ //JP 28.01.99: der WinWord Import benoetigt ihn auch
+ pDrawModel->SetLinkManager( &GetLinkManager() );
+ pDrawModel->SetAddExtLeading( get(IDocumentSettingAccess::ADD_EXT_LEADING) );
+
+ OutputDevice* pRefDev = getReferenceDevice( false );
+ if ( pRefDev )
+ pDrawModel->SetRefDevice( pRefDev );
+
+ pDrawModel->SetNotifyUndoActionHdl( LINK( this, SwDoc, AddDrawUndo ));
+ if ( pLayout )
+ {
+ pLayout->SetDrawPage( pDrawModel->GetPage( 0 ) );
+ pLayout->GetDrawPage()->SetSize( pLayout->Frm().SSize() );
+ }
+}
+
+/** method to notify drawing page view about the invisible layers
+
+ OD 26.06.2003 #108784#
+
+ @author OD
+*/
+void SwDoc::NotifyInvisibleLayers( SdrPageView& _rSdrPageView )
+{
+ String sLayerNm;
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleHell" ));
+ _rSdrPageView.SetLayerVisible( sLayerNm, sal_False );
+
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleHeaven" ));
+ _rSdrPageView.SetLayerVisible( sLayerNm, sal_False );
+
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleControls" ));
+ _rSdrPageView.SetLayerVisible( sLayerNm, sal_False );
+}
+
+/** method to determine, if a layer ID belongs to the visible ones.
+
+ OD 25.06.2003 #108784#
+ Note: If given layer ID is unknown, method asserts and returns <false>.
+
+ @author OD
+*/
+bool SwDoc::IsVisibleLayerId( const SdrLayerID& _nLayerId ) const
+{
+ bool bRetVal;
+
+ if ( _nLayerId == GetHeavenId() ||
+ _nLayerId == GetHellId() ||
+ _nLayerId == GetControlsId() )
+ {
+ bRetVal = true;
+ }
+ else if ( _nLayerId == GetInvisibleHeavenId() ||
+ _nLayerId == GetInvisibleHellId() ||
+ _nLayerId == GetInvisibleControlsId() )
+ {
+ bRetVal = false;
+ }
+ else
+ {
+ ASSERT( false, "<SwDoc::IsVisibleLayerId(..)> - unknown layer ID." );
+ bRetVal = false;
+ }
+
+ return bRetVal;
+}
+
+/** method to determine, if the corresponding visible layer ID for a invisible one.
+
+ OD 25.06.2003 #108784#
+ Note: If given layer ID is a visible one, method returns given layer ID.
+ Note: If given layer ID is unknown, method returns given layer ID.
+
+ @author OD
+*/
+SdrLayerID SwDoc::GetVisibleLayerIdByInvisibleOne( const SdrLayerID& _nInvisibleLayerId )
+{
+ SdrLayerID nVisibleLayerId;
+
+ if ( _nInvisibleLayerId == GetInvisibleHeavenId() )
+ {
+ nVisibleLayerId = GetHeavenId();
+ }
+ else if ( _nInvisibleLayerId == GetInvisibleHellId() )
+ {
+ nVisibleLayerId = GetHellId();
+ }
+ else if ( _nInvisibleLayerId == GetInvisibleControlsId() )
+ {
+ nVisibleLayerId = GetControlsId();
+ }
+ else if ( _nInvisibleLayerId == GetHeavenId() ||
+ _nInvisibleLayerId == GetHellId() ||
+ _nInvisibleLayerId == GetControlsId() )
+ {
+ ASSERT( false, "<SwDoc::GetVisibleLayerIdByInvisibleOne(..)> - given layer ID already an invisible one." );
+ nVisibleLayerId = _nInvisibleLayerId;
+ }
+ else
+ {
+ ASSERT( false, "<SwDoc::GetVisibleLayerIdByInvisibleOne(..)> - given layer ID is unknown." );
+ nVisibleLayerId = _nInvisibleLayerId;
+ }
+
+ return nVisibleLayerId;
+}
+
+/** method to determine, if the corresponding invisible layer ID for a visible one.
+
+ OD 25.06.2003 #108784#
+ Note: If given layer ID is a invisible one, method returns given layer ID.
+ Note: If given layer ID is unknown, method returns given layer ID.
+
+ @author OD
+*/
+SdrLayerID SwDoc::GetInvisibleLayerIdByVisibleOne( const SdrLayerID& _nVisibleLayerId )
+{
+ SdrLayerID nInvisibleLayerId;
+
+ if ( _nVisibleLayerId == GetHeavenId() )
+ {
+ nInvisibleLayerId = GetInvisibleHeavenId();
+ }
+ else if ( _nVisibleLayerId == GetHellId() )
+ {
+ nInvisibleLayerId = GetInvisibleHellId();
+ }
+ else if ( _nVisibleLayerId == GetControlsId() )
+ {
+ nInvisibleLayerId = GetInvisibleControlsId();
+ }
+ else if ( _nVisibleLayerId == GetInvisibleHeavenId() ||
+ _nVisibleLayerId == GetInvisibleHellId() ||
+ _nVisibleLayerId == GetInvisibleControlsId() )
+ {
+ ASSERT( false, "<SwDoc::GetInvisibleLayerIdByVisibleOne(..)> - given layer ID already an invisible one." );
+ nInvisibleLayerId = _nVisibleLayerId;
+ }
+ else
+ {
+ ASSERT( false, "<SwDoc::GetInvisibleLayerIdByVisibleOne(..)> - given layer ID is unknown." );
+ nInvisibleLayerId = _nVisibleLayerId;
+ }
+
+ return nInvisibleLayerId;
+}
+
+/*************************************************************************/
+
+
+void SwDoc::ReleaseDrawModel()
+{
+ if ( pDrawModel )
+ {
+ //!!Den code im sw3io fuer Einfuegen Dokument mitpflegen!!
+
+ delete pDrawModel; pDrawModel = 0;
+ SfxItemPool *pSdrPool = GetAttrPool().GetSecondaryPool();
+
+ ASSERT( pSdrPool, "missing Pool" );
+ SfxItemPool *pEEgPool = pSdrPool->GetSecondaryPool();
+ ASSERT( !pEEgPool->GetSecondaryPool(), "i don't accept additional pools");
+ pSdrPool->Delete(); //Erst die Items vernichten lassen,
+ //dann erst die Verkettung loesen
+ GetAttrPool().SetSecondaryPool( 0 ); //Der ist ein muss!
+ pSdrPool->SetSecondaryPool( 0 ); //Der ist sicherer
+ SfxItemPool::Free(pSdrPool);
+ SfxItemPool::Free(pEEgPool);
+ }
+}
+
+/*************************************************************************/
+
+
+SdrModel* SwDoc::_MakeDrawModel()
+{
+ ASSERT( !pDrawModel, "_MakeDrawModel: Why?" );
+ InitDrawModel();
+ if ( pLayout && pLayout->GetCurrShell() )
+ {
+ ViewShell* pTmp = pLayout->GetCurrShell();
+ do
+ {
+ pTmp->MakeDrawView();
+ pTmp = (ViewShell*) pTmp->GetNext();
+ } while ( pTmp != pLayout->GetCurrShell() );
+
+ //Broadcast, damit die FormShell mit der DrawView verbunden werden kann
+ if( GetDocShell() )
+ {
+ SfxSimpleHint aHnt( SW_BROADCAST_DRAWVIEWS_CREATED );
+ GetDocShell()->Broadcast( aHnt );
+ }
+ }
+ return pDrawModel;
+}
+
+/*************************************************************************/
+
+void SwDoc::DrawNotifyUndoHdl()
+{
+ pDrawModel->SetNotifyUndoActionHdl( Link() );
+}
+
+/*************************************************************************
+*
+* Am Outliner Link auf Methode fuer Felddarstellung in Editobjekten setzen
+*
+*************************************************************************/
+
+void SwDoc::SetCalcFieldValueHdl(Outliner* pOutliner)
+{
+ pOutliner->SetCalcFieldValueHdl(LINK(this, SwDoc, CalcFieldValueHdl));
+}
+
+/*************************************************************************
+|*
+|* Felder bzw URLs im Outliner erkennen und Darstellung festlegen
+|*
+\************************************************************************/
+
+IMPL_LINK(SwDoc, CalcFieldValueHdl, EditFieldInfo*, pInfo)
+{
+ if (pInfo)
+ {
+ const SvxFieldItem& rField = pInfo->GetField();
+ const SvxFieldData* pField = rField.GetField();
+
+ if (pField && pField->ISA(SvxDateField))
+ {
+ /******************************************************************
+ * Date-Field
+ ******************************************************************/
+ pInfo->SetRepresentation(
+ ((const SvxDateField*) pField)->GetFormatted(
+ *GetNumberFormatter( sal_True ), LANGUAGE_SYSTEM) );
+ }
+ else if (pField && pField->ISA(SvxURLField))
+ {
+ /******************************************************************
+ * URL-Field
+ ******************************************************************/
+
+ switch ( ((const SvxURLField*) pField)->GetFormat() )
+ {
+ case SVXURLFORMAT_APPDEFAULT: //!!! einstellbar an App???
+ case SVXURLFORMAT_REPR:
+ {
+ pInfo->SetRepresentation(
+ ((const SvxURLField*)pField)->GetRepresentation());
+ }
+ break;
+
+ case SVXURLFORMAT_URL:
+ {
+ pInfo->SetRepresentation(
+ ((const SvxURLField*)pField)->GetURL());
+ }
+ break;
+ }
+
+ sal_uInt16 nChrFmt;
+
+ if (IsVisitedURL(((const SvxURLField*)pField)->GetURL()))
+ nChrFmt = RES_POOLCHR_INET_VISIT;
+ else
+ nChrFmt = RES_POOLCHR_INET_NORMAL;
+
+ SwFmt *pFmt = GetCharFmtFromPool(nChrFmt);
+
+ Color aColor(COL_LIGHTBLUE);
+ if (pFmt)
+ aColor = pFmt->GetColor().GetValue();
+
+ pInfo->SetTxtColor(aColor);
+ }
+ else if (pField && pField->ISA(SdrMeasureField))
+ {
+ /******************************************************************
+ * Measure-Field
+ ******************************************************************/
+ pInfo->ClearFldColor();
+ }
+ else if ( pField && pField->ISA(SvxExtTimeField))
+ {
+ /******************************************************************
+ * Time-Field
+ ******************************************************************/
+ pInfo->SetRepresentation(
+ ((const SvxExtTimeField*) pField)->GetFormatted(
+ *GetNumberFormatter( sal_True ), LANGUAGE_SYSTEM) );
+ }
+ else
+ {
+ DBG_ERROR("unbekannter Feldbefehl");
+ pInfo->SetRepresentation( String( '?' ) );
+ }
+ }
+
+ return(0);
+}
+
+/* TFFDI: The functions formerly declared 'inline'
+ */
+const SdrModel* SwDoc::GetDrawModel() const { return pDrawModel; }
+SdrModel* SwDoc::GetDrawModel() { return pDrawModel; }
+SdrLayerID SwDoc::GetHeavenId() const { return nHeaven; }
+SdrLayerID SwDoc::GetHellId() const { return nHell; }
+SdrLayerID SwDoc::GetControlsId() const { return nControls; }
+SdrLayerID SwDoc::GetInvisibleHeavenId() const { return nInvisibleHeaven; }
+SdrLayerID SwDoc::GetInvisibleHellId() const { return nInvisibleHell; }
+SdrLayerID SwDoc::GetInvisibleControlsId() const { return nInvisibleControls; }
+SdrModel* SwDoc::GetOrCreateDrawModel() { return GetDrawModel() ? GetDrawModel() : _MakeDrawModel(); }
+
+// --> OD 2006-03-14 #i62875#
+namespace docfunc
+{
+ bool ExistsDrawObjs( SwDoc& p_rDoc )
+ {
+ bool bExistsDrawObjs( false );
+
+ if ( p_rDoc.GetDrawModel() &&
+ p_rDoc.GetDrawModel()->GetPage( 0 ) )
+ {
+ const SdrPage& rSdrPage( *(p_rDoc.GetDrawModel()->GetPage( 0 )) );
+
+ SdrObjListIter aIter( rSdrPage, IM_FLAT );
+ while( aIter.IsMore() )
+ {
+ SdrObject* pObj( aIter.Next() );
+ if ( !dynamic_cast<SwVirtFlyDrawObj*>(pObj) &&
+ !dynamic_cast<SwFlyDrawObj*>(pObj) )
+ {
+ bExistsDrawObjs = true;
+ break;
+ }
+ }
+ }
+
+ return bExistsDrawObjs;
+ }
+
+ bool AllDrawObjsOnPage( SwDoc& p_rDoc )
+ {
+ bool bAllDrawObjsOnPage( true );
+
+ if ( p_rDoc.GetDrawModel() &&
+ p_rDoc.GetDrawModel()->GetPage( 0 ) )
+ {
+ const SdrPage& rSdrPage( *(p_rDoc.GetDrawModel()->GetPage( 0 )) );
+
+ SdrObjListIter aIter( rSdrPage, IM_FLAT );
+ while( aIter.IsMore() )
+ {
+ SdrObject* pObj( aIter.Next() );
+ if ( !dynamic_cast<SwVirtFlyDrawObj*>(pObj) &&
+ !dynamic_cast<SwFlyDrawObj*>(pObj) )
+ {
+ SwDrawContact* pDrawContact =
+ dynamic_cast<SwDrawContact*>(::GetUserCall( pObj ));
+ if ( pDrawContact )
+ {
+ SwAnchoredDrawObject* pAnchoredDrawObj =
+ dynamic_cast<SwAnchoredDrawObject*>(pDrawContact->GetAnchoredObj( pObj ));
+
+ // error handling
+ {
+ if ( !pAnchoredDrawObj )
+ {
+ ASSERT( false,
+ "<docfunc::AllDrawObjsOnPage() - missing anchored draw object" );
+ bAllDrawObjsOnPage = false;
+ break;
+ }
+ }
+
+ if ( pAnchoredDrawObj->NotYetPositioned() )
+ {
+ // The drawing object isn't yet layouted.
+ // Thus, it isn't known, if all drawing objects are on page.
+ bAllDrawObjsOnPage = false;
+ break;
+ }
+ else if ( pAnchoredDrawObj->IsOutsidePage() )
+ {
+ bAllDrawObjsOnPage = false;
+ break;
+ }
+ }
+ else
+ {
+ // contact object of drawing object doesn't exists.
+ // Thus, the drawing object isn't yet positioned.
+ // Thus, it isn't known, if all drawing objects are on page.
+ bAllDrawObjsOnPage = false;
+ break;
+ }
+ }
+ }
+ }
+
+ return bAllDrawObjsOnPage;
+ }
+}
+// <--
+
diff --git a/sw/source/core/doc/docedt.cxx b/sw/source/core/doc/docedt.cxx
new file mode 100644
index 000000000000..6e5c259a9d04
--- /dev/null
+++ b/sw/source/core/doc/docedt.cxx
@@ -0,0 +1,2845 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <string.h> // fuer strchr()
+#include <hintids.hxx>
+
+#include <vcl/sound.hxx>
+#include <editeng/cscoitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <linguistic/lngprops.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/i18n/WordType.hdl>
+#include <unotools/charclass.hxx>
+#include <unotools/transliterationwrapper.hxx>
+#include <fmtanchr.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtpdsc.hxx>
+#include <txtftn.hxx>
+#include <acorrect.hxx> // Autokorrektur
+#include <IMark.hxx> // fuer SwBookmark
+#include <cntfrm.hxx> // fuers Spell
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <UndoManager.hxx>
+#include <docsh.hxx>
+#include <docary.hxx>
+#include <doctxm.hxx> // beim Move: Verzeichnisse korrigieren
+#include <ftnidx.hxx>
+#include <ftninfo.hxx>
+#include <mdiexp.hxx> // Statusanzeige
+#include <mvsave.hxx> // Strukturen zum Sichern beim Move/Delete
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <redline.hxx>
+#include <rootfrm.hxx> // fuers UpdateFtn
+#include <splargs.hxx> // fuer Spell
+#include <swtable.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <txtfrm.hxx>
+#include <hints.hxx>
+#include <UndoSplitMove.hxx>
+#include <UndoRedline.hxx>
+#include <UndoOverwrite.hxx>
+#include <UndoInsert.hxx>
+#include <UndoDelete.hxx>
+#include <breakit.hxx>
+#include <hhcwrp.hxx>
+#include <breakit.hxx>
+#include <vcl/msgbox.hxx>
+#include "comcore.hrc"
+#include "editsh.hxx"
+#include <unoflatpara.hxx>
+#include <SwGrammarMarkUp.hxx>
+
+#include <vector>
+
+using ::rtl::OUString;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::linguistic2;
+using namespace ::com::sun::star::i18n;
+
+//using namespace ::utl;
+#ifndef S2U
+#define S2U(rString) OUString::createFromAscii(rString)
+#endif
+
+struct _SaveRedline
+{
+ SwRedline* pRedl;
+ sal_uInt32 nStt, nEnd;
+ xub_StrLen nSttCnt, nEndCnt;
+
+ _SaveRedline( SwRedline* pR, const SwNodeIndex& rSttIdx )
+ : pRedl( pR )
+ {
+ const SwPosition* pStt = pR->Start(),
+ * pEnd = pR->GetMark() == pStt ? pR->GetPoint() : pR->GetMark();
+ sal_uInt32 nSttIdx = rSttIdx.GetIndex();
+ nStt = pStt->nNode.GetIndex() - nSttIdx;
+ nSttCnt = pStt->nContent.GetIndex();
+ if( pR->HasMark() )
+ {
+ nEnd = pEnd->nNode.GetIndex() - nSttIdx;
+ nEndCnt = pEnd->nContent.GetIndex();
+ }
+
+ pRedl->GetPoint()->nNode = 0;
+ pRedl->GetPoint()->nContent.Assign( 0, 0 );
+ pRedl->GetMark()->nNode = 0;
+ pRedl->GetMark()->nContent.Assign( 0, 0 );
+ }
+
+ _SaveRedline( SwRedline* pR, const SwPosition& rPos )
+ : pRedl( pR )
+ {
+ const SwPosition* pStt = pR->Start(),
+ * pEnd = pR->GetMark() == pStt ? pR->GetPoint() : pR->GetMark();
+ sal_uInt32 nSttIdx = rPos.nNode.GetIndex();
+ nStt = pStt->nNode.GetIndex() - nSttIdx;
+ nSttCnt = pStt->nContent.GetIndex();
+ if( nStt == 0 )
+ nSttCnt = nSttCnt - rPos.nContent.GetIndex();
+ if( pR->HasMark() )
+ {
+ nEnd = pEnd->nNode.GetIndex() - nSttIdx;
+ nEndCnt = pEnd->nContent.GetIndex();
+ if( nEnd == 0 )
+ nEndCnt = nEndCnt - rPos.nContent.GetIndex();
+ }
+
+ pRedl->GetPoint()->nNode = 0;
+ pRedl->GetPoint()->nContent.Assign( 0, 0 );
+ pRedl->GetMark()->nNode = 0;
+ pRedl->GetMark()->nContent.Assign( 0, 0 );
+ }
+
+ void SetPos( sal_uInt32 nInsPos )
+ {
+ pRedl->GetPoint()->nNode = nInsPos + nStt;
+ pRedl->GetPoint()->nContent.Assign( pRedl->GetCntntNode(), nSttCnt );
+ if( pRedl->HasMark() )
+ {
+ pRedl->GetMark()->nNode = nInsPos + nEnd;
+ pRedl->GetMark()->nContent.Assign( pRedl->GetCntntNode(sal_False), nEndCnt );
+ }
+ }
+
+ void SetPos( const SwPosition& aPos )
+ {
+ pRedl->GetPoint()->nNode = aPos.nNode.GetIndex() + nStt;
+ pRedl->GetPoint()->nContent.Assign( pRedl->GetCntntNode(), nSttCnt + ( nStt == 0 ? aPos.nContent.GetIndex() : 0 ) );
+ if( pRedl->HasMark() )
+ {
+ pRedl->GetMark()->nNode = aPos.nNode.GetIndex() + nEnd;
+ pRedl->GetMark()->nContent.Assign( pRedl->GetCntntNode(sal_False), nEndCnt + ( nEnd == 0 ? aPos.nContent.GetIndex() : 0 ) );
+ }
+ }
+};
+
+SV_DECL_PTRARR_DEL( _SaveRedlines, _SaveRedline*, 0, 4 )
+
+SV_IMPL_VARARR( _SaveFlyArr, _SaveFly )
+SV_IMPL_PTRARR( _SaveRedlines, _SaveRedline* )
+
+bool lcl_MayOverwrite( const SwTxtNode *pNode, const xub_StrLen nPos )
+{
+ sal_Unicode cChr = pNode->GetTxt().GetChar( nPos );
+ return !( ( CH_TXTATR_BREAKWORD == cChr || CH_TXTATR_INWORD == cChr ) &&
+ (0 != pNode->GetTxtAttrForCharAt( nPos ) ) );
+}
+
+void lcl_SkipAttr( const SwTxtNode *pNode, SwIndex &rIdx, xub_StrLen &rStart )
+{
+ if( !lcl_MayOverwrite( pNode, rStart ) )
+ {
+ // ueberspringe alle SonderAttribute
+ do {
+ // "Beep" bei jedem ausgelassenen
+ Sound::Beep(SOUND_ERROR);
+ rIdx++;
+ } while( (rStart = rIdx.GetIndex()) < pNode->GetTxt().Len()
+ && !lcl_MayOverwrite(pNode, rStart) );
+ }
+}
+
+// -----------------------------------------------------------------
+
+void _RestFlyInRange( _SaveFlyArr & rArr, const SwNodeIndex& rSttIdx,
+ const SwNodeIndex* pInsertPos )
+{
+ SwPosition aPos( rSttIdx );
+ for( sal_uInt16 n = 0; n < rArr.Count(); ++n )
+ {
+ // neuen Anker anlegen
+ _SaveFly& rSave = rArr[n];
+ SwFrmFmt* pFmt = rSave.pFrmFmt;
+
+ if( rSave.bInsertPosition )
+ {
+ if( pInsertPos != NULL )
+ aPos.nNode = *pInsertPos;
+ else
+ aPos.nNode = rSttIdx.GetIndex();
+ }
+ else
+ aPos.nNode = rSttIdx.GetIndex() + rSave.nNdDiff;
+
+ aPos.nContent.Assign( 0, 0 );
+ SwFmtAnchor aAnchor( pFmt->GetAnchor() );
+ aAnchor.SetAnchor( &aPos );
+ pFmt->GetDoc()->GetSpzFrmFmts()->Insert(
+ pFmt, pFmt->GetDoc()->GetSpzFrmFmts()->Count() );
+ pFmt->SetFmtAttr( aAnchor );
+ SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode();
+ if( pCNd && pCNd->GetFrm( 0, 0, sal_False ) )
+ pFmt->MakeFrms();
+ }
+}
+
+void _SaveFlyInRange( const SwNodeRange& rRg, _SaveFlyArr& rArr )
+{
+ SwSpzFrmFmts& rFmts = *rRg.aStart.GetNode().GetDoc()->GetSpzFrmFmts();
+ for( sal_uInt16 n = 0; n < rFmts.Count(); ++n )
+ {
+ SwFrmFmt *const pFmt = static_cast<SwFrmFmt*>(rFmts[n]);
+ SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
+ (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
+ rRg.aStart <= pAPos->nNode && pAPos->nNode < rRg.aEnd )
+ {
+ _SaveFly aSave( pAPos->nNode.GetIndex() - rRg.aStart.GetIndex(),
+ pFmt, sal_False );
+ rArr.Insert( aSave, rArr.Count());
+ pFmt->DelFrms();
+ rFmts.Remove( n--, 1 );
+ }
+ }
+}
+
+void _SaveFlyInRange( const SwPaM& rPam, const SwNodeIndex& rInsPos,
+ _SaveFlyArr& rArr, bool bMoveAllFlys )
+{
+ SwSpzFrmFmts& rFmts = *rPam.GetPoint()->nNode.GetNode().GetDoc()->GetSpzFrmFmts();
+ SwFrmFmt* pFmt;
+ const SwFmtAnchor* pAnchor;
+
+ const SwPosition* pPos = rPam.Start();
+ const SwNodeIndex& rSttNdIdx = pPos->nNode;
+ short nSttOff = (!bMoveAllFlys && rSttNdIdx.GetNode().IsCntntNode() &&
+ pPos->nContent.GetIndex()) ? 1 : 0;
+
+ pPos = rPam.GetPoint() == pPos ? rPam.GetMark() : rPam.GetPoint();
+ const SwNodeIndex& rEndNdIdx = pPos->nNode;
+ short nOff = ( bMoveAllFlys || ( rEndNdIdx.GetNode().IsCntntNode() &&
+ pPos->nContent == rEndNdIdx.GetNode().GetCntntNode()->Len() ))
+ ? 0 : 1;
+
+ const SwNodeIndex* pCntntIdx;
+
+ for( sal_uInt16 n = 0; n < rFmts.Count(); ++n )
+ {
+ sal_Bool bInsPos = sal_False;
+ pFmt = (SwFrmFmt*)rFmts[n];
+ pAnchor = &pFmt->GetAnchor();
+ const SwPosition* pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
+ (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
+ // nicht verschieben, wenn die InsPos im CntntBereich vom Fly ist
+ ( 0 == ( pCntntIdx = pFmt->GetCntnt().GetCntntIdx() ) ||
+ !( *pCntntIdx < rInsPos &&
+ rInsPos < pCntntIdx->GetNode().EndOfSectionIndex() )) )
+ {
+ if( !bMoveAllFlys && rEndNdIdx == pAPos->nNode )
+ {
+ // wenn nur teil vom EndNode oder der EndNode und SttNode
+ // identisch sind, chaos::Anchor nicht anfassen
+ if( rSttNdIdx != pAPos->nNode )
+ {
+ // Anker nur an Anfang/Ende haengen
+ SwPosition aPos( rSttNdIdx );
+ SwFmtAnchor aAnchor( *pAnchor );
+ aAnchor.SetAnchor( &aPos );
+ pFmt->SetFmtAttr( aAnchor );
+// ((SwFmtAnchor*)pAnchor)->SetAnchor( &aPos );
+ }
+ }
+ else if( ( rSttNdIdx.GetIndex() + nSttOff <= pAPos->nNode.GetIndex()
+ && pAPos->nNode.GetIndex() <= rEndNdIdx.GetIndex() - nOff ) ||
+ 0 != ( bInsPos = rInsPos == pAPos->nNode ))
+
+ {
+ _SaveFly aSave( pAPos->nNode.GetIndex() - rSttNdIdx.GetIndex(),
+ pFmt, bInsPos );
+ rArr.Insert( aSave, rArr.Count());
+ pFmt->DelFrms();
+ rFmts.Remove( n--, 1 );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------
+
+// loesche und verschiebe alle "Fly's am Absatz", die in der SSelection
+// liegen. Steht am SPoint ein Fly, wird dieser auf den Mark verschoben.
+
+void DelFlyInRange( const SwNodeIndex& rMkNdIdx,
+ const SwNodeIndex& rPtNdIdx )
+{
+ const sal_Bool bDelFwrd = rMkNdIdx.GetIndex() <= rPtNdIdx.GetIndex();
+
+ SwDoc* pDoc = rMkNdIdx.GetNode().GetDoc();
+ SwSpzFrmFmts& rTbl = *pDoc->GetSpzFrmFmts();
+ for ( sal_uInt16 i = rTbl.Count(); i; )
+ {
+ SwFrmFmt *pFmt = rTbl[--i];
+ const SwFmtAnchor &rAnch = pFmt->GetAnchor();
+ SwPosition const*const pAPos = rAnch.GetCntntAnchor();
+ if (pAPos &&
+ ((rAnch.GetAnchorId() == FLY_AT_PARA) ||
+ (rAnch.GetAnchorId() == FLY_AT_CHAR)) &&
+ ( bDelFwrd
+ ? rMkNdIdx < pAPos->nNode && pAPos->nNode <= rPtNdIdx
+ : rPtNdIdx <= pAPos->nNode && pAPos->nNode < rMkNdIdx ))
+ {
+ // nur den Anker verschieben ??
+ if( rPtNdIdx == pAPos->nNode )
+ {
+ SwFmtAnchor aAnch( pFmt->GetAnchor() );
+ SwPosition aPos( rMkNdIdx );
+ aAnch.SetAnchor( &aPos );
+ pFmt->SetFmtAttr( aAnch );
+ }
+ else
+ {
+ // wird der Fly geloescht muss auch im seinem Inhalt alle
+ // Flys geloescht werden !!
+ const SwFmtCntnt &rCntnt = pFmt->GetCntnt();
+ if( rCntnt.GetCntntIdx() )
+ {
+ DelFlyInRange( *rCntnt.GetCntntIdx(),
+ SwNodeIndex( *rCntnt.GetCntntIdx()->
+ GetNode().EndOfSectionNode() ));
+ // Position kann sich verschoben haben !
+ if( i > rTbl.Count() )
+ i = rTbl.Count();
+ else if( pFmt != rTbl[i] )
+ i = rTbl.GetPos( pFmt );
+ }
+
+ pDoc->DelLayoutFmt( pFmt );
+
+ // --> FME 2004-10-06 #117913# DelLayoutFmt can also
+ // trigger the deletion of objects.
+ if( i > rTbl.Count() )
+ i = rTbl.Count();
+ // <--
+ }
+ }
+ }
+}
+
+
+bool lcl_SaveFtn( const SwNodeIndex& rSttNd, const SwNodeIndex& rEndNd,
+ const SwNodeIndex& rInsPos,
+ SwFtnIdxs& rFtnArr, SwFtnIdxs& rSaveArr,
+ const SwIndex* pSttCnt = 0, const SwIndex* pEndCnt = 0 )
+{
+ bool bUpdateFtn = sal_False;
+ const SwNodes& rNds = rInsPos.GetNodes();
+ const bool bDelFtn = rInsPos.GetIndex() < rNds.GetEndOfAutotext().GetIndex() &&
+ rSttNd.GetIndex() >= rNds.GetEndOfAutotext().GetIndex();
+ const bool bSaveFtn = !bDelFtn &&
+ rInsPos.GetIndex() >= rNds.GetEndOfExtras().GetIndex();
+ if( rFtnArr.Count() )
+ {
+
+ sal_uInt16 nPos;
+ rFtnArr.SeekEntry( rSttNd, &nPos );
+ SwTxtFtn* pSrch;
+ const SwNode* pFtnNd;
+
+ // loesche/sicher erstmal alle, die dahinter stehen
+ while( nPos < rFtnArr.Count() && ( pFtnNd =
+ &( pSrch = rFtnArr[ nPos ] )->GetTxtNode())->GetIndex()
+ <= rEndNd.GetIndex() )
+ {
+ xub_StrLen nFtnSttIdx = *pSrch->GetStart();
+ if( ( pEndCnt && pSttCnt )
+ ? (( &rSttNd.GetNode() == pFtnNd &&
+ pSttCnt->GetIndex() > nFtnSttIdx) ||
+ ( &rEndNd.GetNode() == pFtnNd &&
+ nFtnSttIdx >= pEndCnt->GetIndex() ))
+ : ( &rEndNd.GetNode() == pFtnNd ))
+ {
+ ++nPos; // weiter suchen
+ }
+ else
+ {
+ // dann weg damit
+ if( bDelFtn )
+ {
+ SwTxtNode& rTxtNd = (SwTxtNode&)pSrch->GetTxtNode();
+ SwIndex aIdx( &rTxtNd, nFtnSttIdx );
+ rTxtNd.EraseText( aIdx, 1 );
+ }
+ else
+ {
+ pSrch->DelFrms();
+ rFtnArr.Remove( nPos );
+ if( bSaveFtn )
+ rSaveArr.Insert( pSrch );
+ }
+ bUpdateFtn = sal_True;
+ }
+ }
+
+ while( nPos-- && ( pFtnNd = &( pSrch = rFtnArr[ nPos ] )->
+ GetTxtNode())->GetIndex() >= rSttNd.GetIndex() )
+ {
+ xub_StrLen nFtnSttIdx = *pSrch->GetStart();
+ if( !pEndCnt || !pSttCnt ||
+ !( (( &rSttNd.GetNode() == pFtnNd &&
+ pSttCnt->GetIndex() > nFtnSttIdx ) ||
+ ( &rEndNd.GetNode() == pFtnNd &&
+ nFtnSttIdx >= pEndCnt->GetIndex() )) ))
+ {
+ if( bDelFtn )
+ {
+ // dann weg damit
+ SwTxtNode& rTxtNd = (SwTxtNode&)pSrch->GetTxtNode();
+ SwIndex aIdx( &rTxtNd, nFtnSttIdx );
+ rTxtNd.EraseText( aIdx, 1 );
+ }
+ else
+ {
+ pSrch->DelFrms();
+ rFtnArr.Remove( nPos );
+ if( bSaveFtn )
+ rSaveArr.Insert( pSrch );
+ }
+ bUpdateFtn = sal_True;
+ }
+ }
+ }
+ // When moving from redline section into document content section, e.g.
+ // after loading a document with (delete-)redlines, the footnote array
+ // has to be adjusted... (#i70572)
+ if( bSaveFtn )
+ {
+ SwNodeIndex aIdx( rSttNd );
+ while( aIdx < rEndNd ) // Check the moved section
+ {
+ SwNode* pNode = &aIdx.GetNode();
+ if( pNode->IsTxtNode() ) // Looking for text nodes...
+ {
+ SwpHints *pHints =
+ static_cast<SwTxtNode*>(pNode)->GetpSwpHints();
+ if( pHints && pHints->HasFtn() ) //...with footnotes
+ {
+ bUpdateFtn = sal_True; // Heureka
+ sal_uInt16 nCount = pHints->Count();
+ for( sal_uInt16 i = 0; i < nCount; ++i )
+ {
+ SwTxtAttr *pAttr = pHints->GetTextHint( i );
+ if ( pAttr->Which() == RES_TXTATR_FTN )
+ {
+ rSaveArr.Insert( static_cast<SwTxtFtn*>(pAttr) );
+ }
+ }
+ }
+ }
+ ++aIdx;
+ }
+ }
+ return bUpdateFtn;
+}
+
+void lcl_SaveRedlines( const SwPaM& aPam, _SaveRedlines& rArr )
+{
+ SwDoc* pDoc = aPam.GetNode()->GetDoc();
+
+ const SwPosition* pStart = aPam.Start();
+ const SwPosition* pEnd = aPam.End();
+
+ // get first relevant redline
+ sal_uInt16 nCurrentRedline;
+ pDoc->GetRedline( *pStart, &nCurrentRedline );
+ if( nCurrentRedline > 0)
+ nCurrentRedline--;
+
+ // redline mode REDLINE_IGNORE|REDLINE_ON; save old mode
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
+
+ // iterate over relevant redlines and decide for each whether it should
+ // be saved, or split + saved
+ SwRedlineTbl& rRedlineTable = const_cast<SwRedlineTbl&>( pDoc->GetRedlineTbl() );
+ for( ; nCurrentRedline < rRedlineTable.Count(); nCurrentRedline++ )
+ {
+ SwRedline* pCurrent = rRedlineTable[ nCurrentRedline ];
+ SwComparePosition eCompare =
+ ComparePosition( *pCurrent->Start(), *pCurrent->End(),
+ *pStart, *pEnd);
+
+ // we must save this redline if it overlaps aPam
+ // (we may have to split it, too)
+ if( eCompare == POS_OVERLAP_BEHIND ||
+ eCompare == POS_OVERLAP_BEFORE ||
+ eCompare == POS_OUTSIDE ||
+ eCompare == POS_INSIDE ||
+ eCompare == POS_EQUAL )
+ {
+ rRedlineTable.Remove( nCurrentRedline-- );
+
+ // split beginning, if necessary
+ if( eCompare == POS_OVERLAP_BEFORE ||
+ eCompare == POS_OUTSIDE )
+ {
+
+ SwRedline* pNewRedline = new SwRedline( *pCurrent );
+ *pNewRedline->End() = *pStart;
+ *pCurrent->Start() = *pStart;
+ pDoc->AppendRedline( pNewRedline, true );
+ }
+
+ // split end, if necessary
+ if( eCompare == POS_OVERLAP_BEHIND ||
+ eCompare == POS_OUTSIDE )
+ {
+ SwRedline* pNewRedline = new SwRedline( *pCurrent );
+ *pNewRedline->Start() = *pEnd;
+ *pCurrent->End() = *pEnd;
+ pDoc->AppendRedline( pNewRedline, true );
+ }
+
+ // save the current redline
+ _SaveRedline* pSave = new _SaveRedline( pCurrent, *pStart );
+ rArr.C40_INSERT( _SaveRedline, pSave, rArr.Count() );
+ }
+ }
+
+ // restore old redline mode
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+void lcl_RestoreRedlines( SwDoc* pDoc, const SwPosition& rPos, _SaveRedlines& rArr )
+{
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
+
+ for( sal_uInt16 n = 0; n < rArr.Count(); ++n )
+ {
+ _SaveRedline* pSave = rArr[ n ];
+ pSave->SetPos( rPos );
+ pDoc->AppendRedline( pSave->pRedl, true );
+ }
+
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+
+void lcl_SaveRedlines( const SwNodeRange& rRg, _SaveRedlines& rArr )
+{
+ SwDoc* pDoc = rRg.aStart.GetNode().GetDoc();
+ sal_uInt16 nRedlPos;
+ SwPosition aSrchPos( rRg.aStart ); aSrchPos.nNode--;
+ aSrchPos.nContent.Assign( aSrchPos.nNode.GetNode().GetCntntNode(), 0 );
+ if( pDoc->GetRedline( aSrchPos, &nRedlPos ) && nRedlPos )
+ --nRedlPos;
+ else if( nRedlPos >= pDoc->GetRedlineTbl().Count() )
+ return ;
+
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
+ SwRedlineTbl& rRedlTbl = (SwRedlineTbl&)pDoc->GetRedlineTbl();
+
+ do {
+ SwRedline* pTmp = rRedlTbl[ nRedlPos ];
+
+ const SwPosition* pRStt = pTmp->Start(),
+ * pREnd = pTmp->GetMark() == pRStt
+ ? pTmp->GetPoint() : pTmp->GetMark();
+
+ if( pRStt->nNode < rRg.aStart )
+ {
+ if( pREnd->nNode > rRg.aStart && pREnd->nNode < rRg.aEnd )
+ {
+ // Kopie erzeugen und Ende vom Original ans Ende des
+ // MoveBereiches setzen. Die Kopie wird mit verschoben
+ SwRedline* pNewRedl = new SwRedline( *pTmp );
+ SwPosition* pTmpPos = pNewRedl->Start();
+ pTmpPos->nNode = rRg.aStart;
+ pTmpPos->nContent.Assign(
+ pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
+
+ _SaveRedline* pSave = new _SaveRedline( pNewRedl, rRg.aStart );
+// rArr.Insert( pSave, rArr.Count() );
+ rArr.C40_INSERT( _SaveRedline, pSave, rArr.Count() );
+
+ pTmpPos = pTmp->End();
+ pTmpPos->nNode = rRg.aEnd;
+ pTmpPos->nContent.Assign(
+ pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
+ }
+ else if( pREnd->nNode == rRg.aStart )
+ {
+ SwPosition* pTmpPos = pTmp->End();
+ pTmpPos->nNode = rRg.aEnd;
+ pTmpPos->nContent.Assign(
+ pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
+ }
+ }
+ else if( pRStt->nNode < rRg.aEnd )
+ {
+ rRedlTbl.Remove( nRedlPos-- );
+ if( pREnd->nNode < rRg.aEnd ||
+ ( pREnd->nNode == rRg.aEnd && !pREnd->nContent.GetIndex()) )
+ {
+ // gesamt verschieben
+ _SaveRedline* pSave = new _SaveRedline( pTmp, rRg.aStart );
+// rArr.Insert( pSave, rArr.Count() );
+ rArr.C40_INSERT( _SaveRedline, pSave, rArr.Count() );
+ }
+ else
+ {
+ // aufsplitten
+ SwRedline* pNewRedl = new SwRedline( *pTmp );
+ SwPosition* pTmpPos = pNewRedl->End();
+ pTmpPos->nNode = rRg.aEnd;
+ pTmpPos->nContent.Assign(
+ pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
+
+ _SaveRedline* pSave = new _SaveRedline( pNewRedl, rRg.aStart );
+// rArr.Insert( pSave, rArr.Count() );
+ rArr.C40_INSERT( _SaveRedline, pSave, rArr.Count() );
+
+ pTmpPos = pTmp->Start();
+ pTmpPos->nNode = rRg.aEnd;
+ pTmpPos->nContent.Assign(
+ pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
+ pDoc->AppendRedline( pTmp, true );
+ }
+ }
+ else
+ break;
+
+ } while( ++nRedlPos < pDoc->GetRedlineTbl().Count() );
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+void lcl_RestoreRedlines( SwDoc* pDoc, sal_uInt32 nInsPos, _SaveRedlines& rArr )
+{
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
+
+ for( sal_uInt16 n = 0; n < rArr.Count(); ++n )
+ {
+ _SaveRedline* pSave = rArr[ n ];
+ pSave->SetPos( nInsPos );
+ pDoc->AppendRedline( pSave->pRedl, true );
+ }
+
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+// ------------------------------------------------------------------------
+// #i59534: Redo of insertion of multiple text nodes runs into trouble
+// because of unnecessary expanded redlines
+// From now on this class saves the redline positions of all redlines which ends exact at the
+// insert position (node _and_ content index)
+
+_SaveRedlEndPosForRestore::_SaveRedlEndPosForRestore( const SwNodeIndex& rInsIdx, xub_StrLen nCnt )
+ : pSavArr( 0 ), pSavIdx( 0 ), nSavCntnt( nCnt )
+{
+ SwNode& rNd = rInsIdx.GetNode();
+ SwDoc* pDest = rNd.GetDoc();
+ if( pDest->GetRedlineTbl().Count() )
+ {
+ sal_uInt16 nFndPos;
+ const SwPosition* pEnd;
+ SwPosition aSrcPos( rInsIdx, SwIndex( rNd.GetCntntNode(), nCnt ));
+ const SwRedline* pRedl = pDest->GetRedline( aSrcPos, &nFndPos );
+ while( nFndPos-- && *( pEnd = ( pRedl =
+ pDest->GetRedlineTbl()[ nFndPos ] )->End() ) == aSrcPos && *pRedl->Start() < aSrcPos )
+ {
+ if( !pSavArr )
+ {
+ pSavArr = new SvPtrarr( 2, 2 );
+ pSavIdx = new SwNodeIndex( rInsIdx, -1 );
+ }
+ void* p = (void*)pEnd;
+ pSavArr->Insert( p, pSavArr->Count() );
+ }
+ }
+}
+
+_SaveRedlEndPosForRestore::~_SaveRedlEndPosForRestore()
+{
+ if( pSavArr )
+ {
+ delete pSavArr;
+ delete pSavIdx;
+ }
+}
+
+void _SaveRedlEndPosForRestore::_Restore()
+{
+ (*pSavIdx)++;
+ SwCntntNode* pNode = pSavIdx->GetNode().GetCntntNode();
+ // If there's no content node at the remembered position, we will not restore the old position
+ // This may happen if a table (or section?) will be inserted.
+ if( pNode )
+ {
+ SwPosition aPos( *pSavIdx, SwIndex( pNode, nSavCntnt ));
+ for( sal_uInt16 n = pSavArr->Count(); n; )
+ *((SwPosition*)pSavArr->GetObject( --n )) = aPos;
+ }
+}
+
+
+// ------------------------------------------------------------------------
+
+// Loeschen einer vollstaendigen Section des NodesArray.
+// Der uebergebene Node steht irgendwo in der gewuenschten Section
+void SwDoc::DeleteSection( SwNode *pNode )
+{
+ ASSERT( pNode, "Kein Node uebergeben." );
+ SwStartNode* pSttNd = pNode->IsStartNode() ? (SwStartNode*)pNode
+ : pNode->StartOfSectionNode();
+ SwNodeIndex aSttIdx( *pSttNd ), aEndIdx( *pNode->EndOfSectionNode() );
+
+ // dann loesche mal alle Fly's, text::Bookmarks, ...
+ DelFlyInRange( aSttIdx, aEndIdx );
+ DeleteRedline( *pSttNd, true, USHRT_MAX );
+ _DelBookmarks(aSttIdx, aEndIdx);
+
+ {
+ // alle Crsr/StkCrsr/UnoCrsr aus dem Loeschbereich verschieben
+ SwNodeIndex aMvStt( aSttIdx, 1 );
+ CorrAbs( aMvStt, aEndIdx, SwPosition( aSttIdx ), sal_True );
+ }
+
+ GetNodes().DelNodes( aSttIdx, aEndIdx.GetIndex() - aSttIdx.GetIndex() + 1 );
+}
+
+
+void SwDoc::SetModified(SwPaM &rPaM)
+{
+ SwDataChanged aTmp( rPaM, 0 );
+ SetModified();
+}
+
+/*************************************************************************
+ * SwDoc::Overwrite()
+ ************************************************************************/
+
+bool SwDoc::Overwrite( const SwPaM &rRg, const String &rStr )
+{
+ SwPosition& rPt = *(SwPosition*)rRg.GetPoint();
+ if( pACEWord ) // Aufnahme in die Autokorrektur
+ {
+ if( 1 == rStr.Len() )
+ pACEWord->CheckChar( rPt, rStr.GetChar( 0 ) );
+ delete pACEWord, pACEWord = 0;
+ }
+
+ SwTxtNode *pNode = rPt.nNode.GetNode().GetTxtNode();
+ if(!pNode)
+ return sal_False;
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo(); // AppendUndo not always called
+ }
+
+ sal_uInt16 nOldAttrCnt = pNode->GetpSwpHints()
+ ? pNode->GetpSwpHints()->Count() : 0;
+ SwDataChanged aTmp( rRg, 0 );
+ SwIndex& rIdx = rPt.nContent;
+ xub_StrLen nStart = 0;
+
+ sal_Unicode c;
+ String aStr;
+
+ sal_Bool bOldExpFlg = pNode->IsIgnoreDontExpand();
+ pNode->SetIgnoreDontExpand( sal_True );
+
+ for( xub_StrLen nCnt = 0; nCnt < rStr.Len(); ++nCnt )
+ {
+ // hinter das Zeichen (zum aufspannen der Attribute !!)
+ nStart = rIdx.GetIndex();
+ if ( nStart < pNode->GetTxt().Len() )
+ {
+ lcl_SkipAttr( pNode, rIdx, nStart );
+ }
+ c = rStr.GetChar( nCnt );
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ bool bMerged(false);
+ if (GetIDocumentUndoRedo().DoesGroupUndo())
+ {
+ SwUndo *const pUndo = GetUndoManager().GetLastUndo();
+ SwUndoOverwrite *const pUndoOW(
+ dynamic_cast<SwUndoOverwrite *>(pUndo) );
+ if (pUndoOW)
+ {
+ // if CanGrouping() returns true it's already merged
+ bMerged = pUndoOW->CanGrouping( this, rPt, c );
+ }
+ }
+ if (!bMerged)
+ {
+ SwUndo *const pUndoOW( new SwUndoOverwrite(this, rPt, c) );
+ GetIDocumentUndoRedo().AppendUndo(pUndoOW);
+ }
+ }
+ else
+ {
+ // hinter das Zeichen (zum Aufspannen der Attribute !!)
+ if( nStart < pNode->GetTxt().Len() )
+ rIdx++;
+ pNode->InsertText( c, rIdx, INS_EMPTYEXPAND );
+ if( nStart+1 < rIdx.GetIndex() )
+ {
+ rIdx = nStart;
+ pNode->EraseText( rIdx, 1 );
+ rIdx++;
+ }
+ }
+ }
+ pNode->SetIgnoreDontExpand( bOldExpFlg );
+
+ sal_uInt16 nNewAttrCnt = pNode->GetpSwpHints()
+ ? pNode->GetpSwpHints()->Count() : 0;
+ if( nOldAttrCnt != nNewAttrCnt )
+ {
+ SwUpdateAttr aHint( 0, 0, 0 );
+ SwClientIter aIter( *pNode );
+ SwClient* pGTO = aIter.First(TYPE( SwCrsrShell ));
+ while( pGTO )
+ {
+ pGTO->Modify( 0, &aHint );
+ pGTO = aIter.Next();
+ }
+ }
+
+ if (!GetIDocumentUndoRedo().DoesUndo() &&
+ !IsIgnoreRedline() && GetRedlineTbl().Count())
+ {
+ SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() );
+ DeleteRedline( aPam, true, USHRT_MAX );
+ }
+ else if( IsRedlineOn() )
+ {
+ // FIXME: this redline is WRONG: there is no DELETE, and the skipped
+ // characters are also included in aPam
+ SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() );
+ AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
+ }
+
+ SetModified();
+ return sal_True;
+}
+
+
+bool SwDoc::MoveAndJoin( SwPaM& rPaM, SwPosition& rPos, SwMoveFlags eMvFlags )
+{
+ SwNodeIndex aIdx( rPaM.Start()->nNode );
+ sal_Bool bJoinTxt = aIdx.GetNode().IsTxtNode();
+ sal_Bool bOneNode = rPaM.GetPoint()->nNode == rPaM.GetMark()->nNode;
+ aIdx--; // vor den Move Bereich !!
+
+ bool bRet = MoveRange( rPaM, rPos, eMvFlags );
+ if( bRet && !bOneNode )
+ {
+ if( bJoinTxt )
+ aIdx++;
+ SwTxtNode * pTxtNd = aIdx.GetNode().GetTxtNode();
+ SwNodeIndex aNxtIdx( aIdx );
+ if( pTxtNd && pTxtNd->CanJoinNext( &aNxtIdx ) )
+ {
+ { // Block wegen SwIndex in den Node !!
+ CorrRel( aNxtIdx, SwPosition( aIdx, SwIndex( pTxtNd,
+ pTxtNd->GetTxt().Len() ) ), 0, sal_True );
+ }
+ pTxtNd->JoinNext();
+ }
+ }
+ return bRet;
+}
+
+// mst: it seems that this is mostly used by SwDoc internals; the only
+// way to call this from the outside seems to be the special case in
+// SwDoc::CopyRange (but i have not managed to actually hit that case)
+bool SwDoc::MoveRange( SwPaM& rPaM, SwPosition& rPos, SwMoveFlags eMvFlags )
+{
+ // keine Moves-Abfangen
+ const SwPosition *pStt = rPaM.Start(), *pEnd = rPaM.End();
+ if( !rPaM.HasMark() || *pStt >= *pEnd || (*pStt <= rPos && rPos < *pEnd))
+ return false;
+
+ // sicher die absatzgebundenen Flys, damit sie verschoben werden koennen.
+ _SaveFlyArr aSaveFlyArr;
+ _SaveFlyInRange( rPaM, rPos.nNode, aSaveFlyArr, 0 != ( DOC_MOVEALLFLYS & eMvFlags ) );
+
+ // save redlines (if DOC_MOVEREDLINES is used)
+ _SaveRedlines aSaveRedl( 0, 4 );
+ if( DOC_MOVEREDLINES & eMvFlags && GetRedlineTbl().Count() )
+ {
+ lcl_SaveRedlines( rPaM, aSaveRedl );
+
+ // #i17764# unfortunately, code below relies on undos being
+ // in a particular order, and presence of bookmarks
+ // will change this order. Hence, we delete bookmarks
+ // here without undo.
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+ _DelBookmarks(
+ pStt->nNode,
+ pEnd->nNode,
+ NULL,
+ &pStt->nContent,
+ &pEnd->nContent);
+ }
+
+
+ int bUpdateFtn = sal_False;
+ SwFtnIdxs aTmpFntIdx;
+
+ // falls Undo eingeschaltet, erzeuge das UndoMove-Objekt
+ SwUndoMove * pUndoMove = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ pUndoMove = new SwUndoMove( rPaM, rPos );
+ pUndoMove->SetMoveRedlines( eMvFlags == DOC_MOVEREDLINES );
+ }
+ else
+ {
+ bUpdateFtn = lcl_SaveFtn( pStt->nNode, pEnd->nNode, rPos.nNode,
+ GetFtnIdxs(), aTmpFntIdx,
+ &pStt->nContent, &pEnd->nContent );
+ }
+
+ sal_Bool bSplit = sal_False;
+ SwPaM aSavePam( rPos, rPos );
+
+ // stelle den SPoint an den Anfang vom Bereich (Definition)
+ if( rPaM.GetPoint() == pEnd )
+ rPaM.Exchange();
+
+ // in der EditShell wird nach dem Move ein JoinNext erzeugt, wenn
+ // vor und nach dem Move ein Text-Node steht.
+ SwTxtNode* pSrcNd = rPaM.GetPoint()->nNode.GetNode().GetTxtNode();
+ sal_Bool bCorrSavePam = pSrcNd && pStt->nNode != pEnd->nNode;
+
+ // werden ein oder mehr TextNodes bewegt, so wird
+ // im SwNodes::Move ein SplitNode erzeugt. Dieser Updated aber nicht
+ // den Cursor. Um das zu verhindern, wird hier ein TextNode angelegt,
+ // um die Updaterei der Indizies zu erhalten. Nach dem Move wird
+ // evt. der Node geloescht.
+
+ SwTxtNode * pTNd = rPos.nNode.GetNode().GetTxtNode();
+ if( pTNd && rPaM.GetPoint()->nNode != rPaM.GetMark()->nNode &&
+ ( rPos.nContent.GetIndex() || ( pTNd->Len() && bCorrSavePam )) )
+ {
+ bSplit = sal_True;
+ xub_StrLen nMkCntnt = rPaM.GetMark()->nContent.GetIndex();
+
+ SvULongs aBkmkArr( 15, 15 );
+ _SaveCntntIdx( this, rPos.nNode.GetIndex(), rPos.nContent.GetIndex(),
+ aBkmkArr, SAVEFLY_SPLIT );
+
+ pTNd = static_cast<SwTxtNode*>(pTNd->SplitCntntNode( rPos ));
+
+ if( aBkmkArr.Count() )
+ _RestoreCntntIdx( this, aBkmkArr, rPos.nNode.GetIndex()-1, 0, sal_True );
+
+ // jetzt noch den Pam berichtigen !!
+ if( rPos.nNode == rPaM.GetMark()->nNode )
+ {
+ rPaM.GetMark()->nNode = rPos.nNode.GetIndex()-1;
+ rPaM.GetMark()->nContent.Assign( pTNd, nMkCntnt );
+ }
+ }
+
+ // setze den Pam um einen "Inhalt" zurueck; dadurch steht er immer
+ // ausserhalb des manipulierten Bereiches. Falls kein Inhalt mehr vor-
+ // handen, dann auf den StartNode (es ist immer einer vorhanden !!!)
+ sal_Bool bNullCntnt = !aSavePam.Move( fnMoveBackward, fnGoCntnt );
+ if( bNullCntnt )
+ {
+ aSavePam.GetPoint()->nNode--;
+ }
+
+ // kopiere alle Bookmarks, die im Move Bereich stehen in ein
+ // Array, das alle Angaben auf die Position als Offset speichert.
+ // Die neue Zuordung erfolgt nach dem Moven.
+ ::std::vector< ::sw::mark::SaveBookmark> aSaveBkmks;
+ _DelBookmarks(
+ pStt->nNode,
+ pEnd->nNode,
+ &aSaveBkmks,
+ &pStt->nContent,
+ &pEnd->nContent);
+
+ // falls durch die vorherigen Loeschungen (z.B. der Fussnoten) kein
+ // Bereich mehr existiert, ist das immernoch ein gueltiger Move!
+ if( *rPaM.GetPoint() != *rPaM.GetMark() )
+ {
+ // now do the actual move
+ GetNodes().MoveRange( rPaM, rPos, GetNodes() );
+
+ // after a MoveRange() the Mark is deleted
+ if ( rPaM.HasMark() ) // => no Move occurred!
+ {
+ delete pUndoMove;
+ return false;
+ }
+ }
+ else
+ rPaM.DeleteMark();
+
+ ASSERT( *aSavePam.GetMark() == rPos ||
+ ( aSavePam.GetMark()->nNode.GetNode().GetCntntNode() == NULL ),
+ "PaM wurde nicht verschoben, am Anfang/Ende keine ContentNodes?" );
+ *aSavePam.GetMark() = rPos;
+
+ rPaM.SetMark(); // um den neuen Bereich eine Sel. aufspannen
+ pTNd = aSavePam.GetNode()->GetTxtNode();
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // korrigiere erstmal den Content vom SavePam
+ if( bNullCntnt )
+ {
+ aSavePam.GetPoint()->nContent = 0;
+ }
+
+ // die Methode SwEditShell::Move() fuegt nach dem Move den Text-Node
+ // zusammen, in dem der rPaM steht. Wurde der Inhalt nach hinten
+ // geschoben und liegt der SPoint vom SavePam im naechsten Node, so
+ // muss beim Speichern vom Undo-Object das beachtet werden !!
+ SwTxtNode * pPamTxtNd = 0;
+
+ // wird ans SwUndoMove weitergegeben, das dann beim Undo JoinNext
+ // aufruft. (falls es hier nicht moeglich ist).
+ sal_Bool bJoin = bSplit && pTNd;
+ bCorrSavePam = bCorrSavePam &&
+ 0 != ( pPamTxtNd = rPaM.GetNode()->GetTxtNode() )
+ && pPamTxtNd->CanJoinNext()
+ && (*rPaM.GetPoint() <= *aSavePam.GetPoint());
+
+ // muessen am SavePam 2 Nodes zusammengefasst werden ??
+ if( bJoin && pTNd->CanJoinNext() )
+ {
+ pTNd->JoinNext();
+ // kein temp. sdbcx::Index bei &&
+ // es sollten wohl nur die Indexwerte verglichen werden.
+ if( bCorrSavePam && rPaM.GetPoint()->nNode.GetIndex()+1 ==
+ aSavePam.GetPoint()->nNode.GetIndex() )
+ {
+ aSavePam.GetPoint()->nContent += pPamTxtNd->Len();
+ }
+ bJoin = sal_False;
+ }
+// else if( !bCorrSavePam && !pSavePam->Move( fnMoveForward, fnGoCntnt ))
+ else if ( !aSavePam.Move( fnMoveForward, fnGoCntnt ) )
+ {
+ aSavePam.GetPoint()->nNode++;
+ }
+
+ // zwischen SPoint und GetMark steht jetzt der neu eingefuegte Bereich
+ pUndoMove->SetDestRange( aSavePam, *rPaM.GetPoint(),
+ bJoin, bCorrSavePam );
+ GetIDocumentUndoRedo().AppendUndo( pUndoMove );
+ }
+ else
+ {
+ bool bRemove = true;
+ // muessen am SavePam 2 Nodes zusammengefasst werden ??
+ if( bSplit && pTNd )
+ {
+ if( pTNd->CanJoinNext())
+ {
+ // --> OD 2009-08-20 #i100466#
+ // Always join next, because <pTNd> has to stay as it is.
+ // A join previous from its next would more or less delete <pTNd>
+ pTNd->JoinNext();
+ // <--
+ bRemove = false;
+ }
+ }
+ if( bNullCntnt )
+ {
+ aSavePam.GetPoint()->nNode++;
+ aSavePam.GetPoint()->nContent.Assign( aSavePam.GetCntntNode(), 0 );
+ }
+ else if( bRemove ) // No move forward after joining with next paragraph
+ {
+ aSavePam.Move( fnMoveForward, fnGoCntnt );
+ }
+ }
+
+ // setze jetzt wieder die text::Bookmarks in das Dokument
+ *rPaM.GetMark() = *aSavePam.Start();
+ for(
+ ::std::vector< ::sw::mark::SaveBookmark>::iterator pBkmk = aSaveBkmks.begin();
+ pBkmk != aSaveBkmks.end();
+ ++pBkmk)
+ pBkmk->SetInDoc(
+ this,
+ rPaM.GetMark()->nNode,
+ &rPaM.GetMark()->nContent);
+ *rPaM.GetPoint() = *aSavePam.End();
+
+ // verschiebe die Flys an die neue Position
+ _RestFlyInRange( aSaveFlyArr, rPaM.Start()->nNode, &(rPos.nNode) );
+
+ // restore redlines (if DOC_MOVEREDLINES is used)
+ if( aSaveRedl.Count() )
+ {
+ lcl_RestoreRedlines( this, *aSavePam.Start(), aSaveRedl );
+ }
+
+ if( bUpdateFtn )
+ {
+ if( aTmpFntIdx.Count() )
+ {
+ GetFtnIdxs().Insert( &aTmpFntIdx );
+ aTmpFntIdx.Remove( sal_uInt16( 0 ), aTmpFntIdx.Count() );
+ }
+
+ GetFtnIdxs().UpdateAllFtn();
+ }
+
+ SetModified();
+ return true;
+}
+
+bool SwDoc::MoveNodeRange( SwNodeRange& rRange, SwNodeIndex& rPos,
+ SwMoveFlags eMvFlags )
+{
+ // bewegt alle Nodes an die neue Position. Dabei werden die
+ // text::Bookmarks mit verschoben !! (zur Zeit ohne Undo)
+
+ // falls durchs Move Fussnoten in den Sonderbereich kommen sollten,
+ // dann entferne sie jetzt.
+ //JP 13.07.95:
+ // ansonsten bei allen Fussnoten, die verschoben werden, die Frames
+ // loeschen und nach dem Move wieder aufbauen lassen (Fussnoten koennen
+ // die Seite wechseln). Zusaetzlich muss natuerlich die Sortierung
+ // der FtnIdx-Array wieder korrigiert werden.
+
+ int bUpdateFtn = sal_False;
+ SwFtnIdxs aTmpFntIdx;
+
+ SwUndoMove* pUndo = 0;
+ if ((DOC_CREATEUNDOOBJ & eMvFlags ) && GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo = new SwUndoMove( this, rRange, rPos );
+ }
+ else
+ {
+ bUpdateFtn = lcl_SaveFtn( rRange.aStart, rRange.aEnd, rPos,
+ GetFtnIdxs(), aTmpFntIdx );
+ }
+
+ _SaveRedlines aSaveRedl( 0, 4 );
+ SvPtrarr aSavRedlInsPosArr( 0, 4 );
+ if( DOC_MOVEREDLINES & eMvFlags && GetRedlineTbl().Count() )
+ {
+ lcl_SaveRedlines( rRange, aSaveRedl );
+
+ // suche alle Redlines, die an der InsPos aufhoeren. Diese muessen
+ // nach dem Move wieder an die "alte" Position verschoben werden
+ sal_uInt16 nRedlPos = GetRedlinePos( rPos.GetNode(), USHRT_MAX );
+ if( USHRT_MAX != nRedlPos )
+ {
+ const SwPosition *pRStt, *pREnd;
+ do {
+ SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
+ pRStt = pTmp->Start();
+ pREnd = pTmp->End();
+ if( pREnd->nNode == rPos && pRStt->nNode < rPos )
+ {
+ void* p = pTmp;
+ aSavRedlInsPosArr.Insert( p, aSavRedlInsPosArr.Count() );
+ }
+ } while( pRStt->nNode < rPos && ++nRedlPos < GetRedlineTbl().Count());
+ }
+ }
+
+ // kopiere alle Bookmarks, die im Move Bereich stehen in ein
+ // Array, das alle Angaben auf die Position als Offset speichert.
+ // Die neue Zuordung erfolgt nach dem Moven.
+ ::std::vector< ::sw::mark::SaveBookmark> aSaveBkmks;
+ _DelBookmarks(rRange.aStart, rRange.aEnd, &aSaveBkmks);
+
+ // sicher die absatzgebundenen Flys, damit verschoben werden koennen.
+ _SaveFlyArr aSaveFlyArr;
+ if( GetSpzFrmFmts()->Count() )
+ _SaveFlyInRange( rRange, aSaveFlyArr );
+
+ // vor die Position setzen, damit er nicht weitergeschoben wird
+ SwNodeIndex aIdx( rPos, -1 );
+
+ SwNodeIndex* pSaveInsPos = 0;
+ if( pUndo )
+ pSaveInsPos = new SwNodeIndex( rRange.aStart, -1 );
+
+ // verschiebe die Nodes
+ sal_Bool bNoDelFrms = 0 != (DOC_NO_DELFRMS & eMvFlags);
+ if( GetNodes()._MoveNodes( rRange, GetNodes(), rPos, !bNoDelFrms ) )
+ {
+ aIdx++; // wieder auf alte Position
+ if( pSaveInsPos )
+ (*pSaveInsPos)++;
+ }
+ else
+ {
+ aIdx = rRange.aStart;
+ delete pUndo, pUndo = 0;
+ }
+
+ // verschiebe die Flys an die neue Position
+ if( aSaveFlyArr.Count() )
+ _RestFlyInRange( aSaveFlyArr, aIdx, NULL );
+
+ // setze jetzt wieder die text::Bookmarks in das Dokument
+ for(
+ ::std::vector< ::sw::mark::SaveBookmark>::iterator pBkmk = aSaveBkmks.begin();
+ pBkmk != aSaveBkmks.end();
+ ++pBkmk)
+ pBkmk->SetInDoc(this, aIdx);
+
+ if( aSavRedlInsPosArr.Count() )
+ {
+ SwNode* pNewNd = &aIdx.GetNode();
+ for( sal_uInt16 n = 0; n < aSavRedlInsPosArr.Count(); ++n )
+ {
+ SwRedline* pTmp = (SwRedline*)aSavRedlInsPosArr[ n ];
+ if( USHRT_MAX != GetRedlineTbl().GetPos( pTmp ) )
+ {
+ SwPosition* pEnd = pTmp->End();
+ pEnd->nNode = aIdx;
+ pEnd->nContent.Assign( pNewNd->GetCntntNode(), 0 );
+ }
+ }
+ }
+
+ if( aSaveRedl.Count() )
+ lcl_RestoreRedlines( this, aIdx.GetIndex(), aSaveRedl );
+
+ if( pUndo )
+ {
+ pUndo->SetDestRange( aIdx, rPos, *pSaveInsPos );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ if( pSaveInsPos )
+ delete pSaveInsPos;
+
+ if( bUpdateFtn )
+ {
+ if( aTmpFntIdx.Count() )
+ {
+ GetFtnIdxs().Insert( &aTmpFntIdx );
+ aTmpFntIdx.Remove( sal_uInt16( 0 ), aTmpFntIdx.Count() );
+ }
+
+ GetFtnIdxs().UpdateAllFtn();
+ }
+
+ SetModified();
+ return sal_True;
+}
+
+/* #107318# Convert list of ranges of whichIds to a corresponding list
+ of whichIds*/
+SvUShorts * lcl_RangesToUShorts(sal_uInt16 * pRanges)
+{
+ SvUShorts * pResult = new SvUShorts();
+
+ int i = 0;
+ while (pRanges[i] != 0)
+ {
+ ASSERT(pRanges[i+1] != 0, "malformed ranges");
+
+ for (sal_uInt16 j = pRanges[i]; j < pRanges[i+1]; j++)
+ pResult->Insert(j, pResult->Count());
+
+ i += 2;
+ }
+
+ return pResult;
+}
+
+bool lcl_StrLenOverFlow( const SwPaM& rPam )
+{
+ // If we try to merge two paragraph we have to test if afterwards
+ // the string doesn't exceed the allowed string length
+ bool bRet = false;
+ if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode )
+ {
+ const SwPosition* pStt = rPam.Start(), *pEnd = rPam.End();
+ const SwTxtNode* pEndNd = pEnd->nNode.GetNode().GetTxtNode();
+ if( (0 != pEndNd) && pStt->nNode.GetNode().IsTxtNode() )
+ {
+ sal_uInt64 nSum = pStt->nContent.GetIndex() +
+ pEndNd->GetTxt().Len() - pEnd->nContent.GetIndex();
+ if( nSum > STRING_LEN )
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+void lcl_GetJoinFlags( SwPaM& rPam, sal_Bool& rJoinTxt, sal_Bool& rJoinPrev )
+{
+ rJoinTxt = sal_False;
+ rJoinPrev = sal_False;
+ if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode )
+ {
+ const SwPosition* pStt = rPam.Start(), *pEnd = rPam.End();
+ SwTxtNode *pSttNd = pStt->nNode.GetNode().GetTxtNode();
+ if( pSttNd )
+ {
+ SwTxtNode *pEndNd = pEnd->nNode.GetNode().GetTxtNode();
+ rJoinTxt = 0 != pEndNd;
+ if( rJoinTxt )
+ {
+ bool bExchange = pStt == rPam.GetPoint();
+ if( !pStt->nContent.GetIndex() &&
+ pEndNd->GetTxt().Len() != pEnd->nContent.GetIndex() )
+ bExchange = !bExchange;
+ if( bExchange )
+ rPam.Exchange();
+ rJoinPrev = rPam.GetPoint() == pStt;
+ ASSERT( !pStt->nContent.GetIndex() &&
+ pEndNd->GetTxt().Len() != pEnd->nContent.GetIndex()
+ ? rPam.GetPoint()->nNode < rPam.GetMark()->nNode
+ : rPam.GetPoint()->nNode > rPam.GetMark()->nNode,
+ "lcl_GetJoinFlags");
+ }
+ }
+ }
+}
+
+void lcl_JoinText( SwPaM& rPam, sal_Bool bJoinPrev )
+{
+ SwNodeIndex aIdx( rPam.GetPoint()->nNode );
+ SwTxtNode *pTxtNd = aIdx.GetNode().GetTxtNode();
+ SwNodeIndex aOldIdx( aIdx );
+ SwTxtNode *pOldTxtNd = pTxtNd;
+
+ if( pTxtNd && pTxtNd->CanJoinNext( &aIdx ) )
+ {
+ SwDoc* pDoc = rPam.GetDoc();
+ if( bJoinPrev )
+ {
+ // N.B.: we do not need to handle xmlids in this case, because
+ // it is only invoked if one paragraph is completely empty
+ // (see lcl_GetJoinFlags)
+ {
+ // falls PageBreaks geloescht / gesetzt werden, darf das
+ // nicht in die Undo-History aufgenommen werden !!
+ // (das loeschen vom Node geht auch am Undo vorbei !!!)
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ /* PageBreaks, PageDesc, ColumnBreaks */
+ // Sollte an der Logik zum Kopieren der PageBreak's ...
+ // etwas geaendert werden, muss es auch im SwUndoDelete
+ // geandert werden. Dort wird sich das AUTO-PageBreak
+ // aus dem GetMarkNode kopiert.!!!
+
+ /* Der GetMarkNode */
+ if( ( pTxtNd = aIdx.GetNode().GetTxtNode())->HasSwAttrSet() )
+ {
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pTxtNd->GetpSwAttrSet()->GetItemState(
+ RES_BREAK, sal_False, &pItem ) )
+ pTxtNd->ResetAttr( RES_BREAK );
+ if( pTxtNd->HasSwAttrSet() &&
+ SFX_ITEM_SET == pTxtNd->GetpSwAttrSet()->GetItemState(
+ RES_PAGEDESC, sal_False, &pItem ) )
+ pTxtNd->ResetAttr( RES_PAGEDESC );
+ }
+
+ /* Der PointNode */
+ if( pOldTxtNd->HasSwAttrSet() )
+ {
+ const SfxPoolItem* pItem;
+ SfxItemSet aSet( pDoc->GetAttrPool(), aBreakSetRange );
+ const SfxItemSet* pSet = pOldTxtNd->GetpSwAttrSet();
+ if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK,
+ sal_False, &pItem ) )
+ aSet.Put( *pItem );
+ if( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC,
+ sal_False, &pItem ) )
+ aSet.Put( *pItem );
+ if( aSet.Count() )
+ pTxtNd->SetAttr( aSet );
+ }
+ pOldTxtNd->FmtToTxtAttr( pTxtNd );
+
+ SvULongs aBkmkArr( 15, 15 );
+ ::_SaveCntntIdx( pDoc, aOldIdx.GetIndex(),
+ pOldTxtNd->Len(), aBkmkArr );
+
+ SwIndex aAlphaIdx(pTxtNd);
+ pOldTxtNd->CutText( pTxtNd, aAlphaIdx, SwIndex(pOldTxtNd),
+ pOldTxtNd->Len() );
+ SwPosition aAlphaPos( aIdx, aAlphaIdx );
+ pDoc->CorrRel( rPam.GetPoint()->nNode, aAlphaPos, 0, sal_True );
+
+ // verschiebe noch alle Bookmarks/TOXMarks
+ if( aBkmkArr.Count() )
+ ::_RestoreCntntIdx( pDoc, aBkmkArr, aIdx.GetIndex() );
+
+ // falls der uebergebene PaM nicht im Crsr-Ring steht,
+ // gesondert behandeln (z.B. Aufruf aus dem Auto-Format)
+ if( pOldTxtNd == rPam.GetBound( sal_True ).nContent.GetIdxReg() )
+ rPam.GetBound( sal_True ) = aAlphaPos;
+ if( pOldTxtNd == rPam.GetBound( sal_False ).nContent.GetIdxReg() )
+ rPam.GetBound( sal_False ) = aAlphaPos;
+ }
+ // jetzt nur noch den Node loeschen
+ pDoc->GetNodes().Delete( aOldIdx, 1 );
+ }
+ else
+ {
+ SwTxtNode* pDelNd = aIdx.GetNode().GetTxtNode();
+ if( pTxtNd->Len() )
+ pDelNd->FmtToTxtAttr( pTxtNd );
+ else
+ {
+ /* #107318# This case was missed:
+
+ <something></something> <-- pTxtNd
+ <other>ccc</other> <-- pDelNd
+
+ <something> and <other> are paragraph
+ attributes. The attribute <something> stayed if not
+ overwritten by an attribute in "ccc". Fixed by
+ first resetting all character attributes in first
+ paragraph (pTxtNd).
+ */
+ SvUShorts * pShorts =
+ lcl_RangesToUShorts(aCharFmtSetRange);
+ pTxtNd->ResetAttr(*pShorts);
+ delete pShorts;
+
+ if( pDelNd->HasSwAttrSet() )
+ {
+ // nur die Zeichenattribute kopieren
+ SfxItemSet aTmpSet( pDoc->GetAttrPool(), aCharFmtSetRange );
+ aTmpSet.Put( *pDelNd->GetpSwAttrSet() );
+ pTxtNd->SetAttr( aTmpSet );
+ }
+ }
+
+ pDoc->CorrRel( aIdx, *rPam.GetPoint(), 0, sal_True );
+ // --> OD 2009-08-20 #i100466#
+ // adjust given <rPam>, if it does not belong to the cursors
+ if ( pDelNd == rPam.GetBound( sal_True ).nContent.GetIdxReg() )
+ {
+ rPam.GetBound( sal_True ) = SwPosition( SwNodeIndex( *pTxtNd ), SwIndex( pTxtNd ) );
+ }
+ if( pDelNd == rPam.GetBound( sal_False ).nContent.GetIdxReg() )
+ {
+ rPam.GetBound( sal_False ) = SwPosition( SwNodeIndex( *pTxtNd ), SwIndex( pTxtNd ) );
+ }
+ // <--
+ pTxtNd->JoinNext();
+ }
+ }
+}
+
+static void
+lcl_CalcBreaks( ::std::vector<xub_StrLen> & rBreaks, SwPaM const & rPam )
+{
+ SwTxtNode const * const pTxtNode(
+ rPam.End()->nNode.GetNode().GetTxtNode() );
+ if (!pTxtNode)
+ return; // left-overlap only possible at end of selection...
+
+ const xub_StrLen nStart(rPam.Start()->nContent.GetIndex());
+ const xub_StrLen nEnd (rPam.End ()->nContent.GetIndex());
+ if (nEnd == pTxtNode->Len())
+ return; // paragraph selected until the end
+
+ for (xub_StrLen i = nStart; i < nEnd; ++i)
+ {
+ const sal_Unicode c(pTxtNode->GetTxt().GetChar(i));
+ if ((CH_TXTATR_INWORD == c) || (CH_TXTATR_BREAKWORD == c))
+ {
+ SwTxtAttr const * const pAttr( pTxtNode->GetTxtAttrForCharAt(i) );
+ if (pAttr && pAttr->GetEnd() && (*pAttr->GetEnd() > nEnd))
+ {
+ ASSERT(pAttr->HasDummyChar(), "GetTxtAttrForCharAt broken?");
+ rBreaks.push_back(i);
+ }
+ }
+ }
+}
+
+bool lcl_DoWithBreaks(SwDoc & rDoc, SwPaM & rPam,
+ bool (SwDoc::*pFunc)(SwPaM&, bool), const bool bForceJoinNext = false)
+{
+ ::std::vector<xub_StrLen> Breaks;
+
+ lcl_CalcBreaks(Breaks, rPam);
+
+ if (!Breaks.size())
+ {
+ return (rDoc.*pFunc)(rPam, bForceJoinNext);
+ }
+
+ // N.B.: deletion must be split into several parts if the text node
+ // contains a text attribute with end and with dummy character
+ // and the selection does not contain the text attribute completely,
+ // but overlaps its start (left), where the dummy character is.
+
+ SwPosition const & rSelectionEnd( *rPam.End() );
+
+ bool bRet( true );
+ // iterate from end to start, to avoid invalidating the offsets!
+ ::std::vector<xub_StrLen>::reverse_iterator iter( Breaks.rbegin() );
+ SwPaM aPam( rSelectionEnd, rSelectionEnd ); // end node!
+ SwPosition & rEnd( *aPam.End() );
+ SwPosition & rStart( *aPam.Start() );
+
+ while (iter != Breaks.rend())
+ {
+ rStart.nContent = *iter + 1;
+ if (rEnd.nContent > rStart.nContent) // check if part is empty
+ {
+ bRet &= (rDoc.*pFunc)(aPam, bForceJoinNext);
+ }
+ rEnd.nContent = *iter;
+ ++iter;
+ }
+
+ rStart = *rPam.Start(); // set to original start
+ if (rEnd.nContent > rStart.nContent) // check if part is empty
+ {
+ bRet &= (rDoc.*pFunc)(aPam, bForceJoinNext);
+ }
+
+ return bRet;
+}
+
+
+bool SwDoc::DeleteAndJoinWithRedlineImpl( SwPaM & rPam, const bool )
+{
+ ASSERT( IsRedlineOn(), "DeleteAndJoinWithRedline: redline off" );
+
+ {
+ SwUndoRedlineDelete* pUndo = 0;
+ RedlineMode_t eOld = GetRedlineMode();
+ checkRedlining(eOld);
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+
+ //JP 06.01.98: MUSS noch optimiert werden!!!
+ SetRedlineMode(
+ (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE ));
+
+ GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+ pUndo = new SwUndoRedlineDelete( rPam, UNDO_DELETE );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ if( *rPam.GetPoint() != *rPam.GetMark() )
+ AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE, rPam ), true);
+ SetModified();
+
+ if( pUndo )
+ {
+ GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+ // ??? why the hell is the AppendUndo not below the
+ // CanGrouping, so this hideous cleanup wouldn't be necessary?
+ // bah, this is redlining, probably changing this would break it...
+ if (GetIDocumentUndoRedo().DoesGroupUndo())
+ {
+ SwUndo *const pLastUndo( GetUndoManager().GetLastUndo() );
+ SwUndoRedlineDelete *const pUndoRedlineDel(
+ dynamic_cast<SwUndoRedlineDelete*>(pLastUndo) );
+ if (pUndoRedlineDel)
+ {
+ bool const bMerged = pUndoRedlineDel->CanGrouping(*pUndo);
+ if (bMerged)
+ {
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+ SwUndo const*const pDeleted =
+ GetUndoManager().RemoveLastUndo();
+ OSL_ENSURE(pDeleted == pUndo,
+ "DeleteAndJoinWithRedlineImpl: "
+ "undo removed is not undo inserted?");
+ delete pDeleted;
+ }
+ }
+ }
+//JP 06.01.98: MUSS noch optimiert werden!!!
+SetRedlineMode( eOld );
+ }
+ return true;
+ }
+}
+
+bool SwDoc::DeleteAndJoinImpl( SwPaM & rPam,
+ const bool bForceJoinNext )
+{
+ sal_Bool bJoinTxt, bJoinPrev;
+ lcl_GetJoinFlags( rPam, bJoinTxt, bJoinPrev );
+ // --> OD 2009-08-20 #i100466#
+ if ( bForceJoinNext )
+ {
+ bJoinPrev = sal_False;
+ }
+ // <--
+ {
+ bool const bSuccess( DeleteRangeImpl( rPam ) );
+ if (!bSuccess)
+ return false;
+ }
+
+ if( bJoinTxt )
+ {
+ lcl_JoinText( rPam, bJoinPrev );
+ }
+
+ return true;
+}
+
+bool SwDoc::DeleteRangeImpl(SwPaM & rPam, const bool)
+{
+ // move all cursors out of the deleted range.
+ // but first copy the given PaM, because it could be a cursor that
+ // would be moved!
+ SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
+ ::PaMCorrAbs( aDelPam, *aDelPam.GetPoint() );
+
+ bool const bSuccess( DeleteRangeImplImpl( aDelPam ) );
+ if (bSuccess)
+ { // now copy position from temp copy to given PaM
+ *rPam.GetPoint() = *aDelPam.GetPoint();
+ }
+
+ return bSuccess;
+}
+
+bool SwDoc::DeleteRangeImplImpl(SwPaM & rPam)
+{
+ SwPosition *pStt = (SwPosition*)rPam.Start(), *pEnd = (SwPosition*)rPam.End();
+
+ if( !rPam.HasMark() || *pStt >= *pEnd )
+ return false;
+
+ if( pACEWord )
+ {
+ // ggfs. das gesicherte Word fuer die Ausnahme
+ if( pACEWord->IsDeleted() || pStt->nNode != pEnd->nNode ||
+ pStt->nContent.GetIndex() + 1 != pEnd->nContent.GetIndex() ||
+ !pACEWord->CheckDelChar( *pStt ))
+ delete pACEWord, pACEWord = 0;
+ }
+
+ {
+ // loesche alle leeren TextHints an der Mark-Position
+ SwTxtNode* pTxtNd = rPam.GetMark()->nNode.GetNode().GetTxtNode();
+ SwpHints* pHts;
+ if( pTxtNd && 0 != ( pHts = pTxtNd->GetpSwpHints()) && pHts->Count() )
+ {
+ const xub_StrLen *pEndIdx;
+ xub_StrLen nMkCntPos = rPam.GetMark()->nContent.GetIndex();
+ for( sal_uInt16 n = pHts->Count(); n; )
+ {
+ const SwTxtAttr* pAttr = (*pHts)[ --n ];
+ if( nMkCntPos > *pAttr->GetStart() )
+ break;
+
+ if( nMkCntPos == *pAttr->GetStart() &&
+ 0 != (pEndIdx = pAttr->GetEnd()) &&
+ *pEndIdx == *pAttr->GetStart() )
+ pTxtNd->DestroyAttr( pHts->Cut( n ) );
+ }
+ }
+ }
+
+ {
+ // Bug 26675: DataChanged vorm loeschen verschicken, dann bekommt
+ // man noch mit, welche Objecte sich im Bereich befinden.
+ // Danach koennen sie vor/hinter der Position befinden.
+ SwDataChanged aTmp( rPam, 0 );
+ }
+
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ bool bMerged(false);
+ if (GetIDocumentUndoRedo().DoesGroupUndo())
+ {
+ SwUndo *const pLastUndo( GetUndoManager().GetLastUndo() );
+ SwUndoDelete *const pUndoDelete(
+ dynamic_cast<SwUndoDelete *>(pLastUndo) );
+ if (pUndoDelete)
+ {
+ bMerged = pUndoDelete->CanGrouping( this, rPam );
+ // if CanGrouping() returns true it's already merged
+ }
+ }
+ if (!bMerged)
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoDelete( rPam ) );
+ }
+
+ SetModified();
+
+ return true;
+ }
+
+ if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
+ DeleteRedline( rPam, true, USHRT_MAX );
+
+ // loesche und verschiebe erstmal alle "Fly's am Absatz", die in der
+ // Selection liegen
+ DelFlyInRange(rPam.GetMark()->nNode, rPam.GetPoint()->nNode);
+ _DelBookmarks(
+ pStt->nNode,
+ pEnd->nNode,
+ NULL,
+ &pStt->nContent,
+ &pEnd->nContent);
+
+ SwNodeIndex aSttIdx( pStt->nNode );
+ SwCntntNode * pCNd = aSttIdx.GetNode().GetCntntNode();
+
+ do { // middle checked loop!
+ if( pCNd )
+ {
+ SwTxtNode * pStartTxtNode( pCNd->GetTxtNode() );
+ if ( pStartTxtNode )
+ {
+ // verschiebe jetzt noch den Inhalt in den neuen Node
+ sal_Bool bOneNd = pStt->nNode == pEnd->nNode;
+ xub_StrLen nLen = ( bOneNd ? pEnd->nContent.GetIndex()
+ : pCNd->Len() )
+ - pStt->nContent.GetIndex();
+
+ // falls schon leer, dann nicht noch aufrufen
+ if( nLen )
+ {
+ pStartTxtNode->EraseText( pStt->nContent, nLen );
+
+ if( !pStartTxtNode->Len() )
+ {
+ // METADATA: remove reference if empty (consider node deleted)
+ pStartTxtNode->RemoveMetadataReference();
+ }
+ }
+
+ if( bOneNd ) // das wars schon
+ break;
+
+ aSttIdx++;
+ }
+ else
+ {
+ // damit beim loeschen keine Indizies mehr angemeldet sind,
+ // wird hier der SwPaM aus dem Content entfernt !!
+ pStt->nContent.Assign( 0, 0 );
+ }
+ }
+
+ pCNd = pEnd->nNode.GetNode().GetCntntNode();
+ if( pCNd )
+ {
+ SwTxtNode * pEndTxtNode( pCNd->GetTxtNode() );
+ if( pEndTxtNode )
+ {
+ // falls schon leer, dann nicht noch aufrufen
+ if( pEnd->nContent.GetIndex() )
+ {
+ SwIndex aIdx( pCNd, 0 );
+ pEndTxtNode->EraseText( aIdx, pEnd->nContent.GetIndex() );
+
+ if( !pEndTxtNode->Len() )
+ {
+ // METADATA: remove reference if empty (consider node deleted)
+ pEndTxtNode->RemoveMetadataReference();
+ }
+ }
+ }
+ else
+ {
+ // damit beim Loeschen keine Indizies mehr angemeldet sind,
+ // wird hier der SwPaM aus dem Content entfernt !!
+ pEnd->nContent.Assign( 0, 0 );
+ }
+ }
+
+ // if the end is not a content node, delete it as well
+ sal_uInt32 nEnde = pEnd->nNode.GetIndex();
+ if( pCNd == NULL )
+ nEnde++;
+
+ if( aSttIdx != nEnde )
+ {
+ // loesche jetzt die Nodes in das NodesArary
+ GetNodes().Delete( aSttIdx, nEnde - aSttIdx.GetIndex() );
+ }
+
+ // falls der Node geloescht wurde, in dem der Cursor stand, so
+ // muss der Content im akt. Content angemeldet werden !!!
+ pStt->nContent.Assign( pStt->nNode.GetNode().GetCntntNode(),
+ pStt->nContent.GetIndex() );
+
+ // der PaM wird korrigiert, denn falls ueber Nodegrenzen geloescht
+ // wurde, so stehen sie in unterschieden Nodes. Auch die Selektion
+ // wird aufgehoben !
+ *pEnd = *pStt;
+ rPam.DeleteMark();
+
+ } while( sal_False );
+
+ if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
+ CompressRedlines();
+ SetModified();
+
+ return true;
+}
+
+// OD 2009-08-20 #i100466#
+// Add handling of new optional parameter <bForceJoinNext>
+bool SwDoc::DeleteAndJoin( SwPaM & rPam,
+ const bool bForceJoinNext )
+{
+ if ( lcl_StrLenOverFlow( rPam ) )
+ return false;
+
+ return lcl_DoWithBreaks( *this, rPam, (IsRedlineOn())
+ ? &SwDoc::DeleteAndJoinWithRedlineImpl
+ : &SwDoc::DeleteAndJoinImpl,
+ bForceJoinNext );
+}
+
+bool SwDoc::DeleteRange( SwPaM & rPam )
+{
+ return lcl_DoWithBreaks( *this, rPam, &SwDoc::DeleteRangeImpl );
+}
+
+
+void lcl_syncGrammarError( SwTxtNode &rTxtNode, linguistic2::ProofreadingResult& rResult,
+ xub_StrLen /*nBeginGrammarCheck*/, const ModelToViewHelper::ConversionMap* pConversionMap )
+{
+ if( rTxtNode.IsGrammarCheckDirty() )
+ return;
+ SwGrammarMarkUp* pWrong = rTxtNode.GetGrammarCheck();
+ linguistic2::SingleProofreadingError* pArray = rResult.aErrors.getArray();
+ sal_uInt16 i, j = 0;
+ if( pWrong )
+ {
+ for( i = 0; i < rResult.aErrors.getLength(); ++i )
+ {
+ const linguistic2::SingleProofreadingError &rError = rResult.aErrors[i];
+ xub_StrLen nStart = (xub_StrLen)ModelToViewHelper::ConvertToModelPosition( pConversionMap, rError.nErrorStart ).mnPos;
+ xub_StrLen nEnd = (xub_StrLen)ModelToViewHelper::ConvertToModelPosition( pConversionMap, rError.nErrorStart + rError.nErrorLength ).mnPos;
+ if( i != j )
+ pArray[j] = pArray[i];
+ if( pWrong->LookForEntry( nStart, nEnd ) )
+ ++j;
+ }
+ }
+ if( rResult.aErrors.getLength() > j )
+ rResult.aErrors.realloc( j );
+}
+
+
+uno::Any SwDoc::Spell( SwPaM& rPaM,
+ uno::Reference< XSpellChecker1 > &xSpeller,
+ sal_uInt16* pPageCnt, sal_uInt16* pPageSt,
+ bool bGrammarCheck,
+ SwConversionArgs *pConvArgs ) const
+{
+ SwPosition* pSttPos = rPaM.Start(), *pEndPos = rPaM.End();
+ uno::Reference< beans::XPropertySet > xProp( ::GetLinguPropertySet() );
+
+ SwSpellArgs *pSpellArgs = 0;
+ //SwConversionArgs *pConvArgs = 0;
+ if (pConvArgs)
+ {
+ pConvArgs->SetStart(pSttPos->nNode.GetNode().GetTxtNode(), pSttPos->nContent);
+ pConvArgs->SetEnd( pEndPos->nNode.GetNode().GetTxtNode(), pEndPos->nContent );
+ }
+ else
+ pSpellArgs = new SwSpellArgs( xSpeller,
+ pSttPos->nNode.GetNode().GetTxtNode(), pSttPos->nContent,
+ pEndPos->nNode.GetNode().GetTxtNode(), pEndPos->nContent,
+ bGrammarCheck );
+
+ sal_uLong nCurrNd = pSttPos->nNode.GetIndex();
+ sal_uLong nEndNd = pEndPos->nNode.GetIndex();
+
+ uno::Any aRet;
+ if( nCurrNd <= nEndNd )
+ {
+ SwCntntFrm* pCntFrm;
+ sal_Bool bGoOn = sal_True;
+ while( bGoOn )
+ {
+ SwNode* pNd = GetNodes()[ nCurrNd ];
+ switch( pNd->GetNodeType() )
+ {
+ case ND_TEXTNODE:
+ if( 0 != ( pCntFrm = ((SwTxtNode*)pNd)->GetFrm()) )
+ {
+ // geschutze Cellen/Flys ueberspringen, ausgeblendete
+ //ebenfalls
+ if( pCntFrm->IsProtected() )
+ {
+ nCurrNd = pNd->EndOfSectionIndex();
+ }
+ else if( !((SwTxtFrm*)pCntFrm)->IsHiddenNow() )
+ {
+ if( pPageCnt && *pPageCnt && pPageSt )
+ {
+ sal_uInt16 nPageNr = pCntFrm->GetPhyPageNum();
+ if( !*pPageSt )
+ {
+ *pPageSt = nPageNr;
+ if( *pPageCnt < *pPageSt )
+ *pPageCnt = *pPageSt;
+ }
+ long nStat;
+ if( nPageNr >= *pPageSt )
+ nStat = nPageNr - *pPageSt + 1;
+ else
+ nStat = nPageNr + *pPageCnt - *pPageSt + 1;
+ ::SetProgressState( nStat, (SwDocShell*)GetDocShell() );
+ }
+ //Spell() changes the pSpellArgs in case an error is found
+ xub_StrLen nBeginGrammarCheck = 0;
+ xub_StrLen nEndGrammarCheck = 0;
+ if( pSpellArgs && pSpellArgs->bIsGrammarCheck)
+ {
+ nBeginGrammarCheck = pSpellArgs->pStartNode == pNd ? pSpellArgs->pStartIdx->GetIndex() : 0;
+ // if grammar checking starts inside of a sentence the start position has to be adjusted
+ if( nBeginGrammarCheck )
+ {
+ SwIndex aStartIndex( dynamic_cast< SwTxtNode* >( pNd ), nBeginGrammarCheck );
+ SwPosition aStart( *pNd, aStartIndex );
+ SwCursor aCrsr(aStart, 0, false);
+ SwPosition aOrigPos = *aCrsr.GetPoint();
+ aCrsr.GoSentence( SwCursor::START_SENT );
+ if( aOrigPos != *aCrsr.GetPoint() )
+ {
+ nBeginGrammarCheck = aCrsr.GetPoint()->nContent.GetIndex();
+ }
+ }
+ nEndGrammarCheck = pSpellArgs->pEndNode == pNd ? pSpellArgs->pEndIdx->GetIndex() : ((SwTxtNode*)pNd)->GetTxt().Len();
+ }
+
+ xub_StrLen nSpellErrorPosition = ((SwTxtNode*)pNd)->GetTxt().Len();
+ if( (!pConvArgs &&
+ ((SwTxtNode*)pNd)->Spell( pSpellArgs )) ||
+ ( pConvArgs &&
+ ((SwTxtNode*)pNd)->Convert( *pConvArgs )))
+ {
+ // Abbrechen und Position merken
+ pSttPos->nNode = nCurrNd;
+ pEndPos->nNode = nCurrNd;
+ nCurrNd = nEndNd;
+ if( pSpellArgs )
+ nSpellErrorPosition = pSpellArgs->pStartIdx->GetIndex() > pSpellArgs->pEndIdx->GetIndex() ?
+ pSpellArgs->pEndIdx->GetIndex() :
+ pSpellArgs->pStartIdx->GetIndex();
+ }
+
+
+ if( pSpellArgs && pSpellArgs->bIsGrammarCheck )
+ {
+ uno::Reference< linguistic2::XProofreadingIterator > xGCIterator( GetGCIterator() );
+ if (xGCIterator.is())
+ {
+ String aText( ((SwTxtNode*)pNd)->GetTxt().Copy( nBeginGrammarCheck, nEndGrammarCheck - nBeginGrammarCheck ) );
+ uno::Reference< lang::XComponent > xDoc( ((SwDocShell*)GetDocShell())->GetBaseModel(), uno::UNO_QUERY );
+ // Expand the string:
+ rtl::OUString aExpandText;
+ const ModelToViewHelper::ConversionMap* pConversionMap =
+ ((SwTxtNode*)pNd)->BuildConversionMap( aExpandText );
+ // get XFlatParagraph to use...
+ uno::Reference< text::XFlatParagraph > xFlatPara = new SwXFlatParagraph( *((SwTxtNode*)pNd), aExpandText, pConversionMap );
+
+ // get error position of cursor in XFlatParagraph
+ sal_Int32 nGrammarErrorPosInText;
+ linguistic2::ProofreadingResult aResult;
+ sal_Int32 nGrammarErrors;
+ do
+ {
+ nGrammarErrorPosInText = ModelToViewHelper::ConvertToViewPosition( pConversionMap, nBeginGrammarCheck );
+ aResult = xGCIterator->checkSentenceAtPosition(
+ xDoc, xFlatPara, aExpandText, lang::Locale(), nBeginGrammarCheck, -1, -1 );
+
+ lcl_syncGrammarError( *((SwTxtNode*)pNd), aResult, nBeginGrammarCheck, pConversionMap );
+
+ // get suggestions to use for the specific error position
+ nGrammarErrors = aResult.aErrors.getLength();
+ // if grammar checking doesn't have any progress then quit
+ if( aResult.nStartOfNextSentencePosition <= nBeginGrammarCheck )
+ break;
+ // prepare next iteration
+ nBeginGrammarCheck = (xub_StrLen)aResult.nStartOfNextSentencePosition;
+ }
+ while( nSpellErrorPosition > aResult.nBehindEndOfSentencePosition && !nGrammarErrors && aResult.nBehindEndOfSentencePosition < nEndGrammarCheck );
+
+ if( nGrammarErrors > 0 && nSpellErrorPosition >= aResult.nBehindEndOfSentencePosition )
+ {
+ aRet <<= aResult;
+ //put the cursor to the current error
+ const linguistic2::SingleProofreadingError &rError = aResult.aErrors[0];
+ nCurrNd = pNd->GetIndex();
+ pSttPos->nNode = nCurrNd;
+ pEndPos->nNode = nCurrNd;
+ pSpellArgs->pStartNode = ((SwTxtNode*)pNd);
+ pSpellArgs->pEndNode = ((SwTxtNode*)pNd);
+ pSpellArgs->pStartIdx->Assign(((SwTxtNode*)pNd), (xub_StrLen)ModelToViewHelper::ConvertToModelPosition( pConversionMap, rError.nErrorStart ).mnPos );
+ pSpellArgs->pEndIdx->Assign(((SwTxtNode*)pNd), (xub_StrLen)ModelToViewHelper::ConvertToModelPosition( pConversionMap, rError.nErrorStart + rError.nErrorLength ).mnPos );
+ nCurrNd = nEndNd;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case ND_SECTIONNODE:
+ if( ( ((SwSectionNode*)pNd)->GetSection().IsProtect() ||
+ ((SwSectionNode*)pNd)->GetSection().IsHidden() ) )
+ nCurrNd = pNd->EndOfSectionIndex();
+ break;
+ case ND_ENDNODE:
+ {
+ break;
+ }
+ }
+
+ bGoOn = nCurrNd < nEndNd;
+ ++nCurrNd;
+ }
+ }
+
+ if( !aRet.hasValue() )
+ {
+ if (pConvArgs)
+ aRet <<= pConvArgs->aConvText;
+ else
+ aRet <<= pSpellArgs->xSpellAlt;
+ }
+ delete pSpellArgs;
+
+ return aRet;
+}
+
+class SwHyphArgs : public SwInterHyphInfo
+{
+ const SwNode *pStart;
+ const SwNode *pEnd;
+ SwNode *pNode;
+ sal_uInt16 *pPageCnt;
+ sal_uInt16 *pPageSt;
+
+ sal_uInt32 nNode;
+ xub_StrLen nPamStart;
+ xub_StrLen nPamLen;
+
+public:
+ SwHyphArgs( const SwPaM *pPam, const Point &rPoint,
+ sal_uInt16* pPageCount, sal_uInt16* pPageStart );
+ void SetPam( SwPaM *pPam ) const;
+ inline void SetNode( SwNode *pNew ) { pNode = pNew; }
+ inline const SwNode *GetNode() const { return pNode; }
+ inline void SetRange( const SwNode *pNew );
+ inline void NextNode() { ++nNode; }
+ inline sal_uInt16 *GetPageCnt() { return pPageCnt; }
+ inline sal_uInt16 *GetPageSt() { return pPageSt; }
+};
+
+SwHyphArgs::SwHyphArgs( const SwPaM *pPam, const Point &rCrsrPos,
+ sal_uInt16* pPageCount, sal_uInt16* pPageStart )
+ : SwInterHyphInfo( rCrsrPos ), pNode(0),
+ pPageCnt( pPageCount ), pPageSt( pPageStart )
+{
+ // Folgende Bedingungen muessen eingehalten werden:
+ // 1) es gibt mindestens eine Selektion
+ // 2) SPoint() == Start()
+ ASSERT( pPam->HasMark(), "SwDoc::Hyphenate: blowing in the wind");
+ ASSERT( *pPam->GetPoint() <= *pPam->GetMark(),
+ "SwDoc::Hyphenate: New York, New York");
+
+ const SwPosition *pPoint = pPam->GetPoint();
+ nNode = pPoint->nNode.GetIndex();
+
+ // Start einstellen
+ pStart = pPoint->nNode.GetNode().GetTxtNode();
+ nPamStart = pPoint->nContent.GetIndex();
+
+ // Ende und Laenge einstellen.
+ const SwPosition *pMark = pPam->GetMark();
+ pEnd = pMark->nNode.GetNode().GetTxtNode();
+ nPamLen = pMark->nContent.GetIndex();
+ if( pPoint->nNode == pMark->nNode )
+ nPamLen = nPamLen - pPoint->nContent.GetIndex();
+}
+
+inline void SwHyphArgs::SetRange( const SwNode *pNew )
+{
+ nStart = pStart == pNew ? nPamStart : 0;
+ nLen = pEnd == pNew ? nPamLen : STRING_NOTFOUND;
+}
+
+void SwHyphArgs::SetPam( SwPaM *pPam ) const
+{
+ if( !pNode )
+ *pPam->GetPoint() = *pPam->GetMark();
+ else
+ {
+ pPam->GetPoint()->nNode = nNode;
+ pPam->GetPoint()->nContent.Assign( pNode->GetCntntNode(), nWordStart );
+ pPam->GetMark()->nNode = nNode;
+ pPam->GetMark()->nContent.Assign( pNode->GetCntntNode(),
+ nWordStart + nWordLen );
+ ASSERT( nNode == pNode->GetIndex(),
+ "SwHyphArgs::SetPam: Pam desaster" );
+ }
+}
+
+// liefert sal_True zurueck, wenn es weitergehen soll.
+sal_Bool lcl_HyphenateNode( const SwNodePtr& rpNd, void* pArgs )
+{
+ // Hyphenate liefert sal_True zurueck, wenn eine Trennstelle anliegt
+ // und stellt pPam ein.
+ SwTxtNode *pNode = rpNd->GetTxtNode();
+ SwHyphArgs *pHyphArgs = (SwHyphArgs*)pArgs;
+ if( pNode )
+ {
+ SwCntntFrm* pCntFrm = pNode->GetFrm();
+ if( pCntFrm && !((SwTxtFrm*)pCntFrm)->IsHiddenNow() )
+ {
+ sal_uInt16 *pPageSt = pHyphArgs->GetPageSt();
+ sal_uInt16 *pPageCnt = pHyphArgs->GetPageCnt();
+ if( pPageCnt && *pPageCnt && pPageSt )
+ {
+ sal_uInt16 nPageNr = pCntFrm->GetPhyPageNum();
+ if( !*pPageSt )
+ {
+ *pPageSt = nPageNr;
+ if( *pPageCnt < *pPageSt )
+ *pPageCnt = *pPageSt;
+ }
+ long nStat = nPageNr >= *pPageSt ? nPageNr - *pPageSt + 1
+ : nPageNr + *pPageCnt - *pPageSt + 1;
+ ::SetProgressState( nStat, (SwDocShell*)pNode->GetDoc()->GetDocShell() );
+ }
+ pHyphArgs->SetRange( rpNd );
+ if( pNode->Hyphenate( *pHyphArgs ) )
+ {
+ pHyphArgs->SetNode( rpNd );
+ return sal_False;
+ }
+ }
+ }
+ pHyphArgs->NextNode();
+ return sal_True;
+}
+
+uno::Reference< XHyphenatedWord > SwDoc::Hyphenate(
+ SwPaM *pPam, const Point &rCrsrPos,
+ sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
+{
+ ASSERT(this == pPam->GetDoc(), "SwDoc::Hyphenate: strangers in the night");
+
+ if( *pPam->GetPoint() > *pPam->GetMark() )
+ pPam->Exchange();
+
+ SwHyphArgs aHyphArg( pPam, rCrsrPos, pPageCnt, pPageSt );
+ SwNodeIndex aTmpIdx( pPam->GetMark()->nNode, 1 );
+ GetNodes().ForEach( pPam->GetPoint()->nNode, aTmpIdx,
+ lcl_HyphenateNode, &aHyphArg );
+ aHyphArg.SetPam( pPam );
+ return aHyphArg.GetHyphWord(); // will be set by lcl_HyphenateNode
+}
+
+
+sal_Bool lcl_GetTokenToParaBreak( String& rStr, String& rRet, sal_Bool bRegExpRplc )
+{
+ sal_Bool bRet = sal_False;
+ if( bRegExpRplc )
+ {
+ xub_StrLen nPos = 0;
+ String sPara( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "\\n" )));
+ while( STRING_NOTFOUND != ( nPos = rStr.Search( sPara, nPos )) )
+ {
+ // wurde das escaped?
+ if( nPos && '\\' == rStr.GetChar( nPos-1 ))
+ {
+ if( ++nPos >= rStr.Len() )
+ break;
+ }
+ else
+ {
+ rRet = rStr.Copy( 0, nPos );
+ rStr.Erase( 0, nPos + sPara.Len() );
+ bRet = sal_True;
+ break;
+ }
+ }
+ }
+ if( !bRet )
+ {
+ rRet = rStr;
+ rStr.Erase();
+ }
+ return bRet;
+}
+
+bool SwDoc::ReplaceRange( SwPaM& rPam, const String& rStr,
+ const bool bRegExReplace )
+{
+ // unfortunately replace works slightly differently from delete,
+ // so we cannot use lcl_DoWithBreaks here...
+
+ ::std::vector<xub_StrLen> Breaks;
+
+ SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
+ aPam.Normalize(sal_False);
+ if (aPam.GetPoint()->nNode != aPam.GetMark()->nNode)
+ {
+ aPam.Move(fnMoveBackward);
+ }
+ ASSERT((aPam.GetPoint()->nNode == aPam.GetMark()->nNode), "invalid pam?");
+
+ lcl_CalcBreaks(Breaks, aPam);
+
+ while (!Breaks.empty() // skip over prefix of dummy chars
+ && (aPam.GetMark()->nContent.GetIndex() == *Breaks.begin()) )
+ {
+ // skip!
+ ++aPam.GetMark()->nContent; // always in bounds if Breaks valid
+ Breaks.erase(Breaks.begin());
+ }
+ *rPam.Start() = *aPam.GetMark(); // update start of original pam w/ prefix
+
+ if (!Breaks.size())
+ {
+ return ReplaceRangeImpl(rPam, rStr, bRegExReplace); // original pam!
+ }
+
+ // N.B.: deletion must be split into several parts if the text node
+ // contains a text attribute with end and with dummy character
+ // and the selection does not contain the text attribute completely,
+ // but overlaps its start (left), where the dummy character is.
+
+ bool bRet( true );
+ // iterate from end to start, to avoid invalidating the offsets!
+ ::std::vector<xub_StrLen>::reverse_iterator iter( Breaks.rbegin() );
+ ASSERT(aPam.GetPoint() == aPam.End(), "wrong!");
+ SwPosition & rEnd( *aPam.End() );
+ SwPosition & rStart( *aPam.Start() );
+
+ // set end of temp pam to original end (undo Move backward above)
+ rEnd = *rPam.End();
+ // after first deletion, rEnd will point into the original text node again!
+
+ while (iter != Breaks.rend())
+ {
+ rStart.nContent = *iter + 1;
+ if (rEnd.nContent != rStart.nContent) // check if part is empty
+ {
+ bRet &= (IsRedlineOn())
+ ? DeleteAndJoinWithRedlineImpl(aPam)
+ : DeleteAndJoinImpl(aPam, false);
+ }
+ rEnd.nContent = *iter;
+ ++iter;
+ }
+
+ rStart = *rPam.Start(); // set to original start
+ ASSERT(rEnd.nContent > rStart.nContent, "replace part empty!");
+ if (rEnd.nContent > rStart.nContent) // check if part is empty
+ {
+ bRet &= ReplaceRangeImpl(aPam, rStr, bRegExReplace);
+ }
+
+ rPam = aPam; // update original pam (is this required?)
+
+ return bRet;
+}
+
+// N.B.: it is possible to call Replace with a PaM that spans 2 paragraphs:
+// search with regex for "$", then replace _all_
+bool SwDoc::ReplaceRangeImpl( SwPaM& rPam, const String& rStr,
+ const bool bRegExReplace )
+{
+ if( !rPam.HasMark() || *rPam.GetPoint() == *rPam.GetMark() )
+ return false;
+
+ sal_Bool bJoinTxt, bJoinPrev;
+ lcl_GetJoinFlags( rPam, bJoinTxt, bJoinPrev );
+
+ {
+ // dann eine Kopie vom Cursor erzeugen um alle Pams aus den
+ // anderen Sichten aus dem Loeschbereich zu verschieben
+ // ABER NICHT SICH SELBST !!
+ SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
+ ::PaMCorrAbs( aDelPam, *aDelPam.GetPoint() );
+
+ SwPosition *pStt = (SwPosition*)aDelPam.Start(),
+ *pEnd = (SwPosition*)aDelPam.End();
+ ASSERT( pStt->nNode == pEnd->nNode ||
+ ( pStt->nNode.GetIndex() + 1 == pEnd->nNode.GetIndex() &&
+ !pEnd->nContent.GetIndex() ),
+ "invalid range: Point and Mark on different nodes" );
+ sal_Bool bOneNode = pStt->nNode == pEnd->nNode;
+
+ // eigenes Undo ????
+ String sRepl( rStr );
+ SwTxtNode* pTxtNd = pStt->nNode.GetNode().GetTxtNode();
+ xub_StrLen nStt = pStt->nContent.GetIndex(),
+ nEnd = bOneNode ? pEnd->nContent.GetIndex()
+ : pTxtNd->GetTxt().Len();
+
+ SwDataChanged aTmp( aDelPam, 0 );
+
+ if( IsRedlineOn() )
+ {
+ RedlineMode_t eOld = GetRedlineMode();
+ checkRedlining(eOld);
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+
+ // Bug 68584 - if any Redline will change (split!) the node
+ const ::sw::mark::IMark* pBkmk = getIDocumentMarkAccess()->makeMark( aDelPam, ::rtl::OUString(), IDocumentMarkAccess::UNO_BOOKMARK );
+
+ //JP 06.01.98: MUSS noch optimiert werden!!!
+ SetRedlineMode(
+ (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE ));
+
+ *aDelPam.GetPoint() = pBkmk->GetMarkPos();
+ if(pBkmk->IsExpanded())
+ *aDelPam.GetMark() = pBkmk->GetOtherMarkPos();
+ getIDocumentMarkAccess()->deleteMark(pBkmk);
+ pStt = aDelPam.Start();
+ pTxtNd = pStt->nNode.GetNode().GetTxtNode();
+ nStt = pStt->nContent.GetIndex();
+ }
+
+ if( sRepl.Len() )
+ {
+ // Attribute des 1. Zeichens ueber den ReplaceText setzen
+ SfxItemSet aSet( GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_TXTATR_WITHEND_END - 1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0 );
+ pTxtNd->GetAttr( aSet, nStt+1, nStt+1 );
+
+ aSet.ClearItem( RES_TXTATR_REFMARK );
+ aSet.ClearItem( RES_TXTATR_TOXMARK );
+ aSet.ClearItem( RES_TXTATR_CJK_RUBY );
+ aSet.ClearItem( RES_TXTATR_INETFMT );
+ aSet.ClearItem( RES_TXTATR_META );
+ aSet.ClearItem( RES_TXTATR_METAFIELD );
+
+ if( aDelPam.GetPoint() != aDelPam.End() )
+ aDelPam.Exchange();
+
+ // das Ende merken
+ SwNodeIndex aPtNd( aDelPam.GetPoint()->nNode, -1 );
+ xub_StrLen nPtCnt = aDelPam.GetPoint()->nContent.GetIndex();
+
+ sal_Bool bFirst = sal_True;
+ String sIns;
+ while ( lcl_GetTokenToParaBreak( sRepl, sIns, bRegExReplace ) )
+ {
+ InsertString( aDelPam, sIns );
+ if( bFirst )
+ {
+ SwNodeIndex aMkNd( aDelPam.GetMark()->nNode, -1 );
+ xub_StrLen nMkCnt = aDelPam.GetMark()->nContent.GetIndex();
+
+ SplitNode( *aDelPam.GetPoint(), false );
+
+ aMkNd++;
+ aDelPam.GetMark()->nNode = aMkNd;
+ aDelPam.GetMark()->nContent.Assign(
+ aMkNd.GetNode().GetCntntNode(), nMkCnt );
+ bFirst = sal_False;
+ }
+ else
+ SplitNode( *aDelPam.GetPoint(), false );
+ }
+ if( sIns.Len() )
+ {
+ InsertString( aDelPam, sIns );
+ }
+
+ SwPaM aTmpRange( *aDelPam.GetPoint() );
+ aTmpRange.SetMark();
+
+ aPtNd++;
+ aDelPam.GetPoint()->nNode = aPtNd;
+ aDelPam.GetPoint()->nContent.Assign( aPtNd.GetNode().GetCntntNode(),
+ nPtCnt);
+ *aTmpRange.GetMark() = *aDelPam.GetPoint();
+
+ RstTxtAttrs( aTmpRange );
+ InsertItemSet( aTmpRange, aSet, 0 );
+ }
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndoRD =
+ new SwUndoRedlineDelete( aDelPam, UNDO_REPLACE );
+ GetIDocumentUndoRedo().AppendUndo(pUndoRD);
+ }
+ AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE, aDelPam ), true);
+
+ *rPam.GetMark() = *aDelPam.GetMark();
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ *aDelPam.GetPoint() = *rPam.GetPoint();
+ GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+
+ // Bug 68584 - if any Redline will change (split!) the node
+ const ::sw::mark::IMark* pBkmk = getIDocumentMarkAccess()->makeMark( aDelPam, ::rtl::OUString(), IDocumentMarkAccess::UNO_BOOKMARK );
+
+ SwIndex& rIdx = aDelPam.GetPoint()->nContent;
+ rIdx.Assign( 0, 0 );
+ aDelPam.GetMark()->nContent = rIdx;
+ rPam.GetPoint()->nNode = 0;
+ rPam.GetPoint()->nContent = rIdx;
+ *rPam.GetMark() = *rPam.GetPoint();
+//JP 06.01.98: MUSS noch optimiert werden!!!
+SetRedlineMode( eOld );
+
+ *rPam.GetPoint() = pBkmk->GetMarkPos();
+ if(pBkmk->IsExpanded())
+ *rPam.GetMark() = pBkmk->GetOtherMarkPos();
+ getIDocumentMarkAccess()->deleteMark(pBkmk);
+ }
+ bJoinTxt = sal_False;
+ }
+ else
+ {
+ if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
+ DeleteRedline( aDelPam, true, USHRT_MAX );
+
+ SwUndoReplace* pUndoRpl = 0;
+ bool const bDoesUndo = GetIDocumentUndoRedo().DoesUndo();
+ if (bDoesUndo)
+ {
+ pUndoRpl = new SwUndoReplace(aDelPam, sRepl, bRegExReplace);
+ GetIDocumentUndoRedo().AppendUndo(pUndoRpl);
+ }
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ if( aDelPam.GetPoint() != pStt )
+ aDelPam.Exchange();
+
+ SwNodeIndex aPtNd( pStt->nNode, -1 );
+ xub_StrLen nPtCnt = pStt->nContent.GetIndex();
+
+ // die Werte nochmal setzen, falls schohn Rahmen oder Fussnoten
+ // auf dem Text entfernt wurden!
+ nStt = nPtCnt;
+ nEnd = bOneNode ? pEnd->nContent.GetIndex()
+ : pTxtNd->GetTxt().Len();
+
+ sal_Bool bFirst = sal_True;
+ String sIns;
+ while ( lcl_GetTokenToParaBreak( sRepl, sIns, bRegExReplace ) )
+ {
+ if( !bFirst || nStt == pTxtNd->GetTxt().Len() )
+ {
+ InsertString( aDelPam, sIns );
+ }
+ else if( nStt < nEnd || sIns.Len() )
+ {
+ pTxtNd->ReplaceText( pStt->nContent, nEnd - nStt, sIns );
+ }
+ SplitNode( *pStt, false);
+ bFirst = sal_False;
+ }
+
+ if( bFirst || sIns.Len() )
+ {
+ if( !bFirst || nStt == pTxtNd->GetTxt().Len() )
+ {
+ InsertString( aDelPam, sIns );
+ }
+ else if( nStt < nEnd || sIns.Len() )
+ {
+ pTxtNd->ReplaceText( pStt->nContent, nEnd - nStt, sIns );
+ }
+ }
+
+ *rPam.GetMark() = *aDelPam.GetMark();
+
+ aPtNd++;
+ rPam.GetMark()->nNode = aPtNd;
+ rPam.GetMark()->nContent.Assign( aPtNd.GetNode().GetCntntNode(),
+ nPtCnt );
+ if( bJoinTxt )
+ rPam.Move( fnMoveBackward );
+
+ if( pUndoRpl )
+ {
+ pUndoRpl->SetEnd(rPam);
+ }
+ }
+ }
+
+ if( bJoinTxt )
+ lcl_JoinText( rPam, bJoinPrev );
+
+ SetModified();
+ return true;
+}
+
+ // speicher die akt. Werte fuer die automatische Aufnahme von Ausnahmen
+ // in die Autokorrektur
+void SwDoc::SetAutoCorrExceptWord( SwAutoCorrExceptWord* pNew )
+{
+ if( pACEWord && pNew != pACEWord )
+ delete pACEWord;
+ pACEWord = pNew;
+}
+
+bool SwDoc::DelFullPara( SwPaM& rPam )
+{
+ const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End();
+ const SwNode* pNd = &rStt.nNode.GetNode();
+ sal_uInt32 nSectDiff = pNd->StartOfSectionNode()->EndOfSectionIndex() -
+ pNd->StartOfSectionIndex();
+ sal_uInt32 nNodeDiff = rEnd.nNode.GetIndex() - rStt.nNode.GetIndex();
+
+ if ( nSectDiff-2 <= nNodeDiff || IsRedlineOn() ||
+ /* #i9185# Prevent getting the node after the end node (see below) */
+ rEnd.nNode.GetIndex() + 1 == GetNodes().Count() )
+ {
+ return sal_False;
+ }
+
+ // harte SeitenUmbrueche am nachfolgenden Node verschieben
+ sal_Bool bSavePageBreak = sal_False, bSavePageDesc = sal_False;
+
+ /* #i9185# This whould lead to a segmentation fault if not catched
+ above. */
+ sal_uLong nNextNd = rEnd.nNode.GetIndex() + 1;
+ SwTableNode *const pTblNd = GetNodes()[ nNextNd ]->GetTableNode();
+
+ if( pTblNd && pNd->IsCntntNode() )
+ {
+ SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
+//JP 24.08.98: will man wirklich den PageDesc/Break vom
+// nachfolgen Absatz ueberbuegeln?
+// const SwAttrSet& rAttrSet = pTableFmt->GetAttrSet();
+// if( SFX_ITEM_SET != rAttrSet.GetItemState( RES_PAGEDESC ) &&
+// SFX_ITEM_SET != rAttrSet.GetItemState( RES_BREAK ))
+ {
+ const SfxPoolItem *pItem;
+ const SfxItemSet* pSet = ((SwCntntNode*)pNd)->GetpSwAttrSet();
+ if( pSet && SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC,
+ sal_False, &pItem ) )
+ {
+ pTableFmt->SetFmtAttr( *pItem );
+ bSavePageDesc = sal_True;
+ }
+
+ if( pSet && SFX_ITEM_SET == pSet->GetItemState( RES_BREAK,
+ sal_False, &pItem ) )
+ {
+ pTableFmt->SetFmtAttr( *pItem );
+ bSavePageBreak = sal_True;
+ }
+ }
+ }
+
+ bool const bDoesUndo = GetIDocumentUndoRedo().DoesUndo();
+ if( bDoesUndo )
+ {
+ if( !rPam.HasMark() )
+ rPam.SetMark();
+ else if( rPam.GetPoint() == &rStt )
+ rPam.Exchange();
+ rPam.GetPoint()->nNode++;
+
+ SwCntntNode *pTmpNode = rPam.GetPoint()->nNode.GetNode().GetCntntNode();
+ rPam.GetPoint()->nContent.Assign( pTmpNode, 0 );
+ bool bGoNext = (0 == pTmpNode);
+ pTmpNode = rPam.GetMark()->nNode.GetNode().GetCntntNode();
+ rPam.GetMark()->nContent.Assign( pTmpNode, 0 );
+
+ GetIDocumentUndoRedo().ClearRedo();
+
+ SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
+ {
+ SwPosition aTmpPos( *aDelPam.GetPoint() );
+ if( bGoNext )
+ {
+ pTmpNode = GetNodes().GoNext( &aTmpPos.nNode );
+ aTmpPos.nContent.Assign( pTmpNode, 0 );
+ }
+ ::PaMCorrAbs( aDelPam, aTmpPos );
+ }
+
+ SwUndoDelete* pUndo = new SwUndoDelete( aDelPam, sal_True );
+
+ *rPam.GetPoint() = *aDelPam.GetPoint();
+ pUndo->SetPgBrkFlags( bSavePageBreak, bSavePageDesc );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ else
+ {
+ SwNodeRange aRg( rStt.nNode, rEnd.nNode );
+ if( rPam.GetPoint() != &rEnd )
+ rPam.Exchange();
+
+ // versuche hinters Ende zu verschieben
+ if( !rPam.Move( fnMoveForward, fnGoNode ) )
+ {
+ // na gut, dann an den Anfang
+ rPam.Exchange();
+ if( !rPam.Move( fnMoveBackward, fnGoNode ))
+ {
+ ASSERT( sal_False, "kein Node mehr vorhanden" );
+ return sal_False;
+ }
+ }
+ // text::Bookmarks usw. verschieben
+ CorrAbs( aRg.aStart, aRg.aEnd, *rPam.GetPoint(), sal_True );
+
+ // was ist mit Fly's ??
+ {
+ // stehen noch FlyFrames rum, loesche auch diese
+ for( sal_uInt16 n = 0; n < GetSpzFrmFmts()->Count(); ++n )
+ {
+ SwFrmFmt* pFly = (*GetSpzFrmFmts())[n];
+ const SwFmtAnchor* pAnchor = &pFly->GetAnchor();
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
+ (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
+ aRg.aStart <= pAPos->nNode && pAPos->nNode <= aRg.aEnd )
+ {
+ DelLayoutFmt( pFly );
+ --n;
+ }
+ }
+ }
+
+ SwCntntNode *pTmpNode = rPam.GetBound( sal_True ).nNode.GetNode().GetCntntNode();
+ rPam.GetBound( sal_True ).nContent.Assign( pTmpNode, 0 );
+ pTmpNode = rPam.GetBound( sal_False ).nNode.GetNode().GetCntntNode();
+ rPam.GetBound( sal_False ).nContent.Assign( pTmpNode, 0 );
+ GetNodes().Delete( aRg.aStart, nNodeDiff+1 );
+ }
+ rPam.DeleteMark();
+ SetModified();
+
+ return sal_True;
+}
+
+
+void SwDoc::TransliterateText(
+ const SwPaM& rPaM,
+ utl::TransliterationWrapper& rTrans )
+{
+ SwUndoTransliterate *const pUndo = (GetIDocumentUndoRedo().DoesUndo())
+ ? new SwUndoTransliterate( rPaM, rTrans )
+ : 0;
+
+ const SwPosition* pStt = rPaM.Start(),
+ * pEnd = rPaM.End();
+ sal_uLong nSttNd = pStt->nNode.GetIndex(),
+ nEndNd = pEnd->nNode.GetIndex();
+ xub_StrLen nSttCnt = pStt->nContent.GetIndex(),
+ nEndCnt = pEnd->nContent.GetIndex();
+
+ SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode();
+ if( pStt == pEnd && pTNd ) // no selection?
+ {
+ // set current word as 'area of effect'
+
+ Boundary aBndry;
+ if( pBreakIt->GetBreakIter().is() )
+ aBndry = pBreakIt->GetBreakIter()->getWordBoundary(
+ pTNd->GetTxt(), nSttCnt,
+ pBreakIt->GetLocale( pTNd->GetLang( nSttCnt ) ),
+ WordType::ANY_WORD /*ANYWORD_IGNOREWHITESPACES*/,
+ sal_True );
+
+ if( aBndry.startPos < nSttCnt && nSttCnt < aBndry.endPos )
+ {
+ nSttCnt = (xub_StrLen)aBndry.startPos;
+ nEndCnt = (xub_StrLen)aBndry.endPos;
+ }
+ }
+
+ if( nSttNd != nEndNd ) // is more than one text node involved?
+ {
+ // iterate over all effected text nodes, the first and the last one
+ // may be incomplete because the selection starts and/or ends there
+
+ SwNodeIndex aIdx( pStt->nNode );
+ if( nSttCnt )
+ {
+ aIdx++;
+ if( pTNd )
+ pTNd->TransliterateText( rTrans, nSttCnt, pTNd->GetTxt().Len(), pUndo );
+ }
+
+ for( ; aIdx.GetIndex() < nEndNd; aIdx++ )
+ {
+ if( 0 != ( pTNd = aIdx.GetNode().GetTxtNode() ))
+ pTNd->TransliterateText( rTrans, 0, pTNd->GetTxt().Len(), pUndo );
+ }
+
+ if( nEndCnt && 0 != ( pTNd = pEnd->nNode.GetNode().GetTxtNode() ))
+ pTNd->TransliterateText( rTrans, 0, nEndCnt, pUndo );
+ }
+ else if( pTNd && nSttCnt < nEndCnt )
+ pTNd->TransliterateText( rTrans, nSttCnt, nEndCnt, pUndo );
+
+ if( pUndo )
+ {
+ if( pUndo->HasData() )
+ {
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ else
+ delete pUndo;
+ }
+ SetModified();
+}
+
+
+#define MAX_REDLINE_COUNT 250
+// -----------------------------------------------------------------------------
+void SwDoc::checkRedlining(RedlineMode_t& _rReadlineMode)
+{
+ const SwRedlineTbl& rRedlineTbl = GetRedlineTbl();
+ SwEditShell* pEditShell = GetEditShell();
+ Window* pParent = pEditShell ? pEditShell->GetWin() : NULL;
+ if ( pParent && !mbReadlineChecked && rRedlineTbl.Count() > MAX_REDLINE_COUNT
+ && !((_rReadlineMode & nsRedlineMode_t::REDLINE_SHOW_DELETE) == nsRedlineMode_t::REDLINE_SHOW_DELETE) )
+ {
+ WarningBox aWarning( pParent,SW_RES(MSG_DISABLE_READLINE_QUESTION));
+ sal_uInt16 nResult = aWarning.Execute();
+ mbReadlineChecked = sal_True;
+ if ( nResult == RET_YES )
+ {
+ sal_Int32 nMode = (sal_Int32)_rReadlineMode;
+ nMode |= nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE;
+ _rReadlineMode = (RedlineMode_t)nMode;
+ }
+ }
+}
+// -----------------------------------------------------------------------------
+
+void SwDoc::CountWords( const SwPaM& rPaM, SwDocStat& rStat ) const
+{
+ // This is a modified version of SwDoc::TransliterateText
+ const SwPosition* pStt = rPaM.Start();
+ const SwPosition* pEnd = pStt == rPaM.GetPoint() ? rPaM.GetMark()
+ : rPaM.GetPoint();
+
+ const sal_uLong nSttNd = pStt->nNode.GetIndex();
+ const sal_uLong nEndNd = pEnd->nNode.GetIndex();
+
+ const xub_StrLen nSttCnt = pStt->nContent.GetIndex();
+ const xub_StrLen nEndCnt = pEnd->nContent.GetIndex();
+
+ const SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode();
+ if( pStt == pEnd && pTNd ) // no region ?
+ {
+ // do nothing
+ return;
+ }
+
+ if( nSttNd != nEndNd )
+ {
+ SwNodeIndex aIdx( pStt->nNode );
+ if( nSttCnt )
+ {
+ aIdx++;
+ if( pTNd )
+ pTNd->CountWords( rStat, nSttCnt, pTNd->GetTxt().Len() );
+ }
+
+ for( ; aIdx.GetIndex() < nEndNd; aIdx++ )
+ if( 0 != ( pTNd = aIdx.GetNode().GetTxtNode() ))
+ pTNd->CountWords( rStat, 0, pTNd->GetTxt().Len() );
+
+ if( nEndCnt && 0 != ( pTNd = pEnd->nNode.GetNode().GetTxtNode() ))
+ pTNd->CountWords( rStat, 0, nEndCnt );
+ }
+ else if( pTNd && nSttCnt < nEndCnt )
+ pTNd->CountWords( rStat, nSttCnt, nEndCnt );
+}
+
+void SwDoc::RemoveLeadingWhiteSpace(const SwPosition & rPos )
+{
+ const SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
+ if ( pTNd )
+ {
+ const String& rTxt = pTNd->GetTxt();
+ xub_StrLen nIdx = 0;
+ sal_Unicode cCh;
+ while( nIdx < rTxt.Len() &&
+ ( '\t' == ( cCh = rTxt.GetChar( nIdx ) ) ||
+ ( ' ' == cCh ) ) )
+ ++nIdx;
+
+ if ( nIdx > 0 )
+ {
+ SwPaM aPam(rPos);
+ aPam.GetPoint()->nContent = 0;
+ aPam.SetMark();
+ aPam.GetMark()->nContent = nIdx;
+ DeleteRange( aPam );
+ }
+ }
+}
diff --git a/sw/source/core/doc/docfld.cxx b/sw/source/core/doc/docfld.cxx
new file mode 100644
index 000000000000..28d41e9e5364
--- /dev/null
+++ b/sw/source/core/doc/docfld.cxx
@@ -0,0 +1,2829 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#include <string.h>
+#include <float.h>
+#include <tools/datetime.hxx>
+#ifndef _SVSTDARR_HXX
+#define _SVSTDARR_ULONGS
+#include <svl/svarray.hxx>
+#endif
+#include <vcl/svapp.hxx>
+#include <vcl/svapp.hxx>
+#include <unotools/charclass.hxx>
+#include <unotools/transliterationwrapper.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <cntfrm.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <swtable.hxx>
+#include <calc.hxx>
+#include <txtfld.hxx>
+#include <fmtfld.hxx>
+#include <tox.hxx>
+#include <txttxmrk.hxx>
+#include <docfld.hxx> // fuer Expression-Felder
+#include <docufld.hxx>
+#include <ddefld.hxx>
+#include <usrfld.hxx>
+#include <expfld.hxx>
+#include <dbfld.hxx>
+#include <flddat.hxx>
+#include <chpfld.hxx>
+#include <reffld.hxx>
+#include <flddropdown.hxx>
+#include <dbmgr.hxx>
+#include <section.hxx>
+#include <cellatr.hxx>
+#include <docary.hxx>
+#include <authfld.hxx>
+#include <txtinet.hxx>
+#include <fmtcntnt.hxx>
+#include <poolfmt.hrc> // fuer InitFldTypes
+
+#include <SwUndoField.hxx>
+
+using namespace ::com::sun::star::uno;
+
+extern sal_Bool IsFrameBehind( const SwTxtNode& rMyNd, sal_uInt16 nMySttPos,
+ const SwTxtNode& rBehindNd, sal_uInt16 nSttPos );
+
+SV_IMPL_OP_PTRARR_SORT( _SetGetExpFlds, _SetGetExpFldPtr )
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Feldtypen einfuegen
+ --------------------------------------------------------------------*/
+/*
+ * Implementierung der Feldfunktionen am Doc
+ * Return immer einen gueltigen Pointer auf den Typ. Wenn er also neu
+ * zugefuegt oder schon vorhanden ist.
+ */
+
+SwFieldType* SwDoc::InsertFldType(const SwFieldType &rFldTyp)
+{
+ sal_uInt16 nSize = pFldTypes->Count(),
+ nFldWhich = rFldTyp.Which();
+
+ sal_uInt16 i = INIT_FLDTYPES;
+
+ switch( nFldWhich )
+ {
+ case RES_SETEXPFLD:
+ //JP 29.01.96: SequenceFelder beginnen aber bei INIT_FLDTYPES - 3!!
+ // Sonst gibt es doppelte Nummernkreise!!
+ //MIB 14.03.95: Ab sofort verlaesst sich auch der SW3-Reader
+ //beim Aufbau der String-Pools und beim Einlesen von SetExp-Feldern
+ //hierauf
+ if( nsSwGetSetExpType::GSE_SEQ & ((SwSetExpFieldType&)rFldTyp).GetType() )
+ i -= INIT_SEQ_FLDTYPES;
+ // kein break;
+ case RES_DBFLD:
+ case RES_USERFLD:
+ case RES_DDEFLD:
+ {
+ const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
+ String sFldNm( rFldTyp.GetName() );
+ for( ; i < nSize; ++i )
+ if( nFldWhich == (*pFldTypes)[i]->Which() &&
+ rSCmp.isEqual( sFldNm, (*pFldTypes)[i]->GetName() ))
+ return (*pFldTypes)[i];
+ }
+ break;
+
+ case RES_AUTHORITY:
+ for( ; i < nSize; ++i )
+ if( nFldWhich == (*pFldTypes)[i]->Which() )
+ return (*pFldTypes)[i];
+ break;
+
+ default:
+ for( i = 0; i < nSize; ++i )
+ if( nFldWhich == (*pFldTypes)[i]->Which() )
+ return (*pFldTypes)[i];
+ }
+
+ SwFieldType* pNew = rFldTyp.Copy();
+ switch( nFldWhich )
+ {
+ case RES_DDEFLD:
+ ((SwDDEFieldType*)pNew)->SetDoc( this );
+ break;
+
+ case RES_DBFLD:
+ case RES_TABLEFLD:
+ case RES_DATETIMEFLD:
+ case RES_GETEXPFLD:
+ ((SwValueFieldType*)pNew)->SetDoc( this );
+ break;
+
+ case RES_USERFLD:
+ case RES_SETEXPFLD:
+ ((SwValueFieldType*)pNew)->SetDoc( this );
+ // JP 29.07.96: opt. FeldListe fuer den Calculator vorbereiten:
+ pUpdtFlds->InsertFldType( *pNew );
+ break;
+ case RES_AUTHORITY :
+ ((SwAuthorityFieldType*)pNew)->SetDoc( this );
+ break;
+ }
+
+ pFldTypes->Insert( pNew, nSize );
+ SetModified();
+
+ return (*pFldTypes)[ nSize ];
+}
+
+void SwDoc::InsDeletedFldType( SwFieldType& rFldTyp )
+{
+ // der FeldTyp wurde als geloescht gekennzeichnet und aus dem
+ // Array entfernt. Nun muss man nach diesem wieder suchen.
+ // - Ist der nicht vorhanden, dann kann er eingefuegt werden.
+ // - Wird genau der gleiche Typ gefunden, dann muss der geloeschte
+ // einen anderen Namen erhalten.
+
+ sal_uInt16 nSize = pFldTypes->Count(), nFldWhich = rFldTyp.Which();
+ sal_uInt16 i = INIT_FLDTYPES;
+
+ ASSERT( RES_SETEXPFLD == nFldWhich ||
+ RES_USERFLD == nFldWhich ||
+ RES_DDEFLD == nFldWhich, "Falscher FeldTyp" );
+
+ const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
+ const String& rFldNm = rFldTyp.GetName();
+ SwFieldType* pFnd;
+
+ for( ; i < nSize; ++i )
+ if( nFldWhich == (pFnd = (*pFldTypes)[i])->Which() &&
+ rSCmp.isEqual( rFldNm, pFnd->GetName() ) )
+ {
+ // neuen Namen suchen
+ sal_uInt16 nNum = 1;
+ do {
+ String sSrch( rFldNm );
+ sSrch.Append( String::CreateFromInt32( nNum ));
+ for( i = INIT_FLDTYPES; i < nSize; ++i )
+ if( nFldWhich == (pFnd = (*pFldTypes)[i])->Which() &&
+ rSCmp.isEqual( sSrch, pFnd->GetName() ) )
+ break;
+
+ if( i >= nSize ) // nicht gefunden
+ {
+ ((String&)rFldNm) = sSrch;
+ break; // raus aus der While-Schleife
+ }
+ ++nNum;
+ } while( sal_True );
+ break;
+ }
+
+ // nicht gefunden, also eintragen und Flag loeschen
+ pFldTypes->Insert( &rFldTyp, nSize );
+ switch( nFldWhich )
+ {
+ case RES_SETEXPFLD:
+ ((SwSetExpFieldType&)rFldTyp).SetDeleted( sal_False );
+ break;
+ case RES_USERFLD:
+ ((SwUserFieldType&)rFldTyp).SetDeleted( sal_False );
+ break;
+ case RES_DDEFLD:
+ ((SwDDEFieldType&)rFldTyp).SetDeleted( sal_False );
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Feldtypen loeschen
+ --------------------------------------------------------------------*/
+
+void SwDoc::RemoveFldType(sal_uInt16 nFld)
+{
+ ASSERT( INIT_FLDTYPES <= nFld, "keine InitFields loeschen" );
+ /*
+ * Abheangige Felder vorhanden -> ErrRaise
+ */
+ sal_uInt16 nSize = pFldTypes->Count();
+ if(nFld < nSize)
+ {
+ SwFieldType* pTmp = (*pFldTypes)[nFld];
+
+ // JP 29.07.96: opt. FeldListe fuer den Calculator vorbereiten:
+ sal_uInt16 nWhich = pTmp->Which();
+ switch( nWhich )
+ {
+ case RES_SETEXPFLD:
+ case RES_USERFLD:
+ pUpdtFlds->RemoveFldType( *pTmp );
+ // kein break;
+ case RES_DDEFLD:
+ if( pTmp->GetDepends() && !IsUsed( *pTmp ) )
+ {
+ if( RES_SETEXPFLD == nWhich )
+ ((SwSetExpFieldType*)pTmp)->SetDeleted( sal_True );
+ else if( RES_USERFLD == nWhich )
+ ((SwUserFieldType*)pTmp)->SetDeleted( sal_True );
+ else
+ ((SwDDEFieldType*)pTmp)->SetDeleted( sal_True );
+ nWhich = 0;
+ }
+ break;
+ }
+
+ if( nWhich )
+ {
+ ASSERT( !pTmp->GetDepends(), "Abhaengige vorh.!" );
+ // Feldtype loschen
+ delete pTmp;
+ }
+ pFldTypes->Remove( nFld );
+ SetModified();
+ }
+}
+
+const SwFldTypes* SwDoc::GetFldTypes() const
+{
+ return pFldTypes;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Den ersten Typen mit ResId und Namen finden
+ --------------------------------------------------------------------*/
+
+SwFieldType* SwDoc::GetFldType( sal_uInt16 nResId, const String& rName,
+ bool bDbFieldMatching // used in some UNO calls for RES_DBFLD
+ // to use different string matching code
+ // #i51815#
+ ) const
+{
+ sal_uInt16 nSize = pFldTypes->Count(), i = 0;
+ const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
+
+ switch( nResId )
+ {
+ case RES_SETEXPFLD:
+ //JP 29.01.96: SequenceFelder beginnen aber bei INIT_FLDTYPES - 3!!
+ // Sonst gibt es doppelte Nummernkreise!!
+ //MIB 14.03.95: Ab sofort verlaesst sich auch der SW3-Reader
+ //beim Aufbau der String-Pools und beim Einlesen von SetExp-Feldern
+ //hierauf
+ i = INIT_FLDTYPES - INIT_SEQ_FLDTYPES;
+ break;
+
+ case RES_DBFLD:
+ case RES_USERFLD:
+ case RES_DDEFLD:
+ case RES_AUTHORITY:
+ i = INIT_FLDTYPES;
+ break;
+ }
+
+ SwFieldType* pRet = 0;
+ for( ; i < nSize; ++i )
+ {
+ SwFieldType* pFldType = (*pFldTypes)[i];
+
+ String aFldName( pFldType->GetName() );
+ if (bDbFieldMatching && nResId == RES_DBFLD) // #i51815#
+ aFldName.SearchAndReplaceAll(DB_DELIM, '.');
+
+ if( nResId == pFldType->Which() &&
+ rSCmp.isEqual( rName, aFldName ))
+ {
+ pRet = pFldType;
+ break;
+ }
+ }
+ return pRet;
+}
+
+
+/*************************************************************************
+|* SwDoc::UpdateFlds()
+|* Beschreibung Felder updaten
+*************************************************************************/
+/*
+ * Alle sollen neu evaluiert werden.
+ */
+
+void SwDoc::UpdateFlds( SfxPoolItem *pNewHt, bool bCloseDB )
+{
+ // Modify() fuer jeden Feldtypen rufen,
+ // abhaengige SwTxtFld werden benachrichtigt ...
+
+ for( sal_uInt16 i=0; i < pFldTypes->Count(); ++i)
+ {
+ switch( (*pFldTypes)[i]->Which() )
+ {
+ // Tabellen-Felder als vorletztes Updaten
+ // Referenzen als letztes Updaten
+ case RES_GETREFFLD:
+ case RES_TABLEFLD:
+ case RES_DBFLD:
+ case RES_JUMPEDITFLD:
+ case RES_REFPAGESETFLD: // werden nie expandiert!
+ break;
+
+ case RES_DDEFLD:
+ {
+ if( !pNewHt )
+ {
+ SwMsgPoolItem aUpdateDDE( RES_UPDATEDDETBL );
+ (*pFldTypes)[i]->Modify( 0, &aUpdateDDE );
+ }
+ else
+ (*pFldTypes)[i]->Modify( 0, pNewHt );
+ break;
+ }
+ case RES_GETEXPFLD:
+ case RES_SETEXPFLD:
+ case RES_HIDDENTXTFLD:
+ case RES_HIDDENPARAFLD:
+ // Expression-Felder werden gesondert behandelt
+ if( !pNewHt )
+ break;
+ default:
+ (*pFldTypes)[i]->Modify( 0, pNewHt );
+ }
+ }
+
+ if( !IsExpFldsLocked() )
+ UpdateExpFlds( 0, sal_False ); // Expression-Felder Updaten
+
+ // Tabellen
+ UpdateTblFlds(pNewHt);
+
+ // Referenzen
+ UpdateRefFlds(pNewHt);
+
+ if( bCloseDB )
+ GetNewDBMgr()->CloseAll();
+
+ // Nur bei KomplettUpdate evaluieren
+ SetModified();
+}
+
+/******************************************************************************
+ * void SwDoc::UpdateUsrFlds()
+ ******************************************************************************/
+
+void SwDoc::UpdateUsrFlds()
+{
+ SwCalc* pCalc = 0;
+ const SwFieldType* pFldType;
+ for( sal_uInt16 i = INIT_FLDTYPES; i < pFldTypes->Count(); ++i )
+ if( RES_USERFLD == ( pFldType = (*pFldTypes)[i] )->Which() )
+ {
+ if( !pCalc )
+ pCalc = new SwCalc( *this );
+ ((SwUserFieldType*)pFldType)->GetValue( *pCalc );
+ }
+
+ if( pCalc )
+ {
+ delete pCalc;
+ SetModified();
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Referenzfelder und TableFelder erneuern
+ --------------------------------------------------------------------*/
+
+void SwDoc::UpdateRefFlds( SfxPoolItem* pHt )
+{
+ SwFieldType* pFldType;
+ for( sal_uInt16 i = 0; i < pFldTypes->Count(); ++i )
+ if( RES_GETREFFLD == ( pFldType = (*pFldTypes)[i] )->Which() )
+ pFldType->Modify( 0, pHt );
+}
+
+void SwDoc::UpdateTblFlds( SfxPoolItem* pHt )
+{
+ ASSERT( !pHt || RES_TABLEFML_UPDATE == pHt->Which(),
+ "Was ist das fuer ein MessageItem?" );
+
+ SwFieldType* pFldType(0);
+
+ for (sal_uInt16 i = 0; i < pFldTypes->Count(); ++i)
+ {
+ if( RES_TABLEFLD == ( pFldType = (*pFldTypes)[i] )->Which() )
+ {
+ SwTableFmlUpdate* pUpdtFld = 0;
+ if( pHt && RES_TABLEFML_UPDATE == pHt->Which() )
+ pUpdtFld = (SwTableFmlUpdate*)pHt;
+
+ SwClientIter aIter( *pFldType );
+ for( SwFmtFld* pFmtFld = (SwFmtFld*)aIter.First( TYPE( SwFmtFld ));
+ pFmtFld; pFmtFld = (SwFmtFld*)aIter.Next() )
+ if( pFmtFld->GetTxtFld() )
+ {
+ SwTblField* pFld = (SwTblField*)pFmtFld->GetFld();
+
+ if( pUpdtFld )
+ {
+ // bestimme Tabelle, in der das Feld steht
+ const SwTableNode* pTblNd;
+ const SwTxtNode& rTxtNd = pFmtFld->GetTxtFld()->GetTxtNode();
+ if( !rTxtNd.GetNodes().IsDocNodes() ||
+ 0 == ( pTblNd = rTxtNd.FindTableNode() ) )
+ continue;
+
+ switch( pUpdtFld->eFlags )
+ {
+ case TBL_CALC:
+ // setze das Value-Flag zurueck
+ // JP 17.06.96: interne Darstellung auf alle Formeln
+ // (Referenzen auf andere Tabellen!!!)
+ if( nsSwExtendedSubType::SUB_CMD & pFld->GetSubType() )
+ pFld->PtrToBoxNm( pUpdtFld->pTbl );
+ else
+ pFld->ChgValid( sal_False );
+ break;
+ case TBL_BOXNAME:
+ // ist es die gesuchte Tabelle ??
+ if( &pTblNd->GetTable() == pUpdtFld->pTbl )
+ // zur externen Darstellung
+ pFld->PtrToBoxNm( pUpdtFld->pTbl );
+ break;
+ case TBL_BOXPTR:
+ // zur internen Darstellung
+ // JP 17.06.96: interne Darstellung auf alle Formeln
+ // (Referenzen auf andere Tabellen!!!)
+ pFld->BoxNmToPtr( pUpdtFld->pTbl );
+ break;
+ case TBL_RELBOXNAME:
+ // ist es die gesuchte Tabelle ??
+ if( &pTblNd->GetTable() == pUpdtFld->pTbl )
+ // zur relativen Darstellung
+ pFld->ToRelBoxNm( pUpdtFld->pTbl );
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ // setze bei allen das Value-Flag zurueck
+ pFld->ChgValid( sal_False );
+ }
+
+ break;
+ }
+ pFldType = 0;
+ }
+
+ // und dann noch alle Tabellen Box Formeln abklappern
+ const SfxPoolItem* pItem;
+ sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_BOXATR_FORMULA );
+ for (sal_uInt32 i = 0; i < nMaxItems; ++i)
+ {
+ if( 0 != (pItem = GetAttrPool().GetItem2( RES_BOXATR_FORMULA, i ) ) &&
+ ((SwTblBoxFormula*)pItem)->GetDefinedIn() )
+ {
+ ((SwTblBoxFormula*)pItem)->ChangeState( pHt );
+ }
+ }
+
+
+ // alle Felder/Boxen sind jetzt invalide, also kann das Rechnen anfangen
+ if( pHt && ( RES_TABLEFML_UPDATE != pHt->Which() ||
+ TBL_CALC != ((SwTableFmlUpdate*)pHt)->eFlags ))
+ return ;
+
+ SwCalc* pCalc = 0;
+
+ if( pFldType )
+ {
+ SwClient* pLast;
+ SwClientIter aIter( *pFldType );
+ // dann rechne mal schoen
+ // JP 27.03.97: Beim Berechnen am Ende anfangen - weil neue
+ // Felder immer am Anfang der Modifykette eingefuegt
+ // werden. Beim Import haben wir damit eine bessere/
+ // schnellere Berechnung bei "Kettenformeln"
+ if( 0 != ( pLast = aIter.GoEnd() ))
+ do {
+ SwFmtFld* pFmtFld = (SwFmtFld*)pLast;
+ SwTblField* pFld;
+ if( !pFmtFld->GetTxtFld() || (nsSwExtendedSubType::SUB_CMD &
+ (pFld = (SwTblField*)pFmtFld->GetFld())->GetSubType() ))
+ continue;
+
+ // muss neu berechnet werden (und ist keine textuelle Anzeige)
+ if( !pFld->IsValid() )
+ {
+ // bestimme Tabelle, in der das Feld steht
+ const SwTxtNode& rTxtNd = pFmtFld->GetTxtFld()->GetTxtNode();
+ if( !rTxtNd.GetNodes().IsDocNodes() )
+ continue;
+ const SwTableNode* pTblNd = rTxtNd.FindTableNode();
+ if( !pTblNd )
+ continue;
+
+ // falls dieses Feld nicht in der zu updatenden
+ // Tabelle steht, ueberspringen !!
+ if( pHt && &pTblNd->GetTable() !=
+ ((SwTableFmlUpdate*)pHt)->pTbl )
+ continue;
+
+ if( !pCalc )
+ pCalc = new SwCalc( *this );
+
+ // bestimme die Werte aller SetExpresion Felder, die
+ // bis zur Tabelle gueltig sind
+ SwFrm* pFrm = 0;
+ if( pTblNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
+ {
+ // steht im Sonderbereich, wird teuer !!
+ Point aPt; // den im Layout 1. Frame returnen - Tab.Kopfzeile !!
+ pFrm = rTxtNd.GetFrm( &aPt );
+ if( pFrm )
+ {
+ SwPosition aPos( *pTblNd );
+ if( GetBodyTxtNode( *this, aPos, *pFrm ) )
+ FldsToCalc( *pCalc, _SetGetExpFld(
+ aPos.nNode, pFmtFld->GetTxtFld(),
+ &aPos.nContent ));
+ else
+ pFrm = 0;
+ }
+ }
+ if( !pFrm )
+ {
+ // einen Index fuers bestimmen vom TextNode anlegen
+ SwNodeIndex aIdx( rTxtNd );
+ FldsToCalc( *pCalc,
+ _SetGetExpFld( aIdx, pFmtFld->GetTxtFld() ));
+ }
+
+ SwTblCalcPara aPara( *pCalc, pTblNd->GetTable() );
+ pFld->CalcField( aPara );
+ if( aPara.IsStackOverFlow() )
+ {
+ if( aPara.CalcWithStackOverflow() )
+ pFld->CalcField( aPara );
+#ifdef DBG_UTIL
+ else
+ {
+ // mind. ein ASSERT
+ ASSERT( !this, "die Kettenformel konnte nicht errechnet werden" );
+ }
+#endif
+ }
+ pCalc->SetCalcError( CALC_NOERR );
+ }
+ pFmtFld->Modify( 0, pHt );
+ } while( 0 != ( pLast = aIter-- ));
+ }
+
+ // dann berechene noch die Formeln an den Boxen
+ for (sal_uInt32 i = 0; i < nMaxItems; ++i )
+ {
+ if( 0 != (pItem = GetAttrPool().GetItem2( RES_BOXATR_FORMULA, i ) ) &&
+ ((SwTblBoxFormula*)pItem)->GetDefinedIn() &&
+ !((SwTblBoxFormula*)pItem)->IsValid() )
+ {
+ SwTblBoxFormula* pFml = (SwTblBoxFormula*)pItem;
+ SwTableBox* pBox = pFml->GetTableBox();
+ if( pBox && pBox->GetSttNd() &&
+ pBox->GetSttNd()->GetNodes().IsDocNodes() )
+ {
+ const SwTableNode* pTblNd = pBox->GetSttNd()->FindTableNode();
+ if( !pHt || &pTblNd->GetTable() ==
+ ((SwTableFmlUpdate*)pHt)->pTbl )
+ {
+ double nValue;
+ if( !pCalc )
+ pCalc = new SwCalc( *this );
+
+ // bestimme die Werte aller SetExpresion Felder, die
+ // bis zur Tabelle gueltig sind
+ SwFrm* pFrm = 0;
+ if( pTblNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
+ {
+ // steht im Sonderbereich, wird teuer !!
+ Point aPt; // den im Layout 1. Frame returnen - Tab.Kopfzeile !!
+ SwNodeIndex aCNdIdx( *pTblNd, +2 );
+ SwCntntNode* pCNd = aCNdIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = GetNodes().GoNext( &aCNdIdx );
+
+ if( pCNd && 0 != (pFrm = pCNd->GetFrm( &aPt )) )
+ {
+ SwPosition aPos( *pCNd );
+ if( GetBodyTxtNode( *this, aPos, *pFrm ) )
+ FldsToCalc( *pCalc, _SetGetExpFld( aPos.nNode ));
+ else
+ pFrm = 0;
+ }
+ }
+ if( !pFrm )
+ {
+ // einen Index fuers bestimmen vom TextNode anlegen
+ SwNodeIndex aIdx( *pTblNd );
+ FldsToCalc( *pCalc, _SetGetExpFld( aIdx ));
+ }
+
+ SwTblCalcPara aPara( *pCalc, pTblNd->GetTable() );
+ pFml->Calc( aPara, nValue );
+
+ if( aPara.IsStackOverFlow() )
+ {
+ if( aPara.CalcWithStackOverflow() )
+ pFml->Calc( aPara, nValue );
+#ifdef DBG_UTIL
+ else
+ {
+ // mind. ein ASSERT
+ ASSERT( !this, "die Kettenformel konnte nicht errechnet werden" );
+ }
+#endif
+ }
+
+ SwFrmFmt* pFmt = pBox->ClaimFrmFmt();
+ SfxItemSet aTmp( GetAttrPool(),
+ RES_BOXATR_BEGIN,RES_BOXATR_END-1 );
+
+ if( pCalc->IsCalcError() )
+ nValue = DBL_MAX;
+ aTmp.Put( SwTblBoxValue( nValue ));
+ if( SFX_ITEM_SET != pFmt->GetItemState( RES_BOXATR_FORMAT ))
+ aTmp.Put( SwTblBoxNumFormat( 0 ));
+ pFmt->SetFmtAttr( aTmp );
+
+ pCalc->SetCalcError( CALC_NOERR );
+ }
+ }
+ }
+ }
+
+ if( pCalc )
+ delete pCalc;
+}
+
+void SwDoc::UpdatePageFlds( SfxPoolItem* pMsgHnt )
+{
+ SwFieldType* pFldType;
+ for( sal_uInt16 i = 0; i < INIT_FLDTYPES; ++i )
+ switch( ( pFldType = (*pFldTypes)[ i ] )->Which() )
+ {
+ case RES_PAGENUMBERFLD:
+ case RES_CHAPTERFLD:
+ case RES_GETEXPFLD:
+ case RES_REFPAGEGETFLD:
+ pFldType->Modify( 0, pMsgHnt );
+ break;
+ case RES_DOCSTATFLD:
+ pFldType->Modify( 0, 0 );
+ break;
+ }
+ SetNewFldLst(true);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung:
+ --------------------------------------------------------------------*/
+
+// ---- Loesche alle nicht referenzierten FeldTypen eines Dokumentes --
+void SwDoc::GCFieldTypes()
+{
+ for( sal_uInt16 n = pFldTypes->Count(); n > INIT_FLDTYPES; )
+ if( !(*pFldTypes)[ --n ]->GetDepends() )
+ RemoveFldType( n );
+}
+
+void SwDoc::LockExpFlds()
+{
+ ++nLockExpFld;
+}
+
+void SwDoc::UnlockExpFlds()
+{
+ if( nLockExpFld )
+ --nLockExpFld;
+}
+
+bool SwDoc::IsExpFldsLocked() const
+{
+ return 0 != nLockExpFld;
+}
+
+SwDocUpdtFld& SwDoc::GetUpdtFlds() const
+{
+ return *pUpdtFlds;
+}
+
+bool SwDoc::IsNewFldLst() const
+{
+ return mbNewFldLst;
+}
+
+void SwDoc::SetNewFldLst(bool bFlag)
+{
+ mbNewFldLst = bFlag;
+}
+
+
+//----------------------------------------------------------------------
+
+// der StartIndex kann optional mit angegeben werden (z.B. wenn dieser
+// zuvor schon mal erfragt wurde - ist sonst eine virtuelle Methode !!)
+
+_SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx, const SwTxtFld* pFld,
+ const SwIndex* pIdx )
+{
+ eSetGetExpFldType = TEXTFIELD;
+ CNTNT.pTxtFld = pFld;
+ nNode = rNdIdx.GetIndex();
+ if( pIdx )
+ nCntnt = pIdx->GetIndex();
+ else if( pFld )
+ nCntnt = *pFld->GetStart();
+ else
+ nCntnt = 0;
+}
+
+_SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx,
+ const SwTxtINetFmt& rINet, const SwIndex* pIdx )
+{
+ eSetGetExpFldType = TEXTINET;
+ CNTNT.pTxtINet = &rINet;
+ nNode = rNdIdx.GetIndex();
+ if( pIdx )
+ nCntnt = pIdx->GetIndex();
+ else
+ nCntnt = *rINet.GetStart();
+}
+
+ //Erweiterung fuer Sections:
+ // diese haben immer als Content-Position 0xffff !!
+ // Auf dieser steht nie ein Feld, maximal bis STRING_MAXLEN moeglich
+_SetGetExpFld::_SetGetExpFld( const SwSectionNode& rSectNd,
+ const SwPosition* pPos )
+{
+ eSetGetExpFldType = SECTIONNODE;
+ CNTNT.pSection = &rSectNd.GetSection();
+
+ if( pPos )
+ {
+ nNode = pPos->nNode.GetIndex();
+ nCntnt = pPos->nContent.GetIndex();
+ }
+ else
+ {
+ nNode = rSectNd.GetIndex();
+ nCntnt = 0;
+ }
+}
+
+_SetGetExpFld::_SetGetExpFld( const SwTableBox& rTBox, const SwPosition* pPos )
+{
+ eSetGetExpFldType = TABLEBOX;
+ CNTNT.pTBox = &rTBox;
+
+ if( pPos )
+ {
+ nNode = pPos->nNode.GetIndex();
+ nCntnt = pPos->nContent.GetIndex();
+ }
+ else
+ {
+ nNode = 0;
+ nCntnt = 0;
+ if( rTBox.GetSttNd() )
+ {
+ SwNodeIndex aIdx( *rTBox.GetSttNd() );
+ const SwCntntNode* pNd = aIdx.GetNode().GetNodes().GoNext( &aIdx );
+ if( pNd )
+ nNode = pNd->GetIndex();
+ }
+ }
+}
+
+_SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx,
+ const SwTxtTOXMark& rTOX,
+ const SwIndex* pIdx )
+{
+ eSetGetExpFldType = TEXTTOXMARK;
+ CNTNT.pTxtTOX = &rTOX;
+ nNode = rNdIdx.GetIndex();
+ if( pIdx )
+ nCntnt = pIdx->GetIndex();
+ else
+ nCntnt = *rTOX.GetStart();
+}
+
+_SetGetExpFld::_SetGetExpFld( const SwPosition& rPos )
+{
+ eSetGetExpFldType = CRSRPOS;
+ CNTNT.pPos = &rPos;
+ nNode = rPos.nNode.GetIndex();
+ nCntnt = rPos.nContent.GetIndex();
+}
+
+_SetGetExpFld::_SetGetExpFld( const SwFlyFrmFmt& rFlyFmt,
+ const SwPosition* pPos )
+{
+ eSetGetExpFldType = FLYFRAME;
+ CNTNT.pFlyFmt = &rFlyFmt;
+ if( pPos )
+ {
+ nNode = pPos->nNode.GetIndex();
+ nCntnt = pPos->nContent.GetIndex();
+ }
+ else
+ {
+ const SwFmtCntnt& rCntnt = rFlyFmt.GetCntnt();
+ nNode = rCntnt.GetCntntIdx()->GetIndex() + 1;
+ nCntnt = 0;
+ }
+}
+
+void _SetGetExpFld::GetPos( SwPosition& rPos ) const
+{
+ rPos.nNode = nNode;
+ rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), nCntnt );
+}
+
+void _SetGetExpFld::GetPosOfContent( SwPosition& rPos ) const
+{
+ const SwNode* pNd = GetNodeFromCntnt();
+ if( pNd )
+ pNd = pNd->GetCntntNode();
+
+ if( pNd )
+ {
+ rPos.nNode = *pNd;
+ rPos.nContent.Assign( (SwCntntNode*)pNd,GetCntPosFromCntnt() );
+ }
+ else
+ {
+ rPos.nNode = nNode;
+ rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), nCntnt );
+ }
+}
+
+void _SetGetExpFld::SetBodyPos( const SwCntntFrm& rFrm )
+{
+ if( !rFrm.IsInDocBody() )
+ {
+ SwNodeIndex aIdx( *rFrm.GetNode() );
+ SwDoc& rDoc = *aIdx.GetNodes().GetDoc();
+ SwPosition aPos( aIdx );
+#ifdef DBG_UTIL
+ ASSERT( ::GetBodyTxtNode( rDoc, aPos, rFrm ), "wo steht das Feld" );
+#else
+ ::GetBodyTxtNode( rDoc, aPos, rFrm );
+#endif
+ nNode = aPos.nNode.GetIndex();
+ nCntnt = aPos.nContent.GetIndex();
+ }
+}
+
+sal_Bool _SetGetExpFld::operator<( const _SetGetExpFld& rFld ) const
+{
+ if( nNode < rFld.nNode || ( nNode == rFld.nNode && nCntnt < rFld.nCntnt ))
+ return sal_True;
+ else if( nNode != rFld.nNode || nCntnt != rFld.nCntnt )
+ return sal_False;
+
+ const SwNode *pFirst = GetNodeFromCntnt(),
+ *pNext = rFld.GetNodeFromCntnt();
+
+ // Position gleich: nur weiter wenn beide FeldPointer besetzt sind !!
+ if( !pFirst || !pNext )
+ return sal_False;
+
+ // gleiche Section ??
+ if( pFirst->StartOfSectionNode() != pNext->StartOfSectionNode() )
+ {
+ // sollte einer in der Tabelle stehen ?
+ const SwNode *pFirstStt, *pNextStt;
+ const SwTableNode* pTblNd = pFirst->FindTableNode();
+ if( pTblNd )
+ pFirstStt = pTblNd->StartOfSectionNode();
+ else
+ pFirstStt = pFirst->StartOfSectionNode();
+
+ if( 0 != ( pTblNd = pNext->FindTableNode() ) )
+ pNextStt = pTblNd->StartOfSectionNode();
+ else
+ pNextStt = pNext->StartOfSectionNode();
+
+ if( pFirstStt != pNextStt )
+ {
+ if( pFirst->IsTxtNode() && pNext->IsTxtNode() &&
+ ( pFirst->FindFlyStartNode() || pNext->FindFlyStartNode() ))
+ {
+ return ::IsFrameBehind( *(SwTxtNode*)pNext, nCntnt,
+ *(SwTxtNode*)pFirst, nCntnt );
+ }
+ return pFirstStt->GetIndex() < pNextStt->GetIndex();
+ }
+ }
+
+ // ist gleiche Section, dann Feld im gleichen Node ?
+ if( pFirst != pNext )
+ return pFirst->GetIndex() < pNext->GetIndex();
+
+ // gleicher Node in der Section, dann Position im Node
+ return GetCntPosFromCntnt() < rFld.GetCntPosFromCntnt();
+}
+
+const SwNode* _SetGetExpFld::GetNodeFromCntnt() const
+{
+ const SwNode* pRet = 0;
+ if( CNTNT.pTxtFld )
+ switch( eSetGetExpFldType )
+ {
+ case TEXTFIELD:
+ pRet = &CNTNT.pTxtFld->GetTxtNode();
+ break;
+
+ case TEXTINET:
+ pRet = &CNTNT.pTxtINet->GetTxtNode();
+ break;
+
+ case SECTIONNODE:
+ pRet = CNTNT.pSection->GetFmt()->GetSectionNode();
+ break;
+
+ case CRSRPOS:
+ pRet = &CNTNT.pPos->nNode.GetNode();
+ break;
+
+ case TEXTTOXMARK:
+ pRet = &CNTNT.pTxtTOX->GetTxtNode();
+ break;
+
+ case TABLEBOX:
+ if( CNTNT.pTBox->GetSttNd() )
+ {
+ SwNodeIndex aIdx( *CNTNT.pTBox->GetSttNd() );
+ pRet = aIdx.GetNode().GetNodes().GoNext( &aIdx );
+ }
+ break;
+
+ case FLYFRAME:
+ {
+ SwNodeIndex aIdx( *CNTNT.pFlyFmt->GetCntnt().GetCntntIdx() );
+ pRet = aIdx.GetNode().GetNodes().GoNext( &aIdx );
+ }
+ break;
+ }
+ return pRet;
+}
+
+xub_StrLen _SetGetExpFld::GetCntPosFromCntnt() const
+{
+ sal_uInt16 nRet = 0;
+ if( CNTNT.pTxtFld )
+ switch( eSetGetExpFldType )
+ {
+ case TEXTFIELD:
+ case TEXTINET:
+ case TEXTTOXMARK:
+ nRet = *CNTNT.pTxtFld->GetStart();
+ break;
+ case CRSRPOS:
+ nRet = CNTNT.pPos->nContent.GetIndex();
+ break;
+ default:
+ break;
+ }
+ return nRet;
+}
+
+_HashStr::_HashStr( const String& rName, const String& rText,
+ _HashStr* pNxt )
+ : SwHash( rName ), aSetStr( rText )
+{
+ pNext = pNxt;
+}
+
+// suche nach dem Namen, ist er vorhanden, returne seinen String, sonst
+// einen LeerString
+void LookString( SwHash** ppTbl, sal_uInt16 nSize, const String& rName,
+ String& rRet, sal_uInt16* pPos )
+{
+ rRet = rName;
+ rRet.EraseLeadingChars().EraseTrailingChars();
+ SwHash* pFnd = Find( rRet, ppTbl, nSize, pPos );
+ if( pFnd )
+ rRet = ((_HashStr*)pFnd)->aSetStr;
+ else
+ rRet.Erase();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung:
+ --------------------------------------------------------------------*/
+
+String lcl_GetDBVarName( SwDoc& rDoc, SwDBNameInfField& rDBFld )
+{
+ SwDBData aDBData( rDBFld.GetDBData( &rDoc ));
+ String sDBNumNm;
+ SwDBData aDocData = rDoc.GetDBData();
+
+ if( aDBData != aDocData )
+ {
+ sDBNumNm = aDBData.sDataSource;
+ sDBNumNm += DB_DELIM;
+ sDBNumNm += String(aDBData.sCommand);
+ sDBNumNm += DB_DELIM;
+ }
+ sDBNumNm += SwFieldType::GetTypeStr(TYP_DBSETNUMBERFLD);
+
+ return sDBNumNm;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung:
+ --------------------------------------------------------------------*/
+
+void lcl_CalcFld( SwDoc& rDoc, SwCalc& rCalc, const _SetGetExpFld& rSGEFld,
+ SwNewDBMgr* pMgr )
+{
+ const SwTxtFld* pTxtFld = rSGEFld.GetFld();
+ if( !pTxtFld )
+ return ;
+
+ const SwField* pFld = pTxtFld->GetFld().GetFld();
+ const sal_uInt16 nFldWhich = pFld->GetTyp()->Which();
+
+ if( RES_SETEXPFLD == nFldWhich )
+ {
+ SwSbxValue aValue;
+ if( nsSwGetSetExpType::GSE_EXPR & pFld->GetSubType() )
+ aValue.PutDouble( ((SwSetExpField*)pFld)->GetValue() );
+ else
+ // Erweiterung fuers Rechnen mit Strings
+ aValue.PutString( ((SwSetExpField*)pFld)->GetExpStr() );
+
+ // setze im Calculator den neuen Wert
+ rCalc.VarChange( pFld->GetTyp()->GetName(), aValue );
+ }
+ else if( pMgr )
+ {
+ switch( nFldWhich )
+ {
+ case RES_DBNUMSETFLD:
+ {
+ SwDBNumSetField* pDBFld = (SwDBNumSetField*)pFld;
+
+ SwDBData aDBData(pDBFld->GetDBData(&rDoc));
+
+ if( pDBFld->IsCondValid() &&
+ pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand ))
+ rCalc.VarChange( lcl_GetDBVarName( rDoc, *pDBFld),
+ pDBFld->GetFormat() );
+ }
+ break;
+ case RES_DBNEXTSETFLD:
+ {
+ SwDBNextSetField* pDBFld = (SwDBNextSetField*)pFld;
+ SwDBData aDBData(pDBFld->GetDBData(&rDoc));
+ if( !pDBFld->IsCondValid() ||
+ !pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand ))
+ break;
+
+ String sDBNumNm(lcl_GetDBVarName( rDoc, *pDBFld));
+ SwCalcExp* pExp = rCalc.VarLook( sDBNumNm );
+ if( pExp )
+ rCalc.VarChange( sDBNumNm, pExp->nValue.GetLong() + 1 );
+ }
+ break;
+
+ }
+ }
+}
+
+void SwDoc::FldsToCalc( SwCalc& rCalc, const _SetGetExpFld& rToThisFld )
+{
+ // erzeuge die Sortierteliste aller SetFelder
+ pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC );
+ mbNewFldLst = sal_False;
+
+ SwNewDBMgr* pMgr = GetNewDBMgr();
+ pMgr->CloseAll(sal_False);
+
+ if( pUpdtFlds->GetSortLst()->Count() )
+ {
+ sal_uInt16 nLast;
+ _SetGetExpFld* pFld = (_SetGetExpFld*)&rToThisFld;
+ if( pUpdtFlds->GetSortLst()->Seek_Entry( pFld, &nLast ) )
+ ++nLast;
+
+ const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
+ for( sal_uInt16 n = 0; n < nLast; ++n, ++ppSortLst )
+ lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr );
+ }
+
+ pMgr->CloseAll(sal_False);
+}
+
+void SwDoc::FldsToCalc( SwCalc& rCalc, sal_uLong nLastNd, sal_uInt16 nLastCnt )
+{
+ // erzeuge die Sortierteliste aller SetFelder
+ pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC );
+ mbNewFldLst = sal_False;
+
+ SwNewDBMgr* pMgr = GetNewDBMgr();
+ pMgr->CloseAll(sal_False);
+
+ const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
+
+ for( sal_uInt16 n = pUpdtFlds->GetSortLst()->Count();
+ n &&
+ ( (*ppSortLst)->GetNode() < nLastNd ||
+ ( (*ppSortLst)->GetNode() == nLastNd && (*ppSortLst)->GetCntnt() <= nLastCnt )
+ );
+ --n, ++ppSortLst )
+ lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr );
+
+ pMgr->CloseAll(sal_False);
+}
+
+void SwDoc::FldsToExpand( SwHash**& ppHashTbl, sal_uInt16& rTblSize,
+ const _SetGetExpFld& rToThisFld )
+{
+ // erzeuge die Sortierteliste aller SetFelder
+ pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_EXPAND );
+ mbNewFldLst = sal_False;
+
+ // HashTabelle fuer alle String Ersetzungen, wird "one the fly" gefuellt
+ // (versuche eine "ungerade"-Zahl zu erzeugen)
+ rTblSize = (( pUpdtFlds->GetSortLst()->Count() / 7 ) + 1 ) * 7;
+ ppHashTbl = new SwHash*[ rTblSize ];
+ memset( ppHashTbl, 0, sizeof( _HashStr* ) * rTblSize );
+
+ sal_uInt16 nLast;
+ {
+ _SetGetExpFld* pTmp = (_SetGetExpFld*)&rToThisFld;
+ if( pUpdtFlds->GetSortLst()->Seek_Entry( pTmp, &nLast ) )
+ ++nLast;
+ }
+
+ sal_uInt16 nPos;
+ SwHash* pFnd;
+ String aNew;
+ const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
+ for( ; nLast; --nLast, ++ppSortLst )
+ {
+ const SwTxtFld* pTxtFld = (*ppSortLst)->GetFld();
+ if( !pTxtFld )
+ continue;
+
+ const SwField* pFld = pTxtFld->GetFld().GetFld();
+ switch( pFld->GetTyp()->Which() )
+ {
+ case RES_SETEXPFLD:
+ if( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() )
+ {
+ // setze in der HashTabelle den neuen Wert
+ // ist die "Formel" ein Feld ??
+ SwSetExpField* pSFld = (SwSetExpField*)pFld;
+ LookString( ppHashTbl, rTblSize, pSFld->GetFormula(), aNew );
+
+ if( !aNew.Len() ) // nichts gefunden, dann ist
+ aNew = pSFld->GetFormula(); // die Formel der neue Wert
+
+ // OD 11.02.2003 #i3141# - update expression of field as in
+ // method <SwDoc::UpdateExpFlds(..)> for string/text fields
+ pSFld->ChgExpStr( aNew );
+
+ // suche den Namen vom Feld
+ aNew = ((SwSetExpFieldType*)pSFld->GetTyp())->GetSetRefName();
+ // Eintrag vorhanden ?
+ pFnd = Find( aNew, ppHashTbl, rTblSize, &nPos );
+ if( pFnd )
+ // Eintrag in der HashTabelle aendern
+ ((_HashStr*)pFnd)->aSetStr = pSFld->GetExpStr();
+ else
+ // neuen Eintrag einfuegen
+ *(ppHashTbl + nPos ) = new _HashStr( aNew,
+ pSFld->GetExpStr(), (_HashStr*)*(ppHashTbl + nPos) );
+ }
+ break;
+ case RES_DBFLD:
+ {
+ const String& rName = pFld->GetTyp()->GetName();
+
+ // Eintrag in den HashTable eintragen
+ // Eintrag vorhanden ?
+ pFnd = Find( rName, ppHashTbl, rTblSize, &nPos );
+ String const value(pFld->ExpandField(IsClipBoard()));
+ if( pFnd )
+ {
+ // Eintrag in der HashTabelle aendern
+ static_cast<_HashStr*>(pFnd)->aSetStr = value;
+ }
+ else
+ {
+ // neuen Eintrag einfuegen
+ *(ppHashTbl + nPos ) = new _HashStr( rName,
+ value, static_cast<_HashStr *>(*(ppHashTbl + nPos)));
+ }
+ }
+ break;
+ }
+ }
+}
+
+
+void SwDoc::UpdateExpFlds( SwTxtFld* pUpdtFld, bool bUpdRefFlds )
+{
+ if( IsExpFldsLocked() || IsInReading() )
+ return;
+
+ sal_Bool bOldInUpdateFlds = pUpdtFlds->IsInUpdateFlds();
+ pUpdtFlds->SetInUpdateFlds( sal_True );
+
+ pUpdtFlds->MakeFldList( *this, sal_True, GETFLD_ALL );
+ mbNewFldLst = sal_False;
+
+ if( !pUpdtFlds->GetSortLst()->Count() )
+ {
+ if( bUpdRefFlds )
+ UpdateRefFlds(NULL);
+
+ pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds );
+ pUpdtFlds->SetFieldsDirty( sal_False );
+ return ;
+ }
+
+ sal_uInt16 nWhich, n;
+
+ // HashTabelle fuer alle String Ersetzungen, wird "one the fly" gefuellt
+ // (versuche eine "ungerade"-Zahl zu erzeugen)
+ sal_uInt16 nStrFmtCnt = (( pFldTypes->Count() / 7 ) + 1 ) * 7;
+ SwHash** pHashStrTbl = new SwHash*[ nStrFmtCnt ];
+ memset( pHashStrTbl, 0, sizeof( _HashStr* ) * nStrFmtCnt );
+
+ {
+ const SwFieldType* pFldType;
+ // gesondert behandeln:
+ for( n = pFldTypes->Count(); n; )
+ switch( ( pFldType = (*pFldTypes)[ --n ] )->Which() )
+ {
+ case RES_USERFLD:
+ {
+ // Eintrag vorhanden ?
+ sal_uInt16 nPos;
+ const String& rNm = pFldType->GetName();
+ String sExpand(((SwUserFieldType*)pFldType)->Expand(nsSwGetSetExpType::GSE_STRING, 0, 0));
+ SwHash* pFnd = Find( rNm, pHashStrTbl, nStrFmtCnt, &nPos );
+ if( pFnd )
+ // Eintrag in der HashTabelle aendern ??
+ ((_HashStr*)pFnd)->aSetStr = sExpand;
+ else
+ // neuen Eintrag einfuegen
+ *(pHashStrTbl + nPos ) = new _HashStr( rNm, sExpand,
+ (_HashStr*)*(pHashStrTbl + nPos) );
+ }
+ break;
+ case RES_SETEXPFLD:
+ ((SwSetExpFieldType*)pFldType)->SetOutlineChgNd( 0 );
+ break;
+ }
+ }
+
+ // Ok, das Array ist soweit mit allen Feldern gefuellt, dann rechne mal
+ SwCalc aCalc( *this );
+
+ String sDBNumNm( SwFieldType::GetTypeStr( TYP_DBSETNUMBERFLD ) );
+
+ // aktuelle Datensatznummer schon vorher einstellen
+ SwNewDBMgr* pMgr = GetNewDBMgr();
+ pMgr->CloseAll(sal_False);
+/*
+ if(pMgr && pMgr->OpenDB(DBMGR_STD, GetDBDesc(), sal_False))
+ {
+ if(!pMgr->IsInMerge() )
+ pMgr->ToFirstSelectedRecord(DBMGR_STD);
+
+ aCalc.VarChange( sDBNumNm, pMgr->GetCurSelectedRecordId(DBMGR_STD));
+ }
+*/
+
+ String aNew;
+ const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
+ for( n = pUpdtFlds->GetSortLst()->Count(); n; --n, ++ppSortLst )
+ {
+ SwSection* pSect = (SwSection*)(*ppSortLst)->GetSection();
+ if( pSect )
+ {
+ //!SECTION
+
+// if( pGFld->IsInBodyTxt() )
+ SwSbxValue aValue = aCalc.Calculate(
+ pSect->GetCondition() );
+ if(!aValue.IsVoidValue())
+ pSect->SetCondHidden( aValue.GetBool() );
+ continue;
+ }
+
+ SwTxtFld* pTxtFld = (SwTxtFld*)(*ppSortLst)->GetFld();
+ if( !pTxtFld )
+ {
+ ASSERT( !this, "was ist es denn nun" );
+ continue;
+ }
+
+ SwFmtFld* pFmtFld = (SwFmtFld*)&pTxtFld->GetFld();
+ SwField* pFld = pFmtFld->GetFld();
+
+ switch( nWhich = pFld->GetTyp()->Which() )
+ {
+ case RES_HIDDENTXTFLD:
+ {
+ SwHiddenTxtField* pHFld = (SwHiddenTxtField*)pFld;
+ SwSbxValue aValue = aCalc.Calculate( pHFld->GetPar1() );
+ sal_Bool bValue = !aValue.GetBool();
+ if(!aValue.IsVoidValue())
+ {
+ pHFld->SetValue( bValue );
+ // Feld Evaluieren
+ pHFld->Evaluate(this);
+ }
+ }
+ break;
+ case RES_HIDDENPARAFLD:
+ {
+ SwHiddenParaField* pHPFld = (SwHiddenParaField*)pFld;
+ SwSbxValue aValue = aCalc.Calculate( pHPFld->GetPar1() );
+ sal_Bool bValue = aValue.GetBool();
+ if(!aValue.IsVoidValue())
+ pHPFld->SetHidden( bValue );
+ }
+ break;
+ case RES_DBSETNUMBERFLD:
+ {
+ ((SwDBSetNumberField*)pFld)->Evaluate(this);
+ aCalc.VarChange( sDBNumNm, ((SwDBSetNumberField*)pFld)->GetSetNumber());
+ }
+ break;
+ case RES_DBNEXTSETFLD:
+ case RES_DBNUMSETFLD:
+ UpdateDBNumFlds( *(SwDBNameInfField*)pFld, aCalc );
+ break;
+ case RES_DBFLD:
+ {
+ // Feld Evaluieren
+ ((SwDBField*)pFld)->Evaluate();
+
+ SwDBData aTmpDBData(((SwDBField*)pFld)->GetDBData());
+
+ if( pMgr->IsDataSourceOpen(aTmpDBData.sDataSource, aTmpDBData.sCommand, sal_False))
+ aCalc.VarChange( sDBNumNm, pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType));
+
+ const String& rName = pFld->GetTyp()->GetName();
+
+ // Wert fuer den Calculator setzen
+//JP 10.02.96: GetValue macht hier doch keinen Sinn
+// ((SwDBField*)pFld)->GetValue();
+
+//!OK aCalc.VarChange(aName, ((SwDBField*)pFld)->GetValue(aCalc));
+
+ // Eintrag in den HashTable eintragen
+ // Eintrag vorhanden ?
+ sal_uInt16 nPos;
+ SwHash* pFnd = Find( rName, pHashStrTbl, nStrFmtCnt, &nPos );
+ String const value(pFld->ExpandField(IsClipBoard()));
+ if( pFnd )
+ {
+ // Eintrag in der HashTabelle aendern
+ static_cast<_HashStr*>(pFnd)->aSetStr = value;
+ }
+ else
+ {
+ // neuen Eintrag einfuegen
+ *(pHashStrTbl + nPos ) = new _HashStr( rName,
+ value, static_cast<_HashStr *>(*(pHashStrTbl + nPos)));
+ }
+ }
+ break;
+ case RES_GETEXPFLD:
+ case RES_SETEXPFLD:
+ {
+ if( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() ) // String Ersetzung
+ {
+ if( RES_GETEXPFLD == nWhich )
+ {
+ SwGetExpField* pGFld = (SwGetExpField*)pFld;
+
+ if( (!pUpdtFld || pUpdtFld == pTxtFld )
+ && pGFld->IsInBodyTxt() )
+ {
+ LookString( pHashStrTbl, nStrFmtCnt,
+ pGFld->GetFormula(), aNew );
+ pGFld->ChgExpStr( aNew );
+ }
+ }
+ else
+ {
+ SwSetExpField* pSFld = (SwSetExpField*)pFld;
+ // ist die "Formel" ein Feld ??
+ LookString( pHashStrTbl, nStrFmtCnt,
+ pSFld->GetFormula(), aNew );
+
+ if( !aNew.Len() ) // nichts gefunden, dann ist die
+ aNew = pSFld->GetFormula(); // Formel der neue Wert
+
+ // nur ein spezielles FeldUpdaten ?
+ if( !pUpdtFld || pUpdtFld == pTxtFld )
+ pSFld->ChgExpStr( aNew );
+
+ // suche den Namen vom Feld
+ aNew = ((SwSetExpFieldType*)pSFld->GetTyp())->GetSetRefName();
+ // Eintrag vorhanden ?
+ sal_uInt16 nPos;
+ SwHash* pFnd = Find( aNew, pHashStrTbl, nStrFmtCnt, &nPos );
+ if( pFnd )
+ // Eintrag in der HashTabelle aendern
+ ((_HashStr*)pFnd)->aSetStr = pSFld->GetExpStr();
+ else
+ // neuen Eintrag einfuegen
+ *(pHashStrTbl + nPos ) = pFnd = new _HashStr( aNew,
+ pSFld->GetExpStr(),
+ (_HashStr*)*(pHashStrTbl + nPos) );
+
+ // Erweiterung fuers Rechnen mit Strings
+ SwSbxValue aValue;
+ aValue.PutString( ((_HashStr*)pFnd)->aSetStr );
+ aCalc.VarChange( aNew, aValue );
+ }
+ }
+ else // Formel neu berechnen
+ {
+ if( RES_GETEXPFLD == nWhich )
+ {
+ SwGetExpField* pGFld = (SwGetExpField*)pFld;
+
+ if( (!pUpdtFld || pUpdtFld == pTxtFld )
+ && pGFld->IsInBodyTxt() )
+ {
+ SwSbxValue aValue = aCalc.Calculate(
+ pGFld->GetFormula());
+ if(!aValue.IsVoidValue())
+ pGFld->SetValue(aValue.GetDouble() );
+ }
+ }
+ else
+ {
+ SwSetExpField* pSFld = (SwSetExpField*)pFld;
+ SwSetExpFieldType* pSFldTyp = (SwSetExpFieldType*)pFld->GetTyp();
+ aNew = pSFldTyp->GetName();
+
+ SwNode* pSeqNd = 0;
+
+ if( pSFld->IsSequenceFld() )
+ {
+ const sal_uInt8 nLvl = pSFldTyp->GetOutlineLvl();
+ if( MAXLEVEL > nLvl )
+ {
+ // dann teste, ob die Nummer neu aufsetzen muss
+ pSeqNd = GetNodes()[ (*ppSortLst)->GetNode() ];
+
+ const SwTxtNode* pOutlNd = pSeqNd->
+ FindOutlineNodeOfLevel( nLvl );
+ if( pSFldTyp->GetOutlineChgNd() != pOutlNd )
+ {
+ pSFldTyp->SetOutlineChgNd( pOutlNd );
+ aCalc.VarChange( aNew, 0 );
+ }
+ }
+ }
+
+ aNew += '=';
+ aNew += pSFld->GetFormula();
+
+ SwSbxValue aValue = aCalc.Calculate( aNew );
+ double nErg = aValue.GetDouble();
+ // nur ein spezielles Feld updaten ?
+ if( !aValue.IsVoidValue() && (!pUpdtFld || pUpdtFld == pTxtFld) )
+ {
+ pSFld->SetValue( nErg );
+
+ if( pSeqNd )
+ pSFldTyp->SetChapter( *pSFld, *pSeqNd );
+ }
+ }
+ }
+ }
+ } // switch
+
+ pFmtFld->Modify( 0, 0 ); // Formatierung anstossen
+
+ if( pUpdtFld == pTxtFld ) // sollte nur dieses geupdatet werden
+ {
+ if( RES_GETEXPFLD == nWhich || // nur GetFeld oder
+ RES_HIDDENTXTFLD == nWhich || // HiddenTxt?
+ RES_HIDDENPARAFLD == nWhich) // HiddenParaFld?
+ break; // beenden
+ pUpdtFld = 0; // ab jetzt alle Updaten
+ }
+ }
+
+ pMgr->CloseAll(sal_False);
+ // HashTabelle wieder loeschen
+ ::DeleteHashTable( pHashStrTbl, nStrFmtCnt );
+
+ // Referenzfelder updaten
+ if( bUpdRefFlds )
+ UpdateRefFlds(NULL);
+
+ pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds );
+ pUpdtFlds->SetFieldsDirty( sal_False );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung:
+ --------------------------------------------------------------------*/
+
+void SwDoc::UpdateDBNumFlds( SwDBNameInfField& rDBFld, SwCalc& rCalc )
+{
+ SwNewDBMgr* pMgr = GetNewDBMgr();
+
+ sal_uInt16 nFldType = rDBFld.Which();
+
+ sal_Bool bPar1 = rCalc.Calculate( rDBFld.GetPar1() ).GetBool();
+
+ if( RES_DBNEXTSETFLD == nFldType )
+ ((SwDBNextSetField&)rDBFld).SetCondValid( bPar1 );
+ else
+ ((SwDBNumSetField&)rDBFld).SetCondValid( bPar1 );
+
+ if( rDBFld.GetRealDBData().sDataSource.getLength() )
+ {
+ // Eine bestimmte Datenbank bearbeiten
+ if( RES_DBNEXTSETFLD == nFldType )
+ ((SwDBNextSetField&)rDBFld).Evaluate(this);
+ else
+ ((SwDBNumSetField&)rDBFld).Evaluate(this);
+
+ SwDBData aTmpDBData( rDBFld.GetDBData(this) );
+
+ if( pMgr->OpenDataSource( aTmpDBData.sDataSource, aTmpDBData.sCommand, -1, false ))
+ rCalc.VarChange( lcl_GetDBVarName( *this, rDBFld),
+ pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType) );
+ }
+ else
+ {
+ DBG_ERROR("TODO: what should happen with unnamed DBFields?");
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung:
+ --------------------------------------------------------------------*/
+
+void SwDoc::_InitFieldTypes() // wird vom CTOR gerufen!!
+{
+ // Feldtypen
+ sal_uInt16 nFldType = 0;
+ pFldTypes->Insert( new SwDateTimeFieldType(this), nFldType++ );
+ pFldTypes->Insert( new SwChapterFieldType, nFldType++ );
+ pFldTypes->Insert( new SwPageNumberFieldType, nFldType++ );
+ pFldTypes->Insert( new SwAuthorFieldType, nFldType++ );
+ pFldTypes->Insert( new SwFileNameFieldType(this), nFldType++ );
+ pFldTypes->Insert( new SwDBNameFieldType(this), nFldType++);
+ pFldTypes->Insert( new SwGetExpFieldType(this), nFldType++ );
+ pFldTypes->Insert( new SwGetRefFieldType( this ), nFldType++ );
+ pFldTypes->Insert( new SwHiddenTxtFieldType, nFldType++ );
+ pFldTypes->Insert( new SwPostItFieldType(this), nFldType++ );
+ pFldTypes->Insert( new SwDocStatFieldType(this), nFldType++);
+ pFldTypes->Insert( new SwDocInfoFieldType(this), nFldType++);
+ pFldTypes->Insert( new SwInputFieldType( this ), nFldType++ );
+ pFldTypes->Insert( new SwTblFieldType( this ), nFldType++);
+ pFldTypes->Insert( new SwMacroFieldType(this), nFldType++ );
+ pFldTypes->Insert( new SwHiddenParaFieldType, nFldType++ );
+ pFldTypes->Insert( new SwDBNextSetFieldType, nFldType++ );
+ pFldTypes->Insert( new SwDBNumSetFieldType, nFldType++ );
+ pFldTypes->Insert( new SwDBSetNumberFieldType, nFldType++ );
+ pFldTypes->Insert( new SwTemplNameFieldType(this), nFldType++);
+ pFldTypes->Insert( new SwTemplNameFieldType(this),nFldType++);
+ pFldTypes->Insert( new SwExtUserFieldType, nFldType++ );
+ pFldTypes->Insert( new SwRefPageSetFieldType, nFldType++ );
+ pFldTypes->Insert( new SwRefPageGetFieldType( this ), nFldType++ );
+ pFldTypes->Insert( new SwJumpEditFieldType( this ), nFldType++ );
+ pFldTypes->Insert( new SwScriptFieldType( this ), nFldType++ );
+ pFldTypes->Insert( new SwCombinedCharFieldType, nFldType++ );
+ pFldTypes->Insert( new SwDropDownFieldType, nFldType++ );
+
+ // Types muessen am Ende stehen !!
+ // Im InsertFldType wird davon ausgegangen !!!!
+ // MIB 14.04.95: Im Sw3StringPool::Setup (sw3imp.cxx) und
+ // lcl_sw3io_InSetExpField (sw3field.cxx) jetzt auch
+ pFldTypes->Insert( new SwSetExpFieldType(this,
+ SW_RESSTR(STR_POOLCOLL_LABEL_ABB), nsSwGetSetExpType::GSE_SEQ), nFldType++);
+ pFldTypes->Insert( new SwSetExpFieldType(this,
+ SW_RESSTR(STR_POOLCOLL_LABEL_TABLE), nsSwGetSetExpType::GSE_SEQ),nFldType++);
+ pFldTypes->Insert( new SwSetExpFieldType(this,
+ SW_RESSTR(STR_POOLCOLL_LABEL_FRAME), nsSwGetSetExpType::GSE_SEQ),nFldType++);
+ pFldTypes->Insert( new SwSetExpFieldType(this,
+ SW_RESSTR(STR_POOLCOLL_LABEL_DRAWING), nsSwGetSetExpType::GSE_SEQ),nFldType++);
+
+ ASSERT( nFldType == INIT_FLDTYPES, "Bad initsize: SwFldTypes" );
+}
+
+void SwDoc::InsDelFldInFldLst( bool bIns, const SwTxtFld& rFld )
+{
+ if( !mbNewFldLst || !IsInDtor() )
+ pUpdtFlds->InsDelFldInFldLst( bIns, rFld );
+}
+
+SwDBData SwDoc::GetDBData()
+{
+ return GetDBDesc();
+}
+
+const SwDBData& SwDoc::GetDBDesc()
+{
+ if(!aDBData.sDataSource.getLength())
+ {
+ const sal_uInt16 nSize = pFldTypes->Count();
+ for(sal_uInt16 i = 0; i < nSize && !aDBData.sDataSource.getLength(); ++i)
+ {
+ SwFieldType& rFldType = *((*pFldTypes)[i]);
+ sal_uInt16 nWhich = rFldType.Which();
+ if(IsUsed(rFldType))
+ {
+ switch(nWhich)
+ {
+ case RES_DBFLD:
+ case RES_DBNEXTSETFLD:
+ case RES_DBNUMSETFLD:
+ case RES_DBSETNUMBERFLD:
+ {
+ SwClientIter aIter( rFldType );
+ SwFmtFld* pFld = (SwFmtFld*)aIter.First( TYPE( SwFmtFld ));
+ while(pFld)
+ {
+ if(pFld->IsFldInDoc())
+ {
+ if(RES_DBFLD == nWhich)
+ aDBData =
+ (static_cast < SwDBFieldType * > (pFld->GetFld()->GetTyp()))
+ ->GetDBData();
+ else
+ aDBData = (static_cast < SwDBNameInfField* > (pFld->GetFld()))->GetRealDBData();
+ break;
+ }
+ pFld = (SwFmtFld*)aIter.Next();
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ if(!aDBData.sDataSource.getLength())
+ aDBData = GetNewDBMgr()->GetAddressDBName();
+ return aDBData;
+}
+
+void SwDoc::SetInitDBFields( sal_Bool b )
+{
+ GetNewDBMgr()->SetInitDBFields( b );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Alle von Feldern verwendete Datenbanken herausfinden
+ --------------------------------------------------------------------*/
+String lcl_DBDataToString(const SwDBData& rData)
+{
+ String sRet = rData.sDataSource;
+ sRet += DB_DELIM;
+ sRet += (String)rData.sCommand;
+ sRet += DB_DELIM;
+ sRet += String::CreateFromInt32(rData.nCommandType);
+ return sRet;
+}
+void SwDoc::GetAllUsedDB( SvStringsDtor& rDBNameList,
+ const SvStringsDtor* pAllDBNames )
+{
+ SvStringsDtor aUsedDBNames;
+ SvStringsDtor aAllDBNames;
+
+ if( !pAllDBNames )
+ {
+ GetAllDBNames( aAllDBNames );
+ pAllDBNames = &aAllDBNames;
+ }
+
+ SwSectionFmts& rArr = GetSections();
+ for (sal_uInt16 n = rArr.Count(); n; )
+ {
+ SwSection* pSect = rArr[ --n ]->GetSection();
+
+ if( pSect )
+ {
+ String aCond( pSect->GetCondition() );
+ AddUsedDBToList( rDBNameList, FindUsedDBs( *pAllDBNames,
+ aCond, aUsedDBNames ) );
+ aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() );
+ }
+ }
+
+ const SfxPoolItem* pItem;
+ sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
+ for (sal_uInt32 n = 0; n < nMaxItems; ++n)
+ {
+ if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) ))
+ continue;
+
+ const SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
+ const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
+ if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
+ continue;
+
+ const SwField* pFld = pFmtFld->GetFld();
+ switch( pFld->GetTyp()->Which() )
+ {
+ case RES_DBFLD:
+ AddUsedDBToList( rDBNameList,
+ lcl_DBDataToString(((SwDBField*)pFld)->GetDBData() ));
+ break;
+
+ case RES_DBSETNUMBERFLD:
+ case RES_DBNAMEFLD:
+ AddUsedDBToList( rDBNameList,
+ lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() ));
+ break;
+
+ case RES_DBNUMSETFLD:
+ case RES_DBNEXTSETFLD:
+ AddUsedDBToList( rDBNameList,
+ lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() ));
+ // kein break // JP: ist das so richtig ??
+
+ case RES_HIDDENTXTFLD:
+ case RES_HIDDENPARAFLD:
+ AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames,
+ pFld->GetPar1(), aUsedDBNames ));
+ aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() );
+ break;
+
+ case RES_SETEXPFLD:
+ case RES_GETEXPFLD:
+ case RES_TABLEFLD:
+ AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames,
+ pFld->GetFormula(), aUsedDBNames ));
+ aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() );
+ break;
+ }
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung:
+ --------------------------------------------------------------------*/
+
+void SwDoc::GetAllDBNames( SvStringsDtor& rAllDBNames )
+{
+ SwNewDBMgr* pMgr = GetNewDBMgr();
+
+ const SwDSParamArr& rArr = pMgr->GetDSParamArray();
+ for(sal_uInt16 i = 0; i < rArr.Count(); i++)
+ {
+ SwDSParam* pParam = rArr[i];
+ String* pStr = new String( pParam->sDataSource );
+ (*pStr) += DB_DELIM;
+ (*pStr) += (String)pParam->sCommand;
+ rAllDBNames.Insert( pStr, rAllDBNames.Count() );
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung:
+ --------------------------------------------------------------------*/
+
+SvStringsDtor& SwDoc::FindUsedDBs( const SvStringsDtor& rAllDBNames,
+ const String& rFormel,
+ SvStringsDtor& rUsedDBNames )
+{
+ const CharClass& rCC = GetAppCharClass();
+ String sFormel( rFormel);
+#ifndef UNX
+ rCC.toUpper( sFormel );
+#endif
+
+ xub_StrLen nPos;
+ for (sal_uInt16 i = 0; i < rAllDBNames.Count(); ++i )
+ {
+ const String* pStr = rAllDBNames.GetObject(i);
+
+ if( STRING_NOTFOUND != (nPos = sFormel.Search( *pStr )) &&
+ sFormel.GetChar( nPos + pStr->Len() ) == '.' &&
+ (!nPos || !rCC.isLetterNumeric( sFormel, nPos - 1 )))
+ {
+ // Tabellenname suchen
+ xub_StrLen nEndPos;
+ nPos += pStr->Len() + 1;
+ if( STRING_NOTFOUND != (nEndPos = sFormel.Search('.', nPos)) )
+ {
+ String* pDBNm = new String( *pStr );
+ pDBNm->Append( DB_DELIM );
+ pDBNm->Append( sFormel.Copy( nPos, nEndPos - nPos ));
+ rUsedDBNames.Insert( pDBNm, rUsedDBNames.Count() );
+ }
+ }
+ }
+ return rUsedDBNames;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung:
+ --------------------------------------------------------------------*/
+
+void SwDoc::AddUsedDBToList( SvStringsDtor& rDBNameList,
+ const SvStringsDtor& rUsedDBNames )
+{
+ for (sal_uInt16 i = 0; i < rUsedDBNames.Count(); i++)
+ AddUsedDBToList( rDBNameList, *rUsedDBNames.GetObject(i) );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung:
+ --------------------------------------------------------------------*/
+
+void SwDoc::AddUsedDBToList( SvStringsDtor& rDBNameList, const String& rDBName)
+{
+ if( !rDBName.Len() )
+ return;
+
+#ifdef UNX
+ for( sal_uInt16 i = 0; i < rDBNameList.Count(); ++i )
+ if( rDBName == rDBNameList.GetObject(i)->GetToken(0) )
+ return;
+#else
+ const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
+ for( sal_uInt16 i = 0; i < rDBNameList.Count(); ++i )
+ if( rSCmp.isEqual( rDBName, rDBNameList.GetObject(i)->GetToken(0) ) )
+ return;
+#endif
+
+ SwDBData aData;
+ aData.sDataSource = rDBName.GetToken(0, DB_DELIM);
+ aData.sCommand = rDBName.GetToken(1, DB_DELIM);
+ aData.nCommandType = -1;
+ GetNewDBMgr()->CreateDSData(aData);
+ String* pNew = new String( rDBName );
+ rDBNameList.Insert( pNew, rDBNameList.Count() );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung:
+ --------------------------------------------------------------------*/
+
+void SwDoc::ChangeDBFields( const SvStringsDtor& rOldNames,
+ const String& rNewName )
+{
+ SwDBData aNewDBData;
+ aNewDBData.sDataSource = rNewName.GetToken(0, DB_DELIM);
+ aNewDBData.sCommand = rNewName.GetToken(1, DB_DELIM);
+ aNewDBData.nCommandType = (short)rNewName.GetToken(2, DB_DELIM).ToInt32();
+
+ String sFormel;
+
+ SwSectionFmts& rArr = GetSections();
+ for (sal_uInt16 n = rArr.Count(); n; )
+ {
+ SwSection* pSect = rArr[ --n ]->GetSection();
+
+ if( pSect )
+ {
+ sFormel = pSect->GetCondition();
+ ReplaceUsedDBs( rOldNames, rNewName, sFormel);
+ pSect->SetCondition(sFormel);
+ }
+ }
+
+ const SfxPoolItem* pItem;
+ sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
+
+ for (sal_uInt32 n = 0; n < nMaxItems; ++n )
+ {
+ if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) ))
+ continue;
+
+ SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
+ SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
+ if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
+ continue;
+
+ SwField* pFld = pFmtFld->GetFld();
+ sal_Bool bExpand = sal_False;
+
+ switch( pFld->GetTyp()->Which() )
+ {
+ case RES_DBFLD:
+ if( IsNameInArray( rOldNames, lcl_DBDataToString(((SwDBField*)pFld)->GetDBData())))
+ {
+ SwDBFieldType* pOldTyp = (SwDBFieldType*)pFld->GetTyp();
+
+ SwDBFieldType* pTyp = (SwDBFieldType*)InsertFldType(
+ SwDBFieldType(this, pOldTyp->GetColumnName(), aNewDBData));
+
+ pTyp->Add(pFmtFld); // Feld auf neuen Typ umhaengen
+ pFld->ChgTyp(pTyp);
+
+ ((SwDBField*)pFld)->ClearInitialized();
+ ((SwDBField*)pFld)->InitContent();
+
+ bExpand = sal_True;
+ }
+ break;
+
+ case RES_DBSETNUMBERFLD:
+ case RES_DBNAMEFLD:
+ if( IsNameInArray( rOldNames,
+ lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData())))
+ {
+ ((SwDBNameInfField*)pFld)->SetDBData(aNewDBData);
+ bExpand = sal_True;
+ }
+ break;
+
+ case RES_DBNUMSETFLD:
+ case RES_DBNEXTSETFLD:
+ if( IsNameInArray( rOldNames,
+ lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData())))
+ {
+ ((SwDBNameInfField*)pFld)->SetDBData(aNewDBData);
+ bExpand = sal_True;
+ }
+ // kein break;
+ case RES_HIDDENTXTFLD:
+ case RES_HIDDENPARAFLD:
+ sFormel = pFld->GetPar1();
+ ReplaceUsedDBs( rOldNames, rNewName, sFormel);
+ pFld->SetPar1( sFormel );
+ bExpand = sal_True;
+ break;
+
+ case RES_SETEXPFLD:
+ case RES_GETEXPFLD:
+ case RES_TABLEFLD:
+ sFormel = pFld->GetFormula();
+ ReplaceUsedDBs( rOldNames, rNewName, sFormel);
+ pFld->SetPar2( sFormel );
+ bExpand = sal_True;
+ break;
+ }
+
+ if (bExpand)
+ pTxtFld->ExpandAlways();
+ }
+ SetModified();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung:
+ --------------------------------------------------------------------*/
+
+void SwDoc::ReplaceUsedDBs( const SvStringsDtor& rUsedDBNames,
+ const String& rNewName, String& rFormel )
+{
+ const CharClass& rCC = GetAppCharClass();
+ String sFormel(rFormel);
+ String sNewName( rNewName );
+ sNewName.SearchAndReplace( DB_DELIM, '.');
+ //the command type is not part of the condition
+ sNewName = sNewName.GetToken(0, DB_DELIM);
+ String sUpperNewNm( sNewName );
+
+
+ for( sal_uInt16 i = 0; i < rUsedDBNames.Count(); ++i )
+ {
+ String sDBName( *rUsedDBNames.GetObject( i ) );
+
+ sDBName.SearchAndReplace( DB_DELIM, '.');
+ //cut off command type
+ sDBName = sDBName.GetToken(0, DB_DELIM);
+ if( !sDBName.Equals( sUpperNewNm ))
+ {
+ xub_StrLen nPos = 0;
+
+ while ((nPos = sFormel.Search(sDBName, nPos)) != STRING_NOTFOUND)
+ {
+ if( sFormel.GetChar( nPos + sDBName.Len() ) == '.' &&
+ (!nPos || !rCC.isLetterNumeric( sFormel, nPos - 1 )))
+ {
+ rFormel.Erase( nPos, sDBName.Len() );
+ rFormel.Insert( sNewName, nPos );
+ //prevent re-searching - this is useless and provokes
+ //endless loops when names containing each other and numbers are exchanged
+ //e.g.: old ?12345.12345 new: i12345.12345
+ nPos = nPos + sNewName.Len();
+ sFormel = rFormel;
+ }
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung:
+ --------------------------------------------------------------------*/
+
+sal_Bool SwDoc::IsNameInArray( const SvStringsDtor& rArr, const String& rName )
+{
+#ifdef UNX
+ for( sal_uInt16 i = 0; i < rArr.Count(); ++i )
+ if( rName == *rArr[ i ] )
+ return sal_True;
+#else
+ const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
+ for( sal_uInt16 i = 0; i < rArr.Count(); ++i )
+ if( rSCmp.isEqual( rName, *rArr[ i] ))
+ return sal_True;
+#endif
+ return sal_False;
+}
+
+void SwDoc::SetFixFields( bool bOnlyTimeDate, const DateTime* pNewDateTime )
+{
+ sal_Bool bIsModified = IsModified();
+
+ sal_uLong nDate, nTime;
+ if( pNewDateTime )
+ {
+ nDate = pNewDateTime->GetDate();
+ nTime = pNewDateTime->GetTime();
+ }
+ else
+ {
+ nDate = Date().GetDate();
+ nTime = Time().GetTime();
+ }
+
+ sal_uInt16 aTypes[5] = {
+ /*0*/ RES_DOCINFOFLD,
+ /*1*/ RES_AUTHORFLD,
+ /*2*/ RES_EXTUSERFLD,
+ /*3*/ RES_FILENAMEFLD,
+ /*4*/ RES_DATETIMEFLD }; // MUSS am Ende stehen!!
+
+ sal_uInt16 nStt = bOnlyTimeDate ? 4 : 0;
+
+ for( ; nStt < 5; ++nStt )
+ {
+ SwFieldType* pFldType = GetSysFldType( aTypes[ nStt ] );
+ SwClientIter aDocInfIter( *pFldType );
+
+ for( SwFmtFld* pFld = (SwFmtFld*)aDocInfIter.First( TYPE( SwFmtFld ));
+ pFld; pFld = (SwFmtFld*)aDocInfIter.Next() )
+ {
+ if( pFld && pFld->GetTxtFld() )
+ {
+ sal_Bool bChgd = sal_False;
+ switch( aTypes[ nStt ] )
+ {
+ case RES_DOCINFOFLD:
+ if( ((SwDocInfoField*)pFld->GetFld())->IsFixed() )
+ {
+ bChgd = sal_True;
+ SwDocInfoField* pDocInfFld = (SwDocInfoField*)pFld->GetFld();
+ pDocInfFld->SetExpansion( ((SwDocInfoFieldType*)
+ pDocInfFld->GetTyp())->Expand(
+ pDocInfFld->GetSubType(),
+ pDocInfFld->GetFormat(),
+ pDocInfFld->GetLanguage(),
+ pDocInfFld->GetName() ) );
+ }
+ break;
+
+ case RES_AUTHORFLD:
+ if( ((SwAuthorField*)pFld->GetFld())->IsFixed() )
+ {
+ bChgd = sal_True;
+ SwAuthorField* pAuthorFld = (SwAuthorField*)pFld->GetFld();
+ pAuthorFld->SetExpansion( ((SwAuthorFieldType*)
+ pAuthorFld->GetTyp())->Expand(
+ pAuthorFld->GetFormat() ) );
+ }
+ break;
+
+ case RES_EXTUSERFLD:
+ if( ((SwExtUserField*)pFld->GetFld())->IsFixed() )
+ {
+ bChgd = sal_True;
+ SwExtUserField* pExtUserFld = (SwExtUserField*)pFld->GetFld();
+ pExtUserFld->SetExpansion( ((SwExtUserFieldType*)
+ pExtUserFld->GetTyp())->Expand(
+ pExtUserFld->GetSubType(),
+ pExtUserFld->GetFormat()));
+ }
+ break;
+
+ case RES_DATETIMEFLD:
+ if( ((SwDateTimeField*)pFld->GetFld())->IsFixed() )
+ {
+ bChgd = sal_True;
+ ((SwDateTimeField*)pFld->GetFld())->SetDateTime(
+ DateTime(Date(nDate), Time(nTime)) );
+ }
+ break;
+
+ case RES_FILENAMEFLD:
+ if( ((SwFileNameField*)pFld->GetFld())->IsFixed() )
+ {
+ bChgd = sal_True;
+ SwFileNameField* pFileNameFld =
+ (SwFileNameField*)pFld->GetFld();
+ pFileNameFld->SetExpansion( ((SwFileNameFieldType*)
+ pFileNameFld->GetTyp())->Expand(
+ pFileNameFld->GetFormat() ) );
+ }
+ break;
+ }
+
+ // Formatierung anstossen
+ if( bChgd )
+ pFld->Modify( 0, 0 );
+ }
+ }
+ }
+
+ if( !bIsModified )
+ ResetModified();
+}
+
+bool SwDoc::SetFieldsDirty( bool b, const SwNode* pChk, sal_uLong nLen )
+{
+ // teste ggfs. mal, ob die angegbenen Nodes ueberhaupt Felder beinhalten.
+ // wenn nicht, braucht das Flag nicht veraendert werden.
+ sal_Bool bFldsFnd = sal_False;
+ if( b && pChk && !GetUpdtFlds().IsFieldsDirty() && !IsInDtor()
+ // ?? was ist mit Undo, da will man es doch auch haben !!
+ /*&& &pChk->GetNodes() == &GetNodes()*/ )
+ {
+ b = sal_False;
+ if( !nLen )
+ ++nLen;
+ sal_uLong nStt = pChk->GetIndex();
+ const SwNodes& rNds = pChk->GetNodes();
+ while( nLen-- )
+ {
+ const SwTxtNode* pTNd = rNds[ nStt++ ]->GetTxtNode();
+ if( pTNd )
+ {
+ if( //pTNd->GetFmtColl() && //#outline level,zhaojianwei
+ // MAXLEVEL > pTNd->GetTxtColl()->GetOutlineLevel() )
+ pTNd->GetAttrOutlineLevel() != 0 )//<-end,zhaojianwei
+ // Kapitelfelder aktualisieren
+ b = sal_True;
+ else if( pTNd->GetpSwpHints() && pTNd->GetSwpHints().Count() )
+ for( sal_uInt16 n = 0, nEnd = pTNd->GetSwpHints().Count();
+ n < nEnd; ++n )
+ {
+ const SwTxtAttr* pAttr = pTNd->GetSwpHints()[ n ];
+ if( RES_TXTATR_FIELD == pAttr->Which() )
+ {
+ b = sal_True;
+ break;
+ }
+ }
+
+ if( b )
+ break;
+ }
+ }
+ bFldsFnd = b;
+ }
+ GetUpdtFlds().SetFieldsDirty( b );
+ return bFldsFnd;
+}
+/* -----------------------------21.12.99 12:55--------------------------------
+
+ ---------------------------------------------------------------------------*/
+void SwDoc::ChangeAuthorityData( const SwAuthEntry* pNewData )
+{
+ const sal_uInt16 nSize = pFldTypes->Count();
+
+ for( sal_uInt16 i = INIT_FLDTYPES; i < nSize; ++i )
+ {
+ SwFieldType* pFldType = (*pFldTypes)[i];
+ if( RES_AUTHORITY == pFldType->Which() )
+ {
+ SwAuthorityFieldType* pAuthType = (SwAuthorityFieldType*)pFldType;
+ pAuthType->ChangeEntryContent(pNewData);
+ break;
+ }
+ }
+
+}
+/*--------------------------------------------------------------------
+ Beschreibung:
+ --------------------------------------------------------------------*/
+
+void SwDocUpdtFld::InsDelFldInFldLst( sal_Bool bIns, const SwTxtFld& rFld )
+{
+ sal_uInt16 nWhich = rFld.GetFld().GetFld()->GetTyp()->Which();
+ switch( nWhich )
+ {
+ case RES_DBFLD:
+ case RES_SETEXPFLD:
+ case RES_HIDDENPARAFLD:
+ case RES_HIDDENTXTFLD:
+ case RES_DBNUMSETFLD:
+ case RES_DBNEXTSETFLD:
+ case RES_DBSETNUMBERFLD:
+ case RES_GETEXPFLD:
+ break; // diese muessen ein-/ausgetragen werden!
+
+ default:
+ return;
+ }
+
+ SetFieldsDirty( sal_True );
+ if( !pFldSortLst )
+ {
+ if( !bIns ) // keine Liste vorhanden und loeschen
+ return; // dann nichts tun
+ pFldSortLst = new _SetGetExpFlds( 64, 16 );
+ }
+
+ if( bIns ) // neu einfuegen:
+ GetBodyNode( rFld, nWhich );
+ else
+ {
+ // ueber den pTxtFld Pointer suchen. Ist zwar eine Sortierte
+ // Liste, aber nach Node-Positionen sortiert. Bis dieser
+ // bestimmt ist, ist das Suchen nach dem Pointer schon fertig
+ for( sal_uInt16 n = 0; n < pFldSortLst->Count(); ++n )
+ if( &rFld == (*pFldSortLst)[ n ]->GetPointer() )
+ pFldSortLst->DeleteAndDestroy( n--, 1 );
+ // ein Feld kann mehrfach vorhanden sein!
+ }
+}
+
+void SwDocUpdtFld::MakeFldList( SwDoc& rDoc, int bAll, int eGetMode )
+{
+ if( !pFldSortLst || bAll || !( eGetMode & nFldLstGetMode ) ||
+ rDoc.GetNodes().Count() != nNodes )
+ _MakeFldList( rDoc, eGetMode );
+}
+
+void SwDocUpdtFld::_MakeFldList( SwDoc& rDoc, int eGetMode )
+{
+ // neue Version: gehe ueber alle Felder vom Attribut-Pool
+ if( pFldSortLst )
+ delete pFldSortLst;
+ pFldSortLst = new _SetGetExpFlds( 64, 16 );
+
+ /// OD 09.08.2002 [#101207#,#101216#,#101778#] - consider and unhide sections
+ /// with hide condition, only in mode GETFLD_ALL (<eGetMode == GETFLD_ALL>)
+ /// notes by OD:
+ /// eGetMode == GETFLD_CALC in call from methods SwDoc::FldsToCalc
+ /// eGetMode == GETFLD_EXPAND in call from method SwDoc::FldsToExpand
+ /// eGetMode == GETFLD_ALL in call from method SwDoc::UpdateExpFlds
+ /// I figured out that hidden section only have to be shown,
+ /// if fields have updated (call by SwDoc::UpdateExpFlds) and thus
+ /// the hide conditions of section have to be updated.
+ /// For correct updating the hide condition of a section, its position
+ /// have to be known in order to insert the hide condition as a new
+ /// expression field into the sorted field list (<pFldSortLst>).
+ if ( eGetMode == GETFLD_ALL )
+ // zuerst die Bereiche einsammeln. Alle die ueber Bedingung
+ // gehiddet sind, wieder mit Frames versorgen, damit die darin
+ // enthaltenen Felder richtig einsortiert werden!!!
+ {
+ // damit die Frames richtig angelegt werden, muessen sie in der
+ // Reihenfolgen von oben nach unten expandiert werden
+ SvULongs aTmpArr;
+ SwSectionFmts& rArr = rDoc.GetSections();
+ SwSectionNode* pSectNd;
+ sal_uInt16 nArrStt = 0;
+ sal_uLong nSttCntnt = rDoc.GetNodes().GetEndOfExtras().GetIndex();
+
+ for (sal_uInt16 n = rArr.Count(); n; )
+ {
+ SwSection* pSect = rArr[ --n ]->GetSection();
+ if( pSect && pSect->IsHidden() && pSect->GetCondition().Len() &&
+ 0 != ( pSectNd = pSect->GetFmt()->GetSectionNode() ))
+ {
+ sal_uLong nIdx = pSectNd->GetIndex();
+ sal_uInt16 i;
+
+ for( i = 0; i < aTmpArr.Count() && aTmpArr[ i ] < nIdx; ++i )
+ ;
+ aTmpArr.Insert( nIdx, i );
+ if( nIdx < nSttCntnt )
+ ++nArrStt;
+ }
+ }
+
+ // erst alle anzeigen, damit die Frames vorhanden sind. Mit deren
+ // Position wird das BodyAnchor ermittelt.
+ // Dafuer erst den ContentBereich, dann die Sonderbereiche!!!
+ for (sal_uInt16 n = nArrStt; n < aTmpArr.Count(); ++n)
+ {
+ pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode();
+ ASSERT( pSectNd, "Wo ist mein SectionNode" );
+ pSectNd->GetSection().SetCondHidden( sal_False );
+ }
+ for (sal_uInt16 n = 0; n < nArrStt; ++n)
+ {
+ pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode();
+ ASSERT( pSectNd, "Wo ist mein SectionNode" );
+ pSectNd->GetSection().SetCondHidden( sal_False );
+ }
+
+ // so, erst jetzt alle sortiert in die Liste eintragen
+ for (sal_uInt16 n = 0; n < aTmpArr.Count(); ++n)
+ {
+ GetBodyNode( *rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode() );
+ }
+ }
+
+ String sTrue( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "sal_True" ))),
+ sFalse( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "sal_False" )));
+
+ sal_Bool bIsDBMgr = 0 != rDoc.GetNewDBMgr();
+ sal_uInt16 nWhich, n;
+ const String* pFormel = 0;
+ const SfxPoolItem* pItem;
+ sal_uInt32 nMaxItems = rDoc.GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
+ for( n = 0; n < nMaxItems; ++n )
+ {
+ if( 0 == (pItem = rDoc.GetAttrPool().GetItem2( RES_TXTATR_FIELD, n )) )
+ continue;
+
+ const SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
+ const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
+ if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
+ continue;
+
+ const SwField* pFld = pFmtFld->GetFld();
+ switch( nWhich = pFld->GetTyp()->Which() )
+ {
+ case RES_DBSETNUMBERFLD:
+ case RES_GETEXPFLD:
+ if( GETFLD_ALL == eGetMode )
+ pFormel = &sTrue;
+ break;
+
+ case RES_DBFLD:
+ if( GETFLD_EXPAND & eGetMode )
+ pFormel = &sTrue;
+ break;
+
+ case RES_SETEXPFLD:
+ /// OD 04.10.2002 #102894#
+ /// fields of subtype <string> have also been add
+ /// for calculation (eGetMode == GETFLD_CALC).
+ /// Thus, add fields of subtype <string> in all modes
+ /// (eGetMode == GETFLD_EXPAND||GETFLD_CALC||GETFLD_ALL)
+ /// and fields of other subtypes only in the modes
+ /// (eGetMode == GETFLD_CALC||GETFLD_ALL)
+ /* "old" if construct - not deleted for history and code review
+ if( ( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType()
+ ? GETFLD_EXPAND : GETFLD_CALC )
+ & eGetMode )
+ */
+ if ( !(eGetMode == GETFLD_EXPAND) ||
+ (nsSwGetSetExpType::GSE_STRING & pFld->GetSubType()) )
+ {
+ pFormel = &sTrue;
+ }
+ break;
+
+ case RES_HIDDENPARAFLD:
+ if( GETFLD_ALL == eGetMode )
+ {
+ pFormel = &pFld->GetPar1();
+ if( !pFormel->Len() || pFormel->Equals( sFalse ))
+ ((SwHiddenParaField*)pFld)->SetHidden( sal_False );
+ else if( pFormel->Equals( sTrue ))
+ ((SwHiddenParaField*)pFld)->SetHidden( sal_True );
+ else
+ break;
+
+ pFormel = 0;
+ // Formatierung anstossen
+ ((SwFmtFld*)pFmtFld)->Modify( 0, 0 );
+ }
+ break;
+
+ case RES_HIDDENTXTFLD:
+ if( GETFLD_ALL == eGetMode )
+ {
+ pFormel = &pFld->GetPar1();
+ if( !pFormel->Len() || pFormel->Equals( sFalse ))
+ ((SwHiddenTxtField*)pFld)->SetValue( sal_True );
+ else if( pFormel->Equals( sTrue ))
+ ((SwHiddenTxtField*)pFld)->SetValue( sal_False );
+ else
+ break;
+
+ pFormel = 0;
+
+ // Feld Evaluieren
+ ((SwHiddenTxtField*)pFld)->Evaluate(&rDoc);
+ // Formatierung anstossen
+ ((SwFmtFld*)pFmtFld)->Modify( 0, 0 );
+ }
+ break;
+
+ case RES_DBNUMSETFLD:
+ {
+ SwDBData aDBData(((SwDBNumSetField*)pFld)->GetDBData(&rDoc));
+
+ if (
+ (bIsDBMgr && rDoc.GetNewDBMgr()->OpenDataSource(aDBData.sDataSource, aDBData.sCommand)) &&
+ (GETFLD_ALL == eGetMode || (GETFLD_CALC & eGetMode && ((SwDBNumSetField*)pFld)->IsCondValid()))
+ )
+ {
+ pFormel = &pFld->GetPar1();
+ }
+ }
+ break;
+ case RES_DBNEXTSETFLD:
+ {
+ SwDBData aDBData(((SwDBNextSetField*)pFld)->GetDBData(&rDoc));
+
+ if (
+ (bIsDBMgr && rDoc.GetNewDBMgr()->OpenDataSource(aDBData.sDataSource, aDBData.sCommand)) &&
+ (GETFLD_ALL == eGetMode || (GETFLD_CALC & eGetMode && ((SwDBNextSetField*)pFld)->IsCondValid()))
+ )
+ {
+ pFormel = &pFld->GetPar1();
+ }
+ }
+ break;
+ }
+
+ if( pFormel && pFormel->Len() )
+ {
+ GetBodyNode( *pTxtFld, nWhich );
+ pFormel = 0;
+ }
+ }
+ nFldLstGetMode = static_cast<sal_uInt8>( eGetMode );
+ nNodes = rDoc.GetNodes().Count();
+
+#ifdef JP_DEBUG
+ {
+ SvFileStream sOut( "f:\\x.x", STREAM_STD_WRITE );
+ sOut.Seek( STREAM_SEEK_TO_END );
+ sOut << "------------------" << endl;
+ const _SetGetExpFldPtr* pSortLst = pFldSortLst->GetData();
+ for( sal_uInt16 n = pFldSortLst->Count(); n; --n, ++pSortLst )
+ {
+ String sStr( (*pSortLst)->GetNode() );
+ sStr += "\t, ";
+ sStr += (*pSortLst)->GetCntnt();
+ sStr += "\tNode: ";
+ sStr += (*pSortLst)->GetFld()->GetTxtNode().StartOfSectionIndex();
+ sStr += "\tPos: ";
+ sStr += *(*pSortLst)->GetFld()->GetStart();
+ sStr += "\tType: ";
+ sStr += (*pSortLst)->GetFld()->GetFld().GetFld()->GetTyp()->Which();
+
+ sOut << sStr.GetStr() << endl;
+ }
+ }
+#endif
+ // JP_DEBUG
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung:
+ --------------------------------------------------------------------*/
+
+void SwDocUpdtFld::GetBodyNode( const SwTxtFld& rTFld, sal_uInt16 nFldWhich )
+{
+ const SwTxtNode& rTxtNd = rTFld.GetTxtNode();
+ const SwDoc& rDoc = *rTxtNd.GetDoc();
+
+ // immer den ersten !! (in Tab-Headline, Kopf-/Fuss )
+ Point aPt;
+ const SwCntntFrm* pFrm = rTxtNd.GetFrm( &aPt, 0, sal_False );
+
+ _SetGetExpFld* pNew = NULL;
+ sal_Bool bIsInBody = sal_False;
+
+ if( !pFrm || pFrm->IsInDocBody() )
+ {
+ // einen Index fuers bestimmen vom TextNode anlegen
+ SwNodeIndex aIdx( rTxtNd );
+ bIsInBody = rDoc.GetNodes().GetEndOfExtras().GetIndex() < aIdx.GetIndex();
+
+ // #104291# dvo: We don't want to update fields in redlines, or those
+ // in frames whose anchor is in redline. However, we do want to update
+ // fields in hidden sections. So: In order to be updated, a field 1)
+ // must have a frame, or 2) it must be in the document body.
+ if( (pFrm != NULL) || bIsInBody )
+ pNew = new _SetGetExpFld( aIdx, &rTFld );
+ }
+ else
+ {
+ // einen Index fuers bestimmen vom TextNode anlegen
+ SwPosition aPos( rDoc.GetNodes().GetEndOfPostIts() );
+#ifdef DBG_UTIL
+ ASSERT( GetBodyTxtNode( rDoc, aPos, *pFrm ), "wo steht das Feld" );
+#else
+ GetBodyTxtNode( rDoc, aPos, *pFrm );
+#endif
+ pNew = new _SetGetExpFld( aPos.nNode, &rTFld, &aPos.nContent );
+ }
+
+ // bei GetExp.-/DB.-Felder immer das BodyTxtFlag setzen
+ if( RES_GETEXPFLD == nFldWhich )
+ {
+ SwGetExpField* pGetFld = (SwGetExpField*)rTFld.GetFld().GetFld();
+ pGetFld->ChgBodyTxtFlag( bIsInBody );
+ }
+ else if( RES_DBFLD == nFldWhich )
+ {
+ SwDBField* pDBFld = (SwDBField*)rTFld.GetFld().GetFld();
+ pDBFld->ChgBodyTxtFlag( bIsInBody );
+ }
+
+ if( pNew != NULL )
+ if( !pFldSortLst->Insert( pNew ))
+ delete pNew;
+}
+
+void SwDocUpdtFld::GetBodyNode( const SwSectionNode& rSectNd )
+{
+ const SwDoc& rDoc = *rSectNd.GetDoc();
+ _SetGetExpFld* pNew = 0;
+
+ if( rSectNd.GetIndex() < rDoc.GetNodes().GetEndOfExtras().GetIndex() )
+ {
+ do { // middle check loop
+
+ // dann muessen wir uns mal den Anker besorgen!
+ // einen Index fuers bestimmen vom TextNode anlegen
+ SwPosition aPos( rSectNd );
+ SwCntntNode* pCNd = rDoc.GetNodes().GoNext( &aPos.nNode ); // zum naechsten ContentNode
+
+ if( !pCNd || !pCNd->IsTxtNode() )
+ break;
+
+ // immer den ersten !! (in Tab-Headline, Kopf-/Fuss )
+ Point aPt;
+ const SwCntntFrm* pFrm = pCNd->GetFrm( &aPt, 0, sal_False );
+ if( !pFrm )
+ break;
+
+#ifdef DBG_UTIL
+ ASSERT( GetBodyTxtNode( rDoc, aPos, *pFrm ), "wo steht das Feld" );
+#else
+ GetBodyTxtNode( rDoc, aPos, *pFrm );
+#endif
+ pNew = new _SetGetExpFld( rSectNd, &aPos );
+
+ } while( sal_False );
+ }
+
+ if( !pNew )
+ pNew = new _SetGetExpFld( rSectNd );
+
+ if( !pFldSortLst->Insert( pNew ))
+ delete pNew;
+}
+
+void SwDocUpdtFld::InsertFldType( const SwFieldType& rType )
+{
+ String sFldName;
+ switch( rType.Which() )
+ {
+ case RES_USERFLD :
+ sFldName = ((SwUserFieldType&)rType).GetName();
+ break;
+ case RES_SETEXPFLD:
+ sFldName = ((SwSetExpFieldType&)rType).GetName();
+ break;
+ default:
+ ASSERT( !this, "kein gueltiger FeldTyp" );
+ }
+
+ if( sFldName.Len() )
+ {
+ SetFieldsDirty( sal_True );
+ // suchen und aus der HashTabelle entfernen
+ GetAppCharClass().toLower( sFldName );
+ sal_uInt16 n;
+
+ SwHash* pFnd = Find( sFldName, GetFldTypeTable(), TBLSZ, &n );
+
+ if( !pFnd )
+ {
+ SwCalcFldType* pNew = new SwCalcFldType( sFldName, &rType );
+ pNew->pNext = aFldTypeTable[ n ];
+ aFldTypeTable[ n ] = pNew;
+ }
+ }
+}
+
+void SwDocUpdtFld::RemoveFldType( const SwFieldType& rType )
+{
+ String sFldName;
+ switch( rType.Which() )
+ {
+ case RES_USERFLD :
+ sFldName = ((SwUserFieldType&)rType).GetName();
+ break;
+ case RES_SETEXPFLD:
+ sFldName = ((SwSetExpFieldType&)rType).GetName();
+ break;
+ }
+
+ if( sFldName.Len() )
+ {
+ SetFieldsDirty( sal_True );
+ // suchen und aus der HashTabelle entfernen
+ GetAppCharClass().toLower( sFldName );
+ sal_uInt16 n;
+
+ SwHash* pFnd = Find( sFldName, GetFldTypeTable(), TBLSZ, &n );
+ if( pFnd )
+ {
+ if( aFldTypeTable[ n ] == pFnd )
+ aFldTypeTable[ n ] = (SwCalcFldType*)pFnd->pNext;
+ else
+ {
+ SwHash* pPrev = aFldTypeTable[ n ];
+ while( pPrev->pNext != pFnd )
+ pPrev = pPrev->pNext;
+ pPrev->pNext = pFnd->pNext;
+ }
+ pFnd->pNext = 0;
+ delete pFnd;
+ }
+ }
+}
+
+SwDocUpdtFld::SwDocUpdtFld()
+ : pFldSortLst(0), nFldUpdtPos(LONG_MAX), nFldLstGetMode(0)
+{
+ bInUpdateFlds = bFldsDirty = sal_False;
+ memset( aFldTypeTable, 0, sizeof( aFldTypeTable ) );
+}
+
+SwDocUpdtFld::~SwDocUpdtFld()
+{
+ delete pFldSortLst;
+
+ for( sal_uInt16 n = 0; n < TBLSZ; ++n )
+ delete aFldTypeTable[n];
+}
+
+// #111840#
+bool SwDoc::UpdateFld(SwTxtFld * pDstTxtFld, SwField & rSrcFld,
+ SwMsgPoolItem * pMsgHnt,
+ bool bUpdateFlds)
+{
+ ASSERT(pDstTxtFld, "no field to update!");
+
+ sal_Bool bTblSelBreak = sal_False;
+
+ SwFmtFld * pDstFmtFld = (SwFmtFld*)&pDstTxtFld->GetFld();
+ SwField * pDstFld = pDstFmtFld->GetFld();
+ sal_uInt16 nFldWhich = rSrcFld.GetTyp()->Which();
+ SwNodeIndex aTblNdIdx(pDstTxtFld->GetTxtNode());
+
+ if (pDstFld->GetTyp()->Which() ==
+ rSrcFld.GetTyp()->Which())
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwPosition aPosition( pDstTxtFld->GetTxtNode() );
+ aPosition.nContent = *pDstTxtFld->GetStart();
+
+ SwUndo *const pUndo( new SwUndoFieldFromDoc(
+ aPosition, *pDstFld, rSrcFld, pMsgHnt, bUpdateFlds) );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ // Das gefundene Feld wird angepasst ...
+ //pDstFld->ChangeFormat( rSrcFld.GetFormat() );
+ //pDstFld->SetLanguage( rSrcFld.GetLanguage() );
+
+ SwField * pNewFld = rSrcFld.CopyField();
+ pDstFmtFld->SetFld(pNewFld);
+
+ switch( nFldWhich )
+ {
+ case RES_SETEXPFLD:
+ case RES_GETEXPFLD:
+ case RES_HIDDENTXTFLD:
+ case RES_HIDDENPARAFLD:
+ UpdateExpFlds( pDstTxtFld, true );
+ break;
+
+ case RES_TABLEFLD:
+ {
+ const SwTableNode* pTblNd =
+ IsIdxInTbl(aTblNdIdx);
+ if( pTblNd )
+ {
+ SwTableFmlUpdate aTblUpdate( &pTblNd->
+ GetTable() );
+ if (bUpdateFlds)
+ UpdateTblFlds( &aTblUpdate );
+ else
+ pNewFld->GetTyp()->Modify(0, &aTblUpdate);
+
+ if (! bUpdateFlds)
+ bTblSelBreak = sal_True;
+ }
+ }
+ break;
+
+ case RES_MACROFLD:
+ if( bUpdateFlds && pDstTxtFld->GetpTxtNode() )
+ (pDstTxtFld->GetpTxtNode())->
+ Modify( 0, pDstFmtFld );
+ break;
+
+ case RES_DBNAMEFLD:
+ case RES_DBNEXTSETFLD:
+ case RES_DBNUMSETFLD:
+ case RES_DBSETNUMBERFLD:
+ ChgDBData(((SwDBNameInfField*) pNewFld)->GetRealDBData());
+ pNewFld->GetTyp()->UpdateFlds();
+
+ break;
+
+ case RES_DBFLD:
+ {
+ // JP 10.02.96: ChgValue aufrufen, damit
+ //die Format- aenderung den ContentString
+ //richtig setzt
+ SwDBField* pDBFld = (SwDBField*)pNewFld;
+ if (pDBFld->IsInitialized())
+ pDBFld->ChgValue( pDBFld->GetValue(), sal_True );
+
+ pDBFld->ClearInitialized();
+ pDBFld->InitContent();
+ }
+ // kein break;
+
+ default:
+ pDstFmtFld->Modify( 0, pMsgHnt );
+ }
+
+ // Die Felder die wir berechnen koennen werden hier expli.
+ // zum Update angestossen.
+ if( nFldWhich == RES_USERFLD )
+ UpdateUsrFlds();
+ }
+
+ return bTblSelBreak;
+}
+
+bool SwDoc::PutValueToField(const SwPosition & rPos,
+ const Any& rVal, sal_uInt16 nWhich)
+{
+ Any aOldVal;
+ SwField * pField = GetField(rPos);
+
+
+ if (GetIDocumentUndoRedo().DoesUndo() &&
+ pField->QueryValue(aOldVal, nWhich))
+ {
+ SwUndo *const pUndo(new SwUndoFieldFromAPI(rPos, aOldVal, rVal, nWhich));
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ return pField->PutValue(rVal, nWhich);
+}
diff --git a/sw/source/core/doc/docfly.cxx b/sw/source/core/doc/docfly.cxx
new file mode 100644
index 000000000000..fb0ccdd97a80
--- /dev/null
+++ b/sw/source/core/doc/docfly.cxx
@@ -0,0 +1,1063 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <svl/itemiter.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdocapt.hxx>
+#include <svx/svdmark.hxx>
+#include <fmtfsize.hxx>
+#include <fmtornt.hxx>
+#include <fmtsrnd.hxx>
+#include <dcontact.hxx>
+
+#include <ndgrf.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <ndindex.hxx>
+#include <docary.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtanchr.hxx>
+#include <txtflcnt.hxx>
+#include <fmtflcnt.hxx>
+#include <txtfrm.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <flyfrms.hxx>
+#include <frmtool.hxx>
+#include <frmfmt.hxx>
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <tblsel.hxx>
+#include <swundo.hxx>
+#include <swtable.hxx>
+#include <crstate.hxx>
+#include <UndoCore.hxx>
+#include <UndoAttribute.hxx>
+#include <fmtcnct.hxx>
+#include <dflyobj.hxx>
+
+// --> OD 2009-07-20 #i73249#
+#include <undoflystrattr.hxx>
+// <--
+
+extern sal_uInt16 GetHtmlMode( const SwDocShell* );
+
+
+using namespace ::com::sun::star;
+
+/*-----------------17.02.98 08:35-------------------
+
+--------------------------------------------------*/
+sal_uInt16 SwDoc::GetFlyCount( FlyCntType eType ) const
+{
+ const SwSpzFrmFmts& rFmts = *GetSpzFrmFmts();
+ sal_uInt16 nSize = rFmts.Count();
+ sal_uInt16 nCount = 0;
+ const SwNodeIndex* pIdx;
+ for ( sal_uInt16 i = 0; i < nSize; i++)
+ {
+ const SwFrmFmt* pFlyFmt = rFmts[ i ];
+ if( RES_FLYFRMFMT == pFlyFmt->Which()
+ && 0 != ( pIdx = pFlyFmt->GetCntnt().GetCntntIdx() )
+ && pIdx->GetNodes().IsDocNodes()
+ )
+ {
+ const SwNode* pNd = GetNodes()[ pIdx->GetIndex() + 1 ];
+
+ switch( eType )
+ {
+ case FLYCNTTYPE_FRM:
+ if(!pNd->IsNoTxtNode())
+ nCount++;
+ break;
+
+ case FLYCNTTYPE_GRF:
+ if( pNd->IsGrfNode() )
+ nCount++;
+ break;
+
+ case FLYCNTTYPE_OLE:
+ if(pNd->IsOLENode())
+ nCount++;
+ break;
+
+ default:
+ nCount++;
+ }
+ }
+ }
+ return nCount;
+}
+
+/*-----------------17.02.98 08:35-------------------
+
+--------------------------------------------------*/
+// If you change this, also update SwXFrameEnumeration in unocoll.
+SwFrmFmt* SwDoc::GetFlyNum( sal_uInt16 nIdx, FlyCntType eType )
+{
+ SwSpzFrmFmts& rFmts = *GetSpzFrmFmts();
+ SwFrmFmt* pRetFmt = 0;
+ sal_uInt16 nSize = rFmts.Count();
+ const SwNodeIndex* pIdx;
+ sal_uInt16 nCount = 0;
+ for( sal_uInt16 i = 0; !pRetFmt && i < nSize; ++i )
+ {
+ SwFrmFmt* pFlyFmt = rFmts[ i ];
+ if( RES_FLYFRMFMT == pFlyFmt->Which()
+ && 0 != ( pIdx = pFlyFmt->GetCntnt().GetCntntIdx() )
+ && pIdx->GetNodes().IsDocNodes()
+ )
+ {
+ const SwNode* pNd = GetNodes()[ pIdx->GetIndex() + 1 ];
+ switch( eType )
+ {
+ case FLYCNTTYPE_FRM:
+ if( !pNd->IsNoTxtNode() && nIdx == nCount++)
+ pRetFmt = pFlyFmt;
+ break;
+ case FLYCNTTYPE_GRF:
+ if(pNd->IsGrfNode() && nIdx == nCount++ )
+ pRetFmt = pFlyFmt;
+ break;
+ case FLYCNTTYPE_OLE:
+ if(pNd->IsOLENode() && nIdx == nCount++)
+ pRetFmt = pFlyFmt;
+ break;
+ default:
+ if(nIdx == nCount++)
+ pRetFmt = pFlyFmt;
+ }
+ }
+ }
+ return pRetFmt;
+}
+
+/* */
+
+/***********************************************************************
+#* Class : SwDoc
+#* Methode : SetFlyFrmAnchor
+#* Beschreibung: Das Ankerattribut des FlyFrms aendert sich.
+#* Datum : MA 01. Feb. 94
+#* Update : JP 09.03.98
+#***********************************************************************/
+
+Point lcl_FindAnchorLayPos( SwDoc& rDoc, const SwFmtAnchor& rAnch,
+ const SwFrmFmt* pFlyFmt )
+{
+ Point aRet;
+ if( rDoc.GetRootFrm() )
+ switch( rAnch.GetAnchorId() )
+ {
+ case FLY_AS_CHAR:
+ if( pFlyFmt && rAnch.GetCntntAnchor() )
+ {
+ const SwFrm* pOld = ((SwFlyFrmFmt*)pFlyFmt)->GetFrm( &aRet, sal_False );
+ if( pOld )
+ aRet = pOld->Frm().Pos();
+ }
+ break;
+
+ case FLY_AT_PARA:
+ case FLY_AT_CHAR: // LAYER_IMPL
+ if( rAnch.GetCntntAnchor() )
+ {
+ const SwPosition *pPos = rAnch.GetCntntAnchor();
+ const SwCntntNode* pNd = pPos->nNode.GetNode().GetCntntNode();
+ const SwFrm* pOld = pNd ? pNd->GetFrm( &aRet, 0, sal_False ) : 0;
+ if( pOld )
+ aRet = pOld->Frm().Pos();
+ }
+ break;
+
+ case FLY_AT_FLY: // LAYER_IMPL
+ if( rAnch.GetCntntAnchor() )
+ {
+ const SwFlyFrmFmt* pFmt = (SwFlyFrmFmt*)rAnch.GetCntntAnchor()->
+ nNode.GetNode().GetFlyFmt();
+ const SwFrm* pOld = pFmt ? pFmt->GetFrm( &aRet, sal_False ) : 0;
+ if( pOld )
+ aRet = pOld->Frm().Pos();
+ }
+ break;
+
+ case FLY_AT_PAGE:
+ {
+ sal_uInt16 nPgNum = rAnch.GetPageNum();
+ const SwPageFrm *pPage = (SwPageFrm*)rDoc.GetRootFrm()->Lower();
+ for( sal_uInt16 i = 1; (i <= nPgNum) && pPage; ++i,
+ pPage = (const SwPageFrm*)pPage->GetNext() )
+ if( i == nPgNum )
+ {
+ aRet = pPage->Frm().Pos();
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return aRet;
+}
+
+#define MAKEFRMS 0
+#define IGNOREANCHOR 1
+#define DONTMAKEFRMS 2
+
+sal_Int8 SwDoc::SetFlyFrmAnchor( SwFrmFmt& rFmt, SfxItemSet& rSet, sal_Bool bNewFrms )
+{
+ //Ankerwechsel sind fast immer in alle 'Richtungen' erlaubt.
+ //Ausnahme: Absatz- bzw. Zeichengebundene Rahmen duerfen wenn sie in
+ //Kopf-/Fusszeilen stehen nicht Seitengebunden werden.
+ const SwFmtAnchor &rOldAnch = rFmt.GetAnchor();
+ const RndStdIds nOld = rOldAnch.GetAnchorId();
+
+ SwFmtAnchor aNewAnch( (SwFmtAnchor&)rSet.Get( RES_ANCHOR ) );
+ RndStdIds nNew = aNewAnch.GetAnchorId();
+
+ // ist der neue ein gueltiger Anker?
+ if( !aNewAnch.GetCntntAnchor() && (FLY_AT_FLY == nNew ||
+ (FLY_AT_PARA == nNew) || (FLY_AS_CHAR == nNew) ||
+ (FLY_AT_CHAR == nNew) ))
+ {
+ return IGNOREANCHOR;
+ }
+
+ if( nOld == nNew )
+ return DONTMAKEFRMS;
+
+
+ Point aOldAnchorPos( ::lcl_FindAnchorLayPos( *this, rOldAnch, &rFmt ));
+ Point aNewAnchorPos( ::lcl_FindAnchorLayPos( *this, aNewAnch, 0 ));
+
+ //Die alten Frms vernichten. Dabei werden die Views implizit gehidet und
+ //doppeltes hiden waere so eine art Show!
+ rFmt.DelFrms();
+
+ if ( FLY_AS_CHAR == nOld )
+ {
+ //Bei InCntnt's wird es spannend: Das TxtAttribut muss vernichtet
+ //werden. Leider reisst dies neben den Frms auch noch das Format mit
+ //in sein Grab. Um dass zu unterbinden loesen wir vorher die
+ //Verbindung zwischen Attribut und Format.
+ const SwPosition *pPos = rOldAnch.GetCntntAnchor();
+ SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
+ ASSERT( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
+ const xub_StrLen nIdx = pPos->nContent.GetIndex();
+ SwTxtAttr * const pHnt =
+ pTxtNode->GetTxtAttrForCharAt( nIdx, RES_TXTATR_FLYCNT );
+ ASSERT( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
+ "Missing FlyInCnt-Hint." );
+ ASSERT( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == &rFmt,
+ "Wrong TxtFlyCnt-Hint." );
+ const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt();
+
+ //Die Verbindung ist geloest, jetzt muss noch das Attribut vernichtet
+ //werden.
+ pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx, nIdx );
+ }
+
+ //Endlich kann das Attribut gesetzt werden. Es muss das erste Attribut
+ //sein; Undo depends on it!
+ rFmt.SetFmtAttr( aNewAnch );
+
+ //Positionskorrekturen
+ const SfxPoolItem* pItem;
+ switch( nNew )
+ {
+ case FLY_AS_CHAR:
+ //Wenn keine Positionsattribute hereinkommen, dann muss dafuer
+ //gesorgt werden, das keine unerlaubte automatische Ausrichtung
+ //bleibt.
+ {
+ const SwPosition *pPos = aNewAnch.GetCntntAnchor();
+ SwTxtNode *pNd = pPos->nNode.GetNode().GetTxtNode();
+ ASSERT( pNd, "Crsr steht nicht auf TxtNode." );
+
+ SwFmtFlyCnt aFmt( static_cast<SwFlyFrmFmt*>(&rFmt) );
+ pNd->InsertItem( aFmt, pPos->nContent.GetIndex(), 0 );
+ }
+
+ if( SFX_ITEM_SET != rSet.GetItemState( RES_VERT_ORIENT, sal_False, &pItem ))
+ {
+ SwFmtVertOrient aOldV( rFmt.GetVertOrient() );
+ sal_Bool bSet = sal_True;
+ switch( aOldV.GetVertOrient() )
+ {
+ case text::VertOrientation::LINE_TOP: aOldV.SetVertOrient( text::VertOrientation::TOP ); break;
+ case text::VertOrientation::LINE_CENTER: aOldV.SetVertOrient( text::VertOrientation::CENTER); break;
+ case text::VertOrientation::LINE_BOTTOM: aOldV.SetVertOrient( text::VertOrientation::BOTTOM); break;
+ case text::VertOrientation::NONE: aOldV.SetVertOrient( text::VertOrientation::CENTER); break;
+ default:
+ bSet = sal_False;
+ }
+ if( bSet )
+ rSet.Put( aOldV );
+ }
+ break;
+
+ case FLY_AT_PARA:
+ case FLY_AT_CHAR: // LAYER_IMPL
+ case FLY_AT_FLY: // LAYER_IMPL
+ case FLY_AT_PAGE:
+ {
+ //Wenn keine Positionsattribute hereinschneien korrigieren wir
+ //die Position so, dass die Dokumentkoordinaten des Flys erhalten
+ //bleiben.
+ //Chg: Wenn sich in den Positionsattributen lediglich die
+ //Ausrichtung veraendert (text::RelOrientation::FRAME vs. text::RelOrientation::PRTAREA), dann wird die
+ //Position ebenfalls korrigiert.
+ if( SFX_ITEM_SET != rSet.GetItemState( RES_HORI_ORIENT, sal_False, &pItem ))
+ pItem = 0;
+
+ SwFmtHoriOrient aOldH( rFmt.GetHoriOrient() );
+
+ if( text::HoriOrientation::NONE == aOldH.GetHoriOrient() && ( !pItem ||
+ aOldH.GetPos() == ((SwFmtHoriOrient*)pItem)->GetPos() ))
+ {
+ SwTwips nPos = (FLY_AS_CHAR == nOld) ? 0 : aOldH.GetPos();
+ nPos += aOldAnchorPos.X() - aNewAnchorPos.X();
+
+ if( pItem )
+ {
+ SwFmtHoriOrient* pH = (SwFmtHoriOrient*)pItem;
+ aOldH.SetHoriOrient( pH->GetHoriOrient() );
+ aOldH.SetRelationOrient( pH->GetRelationOrient() );
+ }
+ aOldH.SetPos( nPos );
+ rSet.Put( aOldH );
+ }
+
+ if( SFX_ITEM_SET != rSet.GetItemState( RES_VERT_ORIENT, sal_False, &pItem ))
+ pItem = 0;
+ SwFmtVertOrient aOldV( rFmt.GetVertOrient() );
+
+ // OD 2004-05-14 #i28922# - correction: compare <aOldV.GetVertOrient()
+ // with <text::VertOrientation::NONE>
+ if( text::VertOrientation::NONE == aOldV.GetVertOrient() && (!pItem ||
+ aOldV.GetPos() == ((SwFmtVertOrient*)pItem)->GetPos() ) )
+ {
+ SwTwips nPos = (FLY_AS_CHAR == nOld) ? 0 : aOldV.GetPos();
+ nPos += aOldAnchorPos.Y() - aNewAnchorPos.Y();
+ if( pItem )
+ {
+ SwFmtVertOrient* pV = (SwFmtVertOrient*)pItem;
+ aOldV.SetVertOrient( pV->GetVertOrient() );
+ aOldV.SetRelationOrient( pV->GetRelationOrient() );
+ }
+ aOldV.SetPos( nPos );
+ rSet.Put( aOldV );
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if( bNewFrms )
+ rFmt.MakeFrms();
+
+ return MAKEFRMS;
+}
+
+static bool
+lcl_SetFlyFrmAttr(SwDoc & rDoc,
+ sal_Int8 (SwDoc::*pSetFlyFrmAnchor)(SwFrmFmt &, SfxItemSet &, sal_Bool),
+ SwFrmFmt & rFlyFmt, SfxItemSet & rSet)
+{
+ // #i32968# Inserting columns in the frame causes MakeFrmFmt to put two
+ // objects of type SwUndoFrmFmt on the undo stack. We don't want them.
+ ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
+
+ //Ist das Ankerattribut dabei? Falls ja ueberlassen wir die Verarbeitung
+ //desselben einer Spezialmethode. Sie Returnt sal_True wenn der Fly neu
+ //erzeugt werden muss (z.B. weil ein Wechsel des FlyTyps vorliegt).
+ sal_Int8 const nMakeFrms =
+ (SFX_ITEM_SET == rSet.GetItemState( RES_ANCHOR, sal_False ))
+ ? (rDoc.*pSetFlyFrmAnchor)( rFlyFmt, rSet, sal_False )
+ : DONTMAKEFRMS;
+
+ const SfxPoolItem* pItem;
+ SfxItemIter aIter( rSet );
+ SfxItemSet aTmpSet( rDoc.GetAttrPool(), aFrmFmtSetRange );
+ sal_uInt16 nWhich = aIter.GetCurItem()->Which();
+ do {
+ switch( nWhich )
+ {
+ case RES_FILL_ORDER:
+ case RES_BREAK:
+ case RES_PAGEDESC:
+ case RES_CNTNT:
+ case RES_FOOTER:
+ OSL_ENSURE(false, ":-) unknown Attribute for Fly.");
+ // kein break;
+ case RES_CHAIN:
+ rSet.ClearItem( nWhich );
+ break;
+ case RES_ANCHOR:
+ if( DONTMAKEFRMS != nMakeFrms )
+ break;
+
+ default:
+ if( !IsInvalidItem( aIter.GetCurItem() ) && ( SFX_ITEM_SET !=
+ rFlyFmt.GetAttrSet().GetItemState( nWhich, sal_True, &pItem ) ||
+ *pItem != *aIter.GetCurItem() ))
+ aTmpSet.Put( *aIter.GetCurItem() );
+ break;
+ }
+
+ if( aIter.IsAtEnd() )
+ break;
+
+ } while( 0 != ( nWhich = aIter.NextItem()->Which() ) );
+
+ if( aTmpSet.Count() )
+ rFlyFmt.SetFmtAttr( aTmpSet );
+
+ if( MAKEFRMS == nMakeFrms )
+ rFlyFmt.MakeFrms();
+
+ return aTmpSet.Count() || MAKEFRMS == nMakeFrms;
+}
+
+sal_Bool SwDoc::SetFlyFrmAttr( SwFrmFmt& rFlyFmt, SfxItemSet& rSet )
+{
+ if( !rSet.Count() )
+ return sal_False;
+
+ ::std::auto_ptr<SwUndoFmtAttrHelper> pSaveUndo;
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo(); // AppendUndo far below, so leave it
+ pSaveUndo.reset( new SwUndoFmtAttrHelper( rFlyFmt ) );
+ }
+
+ bool const bRet =
+ lcl_SetFlyFrmAttr(*this, &SwDoc::SetFlyFrmAnchor, rFlyFmt, rSet);
+
+ if ( pSaveUndo.get() )
+ {
+ if ( pSaveUndo->GetUndo() )
+ {
+ GetIDocumentUndoRedo().AppendUndo( pSaveUndo->ReleaseUndo() );
+ }
+ }
+
+ SetModified();
+
+ return bRet;
+}
+
+// --> OD 2009-07-20 #i73249#
+void SwDoc::SetFlyFrmTitle( SwFlyFrmFmt& rFlyFrmFmt,
+ const String& sNewTitle )
+{
+ if ( rFlyFrmFmt.GetObjTitle() == sNewTitle )
+ {
+ return;
+ }
+
+ ::sw::DrawUndoGuard const drawUndoGuard(GetIDocumentUndoRedo());
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoFlyStrAttr( rFlyFrmFmt,
+ UNDO_FLYFRMFMT_TITLE,
+ rFlyFrmFmt.GetObjTitle(),
+ sNewTitle ) );
+ }
+
+ rFlyFrmFmt.SetObjTitle( sNewTitle, true );
+
+ SetModified();
+}
+
+void SwDoc::SetFlyFrmDescription( SwFlyFrmFmt& rFlyFrmFmt,
+ const String& sNewDescription )
+{
+ if ( rFlyFrmFmt.GetObjDescription() == sNewDescription )
+ {
+ return;
+ }
+
+ ::sw::DrawUndoGuard const drawUndoGuard(GetIDocumentUndoRedo());
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoFlyStrAttr( rFlyFrmFmt,
+ UNDO_FLYFRMFMT_DESCRIPTION,
+ rFlyFrmFmt.GetObjDescription(),
+ sNewDescription ) );
+ }
+
+ rFlyFrmFmt.SetObjDescription( sNewDescription, true );
+
+ SetModified();
+}
+// <--
+
+/***************************************************************************
+ * Methode : sal_Bool SwDoc::SetFrmFmtToFly( SwFlyFrm&, SwFrmFmt& )
+ * Beschreibung:
+ * Erstellt : OK 14.04.94 15:40
+ * Aenderung : JP 23.04.98
+ ***************************************************************************/
+
+sal_Bool SwDoc::SetFrmFmtToFly( SwFrmFmt& rFmt, SwFrmFmt& rNewFmt,
+ SfxItemSet* pSet, sal_Bool bKeepOrient )
+{
+ sal_Bool bChgAnchor = sal_False, bFrmSz = sal_False;
+
+ const SwFmtFrmSize aFrmSz( rFmt.GetFrmSize() );
+ const SwFmtVertOrient aVert( rFmt.GetVertOrient() );
+ const SwFmtHoriOrient aHori( rFmt.GetHoriOrient() );
+
+ SwUndoSetFlyFmt* pUndo = 0;
+ bool const bUndo = GetIDocumentUndoRedo().DoesUndo();
+ if (bUndo)
+ {
+ pUndo = new SwUndoSetFlyFmt( rFmt, rNewFmt );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ // #i32968# Inserting columns in the section causes MakeFrmFmt to put
+ // 2 objects of type SwUndoFrmFmt on the undo stack. We don't want them.
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ //Erstmal die Spalten setzen, sonst gibts nix als Aerger mit dem
+ //Set/Reset/Abgleich usw.
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET != rNewFmt.GetAttrSet().GetItemState( RES_COL ))
+ rFmt.ResetFmtAttr( RES_COL );
+
+ if( rFmt.DerivedFrom() != &rNewFmt )
+ {
+ rFmt.SetDerivedFrom( &rNewFmt );
+
+ // 1. wenn nicht automatisch -> ignorieren, sonst -> wech
+ // 2. wech damit, MB!
+ if( SFX_ITEM_SET == rNewFmt.GetAttrSet().GetItemState( RES_FRM_SIZE, sal_False ))
+ {
+ rFmt.ResetFmtAttr( RES_FRM_SIZE );
+ bFrmSz = sal_True;
+ }
+
+ const SfxItemSet* pAsk = pSet;
+ if( !pAsk ) pAsk = &rNewFmt.GetAttrSet();
+ if( SFX_ITEM_SET == pAsk->GetItemState( RES_ANCHOR, sal_False, &pItem )
+ && ((SwFmtAnchor*)pItem)->GetAnchorId() !=
+ rFmt.GetAnchor().GetAnchorId() )
+ {
+ if( pSet )
+ bChgAnchor = MAKEFRMS == SetFlyFrmAnchor( rFmt, *pSet, sal_False );
+ else
+ {
+ //JP 23.04.98: muss den FlyFmt-Range haben, denn im SetFlyFrmAnchor
+ // werden Attribute in diesen gesetzt!
+ SfxItemSet aFlySet( *rNewFmt.GetAttrSet().GetPool(),
+ rNewFmt.GetAttrSet().GetRanges() );
+ aFlySet.Put( *pItem );
+ bChgAnchor = MAKEFRMS == SetFlyFrmAnchor( rFmt, aFlySet, sal_False);
+ }
+ }
+ }
+
+ //Hori und Vert nur dann resetten, wenn in der Vorlage eine
+ //automatische Ausrichtung eingestellt ist, anderfalls den alten Wert
+ //wieder hineinstopfen.
+ //JP 09.06.98: beim Update der RahmenVorlage sollte der Fly NICHT
+ // seine Orientierng verlieren (diese wird nicht geupdatet!)
+ //OS: #96584# text::HoriOrientation::NONE and text::VertOrientation::NONE are allowed now
+ if (!bKeepOrient)
+ {
+ rFmt.ResetFmtAttr(RES_VERT_ORIENT);
+ rFmt.ResetFmtAttr(RES_HORI_ORIENT);
+ }
+
+ rFmt.ResetFmtAttr( RES_PRINT, RES_SURROUND );
+ rFmt.ResetFmtAttr( RES_LR_SPACE, RES_UL_SPACE );
+ rFmt.ResetFmtAttr( RES_BACKGROUND, RES_COL );
+ rFmt.ResetFmtAttr( RES_URL, RES_EDIT_IN_READONLY );
+
+ if( !bFrmSz )
+ rFmt.SetFmtAttr( aFrmSz );
+
+ if( bChgAnchor )
+ rFmt.MakeFrms();
+
+ if( pUndo )
+ rFmt.Remove( pUndo );
+
+ SetModified();
+
+ return bChgAnchor;
+}
+
+void SwDoc::GetGrfNms( const SwFlyFrmFmt& rFmt, String* pGrfName,
+ String* pFltName ) const
+{
+ SwNodeIndex aIdx( *rFmt.GetCntnt().GetCntntIdx(), 1 );
+ const SwGrfNode* pGrfNd = aIdx.GetNode().GetGrfNode();
+ if( pGrfNd && pGrfNd->IsLinkedFile() )
+ pGrfNd->GetFileFilterNms( pGrfName, pFltName );
+}
+
+/*************************************************************************
+|*
+|* SwDoc::ChgAnchor()
+|*
+|* Ersterstellung MA 10. Jan. 95
+|* Letzte Aenderung JP 08.07.98
+|*
+*************************************************************************/
+
+sal_Bool SwDoc::ChgAnchor( const SdrMarkList& _rMrkList,
+ RndStdIds _eAnchorType,
+ const sal_Bool _bSameOnly,
+ const sal_Bool _bPosCorr )
+{
+ ASSERT( GetRootFrm(), "Ohne Layout geht gar nichts" );
+
+ if ( !_rMrkList.GetMarkCount() ||
+ _rMrkList.GetMark( 0 )->GetMarkedSdrObj()->GetUpGroup() )
+ {
+ return false;
+ }
+
+ GetIDocumentUndoRedo().StartUndo( UNDO_INSATTR, NULL );
+
+ sal_Bool bUnmark = sal_False;
+ for ( sal_uInt16 i = 0; i < _rMrkList.GetMarkCount(); ++i )
+ {
+ SdrObject* pObj = _rMrkList.GetMark( i )->GetMarkedSdrObj();
+ if ( !pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ SwDrawContact* pContact = static_cast<SwDrawContact*>(GetUserCall(pObj));
+
+ // OD 27.06.2003 #108784# - consider, that drawing object has
+ // no user call. E.g.: a 'virtual' drawing object is disconnected by
+ // the anchor type change of the 'master' drawing object.
+ // Continue with next selected object and assert, if this isn't excepted.
+ if ( !pContact )
+ {
+#ifdef DBG_UTIL
+ bool bNoUserCallExcepted =
+ pObj->ISA(SwDrawVirtObj) &&
+ !static_cast<SwDrawVirtObj*>(pObj)->IsConnected();
+ ASSERT( bNoUserCallExcepted, "SwDoc::ChgAnchor(..) - no contact at selected drawing object" );
+#endif
+ continue;
+ }
+
+ // OD 2004-03-29 #i26791#
+ const SwFrm* pOldAnchorFrm = pContact->GetAnchorFrm( pObj );
+ const SwFrm* pNewAnchorFrm = pOldAnchorFrm;
+
+ // --> OD 2006-03-01 #i54336#
+ // Instead of only keeping the index position for an as-character
+ // anchored object the complete <SwPosition> is kept, because the
+ // anchor index position could be moved, if the object again is
+ // anchored as character.
+// xub_StrLen nIndx = STRING_NOTFOUND;
+ const SwPosition* pOldAsCharAnchorPos( 0L );
+ const RndStdIds eOldAnchorType = pContact->GetAnchorId();
+ if ( !_bSameOnly && eOldAnchorType == FLY_AS_CHAR )
+ {
+ pOldAsCharAnchorPos = new SwPosition( pContact->GetCntntAnchor() );
+ }
+ // <--
+
+ if ( _bSameOnly )
+ _eAnchorType = eOldAnchorType;
+
+ SwFmtAnchor aNewAnch( _eAnchorType );
+ Rectangle aObjRect( pContact->GetAnchoredObj( pObj )->GetObjRect().SVRect() );
+ const Point aPt( aObjRect.TopLeft() );
+
+ switch ( _eAnchorType )
+ {
+ case FLY_AT_PARA:
+ case FLY_AT_CHAR:
+ {
+ const Point aNewPoint = pOldAnchorFrm &&
+ ( pOldAnchorFrm->IsVertical() ||
+ pOldAnchorFrm->IsRightToLeft() )
+ ? aObjRect.TopRight()
+ : aPt;
+
+ // OD 18.06.2003 #108784# - allow drawing objects in header/footer
+ pNewAnchorFrm = ::FindAnchor( pOldAnchorFrm, aNewPoint, false );
+ if ( pNewAnchorFrm->IsTxtFrm() && ((SwTxtFrm*)pNewAnchorFrm)->IsFollow() )
+ {
+ pNewAnchorFrm = ((SwTxtFrm*)pNewAnchorFrm)->FindMaster();
+ }
+ if ( pNewAnchorFrm->IsProtected() )
+ {
+ pNewAnchorFrm = 0;
+ }
+ else
+ {
+ SwPosition aPos( *((SwCntntFrm*)pNewAnchorFrm)->GetNode() );
+ aNewAnch.SetType( _eAnchorType );
+ aNewAnch.SetAnchor( &aPos );
+ }
+ }
+ break;
+
+ case FLY_AT_FLY: // LAYER_IMPL
+ {
+ //Ausgehend von der linken oberen Ecke des Fly den
+ //dichtesten SwFlyFrm suchen.
+ SwFrm *pTxtFrm;
+ {
+ SwCrsrMoveState aState( MV_SETONLYTEXT );
+ SwPosition aPos( GetNodes() );
+ Point aPoint( aPt );
+ aPoint.X() -= 1;
+ GetRootFrm()->GetCrsrOfst( &aPos, aPoint, &aState );
+ // OD 20.06.2003 #108784# - consider that drawing objects
+ // can be in header/footer. Thus, <GetFrm()> by left-top-corner
+ pTxtFrm = aPos.nNode.GetNode().
+ GetCntntNode()->GetFrm( &aPt, 0, sal_False );
+ }
+ const SwFrm *pTmp = ::FindAnchor( pTxtFrm, aPt );
+ pNewAnchorFrm = pTmp->FindFlyFrm();
+ if( pNewAnchorFrm && !pNewAnchorFrm->IsProtected() )
+ {
+ const SwFrmFmt *pTmpFmt = ((SwFlyFrm*)pNewAnchorFrm)->GetFmt();
+ const SwFmtCntnt& rCntnt = pTmpFmt->GetCntnt();
+ SwPosition aPos( *rCntnt.GetCntntIdx() );
+ aNewAnch.SetAnchor( &aPos );
+ break;
+ }
+
+ aNewAnch.SetType( FLY_AT_PAGE );
+ // no break
+ }
+ case FLY_AT_PAGE:
+ {
+ pNewAnchorFrm = GetRootFrm()->Lower();
+ while ( pNewAnchorFrm && !pNewAnchorFrm->Frm().IsInside( aPt ) )
+ pNewAnchorFrm = pNewAnchorFrm->GetNext();
+ if ( !pNewAnchorFrm )
+ continue;
+
+ aNewAnch.SetPageNum( ((SwPageFrm*)pNewAnchorFrm)->GetPhyPageNum());
+ }
+ break;
+ case FLY_AS_CHAR:
+ if( _bSameOnly ) // Positions/Groessenaenderung
+ {
+ if( !pOldAnchorFrm )
+ {
+ pContact->ConnectToLayout();
+ pOldAnchorFrm = pContact->GetAnchorFrm();
+ }
+ ((SwTxtFrm*)pOldAnchorFrm)->Prepare();
+ }
+ else // Ankerwechsel
+ {
+ // OD 18.06.2003 #108784# - allow drawing objects in header/footer
+ pNewAnchorFrm = ::FindAnchor( pOldAnchorFrm, aPt, false );
+ if( pNewAnchorFrm->IsProtected() )
+ {
+ pNewAnchorFrm = 0;
+ break;
+ }
+
+ bUnmark = ( 0 != i );
+ Point aPoint( aPt );
+ aPoint.X() -= 1; // nicht im DrawObj landen!!
+ aNewAnch.SetType( FLY_AS_CHAR );
+ SwPosition aPos( *((SwCntntFrm*)pNewAnchorFrm)->GetNode() );
+ if ( pNewAnchorFrm->Frm().IsInside( aPoint ) )
+ {
+ // es muss ein TextNode gefunden werden, denn nur dort
+ // ist ein inhaltsgebundenes DrawObjekt zu verankern
+ SwCrsrMoveState aState( MV_SETONLYTEXT );
+ GetRootFrm()->GetCrsrOfst( &aPos, aPoint, &aState );
+ }
+ else
+ {
+ SwCntntNode &rCNd = (SwCntntNode&)
+ *((SwCntntFrm*)pNewAnchorFrm)->GetNode();
+ if ( pNewAnchorFrm->Frm().Bottom() < aPt.Y() )
+ rCNd.MakeStartIndex( &aPos.nContent );
+ else
+ rCNd.MakeEndIndex( &aPos.nContent );
+ }
+ aNewAnch.SetAnchor( &aPos );
+ SetAttr( aNewAnch, *pContact->GetFmt() );
+ // OD 2004-04-13 #i26791# - adjust vertical positioning to
+ // 'center to baseline'
+ SetAttr( SwFmtVertOrient( 0, text::VertOrientation::CENTER, text::RelOrientation::FRAME ), *pContact->GetFmt() );
+ SwTxtNode *pNd = aPos.nNode.GetNode().GetTxtNode();
+ ASSERT( pNd, "Cursor not positioned at TxtNode." );
+
+ SwFmtFlyCnt aFmt( pContact->GetFmt() );
+ pNd->InsertItem( aFmt, aPos.nContent.GetIndex(), 0 );
+ }
+ break;
+ default:
+ ASSERT( !this, "unexpected AnchorId." );
+ }
+
+ if ( (FLY_AS_CHAR != _eAnchorType) &&
+ pNewAnchorFrm &&
+ ( !_bSameOnly || pNewAnchorFrm != pOldAnchorFrm ) )
+ {
+ // OD 2004-04-06 #i26791# - Direct object positioning no longer
+ // needed. Apply of attributes (method call <SetAttr(..)>) takes
+ // care of the invalidation of the object position.
+ SetAttr( aNewAnch, *pContact->GetFmt() );
+ if ( _bPosCorr )
+ {
+ // --> OD 2004-08-24 #i33313# - consider not connected
+ // 'virtual' drawing objects
+ if ( pObj->ISA(SwDrawVirtObj) &&
+ !static_cast<SwDrawVirtObj*>(pObj)->IsConnected() )
+ {
+ SwRect aNewObjRect( aObjRect );
+ static_cast<SwAnchoredDrawObject*>(pContact->GetAnchoredObj( 0L ))
+ ->AdjustPositioningAttr( pNewAnchorFrm,
+ &aNewObjRect );
+
+ }
+ else
+ {
+ static_cast<SwAnchoredDrawObject*>(pContact->GetAnchoredObj( pObj ))
+ ->AdjustPositioningAttr( pNewAnchorFrm );
+ }
+ }
+ }
+
+ // --> OD 2006-03-01 #i54336#
+ if ( pNewAnchorFrm && pOldAsCharAnchorPos )
+ {
+ //Bei InCntnt's wird es spannend: Das TxtAttribut muss vernichtet
+ //werden. Leider reisst dies neben den Frms auch noch das Format mit
+ //in sein Grab. Um dass zu unterbinden loesen wir vorher die
+ //Verbindung zwischen Attribut und Format.
+ const xub_StrLen nIndx( pOldAsCharAnchorPos->nContent.GetIndex() );
+ SwTxtNode* pTxtNode( pOldAsCharAnchorPos->nNode.GetNode().GetTxtNode() );
+ ASSERT( pTxtNode, "<SwDoc::ChgAnchor(..)> - missing previous anchor text node for as-character anchored object" );
+ ASSERT( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
+ SwTxtAttr * const pHnt =
+ pTxtNode->GetTxtAttrForCharAt( nIndx, RES_TXTATR_FLYCNT );
+ const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt();
+
+ //Die Verbindung ist geloest, jetzt muss noch das Attribut vernichtet
+ //werden.
+ pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIndx, nIndx );
+ delete pOldAsCharAnchorPos;
+ }
+ // <--
+ }
+ }
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ SetModified();
+
+ return bUnmark;
+}
+
+
+/* -----------------23.07.98 13:56-------------------
+ *
+ * --------------------------------------------------*/
+int SwDoc::Chainable( const SwFrmFmt &rSource, const SwFrmFmt &rDest )
+{
+ //Die Source darf noch keinen Follow haben.
+ const SwFmtChain &rOldChain = rSource.GetChain();
+ if ( rOldChain.GetNext() )
+ return SW_CHAIN_SOURCE_CHAINED;
+
+ //Ziel darf natuerlich nicht gleich Source sein und es
+ //darf keine geschlossene Kette entstehen.
+ const SwFrmFmt *pFmt = &rDest;
+ do {
+ if( pFmt == &rSource )
+ return SW_CHAIN_SELF;
+ pFmt = pFmt->GetChain().GetNext();
+ } while ( pFmt );
+
+ //Auch eine Verkettung von Innen nach aussen oder von aussen
+ //nach innen ist nicht zulaessig.
+ if( rDest.IsLowerOf( rSource ) || rSource .IsLowerOf( rDest ) )
+ return SW_CHAIN_SELF;
+
+ //Das Ziel darf noch keinen Master haben.
+ const SwFmtChain &rChain = rDest.GetChain();
+ if( rChain.GetPrev() )
+ return SW_CHAIN_IS_IN_CHAIN;
+
+ //Das Ziel muss leer sein.
+ const SwNodeIndex* pCntIdx = rDest.GetCntnt().GetCntntIdx();
+ if( !pCntIdx )
+ return SW_CHAIN_NOT_FOUND;
+
+ SwNodeIndex aNxtIdx( *pCntIdx, 1 );
+ const SwTxtNode* pTxtNd = aNxtIdx.GetNode().GetTxtNode();
+ if( !pTxtNd )
+ return SW_CHAIN_NOT_FOUND;
+
+ const sal_uLong nFlySttNd = pCntIdx->GetIndex();
+ if( 2 != ( pCntIdx->GetNode().EndOfSectionIndex() - nFlySttNd ) ||
+ pTxtNd->GetTxt().Len() )
+ return SW_CHAIN_NOT_EMPTY;
+
+ sal_uInt16 nArrLen = GetSpzFrmFmts()->Count();
+ for( sal_uInt16 n = 0; n < nArrLen; ++n )
+ {
+ const SwFmtAnchor& rAnchor = (*GetSpzFrmFmts())[ n ]->GetAnchor();
+ sal_uLong nTstSttNd;
+ // OD 11.12.2003 #i20622# - to-frame anchored objects are allowed.
+ if ( ((rAnchor.GetAnchorId() == FLY_AT_PARA) ||
+ (rAnchor.GetAnchorId() == FLY_AT_CHAR)) &&
+ 0 != rAnchor.GetCntntAnchor() &&
+ nFlySttNd <= ( nTstSttNd =
+ rAnchor.GetCntntAnchor()->nNode.GetIndex() ) &&
+ nTstSttNd < nFlySttNd + 2 )
+ {
+ return SW_CHAIN_NOT_EMPTY;
+ }
+ }
+
+ //Auf die richtige Area muessen wir auch noch einen Blick werfen.
+ //Beide Flys muessen im selben Bereich (Body, Head/Foot, Fly) sitzen
+ //Wenn die Source nicht der selektierte Rahmen ist, so reicht es
+ //Wenn ein passender gefunden wird (Der Wunsch kann z.B. von der API
+ //kommen).
+
+ // both in the same fly, header, footer or on the page?
+ const SwFmtAnchor &rSrcAnchor = rSource.GetAnchor(),
+ &rDstAnchor = rDest.GetAnchor();
+ sal_uLong nEndOfExtras = GetNodes().GetEndOfExtras().GetIndex();
+ sal_Bool bAllowed = sal_False;
+ if ( FLY_AT_PAGE == rSrcAnchor.GetAnchorId() )
+ {
+ if ( (FLY_AT_PAGE == rDstAnchor.GetAnchorId()) ||
+ ( rDstAnchor.GetCntntAnchor() &&
+ rDstAnchor.GetCntntAnchor()->nNode.GetIndex() > nEndOfExtras ))
+ bAllowed = sal_True;
+ }
+ else if( rSrcAnchor.GetCntntAnchor() && rDstAnchor.GetCntntAnchor() )
+ {
+ const SwNodeIndex &rSrcIdx = rSrcAnchor.GetCntntAnchor()->nNode,
+ &rDstIdx = rDstAnchor.GetCntntAnchor()->nNode;
+ const SwStartNode* pSttNd = 0;
+ if( rSrcIdx == rDstIdx ||
+ ( !pSttNd &&
+ 0 != ( pSttNd = rSrcIdx.GetNode().FindFlyStartNode() ) &&
+ pSttNd == rDstIdx.GetNode().FindFlyStartNode() ) ||
+ ( !pSttNd &&
+ 0 != ( pSttNd = rSrcIdx.GetNode().FindFooterStartNode() ) &&
+ pSttNd == rDstIdx.GetNode().FindFooterStartNode() ) ||
+ ( !pSttNd &&
+ 0 != ( pSttNd = rSrcIdx.GetNode().FindHeaderStartNode() ) &&
+ pSttNd == rDstIdx.GetNode().FindHeaderStartNode() ) ||
+ ( !pSttNd && rDstIdx.GetIndex() > nEndOfExtras &&
+ rSrcIdx.GetIndex() > nEndOfExtras ))
+ bAllowed = sal_True;
+ }
+
+ return bAllowed ? SW_CHAIN_OK : SW_CHAIN_WRONG_AREA;
+}
+/* -----------------23.07.98 13:56-------------------
+ *
+ * --------------------------------------------------*/
+int SwDoc::Chain( SwFrmFmt &rSource, const SwFrmFmt &rDest )
+{
+ int nErr = Chainable( rSource, rDest );
+ if ( !nErr )
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_CHAINE, NULL );
+
+ SwFlyFrmFmt& rDestFmt = (SwFlyFrmFmt&)rDest;
+
+ //Follow an den Master haengen.
+ SwFmtChain aChain = rDestFmt.GetChain();
+ aChain.SetPrev( &(SwFlyFrmFmt&)rSource );
+ SetAttr( aChain, rDestFmt );
+
+ SfxItemSet aSet( GetAttrPool(), RES_FRM_SIZE, RES_FRM_SIZE,
+ RES_CHAIN, RES_CHAIN, 0 );
+
+ //Follow an den Master haengen.
+ aChain.SetPrev( &(SwFlyFrmFmt&)rSource );
+ SetAttr( aChain, rDestFmt );
+
+ //Master an den Follow haengen und dafuer sorgen, dass der Master
+ //eine fixierte Hoehe hat.
+ aChain = rSource.GetChain();
+ aChain.SetNext( &rDestFmt );
+ aSet.Put( aChain );
+
+ SwFmtFrmSize aSize( rSource.GetFrmSize() );
+ if ( aSize.GetHeightSizeType() != ATT_FIX_SIZE )
+ {
+ SwClientIter aIter( rSource );
+ SwFlyFrm *pFly = (SwFlyFrm*)aIter.First( TYPE(SwFlyFrm) );
+ if ( pFly )
+ aSize.SetHeight( pFly->Frm().Height() );
+ aSize.SetHeightSizeType( ATT_FIX_SIZE );
+ aSet.Put( aSize );
+ }
+ SetAttr( aSet, rSource );
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_CHAINE, NULL );
+ }
+ return nErr;
+}
+/* -----------------23.07.98 13:56-------------------
+ *
+ * --------------------------------------------------*/
+void SwDoc::Unchain( SwFrmFmt &rFmt )
+{
+ SwFmtChain aChain( rFmt.GetChain() );
+ if ( aChain.GetNext() )
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_UNCHAIN, NULL );
+ SwFrmFmt *pFollow = aChain.GetNext();
+ aChain.SetNext( 0 );
+ SetAttr( aChain, rFmt );
+ aChain = pFollow->GetChain();
+ aChain.SetPrev( 0 );
+ SetAttr( aChain, *pFollow );
+ GetIDocumentUndoRedo().EndUndo( UNDO_UNCHAIN, NULL );
+ }
+}
+
+
+
diff --git a/sw/source/core/doc/docfmt.cxx b/sw/source/core/doc/docfmt.cxx
new file mode 100644
index 000000000000..1154fbf61d88
--- /dev/null
+++ b/sw/source/core/doc/docfmt.cxx
@@ -0,0 +1,2688 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#define _ZFORLIST_DECLARE_TABLE
+#define _SVSTDARR_USHORTSSORT
+#define _SVSTDARR_USHORTS
+#include <hintids.hxx>
+#include <rtl/logfile.hxx>
+#include <svl/itemiter.hxx>
+#include <sfx2/app.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <svl/whiter.hxx>
+#ifndef _ZFORLIST_HXX //autogen
+#define _ZFORLIST_DECLARE_TABLE
+#include <svl/zforlist.hxx>
+#endif
+#include <comphelper/processfactory.hxx>
+#include <unotools/misccfg.hxx>
+#include <com/sun/star/i18n/WordType.hdl>
+#include <fmtpdsc.hxx>
+#include <fmthdft.hxx>
+#include <fmtcntnt.hxx>
+#include <frmatr.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <hints.hxx> // fuer SwHyphenBug (in SetDefault)
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <UndoCore.hxx>
+#include <UndoAttribute.hxx>
+#include <ndgrf.hxx>
+#include <pagedesc.hxx> // Fuer Sonderbehandlung in InsFrmFmt
+#include <rolbck.hxx> // Undo-Attr
+#include <mvsave.hxx> // servieren: Veraenderungen erkennen
+#include <txatbase.hxx>
+#include <swtable.hxx>
+#include <swtblfmt.hxx>
+#include <charfmt.hxx>
+#include <docary.hxx>
+#include <paratr.hxx>
+#include <redline.hxx>
+#include <reffld.hxx>
+#include <txtinet.hxx>
+#include <fmtinfmt.hxx>
+#include <breakit.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <fmtautofmt.hxx>
+#include <istyleaccess.hxx>
+#include <SwUndoFmt.hxx>
+#include <docsh.hxx>
+
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+
+SV_IMPL_PTRARR(SwFrmFmts,SwFrmFmtPtr)
+SV_IMPL_PTRARR(SwCharFmts,SwCharFmtPtr)
+
+//Spezifische Frameformate (Rahmen)
+SV_IMPL_PTRARR(SwSpzFrmFmts,SwFrmFmtPtr)
+
+/*
+ * interne Funktionen
+ */
+
+sal_Bool SetTxtFmtCollNext( const SwTxtFmtCollPtr& rpTxtColl, void* pArgs )
+{
+ SwTxtFmtColl *pDel = (SwTxtFmtColl*) pArgs;
+ if ( &rpTxtColl->GetNextTxtFmtColl() == pDel )
+ {
+ rpTxtColl->SetNextTxtFmtColl( *rpTxtColl );
+ }
+ return sal_True;
+}
+
+/*
+ * Zuruecksetzen der harten Formatierung fuer Text
+ */
+
+// Uebergabeparameter fuer _Rst und lcl_SetTxtFmtColl
+struct ParaRstFmt
+{
+ SwFmtColl* pFmtColl;
+ SwHistory* pHistory;
+ const SwPosition *pSttNd, *pEndNd;
+ const SfxItemSet* pDelSet;
+ sal_uInt16 nWhich;
+ bool bReset;
+ // --> OD 2007-11-06 #i62575#
+ bool bResetListAttrs;
+ // <--
+ bool bResetAll;
+ bool bInclRefToxMark;
+
+ bool bKeepOutlineLevelAttr; //#outline level,add by zhaojianwei
+
+ ParaRstFmt( const SwPosition* pStt, const SwPosition* pEnd,
+ SwHistory* pHst, sal_uInt16 nWhch = 0, const SfxItemSet* pSet = 0 )
+ : pFmtColl(0),
+ pHistory(pHst),
+ pSttNd(pStt),
+ pEndNd(pEnd),
+ pDelSet(pSet),
+ nWhich(nWhch),
+ // --> OD 2007-11-06 #i62675#
+ bReset( false ),
+ bResetListAttrs( false ),
+ // <--
+ bResetAll( true ),
+ bInclRefToxMark( false ),
+ bKeepOutlineLevelAttr( false ) //#outline level,add by zhaojianwei
+ {}
+
+ ParaRstFmt( SwHistory* pHst )
+ : pFmtColl(0),
+ pHistory(pHst),
+ pSttNd(0),
+ pEndNd(0),
+ pDelSet(0),
+ nWhich(0),
+ // --> OD 2007-11-06 #i62675#
+ bReset( false ),
+ bResetListAttrs( false ),
+ // <--
+ bResetAll( true ),
+ bInclRefToxMark( false ),
+ bKeepOutlineLevelAttr( false ) //#outline level,add by zhaojianwei
+ {}
+};
+
+/* in pArgs steht die ChrFmtTablle vom Dokument
+ * (wird bei Selectionen am Start/Ende und bei keiner SSelection benoetigt)
+ */
+
+sal_Bool lcl_RstTxtAttr( const SwNodePtr& rpNd, void* pArgs )
+{
+ ParaRstFmt* pPara = (ParaRstFmt*)pArgs;
+ SwTxtNode * pTxtNode = (SwTxtNode*)rpNd->GetTxtNode();
+ if( pTxtNode && pTxtNode->GetpSwpHints() )
+ {
+ SwIndex aSt( pTxtNode, 0 );
+ sal_uInt16 nEnd = pTxtNode->Len();
+
+ if( &pPara->pSttNd->nNode.GetNode() == pTxtNode &&
+ pPara->pSttNd->nContent.GetIndex() )
+ aSt = pPara->pSttNd->nContent.GetIndex();
+
+ if( &pPara->pEndNd->nNode.GetNode() == rpNd )
+ nEnd = pPara->pEndNd->nContent.GetIndex();
+
+ if( pPara->pHistory )
+ {
+ // fuers Undo alle Attribute sichern
+ SwRegHistory aRHst( *pTxtNode, pPara->pHistory );
+ pTxtNode->GetpSwpHints()->Register( &aRHst );
+ pTxtNode->RstAttr( aSt, nEnd - aSt.GetIndex(), pPara->nWhich,
+ pPara->pDelSet, pPara->bInclRefToxMark );
+ if( pTxtNode->GetpSwpHints() )
+ pTxtNode->GetpSwpHints()->DeRegister();
+ }
+ else
+ pTxtNode->RstAttr( aSt, nEnd - aSt.GetIndex(), pPara->nWhich,
+ pPara->pDelSet, pPara->bInclRefToxMark );
+ }
+ return sal_True;
+}
+
+sal_Bool lcl_RstAttr( const SwNodePtr& rpNd, void* pArgs )
+{
+ ParaRstFmt* pPara = (ParaRstFmt*)pArgs;
+ SwCntntNode* pNode = (SwCntntNode*)rpNd->GetCntntNode();
+ if( pNode && pNode->HasSwAttrSet() )
+ {
+ const sal_Bool bLocked = pNode->IsModifyLocked();
+ pNode->LockModify();
+
+ SwDoc* pDoc = pNode->GetDoc();
+
+ // --> OD 2008-04-14 #refactorlists#
+ // remove unused attribute RES_LR_SPACE
+ // add list attributes
+ SfxItemSet aSet( pDoc->GetAttrPool(),
+ RES_PAGEDESC, RES_BREAK,
+ RES_PARATR_NUMRULE, RES_PARATR_NUMRULE,
+ RES_PARATR_OUTLINELEVEL,RES_PARATR_OUTLINELEVEL,//#outline level,removed by zhaojianwei
+ RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END - 1,
+ 0 );
+ const SfxItemSet* pSet = pNode->GetpSwAttrSet();
+
+ // --> OD 2008-04-15 #refactorlists#
+// std::vector<sal_uInt16> aClearWhichIds;
+ SvUShorts aClearWhichIds;
+ // <--
+ // --> OD 2008-04-15 #refactorlists#
+ // restoring all paragraph list attributes
+ {
+ SfxItemSet aListAttrSet( pDoc->GetAttrPool(),
+ RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END - 1,
+ 0 );
+ aListAttrSet.Set( *pSet );
+ if ( aListAttrSet.Count() )
+ {
+ aSet.Put( aListAttrSet );
+ SfxItemIter aIter( aListAttrSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ while( pItem )
+ {
+ aClearWhichIds.Insert( pItem->Which(), aClearWhichIds.Count() );
+ pItem = aIter.NextItem();
+ }
+ }
+ }
+ // <--
+
+ const SfxPoolItem* pItem;
+ // sal_uInt16 __READONLY_DATA aSavIds[ 3 ] = { RES_PAGEDESC, RES_BREAK, //#outline level,removed by zhaojianwei
+ // RES_PARATR_NUMRULE };
+ //for( sal_uInt16 n = 0; n < 3; ++n )
+ sal_uInt16 __READONLY_DATA aSavIds[ 4 ] = { RES_PAGEDESC, RES_BREAK, //->add by zhaojianwei
+ RES_PARATR_NUMRULE,
+ RES_PARATR_OUTLINELEVEL };
+ for( sal_uInt16 n = 0; n < 4; ++n ) //<-end,zhaojianwei
+ {
+ if( SFX_ITEM_SET == pSet->GetItemState( aSavIds[ n ], sal_False, &pItem ))
+ {
+ bool bSave = false;
+ switch( aSavIds[ n ] )
+ {
+ case RES_PAGEDESC:
+ bSave = 0 != ((SwFmtPageDesc*)pItem)->GetPageDesc();
+ break;
+ case RES_BREAK:
+ bSave = SVX_BREAK_NONE != ((SvxFmtBreakItem*)pItem)->GetBreak();
+ break;
+ case RES_PARATR_NUMRULE:
+ {
+ bSave = 0 != ((SwNumRuleItem*)pItem)->GetValue().Len();
+ }
+ break;
+ case RES_PARATR_OUTLINELEVEL: //#outline level,add by zhaojianwei
+ {
+ bSave = pPara && pPara->bKeepOutlineLevelAttr;
+ }
+ break; //<-end,zhaojianwei
+ }
+ if( bSave )
+ {
+ aSet.Put( *pItem );
+ // --> OD 2008-04-15 #refactorlists#
+// aClearWhichIds.push_back( aSavIds[n] );
+ aClearWhichIds.Insert( aSavIds[n], aClearWhichIds.Count() );
+ }
+ }
+ }
+
+ // --> OD 2008-04-14 #refactorlists#
+ // do not clear items directly from item set and only clear to be kept
+ // attributes, if no deletion item set is found.
+// pNode->ClearItemsFromAttrSet( aClearWhichIds );
+ const bool bKeepAttributes =
+ !pPara || !pPara->pDelSet || pPara->pDelSet->Count() == 0;
+ if ( bKeepAttributes )
+ {
+ pNode->ResetAttr( aClearWhichIds );
+ }
+ // <--
+
+ if( !bLocked )
+ pNode->UnlockModify();
+
+ if( pPara )
+ {
+ SwRegHistory aRegH( pNode, *pNode, pPara->pHistory );
+
+ if( pPara->pDelSet && pPara->pDelSet->Count() )
+ {
+ // --> OD 2008-04-15 #refactorlists#
+ ASSERT( !bKeepAttributes,
+ "<lcl_RstAttr(..)> - certain attributes are kept, but not needed. -> please inform OD" );
+ // <--
+ SfxItemIter aIter( *pPara->pDelSet );
+ pItem = aIter.FirstItem();
+ while( sal_True )
+ {
+ // --> OD 2008-04-14 #refactorlists#
+ //
+ if ( ( pItem->Which() != RES_PAGEDESC &&
+ pItem->Which() != RES_BREAK &&
+ pItem->Which() != RES_PARATR_NUMRULE ) ||
+ ( aSet.GetItemState( pItem->Which(), sal_False ) != SFX_ITEM_SET ) )
+ {
+ pNode->ResetAttr( pItem->Which() );
+ }
+ // <--
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+ }
+ else if( pPara->bResetAll )
+ pNode->ResetAllAttr();
+ else
+ pNode->ResetAttr( RES_PARATR_BEGIN, POOLATTR_END - 1 );
+ }
+ else
+ pNode->ResetAllAttr();
+
+ // --> OD 2008-04-15 #refactorlists#
+ // only restore saved attributes, if needed
+ if ( bKeepAttributes && aSet.Count() )
+ // <--
+ {
+ pNode->LockModify();
+
+ pNode->SetAttr( aSet );
+
+ if( !bLocked )
+ pNode->UnlockModify();
+ }
+ }
+ return sal_True;
+}
+
+void SwDoc::RstTxtAttrs(const SwPaM &rRg, sal_Bool bInclRefToxMark )
+{
+ SwHistory* pHst = 0;
+ SwDataChanged aTmp( rRg, 0 );
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoResetAttr* pUndo = new SwUndoResetAttr( rRg, RES_CHRFMT );
+ pHst = &pUndo->GetHistory();
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ const SwPosition *pStt = rRg.Start(), *pEnd = rRg.End();
+ ParaRstFmt aPara( pStt, pEnd, pHst );
+ aPara.bInclRefToxMark = ( bInclRefToxMark == sal_True );
+ GetNodes().ForEach( pStt->nNode.GetIndex(), pEnd->nNode.GetIndex()+1,
+ lcl_RstTxtAttr, &aPara );
+ SetModified();
+}
+
+void SwDoc::ResetAttrs( const SwPaM &rRg,
+ sal_Bool bTxtAttr,
+ const SvUShortsSort* pAttrs,
+ // --> OD 2008-11-28 #b96644#
+ const bool bSendDataChangedEvents )
+ // <--
+{
+ SwPaM* pPam = (SwPaM*)&rRg;
+ if( !bTxtAttr && pAttrs && pAttrs->Count() &&
+ RES_TXTATR_END > (*pAttrs)[ 0 ] )
+ bTxtAttr = sal_True;
+
+ if( !rRg.HasMark() )
+ {
+ SwTxtNode* pTxtNd = rRg.GetPoint()->nNode.GetNode().GetTxtNode();
+ if( !pTxtNd )
+ return ;
+
+ pPam = new SwPaM( *rRg.GetPoint() );
+
+ SwIndex& rSt = pPam->GetPoint()->nContent;
+ sal_uInt16 nMkPos, nPtPos = rSt.GetIndex();
+
+ // JP 22.08.96: Sonderfall: steht der Crsr in einem URL-Attribut
+ // dann wird dessen Bereich genommen
+ SwTxtAttr const*const pURLAttr(
+ pTxtNd->GetTxtAttrAt(rSt.GetIndex(), RES_TXTATR_INETFMT));
+ if (pURLAttr && pURLAttr->GetINetFmt().GetValue().Len())
+ {
+ nMkPos = *pURLAttr->GetStart();
+ nPtPos = *pURLAttr->GetEnd();
+ }
+ else
+ {
+ Boundary aBndry;
+ if( pBreakIt->GetBreakIter().is() )
+ aBndry = pBreakIt->GetBreakIter()->getWordBoundary(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
+ WordType::ANY_WORD /*ANYWORD_IGNOREWHITESPACES*/,
+ sal_True );
+
+ if( aBndry.startPos < nPtPos && nPtPos < aBndry.endPos )
+ {
+ nMkPos = (xub_StrLen)aBndry.startPos;
+ nPtPos = (xub_StrLen)aBndry.endPos;
+ }
+ else
+ {
+ nPtPos = nMkPos = rSt.GetIndex();
+ if( bTxtAttr )
+ pTxtNd->DontExpandFmt( rSt, sal_True );
+ }
+ }
+
+ rSt = nMkPos;
+ pPam->SetMark();
+ pPam->GetPoint()->nContent = nPtPos;
+ }
+
+ // --> OD 2008-11-28 #i96644#
+// SwDataChanged aTmp( *pPam, 0 );
+ std::auto_ptr< SwDataChanged > pDataChanged;
+ if ( bSendDataChangedEvents )
+ {
+ pDataChanged.reset( new SwDataChanged( *pPam, 0 ) );
+ }
+ // <--
+ SwHistory* pHst = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoResetAttr* pUndo = new SwUndoResetAttr( rRg,
+ static_cast<sal_uInt16>(bTxtAttr ? RES_CONDTXTFMTCOLL : RES_TXTFMTCOLL ));
+ if( pAttrs && pAttrs->Count() )
+ {
+ pUndo->SetAttrs( *pAttrs );
+ }
+ pHst = &pUndo->GetHistory();
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ const SwPosition *pStt = pPam->Start(), *pEnd = pPam->End();
+ ParaRstFmt aPara( pStt, pEnd, pHst );
+
+ // mst: not including META here; it seems attrs with CH_TXTATR are omitted
+ sal_uInt16 __FAR_DATA aResetableSetRange[] = {
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_PARATR_BEGIN, RES_PARATR_END-1,
+ // --> OD 2008-02-25 #refactorlists#
+ RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
+ // <--
+ RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
+ RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
+ RES_TXTATR_CJK_RUBY, RES_TXTATR_CJK_RUBY,
+ RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0
+ };
+
+ SfxItemSet aDelSet( GetAttrPool(), aResetableSetRange );
+ if( pAttrs && pAttrs->Count() )
+ {
+ for( sal_uInt16 n = pAttrs->Count(); n; )
+ if( POOLATTR_END > (*pAttrs)[ --n ] )
+ aDelSet.Put( *GetDfltAttr( (*pAttrs)[ n ] ));
+
+ if( aDelSet.Count() )
+ aPara.pDelSet = &aDelSet;
+ }
+
+ sal_Bool bAdd = sal_True;
+ SwNodeIndex aTmpStt( pStt->nNode );
+ SwNodeIndex aTmpEnd( pEnd->nNode );
+ if( pStt->nContent.GetIndex() ) // nur ein Teil
+ {
+ // dann spaeter aufsetzen und alle CharFmtAttr -> TxtFmtAttr
+ SwTxtNode* pTNd = aTmpStt.GetNode().GetTxtNode();
+ if( pTNd && pTNd->HasSwAttrSet() && pTNd->GetpSwAttrSet()->Count() )
+ {
+ SfxItemIter aIter( *pTNd->GetpSwAttrSet() );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ SfxItemSet aCharSet( GetAttrPool(), RES_CHRATR_BEGIN, RES_CHRATR_END );
+
+ while( sal_True )
+ {
+ if( IsInRange( aCharFmtSetRange, pItem->Which() ))
+ {
+ pTNd->GetOrCreateSwpHints();
+
+ aCharSet.Put( *pItem );
+
+ if( pHst )
+ {
+ SwRegHistory aRegH( pTNd, *pTNd, pHst );
+ pTNd->ResetAttr( pItem->Which() );
+ }
+ else
+ pTNd->ResetAttr( pItem->Which() );
+ }
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+
+ if ( aCharSet.Count() )
+ {
+ if ( pHst )
+ {
+ SwRegHistory history( pTNd, *pTNd, pHst );
+ history.InsertItems( aCharSet, 0, pTNd->GetTxt().Len(),
+ nsSetAttrMode::SETATTR_NOFORMATATTR );
+ }
+ else
+ {
+ SwTxtAttr* pNew =
+ MakeTxtAttr( *this, aCharSet, 0, pTNd->GetTxt().Len() );
+ pTNd->InsertHint( pNew );
+ }
+ }
+ }
+
+ aTmpStt++;
+ }
+ if( pEnd->nContent.GetIndex() == pEnd->nNode.GetNode().GetCntntNode()->Len() )
+ // dann spaeter aufsetzen und alle CharFmtAttr -> TxtFmtAttr
+ aTmpEnd++, bAdd = sal_False;
+ else if( pStt->nNode != pEnd->nNode || !pStt->nContent.GetIndex() )
+ {
+ SwTxtNode* pTNd = aTmpEnd.GetNode().GetTxtNode();
+ if( pTNd && pTNd->HasSwAttrSet() && pTNd->GetpSwAttrSet()->Count() )
+ {
+ SfxItemIter aIter( *pTNd->GetpSwAttrSet() );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ while( sal_True )
+ {
+ if( IsInRange( aCharFmtSetRange, pItem->Which() ))
+ {
+ SwTxtAttr* pTAttr = MakeTxtAttr( *this,
+ const_cast<SfxPoolItem&>(*pItem),
+ 0, pTNd->GetTxt().Len() );
+ SwpHints & rHints = pTNd->GetOrCreateSwpHints();
+ rHints.SwpHintsArray::Insert( pTAttr );
+ if ( pHst )
+ {
+ SwRegHistory aRegH( pTNd, *pTNd, pHst );
+ pTNd->ResetAttr( pItem->Which() );
+ pHst->Add( pTAttr, aTmpEnd.GetIndex(), true );
+ }
+ else
+ pTNd->ResetAttr( pItem->Which() );
+ }
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+ }
+ }
+
+ if( aTmpStt < aTmpEnd )
+ GetNodes().ForEach( pStt->nNode, aTmpEnd, lcl_RstAttr, &aPara );
+ else if( !rRg.HasMark() )
+ {
+ aPara.bResetAll = false ;
+ ::lcl_RstAttr( &pStt->nNode.GetNode(), &aPara );
+ aPara.bResetAll = true ;
+ }
+
+ if( bTxtAttr )
+ {
+ if( bAdd )
+ aTmpEnd++;
+ GetNodes().ForEach( pStt->nNode, aTmpEnd, lcl_RstTxtAttr, &aPara );
+ }
+
+ if( pPam != &rRg )
+ delete pPam;
+
+ SetModified();
+}
+
+#define DELETECHARSETS if ( bDelete ) { delete pCharSet; delete pOtherSet; }
+
+// Einfuegen der Hints nach Inhaltsformen;
+// wird in SwDoc::Insert(..., SwFmtHint &rHt) benutzt
+
+static bool
+lcl_InsAttr(SwDoc *const pDoc, const SwPaM &rRg, const SfxItemSet& rChgSet,
+ const SetAttrMode nFlags, SwUndoAttr *const pUndo)
+{
+ // teil die Sets auf (fuer Selektion in Nodes)
+ const SfxItemSet* pCharSet = 0;
+ const SfxItemSet* pOtherSet = 0;
+ bool bDelete = false;
+ bool bCharAttr = false;
+ bool bOtherAttr = false;
+
+ // Check, if we can work with rChgSet or if we have to create additional SfxItemSets
+ if ( 1 == rChgSet.Count() )
+ {
+ SfxItemIter aIter( rChgSet );
+ const SfxPoolItem* pItem = aIter.FirstItem();
+ const sal_uInt16 nWhich = pItem->Which();
+
+ if ( isCHRATR(nWhich) ||
+ (RES_TXTATR_CHARFMT == nWhich) ||
+ (RES_TXTATR_INETFMT == nWhich) ||
+ (RES_TXTATR_AUTOFMT == nWhich) ||
+ (RES_TXTATR_UNKNOWN_CONTAINER == nWhich) )
+ {
+ pCharSet = &rChgSet;
+ bCharAttr = true;
+ }
+
+ if ( isPARATR(nWhich)
+ // --> OD 2008-02-25 #refactorlists#
+ || isPARATR_LIST(nWhich)
+ // <--
+ || isFRMATR(nWhich)
+ || isGRFATR(nWhich)
+ || isUNKNOWNATR(nWhich) )
+ {
+ pOtherSet = &rChgSet;
+ bOtherAttr = true;
+ }
+ }
+
+ // Build new itemset if either
+ // - rChgSet.Count() > 1 or
+ // - The attribute in rChgSet does not belong to one of the above categories
+ if ( !bCharAttr && !bOtherAttr )
+ {
+ SfxItemSet* pTmpCharItemSet = new SfxItemSet( pDoc->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_TXTATR_AUTOFMT, RES_TXTATR_AUTOFMT,
+ RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
+ RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
+ RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER,
+ 0 );
+
+ SfxItemSet* pTmpOtherItemSet = new SfxItemSet( pDoc->GetAttrPool(),
+ RES_PARATR_BEGIN, RES_PARATR_END-1,
+ // --> OD 2008-02-25 #refactorlists#
+ RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
+ // <--
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_GRFATR_BEGIN, RES_GRFATR_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0 );
+
+ pTmpCharItemSet->Put( rChgSet );
+ pTmpOtherItemSet->Put( rChgSet );
+
+ pCharSet = pTmpCharItemSet;
+ pOtherSet = pTmpOtherItemSet;
+
+ bDelete = true;
+ }
+
+ SwHistory* pHistory = pUndo ? &pUndo->GetHistory() : 0;
+ bool bRet = false;
+ const SwPosition *pStt = rRg.Start(), *pEnd = rRg.End();
+ SwCntntNode* pNode = pStt->nNode.GetNode().GetCntntNode();
+
+ if( pNode && pNode->IsTxtNode() )
+ {
+ // -> #i27615#
+ if (rRg.IsInFrontOfLabel())
+ {
+ SwTxtNode * pTxtNd = pNode->GetTxtNode();
+ SwNumRule * pNumRule = pTxtNd->GetNumRule();
+
+ // --> OD 2005-10-24 #126346# - make code robust:
+ if ( !pNumRule )
+ {
+ ASSERT( false,
+ "<InsAttr(..)> - PaM in front of label, but text node has no numbering rule set. This is a serious defect, please inform OD." );
+ DELETECHARSETS
+ return false;
+ }
+ // <--
+
+ SwNumFmt aNumFmt = pNumRule->Get(static_cast<sal_uInt16>(pTxtNd->GetActualListLevel()));
+ SwCharFmt * pCharFmt =
+ pDoc->FindCharFmtByName(aNumFmt.GetCharFmtName());
+
+ if (pCharFmt)
+ {
+ if (pHistory)
+ pHistory->Add(pCharFmt->GetAttrSet(), *pCharFmt);
+
+ if ( pCharSet )
+ pCharFmt->SetFmtAttr(*pCharSet);
+ }
+
+ DELETECHARSETS
+ return true;
+ }
+ // <- #i27615#
+
+ const SwIndex& rSt = pStt->nContent;
+
+ // Attribute ohne Ende haben keinen Bereich
+ if ( !bCharAttr && !bOtherAttr )
+ {
+ SfxItemSet aTxtSet( pDoc->GetAttrPool(),
+ RES_TXTATR_NOEND_BEGIN, RES_TXTATR_NOEND_END-1 );
+ aTxtSet.Put( rChgSet );
+ if( aTxtSet.Count() )
+ {
+ SwRegHistory history( pNode, *pNode, pHistory );
+ bRet = history.InsertItems(
+ aTxtSet, rSt.GetIndex(), rSt.GetIndex(), nFlags ) || bRet;
+
+ if (bRet && (pDoc->IsRedlineOn() || (!pDoc->IsIgnoreRedline()
+ && pDoc->GetRedlineTbl().Count())))
+ {
+ SwPaM aPam( pStt->nNode, pStt->nContent.GetIndex()-1,
+ pStt->nNode, pStt->nContent.GetIndex() );
+
+ if( pUndo )
+ pUndo->SaveRedlineData( aPam, sal_True );
+
+ if( pDoc->IsRedlineOn() )
+ pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
+ else
+ pDoc->SplitRedline( aPam );
+ }
+ }
+ }
+
+ // TextAttribute mit Ende expandieren nie ihren Bereich
+ if ( !bCharAttr && !bOtherAttr )
+ {
+ // CharFmt wird gesondert behandelt !!!
+ // JP 22.08.96: URL-Attribute auch!!
+ // TEST_TEMP ToDo: AutoFmt!
+ SfxItemSet aTxtSet( pDoc->GetAttrPool(),
+ RES_TXTATR_REFMARK, RES_TXTATR_TOXMARK,
+ RES_TXTATR_META, RES_TXTATR_METAFIELD,
+ RES_TXTATR_CJK_RUBY, RES_TXTATR_CJK_RUBY,
+ 0 );
+
+ aTxtSet.Put( rChgSet );
+ if( aTxtSet.Count() )
+ {
+ sal_uInt16 nInsCnt = rSt.GetIndex();
+ sal_uInt16 nEnd = pStt->nNode == pEnd->nNode
+ ? pEnd->nContent.GetIndex()
+ : pNode->Len();
+ SwRegHistory history( pNode, *pNode, pHistory );
+ bRet = history.InsertItems( aTxtSet, nInsCnt, nEnd, nFlags )
+ || bRet;
+
+ if (bRet && (pDoc->IsRedlineOn() || (!pDoc->IsIgnoreRedline()
+ && pDoc->GetRedlineTbl().Count())))
+ {
+ // wurde Text-Inhalt eingefuegt? (RefMark/TOXMarks ohne Ende)
+ sal_Bool bTxtIns = nInsCnt != rSt.GetIndex();
+ // wurde Inhalt eingefuegt oder ueber die Selektion gesetzt?
+ SwPaM aPam( pStt->nNode, bTxtIns ? nInsCnt + 1 : nEnd,
+ pStt->nNode, nInsCnt );
+ if( pUndo )
+ pUndo->SaveRedlineData( aPam, bTxtIns );
+
+ if( pDoc->IsRedlineOn() )
+ pDoc->AppendRedline( new SwRedline( bTxtIns
+ ? nsRedlineType_t::REDLINE_INSERT : nsRedlineType_t::REDLINE_FORMAT, aPam ), true);
+ else if( bTxtIns )
+ pDoc->SplitRedline( aPam );
+ }
+ }
+ }
+ }
+
+ // bei PageDesc's, die am Node gesetzt werden, muss immer das
+ // Auto-Flag gesetzt werden!!
+ if( pOtherSet && pOtherSet->Count() )
+ {
+ SwTableNode* pTblNd;
+ const SwFmtPageDesc* pDesc;
+ if( SFX_ITEM_SET == pOtherSet->GetItemState( RES_PAGEDESC,
+ sal_False, (const SfxPoolItem**)&pDesc ))
+ {
+ if( pNode )
+ {
+ // Auto-Flag setzen, nur in Vorlagen ist ohne Auto !
+ SwFmtPageDesc aNew( *pDesc );
+ // Bug 38479: AutoFlag wird jetzt in der WrtShell gesetzt
+ // aNew.SetAuto();
+
+ // Tabellen kennen jetzt auch Umbrueche
+ if( 0 == (nFlags & nsSetAttrMode::SETATTR_APICALL) &&
+ 0 != ( pTblNd = pNode->FindTableNode() ) )
+ {
+ SwTableNode* pCurTblNd = pTblNd;
+ while ( 0 != ( pCurTblNd = pCurTblNd->StartOfSectionNode()->FindTableNode() ) )
+ pTblNd = pCurTblNd;
+
+ // dann am Tabellen Format setzen
+ SwFrmFmt* pFmt = pTblNd->GetTable().GetFrmFmt();
+ SwRegHistory aRegH( pFmt, *pTblNd, pHistory );
+ pFmt->SetFmtAttr( aNew );
+ bRet = true;
+ }
+ else
+ {
+ SwRegHistory aRegH( pNode, *pNode, pHistory );
+ bRet = pNode->SetAttr( aNew ) || bRet;
+ }
+ }
+
+ // bOtherAttr = true means that pOtherSet == rChgSet. In this case
+ // we know, that there is only one attribute in pOtherSet. We cannot
+ // perform the following operations, instead we return:
+ if ( bOtherAttr )
+ return bRet;
+
+ const_cast<SfxItemSet*>(pOtherSet)->ClearItem( RES_PAGEDESC );
+ if( !pOtherSet->Count() )
+ {
+ DELETECHARSETS
+ return bRet;
+ }
+ }
+
+ // Tabellen kennen jetzt auch Umbrueche
+ const SvxFmtBreakItem* pBreak;
+ if( pNode && 0 == (nFlags & nsSetAttrMode::SETATTR_APICALL) &&
+ 0 != (pTblNd = pNode->FindTableNode() ) &&
+ SFX_ITEM_SET == pOtherSet->GetItemState( RES_BREAK,
+ sal_False, (const SfxPoolItem**)&pBreak ) )
+ {
+ SwTableNode* pCurTblNd = pTblNd;
+ while ( 0 != ( pCurTblNd = pCurTblNd->StartOfSectionNode()->FindTableNode() ) )
+ pTblNd = pCurTblNd;
+
+ // dann am Tabellen Format setzen
+ SwFrmFmt* pFmt = pTblNd->GetTable().GetFrmFmt();
+ SwRegHistory aRegH( pFmt, *pTblNd, pHistory );
+ pFmt->SetFmtAttr( *pBreak );
+ bRet = true;
+
+ // bOtherAttr = true means that pOtherSet == rChgSet. In this case
+ // we know, that there is only one attribute in pOtherSet. We cannot
+ // perform the following operations, instead we return:
+ if ( bOtherAttr )
+ return bRet;
+
+ const_cast<SfxItemSet*>(pOtherSet)->ClearItem( RES_BREAK );
+ if( !pOtherSet->Count() )
+ {
+ DELETECHARSETS
+ return bRet;
+ }
+ }
+
+ {
+ // wenns eine PoolNumRule ist, diese ggfs. anlegen
+ const SwNumRuleItem* pRule;
+ sal_uInt16 nPoolId;
+ if( SFX_ITEM_SET == pOtherSet->GetItemState( RES_PARATR_NUMRULE,
+ sal_False, (const SfxPoolItem**)&pRule ) &&
+ !pDoc->FindNumRulePtr( pRule->GetValue() ) &&
+ USHRT_MAX != (nPoolId = SwStyleNameMapper::GetPoolIdFromUIName ( pRule->GetValue(),
+ nsSwGetPoolIdFromName::GET_POOLID_NUMRULE )) )
+ pDoc->GetNumRuleFromPool( nPoolId );
+ }
+
+ }
+
+ if( !rRg.HasMark() ) // kein Bereich
+ {
+ if( !pNode )
+ {
+ DELETECHARSETS
+ return bRet;
+ }
+
+ if( pNode->IsTxtNode() && pCharSet && pCharSet->Count() )
+ {
+ SwTxtNode* pTxtNd = static_cast<SwTxtNode*>(pNode);
+ const SwIndex& rSt = pStt->nContent;
+ sal_uInt16 nMkPos, nPtPos = rSt.GetIndex();
+ const String& rStr = pTxtNd->GetTxt();
+
+ // JP 22.08.96: Sonderfall: steht der Crsr in einem URL-Attribut
+ // dann wird dessen Bereich genommen
+ SwTxtAttr const*const pURLAttr(
+ pTxtNd->GetTxtAttrAt(rSt.GetIndex(), RES_TXTATR_INETFMT));
+ if (pURLAttr && pURLAttr->GetINetFmt().GetValue().Len())
+ {
+ nMkPos = *pURLAttr->GetStart();
+ nPtPos = *pURLAttr->GetEnd();
+ }
+ else
+ {
+ Boundary aBndry;
+ if( pBreakIt->GetBreakIter().is() )
+ aBndry = pBreakIt->GetBreakIter()->getWordBoundary(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
+ WordType::ANY_WORD /*ANYWORD_IGNOREWHITESPACES*/,
+ sal_True );
+
+ if( aBndry.startPos < nPtPos && nPtPos < aBndry.endPos )
+ {
+ nMkPos = (xub_StrLen)aBndry.startPos;
+ nPtPos = (xub_StrLen)aBndry.endPos;
+ }
+ else
+ nPtPos = nMkPos = rSt.GetIndex();
+ }
+
+ // erstmal die zu ueberschreibenden Attribute aus dem
+ // SwpHintsArray entfernen, wenn die Selektion den gesamten
+ // Absatz umspannt. (Diese Attribute werden als FormatAttr.
+ // eingefuegt und verdraengen nie die TextAttr.!)
+ if( !(nFlags & nsSetAttrMode::SETATTR_DONTREPLACE ) &&
+ pTxtNd->HasHints() && !nMkPos && nPtPos == rStr.Len() )
+ {
+ SwIndex aSt( pTxtNd );
+ if( pHistory )
+ {
+ // fuers Undo alle Attribute sichern
+ SwRegHistory aRHst( *pTxtNd, pHistory );
+ pTxtNd->GetpSwpHints()->Register( &aRHst );
+ pTxtNd->RstAttr( aSt, nPtPos, 0, pCharSet );
+ if( pTxtNd->GetpSwpHints() )
+ pTxtNd->GetpSwpHints()->DeRegister();
+ }
+ else
+ pTxtNd->RstAttr( aSt, nPtPos, 0, pCharSet );
+ }
+
+ // the SwRegHistory inserts the attribute into the TxtNode!
+ SwRegHistory history( pNode, *pNode, pHistory );
+ bRet = history.InsertItems( *pCharSet, nMkPos, nPtPos, nFlags )
+ || bRet;
+
+ if( pDoc->IsRedlineOn() )
+ {
+ SwPaM aPam( *pNode, nMkPos, *pNode, nPtPos );
+
+ if( pUndo )
+ pUndo->SaveRedlineData( aPam, sal_False );
+ pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_FORMAT, aPam ), true);
+ }
+ }
+ if( pOtherSet && pOtherSet->Count() )
+ {
+ SwRegHistory aRegH( pNode, *pNode, pHistory );
+ bRet = pNode->SetAttr( *pOtherSet ) || bRet;
+ }
+
+ DELETECHARSETS
+ return bRet;
+ }
+
+ if( pDoc->IsRedlineOn() && pCharSet && pCharSet->Count() )
+ {
+ if( pUndo )
+ pUndo->SaveRedlineData( rRg, sal_False );
+ pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_FORMAT, rRg ), true);
+ }
+
+ /* jetzt wenn Bereich */
+ sal_uLong nNodes = 0;
+
+ SwNodeIndex aSt( pDoc->GetNodes() );
+ SwNodeIndex aEnd( pDoc->GetNodes() );
+ SwIndex aCntEnd( pEnd->nContent );
+
+ if( pNode )
+ {
+ sal_uInt16 nLen = pNode->Len();
+ if( pStt->nNode != pEnd->nNode )
+ aCntEnd.Assign( pNode, nLen );
+
+ if( pStt->nContent.GetIndex() != 0 || aCntEnd.GetIndex() != nLen )
+ {
+ // the SwRegHistory inserts the attribute into the TxtNode!
+ if( pNode->IsTxtNode() && pCharSet && pCharSet->Count() )
+ {
+ SwRegHistory history( pNode, *pNode, pHistory );
+ bRet = history.InsertItems(*pCharSet,
+ pStt->nContent.GetIndex(), aCntEnd.GetIndex(), nFlags)
+ || bRet;
+ }
+
+ if( pOtherSet && pOtherSet->Count() )
+ {
+ SwRegHistory aRegH( pNode, *pNode, pHistory );
+ bRet = pNode->SetAttr( *pOtherSet ) || bRet;
+ }
+
+ // lediglich Selektion in einem Node.
+ if( pStt->nNode == pEnd->nNode )
+ {
+ DELETECHARSETS
+ return bRet;
+ }
+ ++nNodes;
+ aSt.Assign( pStt->nNode.GetNode(), +1 );
+ }
+ else
+ aSt = pStt->nNode;
+ aCntEnd = pEnd->nContent; // aEnd wurde veraendert !!
+ }
+ else
+ aSt.Assign( pStt->nNode.GetNode(), +1 );
+
+ // aSt zeigt jetzt auf den ersten vollen Node
+
+ /*
+ * die Selektion umfasst mehr als einen Node
+ */
+ if( pStt->nNode < pEnd->nNode )
+ {
+ pNode = pEnd->nNode.GetNode().GetCntntNode();
+ if(pNode)
+ {
+ sal_uInt16 nLen = pNode->Len();
+ if( aCntEnd.GetIndex() != nLen )
+ {
+ // the SwRegHistory inserts the attribute into the TxtNode!
+ if( pNode->IsTxtNode() && pCharSet && pCharSet->Count() )
+ {
+ SwRegHistory history( pNode, *pNode, pHistory );
+ history.InsertItems(*pCharSet,
+ 0, aCntEnd.GetIndex(), nFlags);
+ }
+
+ if( pOtherSet && pOtherSet->Count() )
+ {
+ SwRegHistory aRegH( pNode, *pNode, pHistory );
+ pNode->SetAttr( *pOtherSet );
+ }
+
+ ++nNodes;
+ aEnd = pEnd->nNode;
+ }
+ else
+ aEnd.Assign( pEnd->nNode.GetNode(), +1 );
+ }
+ else
+ aEnd = pEnd->nNode;
+ }
+ else
+ aEnd.Assign( pEnd->nNode.GetNode(), +1 );
+
+ // aEnd zeigt jetzt HINTER den letzten voll Node
+
+ /* Bearbeitung der vollstaendig selektierten Nodes. */
+// alle Attribute aus dem Set zuruecksetzen !!
+ if( pCharSet && pCharSet->Count() && !( nsSetAttrMode::SETATTR_DONTREPLACE & nFlags ) )
+ {
+
+ ParaRstFmt aPara( pStt, pEnd, pHistory, 0, pCharSet );
+ pDoc->GetNodes().ForEach( aSt, aEnd, lcl_RstTxtAttr, &aPara );
+ }
+
+ sal_Bool bCreateSwpHints = pCharSet && (
+ SFX_ITEM_SET == pCharSet->GetItemState( RES_TXTATR_CHARFMT, sal_False ) ||
+ SFX_ITEM_SET == pCharSet->GetItemState( RES_TXTATR_INETFMT, sal_False ) );
+
+ for(; aSt < aEnd; aSt++ )
+ {
+ pNode = aSt.GetNode().GetCntntNode();
+ if( !pNode )
+ continue;
+
+ SwTxtNode* pTNd = pNode->GetTxtNode();
+ if( pHistory )
+ {
+ SwRegHistory aRegH( pNode, *pNode, pHistory );
+ SwpHints *pSwpHints;
+
+ if( pTNd && pCharSet && pCharSet->Count() )
+ {
+ pSwpHints = bCreateSwpHints ? &pTNd->GetOrCreateSwpHints()
+ : pTNd->GetpSwpHints();
+ if( pSwpHints )
+ pSwpHints->Register( &aRegH );
+
+ pTNd->SetAttr( *pCharSet, 0, pTNd->GetTxt().Len(), nFlags );
+ if( pSwpHints )
+ pSwpHints->DeRegister();
+ }
+ if( pOtherSet && pOtherSet->Count() )
+ pNode->SetAttr( *pOtherSet );
+ }
+ else
+ {
+ if( pTNd && pCharSet && pCharSet->Count() )
+ pTNd->SetAttr( *pCharSet, 0, pTNd->GetTxt().Len(), nFlags );
+ if( pOtherSet && pOtherSet->Count() )
+ pNode->SetAttr( *pOtherSet );
+ }
+ ++nNodes;
+ }
+
+ DELETECHARSETS
+ return (nNodes != 0) || bRet;
+}
+
+
+bool SwDoc::InsertPoolItem( const SwPaM &rRg, const SfxPoolItem &rHt,
+ const SetAttrMode nFlags )
+{
+ SwDataChanged aTmp( rRg, 0 );
+ SwUndoAttr* pUndoAttr = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ pUndoAttr = new SwUndoAttr( rRg, rHt, nFlags );
+ }
+
+ SfxItemSet aSet( GetAttrPool(), rHt.Which(), rHt.Which() );
+ aSet.Put( rHt );
+ bool bRet = lcl_InsAttr( this, rRg, aSet, nFlags, pUndoAttr );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( pUndoAttr );
+ }
+
+ if( bRet )
+ SetModified();
+ return bRet;
+}
+
+bool SwDoc::InsertItemSet ( const SwPaM &rRg, const SfxItemSet &rSet,
+ const SetAttrMode nFlags )
+{
+ SwDataChanged aTmp( rRg, 0 );
+ SwUndoAttr* pUndoAttr = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ pUndoAttr = new SwUndoAttr( rRg, rSet, nFlags );
+ }
+
+ bool bRet = lcl_InsAttr( this, rRg, rSet, nFlags, pUndoAttr );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( pUndoAttr );
+ }
+
+ if( bRet )
+ SetModified();
+ return bRet;
+}
+
+
+ // Setze das Attribut im angegebenen Format. Ist Undo aktiv, wird
+ // das alte in die Undo-History aufgenommen
+void SwDoc::SetAttr( const SfxPoolItem& rAttr, SwFmt& rFmt )
+{
+ SfxItemSet aSet( GetAttrPool(), rAttr.Which(), rAttr.Which() );
+ aSet.Put( rAttr );
+ SetAttr( aSet, rFmt );
+}
+
+
+ // Setze das Attribut im angegebenen Format. Ist Undo aktiv, wird
+ // das alte in die Undo-History aufgenommen
+void SwDoc::SetAttr( const SfxItemSet& rSet, SwFmt& rFmt )
+{
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoFmtAttrHelper aTmp( rFmt );
+ rFmt.SetFmtAttr( rSet );
+ if ( aTmp.GetUndo() )
+ {
+ GetIDocumentUndoRedo().AppendUndo( aTmp.ReleaseUndo() );
+ }
+ else
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ }
+ }
+ else
+ {
+ rFmt.SetFmtAttr( rSet );
+ }
+ SetModified();
+}
+
+// --> OD 2008-02-12 #newlistlevelattrs#
+void SwDoc::ResetAttrAtFormat( const sal_uInt16 nWhichId,
+ SwFmt& rChangedFormat )
+{
+ SwUndo *const pUndo = (GetIDocumentUndoRedo().DoesUndo())
+ ? new SwUndoFmtResetAttr( rChangedFormat, nWhichId )
+ : 0;
+
+ const sal_Bool bAttrReset = rChangedFormat.ResetFmtAttr( nWhichId );
+
+ if ( bAttrReset )
+ {
+ if ( pUndo )
+ {
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+
+ SetModified();
+ }
+ else if ( pUndo )
+ delete pUndo;
+}
+// <--
+
+int lcl_SetNewDefTabStops( SwTwips nOldWidth, SwTwips nNewWidth,
+ SvxTabStopItem& rChgTabStop )
+{
+ // dann aender bei allen TabStop die default's auf den neuen Wert
+ // !!! Achtung: hier wird immer auf dem PoolAttribut gearbeitet,
+ // damit nicht in allen Sets die gleiche Berechnung
+ // auf dem gleichen TabStop (gepoolt!) vorgenommen
+ // wird. Als Modify wird ein FmtChg verschickt.
+
+ sal_uInt16 nOldCnt = rChgTabStop.Count();
+ if( !nOldCnt || nOldWidth == nNewWidth )
+ return sal_False;
+
+ // suche den Anfang der Defaults
+ SvxTabStop* pTabs = ((SvxTabStop*)rChgTabStop.GetStart())
+ + (nOldCnt-1);
+ sal_uInt16 n;
+
+ for( n = nOldCnt; n ; --n, --pTabs )
+ if( SVX_TAB_ADJUST_DEFAULT != pTabs->GetAdjustment() )
+ break;
+ ++n;
+ if( n < nOldCnt ) // die DefTabStops loeschen
+ rChgTabStop.Remove( n, nOldCnt - n );
+ return sal_True;
+}
+
+// Setze das Attribut als neues default Attribut in diesem Dokument.
+// Ist Undo aktiv, wird das alte in die Undo-History aufgenommen
+void SwDoc::SetDefault( const SfxPoolItem& rAttr )
+{
+ SfxItemSet aSet( GetAttrPool(), rAttr.Which(), rAttr.Which() );
+ aSet.Put( rAttr );
+ SetDefault( aSet );
+}
+
+void SwDoc::SetDefault( const SfxItemSet& rSet )
+{
+ if( !rSet.Count() )
+ return;
+
+ SwModify aCallMod( 0 );
+ SwAttrSet aOld( GetAttrPool(), rSet.GetRanges() ),
+ aNew( GetAttrPool(), rSet.GetRanges() );
+ SfxItemIter aIter( rSet );
+ sal_uInt16 nWhich;
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ SfxItemPool* pSdrPool = GetAttrPool().GetSecondaryPool();
+ while( sal_True )
+ {
+ sal_Bool bCheckSdrDflt = sal_False;
+ nWhich = pItem->Which();
+ aOld.Put( GetAttrPool().GetDefaultItem( nWhich ) );
+ GetAttrPool().SetPoolDefaultItem( *pItem );
+ aNew.Put( GetAttrPool().GetDefaultItem( nWhich ) );
+
+ if (isCHRATR(nWhich) || isTXTATR(nWhich))
+ {
+ aCallMod.Add( pDfltTxtFmtColl );
+ aCallMod.Add( pDfltCharFmt );
+ bCheckSdrDflt = 0 != pSdrPool;
+ }
+ else if ( isPARATR(nWhich) ||
+ // --> OD 2008-02-25 #refactorlists#
+ isPARATR_LIST(nWhich) )
+ // <--
+ {
+ aCallMod.Add( pDfltTxtFmtColl );
+ bCheckSdrDflt = 0 != pSdrPool;
+ }
+ else if (isGRFATR(nWhich))
+ {
+ aCallMod.Add( pDfltGrfFmtColl );
+ }
+ else if (isFRMATR(nWhich))
+ {
+ aCallMod.Add( pDfltGrfFmtColl );
+ aCallMod.Add( pDfltTxtFmtColl );
+ aCallMod.Add( pDfltFrmFmt );
+ }
+ else if (isBOXATR(nWhich))
+ {
+ aCallMod.Add( pDfltFrmFmt );
+ }
+
+ // copy also the defaults
+ if( bCheckSdrDflt )
+ {
+ sal_uInt16 nEdtWhich, nSlotId;
+ if( 0 != (nSlotId = GetAttrPool().GetSlotId( nWhich ) ) &&
+ nSlotId != nWhich &&
+ 0 != (nEdtWhich = pSdrPool->GetWhich( nSlotId )) &&
+ nSlotId != nEdtWhich )
+ {
+ SfxPoolItem* pCpy = pItem->Clone();
+ pCpy->SetWhich( nEdtWhich );
+ pSdrPool->SetPoolDefaultItem( *pCpy );
+ delete pCpy;
+ }
+ }
+
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+
+ if( aNew.Count() && aCallMod.GetDepends() )
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoDefaultAttr( aOld ) );
+ }
+
+ const SfxPoolItem* pTmpItem;
+ if( ( SFX_ITEM_SET ==
+ aNew.GetItemState( RES_PARATR_TABSTOP, sal_False, &pTmpItem ) ) &&
+ ((SvxTabStopItem*)pTmpItem)->Count() )
+ {
+ // TabStop-Aenderungen behandeln wir erstmal anders:
+ // dann aender bei allen TabStop die dafault's auf den neuen Wert
+ // !!! Achtung: hier wird immer auf dem PoolAttribut gearbeitet,
+ // damit nicht in allen Sets die gleiche Berechnung
+ // auf dem gleichen TabStop (gepoolt!) vorgenommen
+ // wird. Als Modify wird ein FmtChg verschickt.
+ SwTwips nNewWidth = (*(SvxTabStopItem*)pTmpItem)[ 0 ].GetTabPos(),
+ nOldWidth = ((SvxTabStopItem&)aOld.Get(RES_PARATR_TABSTOP))[ 0 ].GetTabPos();
+
+ int bChg = sal_False;
+ sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_PARATR_TABSTOP );
+ for( sal_uInt32 n = 0; n < nMaxItems; ++n )
+ if( 0 != (pTmpItem = GetAttrPool().GetItem2( RES_PARATR_TABSTOP, n ) ))
+ bChg |= lcl_SetNewDefTabStops( nOldWidth, nNewWidth,
+ *(SvxTabStopItem*)pTmpItem );
+
+ aNew.ClearItem( RES_PARATR_TABSTOP );
+ aOld.ClearItem( RES_PARATR_TABSTOP );
+ if( bChg )
+ {
+ SwFmtChg aChgFmt( pDfltCharFmt );
+ // dann sage mal den Frames bescheid
+ aCallMod.Modify( &aChgFmt, &aChgFmt );
+ }
+ }
+ }
+
+ if( aNew.Count() && aCallMod.GetDepends() )
+ {
+ SwAttrSetChg aChgOld( aOld, aOld );
+ SwAttrSetChg aChgNew( aNew, aNew );
+ aCallMod.Modify( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
+ }
+
+ // und die default-Formate wieder beim Object austragen
+ SwClient* pDep;
+ while( 0 != ( pDep = (SwClient*)aCallMod.GetDepends()) )
+ aCallMod.Remove( pDep );
+
+ SetModified();
+}
+
+ // Erfrage das Default Attribut in diesem Dokument.
+const SfxPoolItem& SwDoc::GetDefault( sal_uInt16 nFmtHint ) const
+{
+ return GetAttrPool().GetDefaultItem( nFmtHint );
+}
+
+/*
+ * Loeschen der Formate
+ */
+void SwDoc::DelCharFmt(sal_uInt16 nFmt, sal_Bool bBroadcast)
+{
+ SwCharFmt * pDel = (*pCharFmtTbl)[nFmt];
+
+ if (bBroadcast)
+ BroadcastStyleOperation(pDel->GetName(), SFX_STYLE_FAMILY_CHAR,
+ SFX_STYLESHEET_ERASED);
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo =
+ new SwUndoCharFmtDelete(pDel, this);
+
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ pCharFmtTbl->DeleteAndDestroy(nFmt);
+
+ SetModified();
+}
+
+void SwDoc::DelCharFmt( SwCharFmt *pFmt, sal_Bool bBroadcast )
+{
+ sal_uInt16 nFmt = pCharFmtTbl->GetPos( pFmt );
+ ASSERT( USHRT_MAX != nFmt, "Fmt not found," );
+
+ DelCharFmt( nFmt, bBroadcast );
+}
+
+void SwDoc::DelFrmFmt( SwFrmFmt *pFmt, sal_Bool bBroadcast )
+{
+ if( pFmt->ISA( SwTableBoxFmt ) || pFmt->ISA( SwTableLineFmt ))
+ {
+ ASSERT( !this, "Format steht nicht mehr im DocArray, "
+ "kann per delete geloescht werden" );
+ delete pFmt;
+ }
+ else
+ {
+
+ //Das Format muss in einem der beiden Arrays stehen, in welchem
+ //werden wir schon merken.
+ sal_uInt16 nPos;
+ if ( USHRT_MAX != ( nPos = pFrmFmtTbl->GetPos( pFmt )) )
+ {
+ if (bBroadcast)
+ BroadcastStyleOperation(pFmt->GetName(),
+ SFX_STYLE_FAMILY_FRAME,
+ SFX_STYLESHEET_ERASED);
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo = new SwUndoFrmFmtDelete(pFmt, this);
+
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ pFrmFmtTbl->DeleteAndDestroy( nPos );
+ }
+ else
+ {
+ nPos = GetSpzFrmFmts()->GetPos( pFmt );
+ ASSERT( nPos != USHRT_MAX, "FrmFmt not found." );
+ if( USHRT_MAX != nPos )
+ GetSpzFrmFmts()->DeleteAndDestroy( nPos );
+ }
+ }
+}
+
+void SwDoc::DelTblFrmFmt( SwTableFmt *pFmt )
+{
+ sal_uInt16 nPos = pTblFrmFmtTbl->GetPos( pFmt );
+ ASSERT( USHRT_MAX != nPos, "Fmt not found," );
+ pTblFrmFmtTbl->DeleteAndDestroy( nPos );
+}
+
+/*
+ * Erzeugen der Formate
+ */
+SwFlyFrmFmt *SwDoc::MakeFlyFrmFmt( const String &rFmtName,
+ SwFrmFmt *pDerivedFrom )
+{
+ SwFlyFrmFmt *pFmt = new SwFlyFrmFmt( GetAttrPool(), rFmtName, pDerivedFrom );
+ GetSpzFrmFmts()->Insert(pFmt, GetSpzFrmFmts()->Count());
+ SetModified();
+ return pFmt;
+}
+
+SwDrawFrmFmt *SwDoc::MakeDrawFrmFmt( const String &rFmtName,
+ SwFrmFmt *pDerivedFrom )
+{
+ SwDrawFrmFmt *pFmt = new SwDrawFrmFmt( GetAttrPool(), rFmtName, pDerivedFrom);
+ GetSpzFrmFmts()->Insert(pFmt,GetSpzFrmFmts()->Count());
+ SetModified();
+ return pFmt;
+}
+
+
+sal_uInt16 SwDoc::GetTblFrmFmtCount(sal_Bool bUsed) const
+{
+ sal_uInt16 nCount = pTblFrmFmtTbl->Count();
+ if(bUsed)
+ {
+ SwAutoFmtGetDocNode aGetHt( &GetNodes() );
+ for ( sal_uInt16 i = nCount; i; )
+ {
+ if((*pTblFrmFmtTbl)[--i]->GetInfo( aGetHt ))
+
+ --nCount;
+ }
+ }
+
+ return nCount;
+}
+
+
+SwFrmFmt& SwDoc::GetTblFrmFmt(sal_uInt16 nFmt, sal_Bool bUsed ) const
+{
+ sal_uInt16 nRemoved = 0;
+ if(bUsed)
+ {
+ SwAutoFmtGetDocNode aGetHt( &GetNodes() );
+ for ( sal_uInt16 i = 0; i <= nFmt; i++ )
+ {
+ while ( (*pTblFrmFmtTbl)[ i + nRemoved]->GetInfo( aGetHt ))
+ {
+ nRemoved++;
+ }
+ }
+ }
+ return *((*pTblFrmFmtTbl)[nRemoved + nFmt]);
+}
+
+SwTableFmt* SwDoc::MakeTblFrmFmt( const String &rFmtName,
+ SwFrmFmt *pDerivedFrom )
+{
+ SwTableFmt* pFmt = new SwTableFmt( GetAttrPool(), rFmtName, pDerivedFrom );
+ pTblFrmFmtTbl->Insert( pFmt, pTblFrmFmtTbl->Count() );
+ SetModified();
+
+ return pFmt;
+}
+
+SwFrmFmt *SwDoc::MakeFrmFmt(const String &rFmtName,
+ SwFrmFmt *pDerivedFrom,
+ sal_Bool bBroadcast, sal_Bool bAuto)
+{
+
+ SwFrmFmt *pFmt = new SwFrmFmt( GetAttrPool(), rFmtName, pDerivedFrom );
+
+ pFmt->SetAuto(bAuto);
+ pFrmFmtTbl->Insert( pFmt, pFrmFmtTbl->Count());
+ SetModified();
+
+ if (bBroadcast)
+ {
+ BroadcastStyleOperation(rFmtName, SFX_STYLE_FAMILY_PARA,
+ SFX_STYLESHEET_CREATED);
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo = new SwUndoFrmFmtCreate(pFmt, pDerivedFrom, this);
+
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ }
+
+ return pFmt;
+}
+
+SwFmt *SwDoc::_MakeFrmFmt(const String &rFmtName,
+ SwFmt *pDerivedFrom,
+ sal_Bool bBroadcast, sal_Bool bAuto)
+{
+ SwFrmFmt *pFrmFmt = dynamic_cast<SwFrmFmt*>(pDerivedFrom);
+ pFrmFmt = MakeFrmFmt( rFmtName, pFrmFmt, bBroadcast, bAuto );
+ return dynamic_cast<SwFmt*>(pFrmFmt);
+}
+
+
+// --> OD 2005-01-13 #i40550# - add parameter <bAuto> - not relevant
+SwCharFmt *SwDoc::MakeCharFmt( const String &rFmtName,
+ SwCharFmt *pDerivedFrom,
+ sal_Bool bBroadcast,
+ sal_Bool )
+// <--
+{
+ SwCharFmt *pFmt = new SwCharFmt( GetAttrPool(), rFmtName, pDerivedFrom );
+ pCharFmtTbl->Insert( pFmt, pCharFmtTbl->Count() );
+ pFmt->SetAuto( sal_False );
+ SetModified();
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo = new SwUndoCharFmtCreate(pFmt, pDerivedFrom, this);
+
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ if (bBroadcast)
+ {
+ BroadcastStyleOperation(rFmtName, SFX_STYLE_FAMILY_CHAR,
+ SFX_STYLESHEET_CREATED);
+ }
+
+ return pFmt;
+}
+
+SwFmt *SwDoc::_MakeCharFmt(const String &rFmtName,
+ SwFmt *pDerivedFrom,
+ sal_Bool bBroadcast, sal_Bool bAuto)
+{
+ SwCharFmt *pCharFmt = dynamic_cast<SwCharFmt*>(pDerivedFrom);
+ pCharFmt = MakeCharFmt( rFmtName, pCharFmt, bBroadcast, bAuto );
+ return dynamic_cast<SwFmt*>(pCharFmt);
+}
+
+
+/*
+ * Erzeugen der FormatCollections
+ */
+// TXT
+// --> OD 2005-01-13 #i40550# - add parameter <bAuto> - not relevant
+SwTxtFmtColl* SwDoc::MakeTxtFmtColl( const String &rFmtName,
+ SwTxtFmtColl *pDerivedFrom,
+ sal_Bool bBroadcast,
+ sal_Bool )
+// <--
+{
+ SwTxtFmtColl *pFmtColl = new SwTxtFmtColl( GetAttrPool(), rFmtName,
+ pDerivedFrom );
+ pTxtFmtCollTbl->Insert(pFmtColl, pTxtFmtCollTbl->Count());
+ pFmtColl->SetAuto( sal_False );
+ SetModified();
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo = new SwUndoTxtFmtCollCreate(pFmtColl, pDerivedFrom,
+ this);
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ if (bBroadcast)
+ BroadcastStyleOperation(rFmtName, SFX_STYLE_FAMILY_PARA,
+ SFX_STYLESHEET_CREATED);
+
+ return pFmtColl;
+}
+
+SwFmt *SwDoc::_MakeTxtFmtColl(const String &rFmtName,
+ SwFmt *pDerivedFrom,
+ sal_Bool bBroadcast, sal_Bool bAuto)
+{
+ SwTxtFmtColl *pTxtFmtColl = dynamic_cast<SwTxtFmtColl*>(pDerivedFrom);
+ pTxtFmtColl = MakeTxtFmtColl( rFmtName, pTxtFmtColl, bBroadcast, bAuto );
+ return dynamic_cast<SwFmt*>(pTxtFmtColl);
+}
+
+
+//FEATURE::CONDCOLL
+SwConditionTxtFmtColl* SwDoc::MakeCondTxtFmtColl( const String &rFmtName,
+ SwTxtFmtColl *pDerivedFrom,
+ sal_Bool bBroadcast)
+{
+ SwConditionTxtFmtColl*pFmtColl = new SwConditionTxtFmtColl( GetAttrPool(),
+ rFmtName, pDerivedFrom );
+ pTxtFmtCollTbl->Insert(pFmtColl, pTxtFmtCollTbl->Count());
+ pFmtColl->SetAuto( sal_False );
+ SetModified();
+
+ if (bBroadcast)
+ BroadcastStyleOperation(rFmtName, SFX_STYLE_FAMILY_PARA,
+ SFX_STYLESHEET_CREATED);
+
+ return pFmtColl;
+}
+//FEATURE::CONDCOLL
+
+// GRF
+
+SwGrfFmtColl* SwDoc::MakeGrfFmtColl( const String &rFmtName,
+ SwGrfFmtColl *pDerivedFrom )
+{
+ SwGrfFmtColl *pFmtColl = new SwGrfFmtColl( GetAttrPool(), rFmtName,
+ pDerivedFrom );
+ pGrfFmtCollTbl->Insert( pFmtColl, pGrfFmtCollTbl->Count() );
+ pFmtColl->SetAuto( sal_False );
+ SetModified();
+ return pFmtColl;
+}
+
+void SwDoc::DelTxtFmtColl(sal_uInt16 nFmtColl, sal_Bool bBroadcast)
+{
+ ASSERT( nFmtColl, "Remove fuer Coll 0." );
+
+ // Wer hat die zu loeschende als Next
+ SwTxtFmtColl *pDel = (*pTxtFmtCollTbl)[nFmtColl];
+ if( pDfltTxtFmtColl == pDel )
+ return; // default nie loeschen !!
+
+ if (bBroadcast)
+ BroadcastStyleOperation(pDel->GetName(), SFX_STYLE_FAMILY_PARA,
+ SFX_STYLESHEET_ERASED);
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoTxtFmtCollDelete * pUndo =
+ new SwUndoTxtFmtCollDelete(pDel, this);
+
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ // Die FmtColl austragen
+ pTxtFmtCollTbl->Remove(nFmtColl);
+ // Next korrigieren
+ pTxtFmtCollTbl->ForEach( 1, pTxtFmtCollTbl->Count(),
+ &SetTxtFmtCollNext, pDel );
+ delete pDel;
+ SetModified();
+}
+
+void SwDoc::DelTxtFmtColl( SwTxtFmtColl *pColl, sal_Bool bBroadcast )
+{
+ sal_uInt16 nFmt = pTxtFmtCollTbl->GetPos( pColl );
+ ASSERT( USHRT_MAX != nFmt, "Collection not found," );
+ DelTxtFmtColl( nFmt, bBroadcast );
+}
+
+sal_Bool lcl_SetTxtFmtColl( const SwNodePtr& rpNode, void* pArgs )
+{
+ // ParaSetFmtColl * pPara = (ParaSetFmtColl*)pArgs;
+ SwCntntNode* pCNd = (SwCntntNode*)rpNode->GetTxtNode();
+ if( pCNd )
+ {
+ ParaRstFmt* pPara = (ParaRstFmt*)pArgs;
+
+ SwTxtFmtColl* pFmt = static_cast<SwTxtFmtColl*>(pPara->pFmtColl);
+ if ( pPara->bReset )
+ {
+
+ if( pFmt->GetAttrOutlineLevel() == 0 && pPara )
+ pPara->bKeepOutlineLevelAttr = true;
+
+ lcl_RstAttr( pCNd, pPara );
+
+ // --> OD 2007-11-06 #i62675#
+ // --> OD 2008-04-15 #refactorlists#
+ // check, if paragraph style has changed
+ if ( pPara->bResetListAttrs &&
+ pFmt != pCNd->GetFmtColl() &&
+ pFmt->GetItemState( RES_PARATR_NUMRULE ) == SFX_ITEM_SET )
+ {
+ // --> OD 2009-09-07 #b6876367#
+ // Check, if the list style of the paragraph will change.
+ bool bChangeOfListStyleAtParagraph( true );
+ SwTxtNode* pTNd( dynamic_cast<SwTxtNode*>(pCNd) );
+ ASSERT( pTNd,
+ "<lcl_SetTxtFmtColl(..)> - text node expected -> crash" );
+ {
+ SwNumRule* pNumRuleAtParagraph( pTNd->GetNumRule() );
+ if ( pNumRuleAtParagraph )
+ {
+ const SwNumRuleItem& rNumRuleItemAtParagraphStyle =
+ pFmt->GetNumRule();
+ if ( rNumRuleItemAtParagraphStyle.GetValue() ==
+ pNumRuleAtParagraph->GetName() )
+ {
+ bChangeOfListStyleAtParagraph = false;
+ }
+ }
+ }
+
+ if ( bChangeOfListStyleAtParagraph )
+ {
+ // --> OD 2008-04-08 #refactorlists#
+ std::auto_ptr< SwRegHistory > pRegH;
+ if ( pPara->pHistory )
+ {
+ pRegH.reset( new SwRegHistory( pTNd, *pTNd, pPara->pHistory ) );
+ }
+
+ pCNd->ResetAttr( RES_PARATR_NUMRULE );
+
+ // reset all list attributes
+ pCNd->ResetAttr( RES_PARATR_LIST_LEVEL );
+ pCNd->ResetAttr( RES_PARATR_LIST_ISRESTART );
+ pCNd->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
+ pCNd->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
+ pCNd->ResetAttr( RES_PARATR_LIST_ID );
+ }
+ // <--
+ }
+ // <--
+ }
+
+ // erst in die History aufnehmen, damit ggfs. alte Daten
+ // gesichert werden koennen
+ if( pPara->pHistory )
+ pPara->pHistory->Add( pCNd->GetFmtColl(), pCNd->GetIndex(),
+ ND_TEXTNODE );
+
+ pCNd->ChgFmtColl( pFmt );
+
+ pPara->nWhich++;
+ }
+ return sal_True;
+}
+
+sal_Bool SwDoc::SetTxtFmtColl( const SwPaM &rRg,
+ SwTxtFmtColl *pFmt,
+ bool bReset,
+ bool bResetListAttrs )
+{
+ SwDataChanged aTmp( rRg, 0 );
+ const SwPosition *pStt = rRg.Start(), *pEnd = rRg.End();
+ SwHistory* pHst = 0;
+ sal_Bool bRet = sal_True;
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // --> OD 2008-04-15 #refactorlists#
+ SwUndoFmtColl* pUndo = new SwUndoFmtColl( rRg, pFmt,
+ bReset,
+ bResetListAttrs );
+ // <--
+ pHst = pUndo->GetHistory();
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ ParaRstFmt aPara( pStt, pEnd, pHst );
+ aPara.pFmtColl = pFmt;
+ aPara.bReset = bReset;
+ // --> OD 2007-11-06 #i62675#
+ aPara.bResetListAttrs = bResetListAttrs;
+ // <--
+
+ GetNodes().ForEach( pStt->nNode.GetIndex(), pEnd->nNode.GetIndex()+1,
+ lcl_SetTxtFmtColl, &aPara );
+ if( !aPara.nWhich )
+ bRet = sal_False; // keinen gueltigen Node gefunden
+
+ if( bRet )
+ SetModified();
+ return bRet;
+}
+
+
+// ---- Kopiere die Formate in sich selbst (SwDoc) ----------------------
+
+SwFmt* SwDoc::CopyFmt( const SwFmt& rFmt,
+ const SvPtrarr& rFmtArr,
+ FNCopyFmt fnCopyFmt, const SwFmt& rDfltFmt )
+{
+ // kein-Autoformat || default Format || Collection-Format
+ // dann suche danach.
+ if( !rFmt.IsAuto() || !rFmt.GetRegisteredIn() )
+ for( sal_uInt16 n = 0; n < rFmtArr.Count(); n++ )
+ {
+ // ist die Vorlage schon im Doc vorhanden ??
+ if( ((SwFmt*)rFmtArr[n])->GetName().Equals( rFmt.GetName() ))
+ return (SwFmt*)rFmtArr[n];
+ }
+
+ // suche erstmal nach dem "Parent"
+ SwFmt* pParent = (SwFmt*)&rDfltFmt;
+ if( rFmt.DerivedFrom() && pParent != rFmt.DerivedFrom() )
+ pParent = CopyFmt( *rFmt.DerivedFrom(), rFmtArr,
+ fnCopyFmt, rDfltFmt );
+
+ // erzeuge das Format und kopiere die Attribute
+ // --> OD 2005-01-13 #i40550#
+ SwFmt* pNewFmt = (this->*fnCopyFmt)( rFmt.GetName(), pParent, sal_False, sal_True );
+ // <--
+ pNewFmt->SetAuto( rFmt.IsAuto() );
+ pNewFmt->CopyAttrs( rFmt, sal_True ); // kopiere Attribute
+
+ pNewFmt->SetPoolFmtId( rFmt.GetPoolFmtId() );
+ pNewFmt->SetPoolHelpId( rFmt.GetPoolHelpId() );
+
+ // HelpFile-Id immer auf dflt setzen !!
+ pNewFmt->SetPoolHlpFileId( UCHAR_MAX );
+
+ return pNewFmt;
+}
+
+
+// ---- kopiere das Frame-Format --------
+SwFrmFmt* SwDoc::CopyFrmFmt( const SwFrmFmt& rFmt )
+{
+
+ return (SwFrmFmt*)CopyFmt( rFmt, *GetFrmFmts(), &SwDoc::_MakeFrmFmt,
+ *GetDfltFrmFmt() );
+}
+
+// ---- kopiere das Char-Format --------
+SwCharFmt* SwDoc::CopyCharFmt( const SwCharFmt& rFmt )
+{
+ return (SwCharFmt*)CopyFmt( rFmt, *GetCharFmts(),
+ &SwDoc::_MakeCharFmt,
+ *GetDfltCharFmt() );
+}
+
+
+// --- Kopiere TextNodes ----
+
+SwTxtFmtColl* SwDoc::CopyTxtColl( const SwTxtFmtColl& rColl )
+{
+ SwTxtFmtColl* pNewColl = FindTxtFmtCollByName( rColl.GetName() );
+ if( pNewColl )
+ return pNewColl;
+
+ // suche erstmal nach dem "Parent"
+ SwTxtFmtColl* pParent = pDfltTxtFmtColl;
+ if( pParent != rColl.DerivedFrom() )
+ pParent = CopyTxtColl( *(SwTxtFmtColl*)rColl.DerivedFrom() );
+
+
+//FEATURE::CONDCOLL
+ if( RES_CONDTXTFMTCOLL == rColl.Which() )
+ {
+ pNewColl = new SwConditionTxtFmtColl( GetAttrPool(), rColl.GetName(),
+ pParent);
+ pTxtFmtCollTbl->Insert( pNewColl, pTxtFmtCollTbl->Count() );
+ pNewColl->SetAuto( sal_False );
+ SetModified();
+
+ // Kopiere noch die Bedingungen
+ ((SwConditionTxtFmtColl*)pNewColl)->SetConditions(
+ ((SwConditionTxtFmtColl&)rColl).GetCondColls() );
+ }
+ else
+//FEATURE::CONDCOLL
+ pNewColl = MakeTxtFmtColl( rColl.GetName(), pParent );
+
+ // kopiere jetzt noch die Auto-Formate oder kopiere die Attribute
+ pNewColl->CopyAttrs( rColl, sal_True );
+
+ // setze noch den Outline-Level
+ //if( NO_NUMBERING != rColl.GetOutlineLevel() ) //#outline level,zhaojianwei
+ // pNewColl->SetOutlineLevel( rColl.GetOutlineLevel() );
+ if(rColl.IsAssignedToListLevelOfOutlineStyle())
+ pNewColl->AssignToListLevelOfOutlineStyle(rColl.GetAssignedOutlineStyleLevel());//<-end,zhaojianwei
+ //<-end
+ pNewColl->SetPoolFmtId( rColl.GetPoolFmtId() );
+ pNewColl->SetPoolHelpId( rColl.GetPoolHelpId() );
+
+ // HelpFile-Id immer auf dflt setzen !!
+ pNewColl->SetPoolHlpFileId( UCHAR_MAX );
+
+ if( &rColl.GetNextTxtFmtColl() != &rColl )
+ pNewColl->SetNextTxtFmtColl( *CopyTxtColl( rColl.GetNextTxtFmtColl() ));
+
+ // ggfs. die NumRule erzeugen
+ if( this != rColl.GetDoc() )
+ {
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pNewColl->GetItemState( RES_PARATR_NUMRULE,
+ sal_False, &pItem ))
+ {
+ const SwNumRule* pRule;
+ const String& rName = ((SwNumRuleItem*)pItem)->GetValue();
+ if( rName.Len() &&
+ 0 != ( pRule = rColl.GetDoc()->FindNumRulePtr( rName )) &&
+ !pRule->IsAutoRule() )
+ {
+ SwNumRule* pDestRule = FindNumRulePtr( rName );
+ if( pDestRule )
+ pDestRule->SetInvalidRule( sal_True );
+ else
+ MakeNumRule( rName, pRule );
+ }
+ }
+ }
+ return pNewColl;
+}
+
+// --- Kopiere GrafikNodes ----
+
+SwGrfFmtColl* SwDoc::CopyGrfColl( const SwGrfFmtColl& rColl )
+{
+ SwGrfFmtColl* pNewColl = FindGrfFmtCollByName( rColl.GetName() );
+ if( pNewColl )
+ return pNewColl;
+
+ // suche erstmal nach dem "Parent"
+ SwGrfFmtColl* pParent = pDfltGrfFmtColl;
+ if( pParent != rColl.DerivedFrom() )
+ pParent = CopyGrfColl( *(SwGrfFmtColl*)rColl.DerivedFrom() );
+
+ // falls nicht, so kopiere sie
+ pNewColl = MakeGrfFmtColl( rColl.GetName(), pParent );
+
+ // noch die Attribute kopieren
+ pNewColl->CopyAttrs( rColl );
+
+ pNewColl->SetPoolFmtId( rColl.GetPoolFmtId() );
+ pNewColl->SetPoolHelpId( rColl.GetPoolHelpId() );
+
+ // HelpFile-Id immer auf dflt setzen !!
+ pNewColl->SetPoolHlpFileId( UCHAR_MAX );
+
+ return pNewColl;
+}
+
+SwPageDesc* lcl_FindPageDesc( const SwPageDescs& rArr, const String& rName )
+{
+ for( sal_uInt16 n = rArr.Count(); n; )
+ {
+ SwPageDesc* pDesc = rArr[ --n ];
+ if( pDesc->GetName() == rName )
+ return pDesc;
+ }
+ return 0;
+}
+
+void SwDoc::CopyFmtArr( const SvPtrarr& rSourceArr,
+ SvPtrarr& rDestArr,
+ FNCopyFmt fnCopyFmt,
+ SwFmt& rDfltFmt )
+{
+ sal_uInt16 nSrc;
+ SwFmt* pSrc, *pDest;
+
+ // 1. Schritt alle Formate anlegen (das 0. ueberspringen - Default!)
+ for( nSrc = rSourceArr.Count(); nSrc > 1; )
+ {
+ pSrc = (SwFmt*)rSourceArr[ --nSrc ];
+ if( pSrc->IsDefault() || pSrc->IsAuto() )
+ continue;
+
+ if( 0 == FindFmtByName( rDestArr, pSrc->GetName() ) )
+ {
+ if( RES_CONDTXTFMTCOLL == pSrc->Which() )
+ MakeCondTxtFmtColl( pSrc->GetName(), (SwTxtFmtColl*)&rDfltFmt );
+ else
+ // --> OD 2005-01-13 #i40550#
+ (this->*fnCopyFmt)( pSrc->GetName(), &rDfltFmt, sal_False, sal_True );
+ // <--
+ }
+ }
+
+ // 2. Schritt alle Attribute kopieren, richtige Parents setzen
+ for( nSrc = rSourceArr.Count(); nSrc > 1; )
+ {
+ pSrc = (SwFmt*)rSourceArr[ --nSrc ];
+ if( pSrc->IsDefault() || pSrc->IsAuto() )
+ continue;
+
+ pDest = FindFmtByName( rDestArr, pSrc->GetName() );
+ pDest->SetAuto( sal_False );
+// pDest->ResetAllAttr();
+// pDest->CopyAttrs( *pSrc, sal_True ); // kopiere Attribute
+//JP 19.02.96: ist so wohl optimaler - loest ggfs. kein Modify aus!
+ pDest->DelDiffs( *pSrc );
+ // --> OD 2009-03-23 #i94285#
+ // copy existing <SwFmtPageDesc> instance, before copying attributes
+// pDest->SetFmtAttr( pSrc->GetAttrSet() ); // kopiere Attribute
+ //JP 18.08.98: Bug 55115 - copy PageDescAttribute in this case
+ const SfxPoolItem* pItem;
+ if( &GetAttrPool() != pSrc->GetAttrSet().GetPool() &&
+ SFX_ITEM_SET == pSrc->GetAttrSet().GetItemState(
+ RES_PAGEDESC, sal_False, &pItem ) &&
+ ((SwFmtPageDesc*)pItem)->GetPageDesc() )
+ {
+ SwFmtPageDesc aPageDesc( *(SwFmtPageDesc*)pItem );
+ const String& rNm = aPageDesc.GetPageDesc()->GetName();
+ SwPageDesc* pPageDesc = ::lcl_FindPageDesc( aPageDescs, rNm );
+ if( !pPageDesc )
+ {
+ pPageDesc = aPageDescs[ MakePageDesc( rNm ) ];
+ }
+ pPageDesc->Add( &aPageDesc );
+// pDest->SetFmtAttr( aPageDesc );
+ SwAttrSet aTmpAttrSet( pSrc->GetAttrSet() );
+ aTmpAttrSet.Put( aPageDesc );
+ pDest->SetFmtAttr( aTmpAttrSet );
+ }
+ else
+ {
+ pDest->SetFmtAttr( pSrc->GetAttrSet() );
+ }
+ // <--
+
+ pDest->SetPoolFmtId( pSrc->GetPoolFmtId() );
+ pDest->SetPoolHelpId( pSrc->GetPoolHelpId() );
+
+ // HelpFile-Id immer auf dflt setzen !!
+ pDest->SetPoolHlpFileId( UCHAR_MAX );
+
+ if( pSrc->DerivedFrom() )
+ pDest->SetDerivedFrom( FindFmtByName( rDestArr,
+ pSrc->DerivedFrom()->GetName() ) );
+ if( RES_TXTFMTCOLL == pSrc->Which() ||
+ RES_CONDTXTFMTCOLL == pSrc->Which() )
+ {
+ SwTxtFmtColl* pSrcColl = (SwTxtFmtColl*)pSrc,
+ * pDstColl = (SwTxtFmtColl*)pDest;
+ if( &pSrcColl->GetNextTxtFmtColl() != pSrcColl )
+ pDstColl->SetNextTxtFmtColl( *(SwTxtFmtColl*)FindFmtByName(
+ rDestArr, pSrcColl->GetNextTxtFmtColl().GetName() ) );
+
+ // setze noch den Outline-Level
+ //if( NO_NUMBERING != pSrcColl->GetOutlineLevel() ) //#outline level,zhaojianwei
+ // pDstColl->SetOutlineLevel( pSrcColl->GetOutlineLevel() );
+ if(pSrcColl->IsAssignedToListLevelOfOutlineStyle())
+ pDstColl->AssignToListLevelOfOutlineStyle(pSrcColl->GetAssignedOutlineStyleLevel());//<-end,zhaojianwei
+ //<-end
+
+//FEATURE::CONDCOLL
+ if( RES_CONDTXTFMTCOLL == pSrc->Which() )
+ // Kopiere noch die Bedingungen
+ // aber erst die alten loeschen!
+ ((SwConditionTxtFmtColl*)pDstColl)->SetConditions(
+ ((SwConditionTxtFmtColl*)pSrc)->GetCondColls() );
+//FEATURE::CONDCOLL
+ }
+ }
+}
+
+void SwDoc::CopyPageDescHeaderFooterImpl( bool bCpyHeader,
+ const SwFrmFmt& rSrcFmt, SwFrmFmt& rDestFmt )
+{
+ // jetzt noch Header-/Footer-Attribute richtig behandeln
+ // Contenten Nodes Dokumentuebergreifend kopieren!
+ sal_uInt16 nAttr = static_cast<sal_uInt16>( bCpyHeader ? RES_HEADER : RES_FOOTER );
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET != rSrcFmt.GetAttrSet().GetItemState( nAttr, sal_False, &pItem ))
+ return ;
+
+ // Im Header steht noch der Verweis auf das Format aus dem
+ // anderen Document!!
+ SfxPoolItem* pNewItem = pItem->Clone();
+
+ SwFrmFmt* pOldFmt;
+ if( bCpyHeader )
+ pOldFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
+ else
+ pOldFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
+
+ if( pOldFmt )
+ {
+ SwFrmFmt* pNewFmt = new SwFrmFmt( GetAttrPool(), "CpyDesc",
+ GetDfltFrmFmt() );
+ pNewFmt->CopyAttrs( *pOldFmt, sal_True );
+
+ if( SFX_ITEM_SET == pNewFmt->GetAttrSet().GetItemState(
+ RES_CNTNT, sal_False, &pItem ))
+ {
+ SwFmtCntnt* pCntnt = (SwFmtCntnt*)pItem;
+ if( pCntnt->GetCntntIdx() )
+ {
+ SwNodeIndex aTmpIdx( GetNodes().GetEndOfAutotext() );
+ const SwNodes& rSrcNds = rSrcFmt.GetDoc()->GetNodes();
+ SwStartNode* pSttNd = GetNodes().MakeEmptySection( aTmpIdx,
+ bCpyHeader
+ ? SwHeaderStartNode
+ : SwFooterStartNode );
+ const SwNode& rCSttNd = pCntnt->GetCntntIdx()->GetNode();
+ SwNodeRange aRg( rCSttNd, 0, *rCSttNd.EndOfSectionNode() );
+ aTmpIdx = *pSttNd->EndOfSectionNode();
+ rSrcNds._Copy( aRg, aTmpIdx );
+ aTmpIdx = *pSttNd;
+ rSrcFmt.GetDoc()->CopyFlyInFlyImpl( aRg, 0, aTmpIdx );
+ pNewFmt->SetFmtAttr( SwFmtCntnt( pSttNd ));
+ }
+ else
+ pNewFmt->ResetFmtAttr( RES_CNTNT );
+ }
+ if( bCpyHeader )
+ pNewFmt->Add( (SwFmtHeader*)pNewItem );
+ else
+ pNewFmt->Add( (SwFmtFooter*)pNewItem );
+ rDestFmt.SetFmtAttr( *pNewItem );
+ }
+ delete pNewItem;
+}
+
+void SwDoc::CopyPageDesc( const SwPageDesc& rSrcDesc, SwPageDesc& rDstDesc,
+ sal_Bool bCopyPoolIds )
+{
+ sal_Bool bNotifyLayout = sal_False;
+
+ rDstDesc.SetLandscape( rSrcDesc.GetLandscape() );
+ rDstDesc.SetNumType( rSrcDesc.GetNumType() );
+ if( rDstDesc.ReadUseOn() != rSrcDesc.ReadUseOn() )
+ {
+ rDstDesc.WriteUseOn( rSrcDesc.ReadUseOn() );
+ bNotifyLayout = sal_True;
+ }
+
+ if( bCopyPoolIds )
+ {
+ rDstDesc.SetPoolFmtId( rSrcDesc.GetPoolFmtId() );
+ rDstDesc.SetPoolHelpId( rSrcDesc.GetPoolHelpId() );
+ // HelpFile-Id immer auf dflt setzen !!
+ rDstDesc.SetPoolHlpFileId( UCHAR_MAX );
+ }
+
+ if( rSrcDesc.GetFollow() != &rSrcDesc )
+ {
+ SwPageDesc* pFollow = ::lcl_FindPageDesc( aPageDescs,
+ rSrcDesc.GetFollow()->GetName() );
+ if( !pFollow )
+ {
+ // dann mal kopieren
+ sal_uInt16 nPos = MakePageDesc( rSrcDesc.GetFollow()->GetName() );
+ pFollow = aPageDescs[ nPos ];
+ CopyPageDesc( *rSrcDesc.GetFollow(), *pFollow );
+ }
+ rDstDesc.SetFollow( pFollow );
+ bNotifyLayout = sal_True;
+ }
+
+ // die Header/Footer-Attribute werden gesondert kopiert, die Content-
+ // Sections muessen vollstaendig mitgenommen werden!
+ {
+ SfxItemSet aAttrSet( rSrcDesc.GetMaster().GetAttrSet() );
+ aAttrSet.ClearItem( RES_HEADER );
+ aAttrSet.ClearItem( RES_FOOTER );
+
+ rDstDesc.GetMaster().DelDiffs( aAttrSet );
+ rDstDesc.GetMaster().SetFmtAttr( aAttrSet );
+
+ aAttrSet.ClearItem();
+ aAttrSet.Put( rSrcDesc.GetLeft().GetAttrSet() );
+ aAttrSet.ClearItem( RES_HEADER );
+ aAttrSet.ClearItem( RES_FOOTER );
+
+ rDstDesc.GetLeft().DelDiffs( aAttrSet );
+ rDstDesc.GetLeft().SetFmtAttr( aAttrSet );
+ }
+
+ CopyHeader( rSrcDesc.GetMaster(), rDstDesc.GetMaster() );
+ CopyFooter( rSrcDesc.GetMaster(), rDstDesc.GetMaster() );
+ if( !rDstDesc.IsHeaderShared() )
+ CopyHeader( rSrcDesc.GetLeft(), rDstDesc.GetLeft() );
+ else
+ rDstDesc.GetLeft().SetFmtAttr( rDstDesc.GetMaster().GetHeader() );
+
+ if( !rDstDesc.IsFooterShared() )
+ CopyFooter( rSrcDesc.GetLeft(), rDstDesc.GetLeft() );
+ else
+ rDstDesc.GetLeft().SetFmtAttr( rDstDesc.GetMaster().GetFooter() );
+
+ if( bNotifyLayout && GetRootFrm() )
+ //Layot benachrichtigen!
+ GetRootFrm()->CheckPageDescs( (SwPageFrm*)GetRootFrm()->Lower() );
+
+ //Wenn sich FussnotenInfo veraendert, so werden die Seiten
+ //angetriggert.
+ if( !(rDstDesc.GetFtnInfo() == rSrcDesc.GetFtnInfo()) )
+ {
+ rDstDesc.SetFtnInfo( rSrcDesc.GetFtnInfo() );
+ SwMsgPoolItem aInfo( RES_PAGEDESC_FTNINFO );
+ {
+ SwClientIter aIter( rDstDesc.GetMaster() );
+ for( SwClient* pLast = aIter.First(TYPE(SwFrm)); pLast;
+ pLast = aIter.Next() )
+ pLast->Modify( &aInfo, 0 );
+ }
+ {
+ SwClientIter aIter( rDstDesc.GetLeft() );
+ for( SwClient* pLast = aIter.First(TYPE(SwFrm)); pLast;
+ pLast = aIter.Next() )
+ pLast->Modify( &aInfo, 0 );
+ }
+ }
+}
+
+void SwDoc::ReplaceStyles( SwDoc& rSource )
+{
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ CopyFmtArr( *rSource.pCharFmtTbl, *pCharFmtTbl,
+ &SwDoc::_MakeCharFmt, *pDfltCharFmt );
+ CopyFmtArr( *rSource.pFrmFmtTbl, *pFrmFmtTbl,
+ &SwDoc::_MakeFrmFmt, *pDfltFrmFmt );
+ CopyFmtArr( *rSource.pTxtFmtCollTbl, *pTxtFmtCollTbl,
+ &SwDoc::_MakeTxtFmtColl, *pDfltTxtFmtColl );
+
+ // und jetzt noch die Seiten-Vorlagen
+ sal_uInt16 nCnt = rSource.aPageDescs.Count();
+ if( nCnt )
+ {
+ // ein anderes Doc -> Numberformatter muessen gemergt werden
+ SwTblNumFmtMerge aTNFM( rSource, *this );
+
+ // 1. Schritt alle Formate anlegen (das 0. ueberspringen - Default!)
+ while( nCnt )
+ {
+ SwPageDesc *pSrc = rSource.aPageDescs[ --nCnt ];
+ if( 0 == ::lcl_FindPageDesc( aPageDescs, pSrc->GetName() ) )
+ MakePageDesc( pSrc->GetName() );
+ }
+
+ // 2. Schritt alle Attribute kopieren, richtige Parents setzen
+ for( nCnt = rSource.aPageDescs.Count(); nCnt; )
+ {
+ SwPageDesc *pSrc = rSource.aPageDescs[ --nCnt ];
+ CopyPageDesc( *pSrc, *::lcl_FindPageDesc( aPageDescs, pSrc->GetName() ));
+ }
+ }
+
+ //JP 08.04.99: und dann sind da noch die Numerierungs-Vorlagen
+ nCnt = rSource.GetNumRuleTbl().Count();
+ if( nCnt )
+ {
+ const SwNumRuleTbl& rArr = rSource.GetNumRuleTbl();
+ for( sal_uInt16 n = 0; n < nCnt; ++n )
+ {
+ const SwNumRule& rR = *rArr[ n ];
+ if( !rR.IsAutoRule() )
+ {
+ SwNumRule* pNew = FindNumRulePtr( rR.GetName());
+ if( pNew )
+ pNew->CopyNumRule( this, rR );
+ else
+ MakeNumRule( rR.GetName(), &rR );
+ }
+ }
+ }
+
+ if (undoGuard.UndoWasEnabled())
+ {
+ // nodes array was modified!
+ GetIDocumentUndoRedo().DelAllUndoObj();
+ }
+
+ SetModified();
+}
+
+SwFmt* SwDoc::FindFmtByName( const SvPtrarr& rFmtArr,
+ const String& rName ) const
+{
+ SwFmt* pFnd = 0;
+ for( sal_uInt16 n = 0; n < rFmtArr.Count(); n++ )
+ {
+ // ist die Vorlage schon im Doc vorhanden ??
+ if( ((SwFmt*)rFmtArr[n])->GetName() == rName )
+ {
+ pFnd = (SwFmt*)rFmtArr[n];
+ break;
+ }
+ }
+ return pFnd;
+}
+
+void SwDoc::MoveLeftMargin( const SwPaM& rPam, sal_Bool bRight, sal_Bool bModulus )
+{
+ SwHistory* pHistory = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoMoveLeftMargin* pUndo = new SwUndoMoveLeftMargin( rPam, bRight,
+ bModulus );
+ pHistory = &pUndo->GetHistory();
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+
+ const SvxTabStopItem& rTabItem = (SvxTabStopItem&)GetDefault( RES_PARATR_TABSTOP );
+ sal_uInt16 nDefDist = rTabItem.Count() ?
+ static_cast<sal_uInt16>(rTabItem[0].GetTabPos()) : 1134;
+ const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End();
+ SwNodeIndex aIdx( rStt.nNode );
+ while( aIdx <= rEnd.nNode )
+ {
+ SwTxtNode* pTNd = aIdx.GetNode().GetTxtNode();
+ if( pTNd )
+ {
+ SvxLRSpaceItem aLS( (SvxLRSpaceItem&)pTNd->SwCntntNode::GetAttr( RES_LR_SPACE ) );
+
+ // --> FME 2008-09-16 #i93873# See also lcl_MergeListLevelIndentAsLRSpaceItem in thints.cxx
+ if ( pTNd->AreListLevelIndentsApplicable() )
+ {
+ const SwNumRule* pRule = pTNd->GetNumRule();
+ if ( pRule )
+ {
+ const int nListLevel = pTNd->GetActualListLevel();
+ if ( nListLevel >= 0 )
+ {
+ const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(nListLevel));
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aLS.SetTxtLeft( rFmt.GetIndentAt() );
+ aLS.SetTxtFirstLineOfst( static_cast<short>(rFmt.GetFirstLineIndent()) );
+ }
+ }
+ }
+ }
+
+ long nNext = aLS.GetTxtLeft();
+ if( bModulus )
+ nNext = ( nNext / nDefDist ) * nDefDist;
+
+ if( bRight )
+ nNext += nDefDist;
+ else
+ nNext -= nDefDist;
+
+ aLS.SetTxtLeft( nNext );
+
+ SwRegHistory aRegH( pTNd, *pTNd, pHistory );
+ pTNd->SetAttr( aLS );
+ }
+ aIdx++;
+ }
+ SetModified();
+}
+
+sal_Bool SwDoc::DontExpandFmt( const SwPosition& rPos, sal_Bool bFlag )
+{
+ sal_Bool bRet = sal_False;
+ SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ if( pTxtNd )
+ {
+ bRet = pTxtNd->DontExpandFmt( rPos.nContent, bFlag );
+ if( bRet && GetIDocumentUndoRedo().DoesUndo() )
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoDontExpandFmt(rPos) );
+ }
+ }
+ return bRet;
+}
+
+SwTableBoxFmt* SwDoc::MakeTableBoxFmt()
+{
+ SwTableBoxFmt* pFmt = new SwTableBoxFmt( GetAttrPool(), aEmptyStr,
+ pDfltFrmFmt );
+ SetModified();
+ return pFmt;
+}
+
+SwTableLineFmt* SwDoc::MakeTableLineFmt()
+{
+ SwTableLineFmt* pFmt = new SwTableLineFmt( GetAttrPool(), aEmptyStr,
+ pDfltFrmFmt );
+ SetModified();
+ return pFmt;
+}
+
+void SwDoc::_CreateNumberFormatter()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLog, "SW", "JP93722", "SwDoc::_CreateNumberFormatter" );
+
+ ASSERT( !pNumberFormatter, "ist doch schon vorhanden" );
+
+
+ LanguageType eLang = LANGUAGE_SYSTEM; //System::GetLanguage();
+/* ((const SvxLanguageItem&)GetAttrPool().
+ GetDefaultItem( RES_CHRATR_LANGUAGE )).GetLanguage();
+*/
+ Reference< XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
+ pNumberFormatter = new SvNumberFormatter( xMSF, eLang );
+ pNumberFormatter->SetEvalDateFormat( NF_EVALDATEFORMAT_FORMAT_INTL );
+ pNumberFormatter->SetYear2000(static_cast<sal_uInt16>(::utl::MiscCfg().GetYear2000()));
+
+}
+
+SwTblNumFmtMerge::SwTblNumFmtMerge( const SwDoc& rSrc, SwDoc& rDest )
+ : pNFmt( 0 )
+{
+ // ein anderes Doc -> Numberformatter muessen gemergt werden
+ SvNumberFormatter* pN;
+ if( &rSrc != &rDest && 0 != ( pN = ((SwDoc&)rSrc).GetNumberFormatter( sal_False ) ))
+ ( pNFmt = rDest.GetNumberFormatter( sal_True ))->MergeFormatter( *pN );
+
+ if( &rSrc != &rDest )
+ ((SwGetRefFieldType*)rSrc.GetSysFldType( RES_GETREFFLD ))->
+ MergeWithOtherDoc( rDest );
+}
+
+SwTblNumFmtMerge::~SwTblNumFmtMerge()
+{
+ if( pNFmt )
+ pNFmt->ClearMergeTable();
+}
+
+
+void SwDoc::SetTxtFmtCollByAutoFmt( const SwPosition& rPos, sal_uInt16 nPoolId,
+ const SfxItemSet* pSet )
+{
+ SwPaM aPam( rPos );
+ SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
+
+ if( mbIsAutoFmtRedline && pTNd )
+ {
+ // dann das Redline Object anlegen
+ const SwTxtFmtColl& rColl = *pTNd->GetTxtColl();
+ SwRedline* pRedl = new SwRedline( nsRedlineType_t::REDLINE_FMTCOLL, aPam );
+ pRedl->SetMark();
+
+ // interressant sind nur die Items, die vom Set NICHT wieder
+ // in den Node gesetzt werden. Also muss man die Differenz nehmen
+ SwRedlineExtraData_FmtColl aExtraData( rColl.GetName(),
+ rColl.GetPoolFmtId() );
+ if( pSet && pTNd->HasSwAttrSet() )
+ {
+ SfxItemSet aTmp( *pTNd->GetpSwAttrSet() );
+ aTmp.Differentiate( *pSet );
+ // das Adjust Item behalten wir extra
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pTNd->GetpSwAttrSet()->GetItemState(
+ RES_PARATR_ADJUST, sal_False, &pItem ))
+ aTmp.Put( *pItem );
+ aExtraData.SetItemSet( aTmp );
+ }
+ pRedl->SetExtraData( &aExtraData );
+
+// !!!!!!!!! Undo fehlt noch !!!!!!!!!!!!!!!!!!
+ AppendRedline( pRedl, true );
+ }
+
+ SetTxtFmtColl( aPam, GetTxtCollFromPool( nPoolId ) );
+
+ if( pSet && pTNd && pSet->Count() )
+ {
+ aPam.SetMark();
+ aPam.GetMark()->nContent.Assign( pTNd, pTNd->GetTxt().Len() );
+ InsertItemSet( aPam, *pSet, 0 );
+ }
+}
+
+void SwDoc::SetFmtItemByAutoFmt( const SwPaM& rPam, const SfxItemSet& rSet )
+{
+ SwTxtNode* pTNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
+
+ RedlineMode_t eOld = GetRedlineMode();
+
+ if( mbIsAutoFmtRedline && pTNd )
+ {
+ // dann das Redline Object anlegen
+ SwRedline* pRedl = new SwRedline( nsRedlineType_t::REDLINE_FORMAT, rPam );
+ if( !pRedl->HasMark() )
+ pRedl->SetMark();
+
+ // interressant sind nur die Items, die vom Set NICHT wieder
+ // in den Node gesetzt werden. Also muss man die Differenz nehmen
+ SwRedlineExtraData_Format aExtraData( rSet );
+
+/*
+ if( pSet && pTNd->HasSwAttrSet() )
+ {
+ SfxItemSet aTmp( *pTNd->GetpSwAttrSet() );
+ aTmp.Differentiate( *pSet );
+ // das Adjust Item behalten wir extra
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pTNd->GetpSwAttrSet()->GetItemState(
+ RES_PARATR_ADJUST, sal_False, &pItem ))
+ aTmp.Put( *pItem );
+ aExtraData.SetItemSet( aTmp );
+ }
+*/
+ pRedl->SetExtraData( &aExtraData );
+
+// !!!!!!!!! Undo fehlt noch !!!!!!!!!!!!!!!!!!
+ AppendRedline( pRedl, true );
+
+ SetRedlineMode_intern( (RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
+ }
+
+ InsertItemSet( rPam, rSet, nsSetAttrMode::SETATTR_DONTEXPAND );
+ SetRedlineMode_intern( eOld );
+}
+
+void SwDoc::ChgFmt(SwFmt & rFmt, const SfxItemSet & rSet)
+{
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // copying <rSet> to <aSet>
+ SfxItemSet aSet(rSet);
+ // remove from <aSet> all items, which are already set at the format
+ aSet.Differentiate(rFmt.GetAttrSet());
+ // <aSet> contains now all *new* items for the format
+
+ // copying current format item set to <aOldSet>
+ SfxItemSet aOldSet(rFmt.GetAttrSet());
+ // insert new items into <aOldSet>
+ aOldSet.Put(aSet);
+ // invalidate all new items in <aOldSet> in order to clear these items,
+ // if the undo action is triggered.
+ {
+ SfxItemIter aIter(aSet);
+
+ const SfxPoolItem * pItem = aIter.FirstItem();
+ while (pItem != NULL)
+ {
+ aOldSet.InvalidateItem(pItem->Which());
+
+ pItem = aIter.NextItem();
+ }
+ }
+
+ SwUndo * pUndo = new SwUndoFmtAttr(aOldSet, rFmt);
+
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ rFmt.SetFmtAttr(rSet);
+}
+
+void SwDoc::RenameFmt(SwFmt & rFmt, const String & sNewName,
+ sal_Bool bBroadcast)
+{
+ SfxStyleFamily eFamily = SFX_STYLE_FAMILY_ALL;
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo = NULL;
+
+ switch (rFmt.Which())
+ {
+ case RES_CHRFMT:
+ pUndo = new SwUndoRenameCharFmt(rFmt.GetName(), sNewName, this);
+ eFamily = SFX_STYLE_FAMILY_PARA;
+ break;
+ case RES_TXTFMTCOLL:
+ pUndo = new SwUndoRenameFmtColl(rFmt.GetName(), sNewName, this);
+ eFamily = SFX_STYLE_FAMILY_CHAR;
+ break;
+ case RES_FRMFMT:
+ pUndo = new SwUndoRenameFrmFmt(rFmt.GetName(), sNewName, this);
+ eFamily = SFX_STYLE_FAMILY_FRAME;
+ break;
+
+ default:
+ break;
+ }
+
+ if (pUndo)
+ {
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ }
+
+ rFmt.SetName(sNewName);
+
+ if (bBroadcast)
+ BroadcastStyleOperation(sNewName, eFamily, SFX_STYLESHEET_MODIFIED);
+}
+
+// --> OD 2006-09-27 #i69627#
+namespace docfunc
+{
+ bool HasOutlineStyleToBeWrittenAsNormalListStyle( SwDoc& rDoc )
+ {
+ // If a parent paragraph style of one of the parargraph styles, which
+ // are assigned to the list levels of the outline style, has a list style
+ // set or inherits a list style from its parent style, the outline style
+ // has to be written as a normal list style to the OpenDocument file
+ // format or the OpenOffice.org file format.
+ bool bRet( false );
+
+ const SwTxtFmtColls* pTxtFmtColls( rDoc.GetTxtFmtColls() );
+ if ( pTxtFmtColls )
+ {
+ const sal_uInt16 nCount = pTxtFmtColls->Count();
+ for ( sal_uInt16 i = 0; i < nCount; ++i )
+ {
+ SwTxtFmtColl* pTxtFmtColl = (*pTxtFmtColls)[i];
+
+ if ( pTxtFmtColl->IsDefault() ||
+ // pTxtFmtColl->GetOutlineLevel() == NO_NUMBERING ) //#outline level,zhaojianwei
+ ! pTxtFmtColl->IsAssignedToListLevelOfOutlineStyle() ) //<-end,zhaojianwei
+ {
+ continue;
+ }
+
+ const SwTxtFmtColl* pParentTxtFmtColl =
+ dynamic_cast<const SwTxtFmtColl*>( pTxtFmtColl->DerivedFrom());
+ if ( !pParentTxtFmtColl )
+ continue;
+
+ if ( SFX_ITEM_SET == pParentTxtFmtColl->GetItemState( RES_PARATR_NUMRULE ) )
+ {
+ // --> OD 2009-11-12 #i106218#
+ // consider that the outline style is set
+ const SwNumRuleItem& rDirectItem = pParentTxtFmtColl->GetNumRule();
+ if ( rDirectItem.GetValue() != rDoc.GetOutlineNumRule()->GetName() )
+ {
+ bRet = true;
+ break;
+ }
+ // <--
+ }
+ }
+
+ }
+ return bRet;
+ }
+}
+// <--
diff --git a/sw/source/core/doc/docftn.cxx b/sw/source/core/doc/docftn.cxx
new file mode 100644
index 000000000000..80798546d041
--- /dev/null
+++ b/sw/source/core/doc/docftn.cxx
@@ -0,0 +1,505 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <ftnidx.hxx>
+#include <rootfrm.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <pam.hxx>
+#include <pagedesc.hxx>
+#include <charfmt.hxx>
+#include <UndoAttribute.hxx>
+#include <hints.hxx>
+#include <rolbck.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <ndtxt.hxx>
+#include <poolfmt.hxx>
+#include <ftninfo.hxx>
+
+/*********************** SwFtnInfo ***************************/
+
+SwEndNoteInfo& SwEndNoteInfo::operator=(const SwEndNoteInfo& rInfo)
+{
+ if( rInfo.GetFtnTxtColl() )
+ rInfo.GetFtnTxtColl()->Add(this);
+ else if ( pRegisteredIn)
+ pRegisteredIn->Remove(this);
+
+ if ( rInfo.aPageDescDep.GetRegisteredIn() )
+ ((SwModify*)rInfo.aPageDescDep.GetRegisteredIn())->Add( &aPageDescDep );
+ else if ( aPageDescDep.GetRegisteredIn() )
+ ((SwModify*)aPageDescDep.GetRegisteredIn())->Remove( &aPageDescDep );
+
+ if ( rInfo.aCharFmtDep.GetRegisteredIn() )
+ ((SwModify*)rInfo.aCharFmtDep.GetRegisteredIn())->Add( &aCharFmtDep );
+ else if ( aCharFmtDep.GetRegisteredIn() )
+ ((SwModify*)aCharFmtDep.GetRegisteredIn())->Remove( &aCharFmtDep );
+
+ if ( rInfo.aAnchorCharFmtDep.GetRegisteredIn() )
+ ((SwModify*)rInfo.aAnchorCharFmtDep.GetRegisteredIn())->Add(
+ &aAnchorCharFmtDep );
+ else if( aAnchorCharFmtDep.GetRegisteredIn() )
+ ((SwModify*)aAnchorCharFmtDep.GetRegisteredIn())->Remove(
+ &aAnchorCharFmtDep );
+
+ aFmt = rInfo.aFmt;
+ nFtnOffset = rInfo.nFtnOffset;
+ m_bEndNote = rInfo.m_bEndNote;
+ sPrefix = rInfo.sPrefix;
+ sSuffix = rInfo.sSuffix;
+ return *this;
+}
+
+
+sal_Bool SwEndNoteInfo::operator==( const SwEndNoteInfo& rInfo ) const
+{
+ return aPageDescDep.GetRegisteredIn() ==
+ rInfo.aPageDescDep.GetRegisteredIn() &&
+ aCharFmtDep.GetRegisteredIn() ==
+ rInfo.aCharFmtDep.GetRegisteredIn() &&
+ aAnchorCharFmtDep.GetRegisteredIn() ==
+ rInfo.aAnchorCharFmtDep.GetRegisteredIn() &&
+ GetFtnTxtColl() == rInfo.GetFtnTxtColl() &&
+ aFmt.GetNumberingType() == rInfo.aFmt.GetNumberingType() &&
+ nFtnOffset == rInfo.nFtnOffset &&
+ m_bEndNote == rInfo.m_bEndNote &&
+ sPrefix == rInfo.sPrefix &&
+ sSuffix == rInfo.sSuffix;
+}
+
+
+SwEndNoteInfo::SwEndNoteInfo(const SwEndNoteInfo& rInfo) :
+ SwClient( rInfo.GetFtnTxtColl() ),
+ aPageDescDep( this, 0 ),
+ aCharFmtDep( this, 0 ),
+ aAnchorCharFmtDep( this, 0 ),
+ sPrefix( rInfo.sPrefix ),
+ sSuffix( rInfo.sSuffix ),
+ m_bEndNote( true ),
+ aFmt( rInfo.aFmt ),
+ nFtnOffset( rInfo.nFtnOffset )
+{
+ if( rInfo.GetPageDescDep()->GetRegisteredIn() )
+ ((SwModify*)rInfo.GetPageDescDep()->GetRegisteredIn())->Add( &aPageDescDep );
+
+ if( rInfo.aCharFmtDep.GetRegisteredIn() )
+ ((SwModify*)rInfo.aCharFmtDep.GetRegisteredIn())->Add( &aCharFmtDep );
+
+ if( rInfo.aAnchorCharFmtDep.GetRegisteredIn() )
+ ((SwModify*)rInfo.aAnchorCharFmtDep.GetRegisteredIn())->Add(
+ &aAnchorCharFmtDep );
+}
+
+SwEndNoteInfo::SwEndNoteInfo(SwTxtFmtColl *pFmt) :
+ SwClient(pFmt),
+ aPageDescDep( this, 0 ),
+ aCharFmtDep( this, 0 ),
+ aAnchorCharFmtDep( this, 0 ),
+ m_bEndNote( true ),
+ nFtnOffset( 0 )
+{
+ aFmt.SetNumberingType(SVX_NUM_ROMAN_LOWER);
+}
+
+SwPageDesc *SwEndNoteInfo::GetPageDesc( SwDoc &rDoc ) const
+{
+ if ( !aPageDescDep.GetRegisteredIn() )
+ {
+ SwPageDesc *pDesc = rDoc.GetPageDescFromPool( static_cast<sal_uInt16>(
+ m_bEndNote ? RES_POOLPAGE_ENDNOTE : RES_POOLPAGE_FOOTNOTE ) );
+ pDesc->Add( &((SwClient&)aPageDescDep) );
+ }
+ return (SwPageDesc*)aPageDescDep.GetRegisteredIn();
+}
+
+void SwEndNoteInfo::ChgPageDesc( SwPageDesc *pDesc )
+{
+ pDesc->Add( &((SwClient&)aPageDescDep) );
+}
+
+void SwEndNoteInfo::SetFtnTxtColl(SwTxtFmtColl& rFmt)
+{
+ rFmt.Add(this);
+}
+
+SwCharFmt* SwEndNoteInfo::GetCharFmt(SwDoc &rDoc) const
+{
+ if ( !aCharFmtDep.GetRegisteredIn() )
+ {
+ SwCharFmt* pFmt = rDoc.GetCharFmtFromPool( static_cast<sal_uInt16>(
+ m_bEndNote ? RES_POOLCHR_ENDNOTE : RES_POOLCHR_FOOTNOTE ) );
+ pFmt->Add( &((SwClient&)aCharFmtDep) );
+ }
+ return (SwCharFmt*)aCharFmtDep.GetRegisteredIn();
+}
+
+void SwEndNoteInfo::SetCharFmt( SwCharFmt* pChFmt )
+{
+ DBG_ASSERT(pChFmt, "kein CharFmt?");
+ pChFmt->Add( &((SwClient&)aCharFmtDep) );
+}
+
+SwCharFmt* SwEndNoteInfo::GetAnchorCharFmt(SwDoc &rDoc) const
+{
+ if( !aAnchorCharFmtDep.GetRegisteredIn() )
+ {
+ SwCharFmt* pFmt = rDoc.GetCharFmtFromPool( static_cast<sal_uInt16>(
+ m_bEndNote ? RES_POOLCHR_ENDNOTE_ANCHOR : RES_POOLCHR_FOOTNOTE_ANCHOR ) );
+ pFmt->Add( &((SwClient&)aAnchorCharFmtDep) );
+ }
+ return (SwCharFmt*)aAnchorCharFmtDep.GetRegisteredIn();
+}
+
+void SwEndNoteInfo::SetAnchorCharFmt( SwCharFmt* pChFmt )
+{
+ DBG_ASSERT(pChFmt, "kein CharFmt?");
+ pChFmt->Add( &((SwClient&)aAnchorCharFmtDep) );
+}
+
+void SwEndNoteInfo::Modify( SfxPoolItem* pOld, SfxPoolItem* pNew )
+{
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
+
+ if( RES_ATTRSET_CHG == nWhich ||
+ RES_FMT_CHG == nWhich )
+ {
+ SwDoc* pDoc;
+ if( aCharFmtDep.GetRegisteredIn() )
+ pDoc = ((SwCharFmt*)aCharFmtDep.GetRegisteredIn())->GetDoc();
+ else
+ pDoc = ((SwCharFmt*)aAnchorCharFmtDep.GetRegisteredIn())->GetDoc();
+ SwFtnIdxs& rFtnIdxs = pDoc->GetFtnIdxs();
+ for( sal_uInt16 nPos = 0; nPos < rFtnIdxs.Count(); ++nPos )
+ {
+ SwTxtFtn *pTxtFtn = rFtnIdxs[ nPos ];
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if ( rFtn.IsEndNote() == m_bEndNote )
+ {
+ pTxtFtn->SetNumber( rFtn.GetNumber(), &rFtn.GetNumStr());
+ }
+ }
+ }
+ else
+ SwClient::Modify( pOld, pNew );
+}
+
+SwFtnInfo& SwFtnInfo::operator=(const SwFtnInfo& rInfo)
+{
+ SwEndNoteInfo::operator=(rInfo);
+ aQuoVadis = rInfo.aQuoVadis;
+ aErgoSum = rInfo.aErgoSum;
+ ePos = rInfo.ePos;
+ eNum = rInfo.eNum;
+ return *this;
+}
+
+
+sal_Bool SwFtnInfo::operator==( const SwFtnInfo& rInfo ) const
+{
+ return ePos == rInfo.ePos &&
+ eNum == rInfo.eNum &&
+ SwEndNoteInfo::operator==(rInfo) &&
+ aQuoVadis == rInfo.aQuoVadis &&
+ aErgoSum == rInfo.aErgoSum;
+}
+
+
+SwFtnInfo::SwFtnInfo(const SwFtnInfo& rInfo) :
+ SwEndNoteInfo( rInfo ),
+ aQuoVadis( rInfo.aQuoVadis ),
+ aErgoSum( rInfo.aErgoSum ),
+ ePos( rInfo.ePos ),
+ eNum( rInfo.eNum )
+{
+ m_bEndNote = false;
+}
+
+SwFtnInfo::SwFtnInfo(SwTxtFmtColl *pFmt) :
+ SwEndNoteInfo( pFmt ),
+ ePos( FTNPOS_PAGE ),
+ eNum( FTNNUM_DOC )
+{
+ aFmt.SetNumberingType(SVX_NUM_ARABIC);
+ m_bEndNote = false;
+}
+
+/*********************** SwDoc ***************************/
+
+
+void SwDoc::SetFtnInfo(const SwFtnInfo& rInfo)
+{
+ if( !(GetFtnInfo() == rInfo) )
+ {
+ const SwFtnInfo &rOld = GetFtnInfo();
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoFootNoteInfo(rOld) );
+ }
+
+ sal_Bool bFtnPos = rInfo.ePos != rOld.ePos;
+ sal_Bool bFtnDesc = rOld.ePos == FTNPOS_CHAPTER &&
+ rInfo.GetPageDesc( *this ) != rOld.GetPageDesc( *this );
+ sal_Bool bExtra = rInfo.aQuoVadis != rOld.aQuoVadis ||
+ rInfo.aErgoSum != rOld.aErgoSum ||
+ rInfo.aFmt.GetNumberingType() != rOld.aFmt.GetNumberingType() ||
+ rInfo.GetPrefix() != rOld.GetPrefix() ||
+ rInfo.GetSuffix() != rOld.GetSuffix();
+ SwCharFmt *pOldChrFmt = rOld.GetCharFmt( *this ),
+ *pNewChrFmt = rInfo.GetCharFmt( *this );
+ sal_Bool bFtnChrFmts = pOldChrFmt != pNewChrFmt;
+
+ *pFtnInfo = rInfo;
+
+ if ( GetRootFrm() )
+ {
+ if ( bFtnPos )
+ GetRootFrm()->RemoveFtns();
+ else
+ {
+ GetRootFrm()->UpdateFtnNums();
+ if ( bFtnDesc )
+ GetRootFrm()->CheckFtnPageDescs( sal_False );
+ if ( bExtra )
+ {
+ //Fuer die Benachrichtung bezueglich ErgoSum usw. sparen wir uns
+ //extra-Code und nutzen die vorhandenen Wege.
+ SwFtnIdxs& rFtnIdxs = GetFtnIdxs();
+ for( sal_uInt16 nPos = 0; nPos < rFtnIdxs.Count(); ++nPos )
+ {
+ SwTxtFtn *pTxtFtn = rFtnIdxs[ nPos ];
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if ( !rFtn.IsEndNote() )
+ pTxtFtn->SetNumber( rFtn.GetNumber(), &rFtn.GetNumStr());
+ }
+ }
+ }
+ }
+ if( FTNNUM_PAGE != rInfo.eNum )
+ GetFtnIdxs().UpdateAllFtn();
+ else if( bFtnChrFmts )
+ {
+ SwFmtChg aOld( pOldChrFmt );
+ SwFmtChg aNew( pNewChrFmt );
+ pFtnInfo->Modify( &aOld, &aNew );
+ }
+
+ // --> OD 2008-01-09 #i81002#
+ // no update during loading
+ if ( !IsInReading() )
+ {
+ UpdateRefFlds(NULL);
+ }
+ SetModified();
+ }
+}
+
+void SwDoc::SetEndNoteInfo(const SwEndNoteInfo& rInfo)
+{
+ if( !(GetEndNoteInfo() == rInfo) )
+ {
+ if(GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo( new SwUndoEndNoteInfo( GetEndNoteInfo() ) );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ sal_Bool bNumChg = rInfo.nFtnOffset != GetEndNoteInfo().nFtnOffset;
+ // this seems to be an optimization: UpdateAllFtn() is only called
+ // if the offset changes; if the offset is the same,
+ // but type/prefix/suffix changes, just set new numbers.
+ bool const bExtra = !bNumChg &&
+ ( (rInfo.aFmt.GetNumberingType() !=
+ GetEndNoteInfo().aFmt.GetNumberingType())
+ || (rInfo.GetPrefix() != GetEndNoteInfo().GetPrefix())
+ || (rInfo.GetSuffix() != GetEndNoteInfo().GetSuffix())
+ );
+ sal_Bool bFtnDesc = rInfo.GetPageDesc( *this ) !=
+ GetEndNoteInfo().GetPageDesc( *this );
+ SwCharFmt *pOldChrFmt = GetEndNoteInfo().GetCharFmt( *this ),
+ *pNewChrFmt = rInfo.GetCharFmt( *this );
+ sal_Bool bFtnChrFmts = pOldChrFmt != pNewChrFmt;
+
+ *pEndNoteInfo = rInfo;
+
+ if ( GetRootFrm() )
+ {
+ if ( bFtnDesc )
+ GetRootFrm()->CheckFtnPageDescs( sal_True );
+ if ( bExtra )
+ {
+ //Fuer die Benachrichtung bezueglich ErgoSum usw. sparen wir uns
+ //extra-Code und nutzen die vorhandenen Wege.
+ SwFtnIdxs& rFtnIdxs = GetFtnIdxs();
+ for( sal_uInt16 nPos = 0; nPos < rFtnIdxs.Count(); ++nPos )
+ {
+ SwTxtFtn *pTxtFtn = rFtnIdxs[ nPos ];
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if ( rFtn.IsEndNote() )
+ pTxtFtn->SetNumber( rFtn.GetNumber(), &rFtn.GetNumStr());
+ }
+ }
+ }
+ if( bNumChg )
+ GetFtnIdxs().UpdateAllFtn();
+ else if( bFtnChrFmts )
+ {
+ SwFmtChg aOld( pOldChrFmt );
+ SwFmtChg aNew( pNewChrFmt );
+ pEndNoteInfo->Modify( &aOld, &aNew );
+ }
+
+ // --> OD 2008-01-09 #i81002#
+ // no update during loading
+ if ( !IsInReading() )
+ {
+ UpdateRefFlds(NULL);
+ }
+ SetModified();
+ }
+}
+
+
+bool SwDoc::SetCurFtn( const SwPaM& rPam, const String& rNumStr,
+ sal_uInt16 nNumber, bool bIsEndNote )
+{
+ SwFtnIdxs& rFtnArr = GetFtnIdxs();
+
+ const SwPosition* pStt = rPam.Start(), *pEnd = rPam.End();
+ const sal_uLong nSttNd = pStt->nNode.GetIndex();
+ const xub_StrLen nSttCnt = pStt->nContent.GetIndex();
+ const sal_uLong nEndNd = pEnd->nNode.GetIndex();
+ const xub_StrLen nEndCnt = pEnd->nContent.GetIndex();
+
+ sal_uInt16 nPos;
+ rFtnArr.SeekEntry( pStt->nNode, &nPos );
+
+ SwUndoChangeFootNote* pUndo = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo(); // AppendUndo far below, so leave it
+ pUndo = new SwUndoChangeFootNote( rPam, rNumStr, nNumber, bIsEndNote );
+ }
+
+ SwTxtFtn* pTxtFtn;
+ sal_uLong nIdx;
+ sal_Bool bChg = sal_False;
+ sal_Bool bTypeChgd = sal_False;
+ sal_uInt16 n = nPos; // sichern
+ while( nPos < rFtnArr.Count() &&
+ (( nIdx = _SwTxtFtn_GetIndex((pTxtFtn = rFtnArr[ nPos++ ] )))
+ < nEndNd || ( nIdx == nEndNd &&
+ nEndCnt >= *pTxtFtn->GetStart() )) )
+ if( nIdx > nSttNd || ( nIdx == nSttNd &&
+ nSttCnt <= *pTxtFtn->GetStart() ) )
+ {
+ const SwFmtFtn& rFtn = pTxtFtn->GetFtn();
+ if( /*rFtn.GetNumber() != nNumber ||*/
+ rFtn.GetNumStr() != rNumStr ||
+ rFtn.IsEndNote() != bIsEndNote )
+ {
+ bChg = sal_True;
+ if ( pUndo )
+ {
+ pUndo->GetHistory().Add( *pTxtFtn );
+ }
+
+ pTxtFtn->SetNumber( nNumber, &rNumStr );
+ if( rFtn.IsEndNote() != bIsEndNote )
+ {
+ ((SwFmtFtn&)rFtn).SetEndNote( bIsEndNote );
+ bTypeChgd = sal_True;
+ pTxtFtn->CheckCondColl();
+ //#i11339# dispose UNO wrapper when a footnote is changed to an endnote or vice versa
+ SwPtrMsgPoolItem aMsgHint( RES_FOOTNOTE_DELETED, (void*)&pTxtFtn->GetAttr() );
+ GetUnoCallBack()->Modify( &aMsgHint, &aMsgHint );
+ }
+ }
+ }
+
+ nPos = n; // nach vorne gibt es auch noch welche !
+ while( nPos &&
+ (( nIdx = _SwTxtFtn_GetIndex((pTxtFtn = rFtnArr[ --nPos ] )))
+ > nSttNd || ( nIdx == nSttNd &&
+ nSttCnt <= *pTxtFtn->GetStart() )) )
+ if( nIdx < nEndNd || ( nIdx == nEndNd &&
+ nEndCnt >= *pTxtFtn->GetStart() ) )
+ {
+ const SwFmtFtn& rFtn = pTxtFtn->GetFtn();
+ if( /*rFtn.GetNumber() != nNumber ||*/
+ rFtn.GetNumStr() != rNumStr ||
+ rFtn.IsEndNote() != bIsEndNote )
+ {
+ bChg = sal_True;
+ if ( pUndo )
+ {
+ pUndo->GetHistory().Add( *pTxtFtn );
+ }
+
+ pTxtFtn->SetNumber( nNumber, &rNumStr );
+ if( rFtn.IsEndNote() != bIsEndNote )
+ {
+ ((SwFmtFtn&)rFtn).SetEndNote( bIsEndNote );
+ bTypeChgd = sal_True;
+ pTxtFtn->CheckCondColl();
+ }
+ }
+ }
+
+ // wer muss angestossen werden ??
+ if( bChg )
+ {
+ if( pUndo )
+ {
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ if ( bTypeChgd )
+ rFtnArr.UpdateAllFtn();
+ if( FTNNUM_PAGE != GetFtnInfo().eNum )
+ {
+ if ( !bTypeChgd )
+ rFtnArr.UpdateAllFtn();
+ }
+ else if( GetRootFrm() )
+ GetRootFrm()->UpdateFtnNums();
+ SetModified();
+ }
+ else
+ delete pUndo;
+ return bChg;
+}
+
+
+
+
+
diff --git a/sw/source/core/doc/docglbl.cxx b/sw/source/core/doc/docglbl.cxx
new file mode 100644
index 000000000000..d31bc4df722a
--- /dev/null
+++ b/sw/source/core/doc/docglbl.cxx
@@ -0,0 +1,856 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <unotools/tempfile.hxx>
+#include <svl/urihelper.hxx>
+#include <svl/stritem.hxx>
+#include <svl/eitem.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/request.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtanchr.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <docsh.hxx>
+#include <globdoc.hxx>
+#include <shellio.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <section.hxx>
+#include <doctxm.hxx>
+#include <poolfmt.hxx>
+
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+
+using namespace ::com::sun::star;
+
+enum SwSplitDocType
+{
+ SPLITDOC_TO_GLOBALDOC,
+ SPLITDOC_TO_HTML
+};
+
+sal_Bool SwDoc::GenerateGlobalDoc( const String& rPath,
+ const SwTxtFmtColl* pSplitColl )
+{
+ return SplitDoc( SPLITDOC_TO_GLOBALDOC, rPath, pSplitColl );
+}
+
+//#outline level,add by zhaojianwei
+sal_Bool SwDoc::GenerateGlobalDoc( const String& rPath, int nOutlineLevel )
+{
+ return SplitDoc( SPLITDOC_TO_GLOBALDOC, rPath, nOutlineLevel );
+}
+sal_Bool SwDoc::GenerateHTMLDoc( const String& rPath, int nOutlineLevel )
+{
+ return SplitDoc( SPLITDOC_TO_HTML, rPath, nOutlineLevel );
+}
+//<-end,zhaojianwei
+
+sal_Bool SwDoc::GenerateHTMLDoc( const String& rPath,
+ const SwTxtFmtColl* pSplitColl )
+{
+#ifdef JP_TEST
+ if( !pSplitColl )
+ {
+ sal_uInt8 nLvl = 1;
+ const SwTxtFmtColls& rFmtColls =*GetTxtFmtColls();
+ for( sal_uInt16 n = rFmtColls.Count(); n; )
+ //if( nLvl == rFmtColls[ --n ]->GetOutlineLevel() )//#outline level,zhaojianwei
+ if( nLvl == rFmtColls[ --n ]->GetAttrOutlineLevel() -1 )//<-end,zhaojianwei 0814
+ {
+ pSplitColl = rFmtColls[ n ];
+ break;
+ }
+
+ if( !pSplitColl )
+ pSplitColl = GetTxtCollFromPool( RES_POOLCOLL_HEADLINE2 );
+ }
+#endif
+
+ return SplitDoc( SPLITDOC_TO_HTML, rPath, pSplitColl );
+}
+
+sal_Bool SwDoc::SplitDoc( sal_uInt16 eDocType, const String& rPath,
+ const SwTxtFmtColl* pSplitColl )
+{
+ // ueber alle Node der Vorlage Iterieren und dafuer einzelne
+ // Dokumente erzeugen und in diesem gegen
+ // - gelinkte Bereiche (GlobalDoc)
+ // - Links (HTML)
+ // austauschen.
+ // Am Ende wird dieses Doc als GlobalDoc/HTML-Doc gespreichert.
+ if( !pDocShell || !pDocShell->GetMedium() ||
+ ( SPLITDOC_TO_GLOBALDOC == eDocType && get(IDocumentSettingAccess::GLOBAL_DOCUMENT) ) )
+ return sal_False;
+
+ sal_uInt16 nOutl = 0;
+ SwOutlineNodes* pOutlNds = (SwOutlineNodes*)&GetNodes().GetOutLineNds();
+ SwNodePtr pSttNd;
+
+ if( pSplitColl )
+ {
+ // wenn keine OutlineNumerierung ist, dann benutze eigenes Array
+ // und sammel die Nodes zusammen.
+ //if( NO_NUMBERING == pSplitColl->GetOutlineLevel() )//#outline level,zhaojianwei
+ if( pSplitColl->GetAttrOutlineLevel() == 0 )//<-end,zhaojianwei, 0814
+ {
+ pOutlNds = new SwOutlineNodes( 8, 8 );
+ SwClientIter aIter( *(SwModify*)pSplitColl );
+ for( SwTxtNode* pTNd = (SwTxtNode*)aIter.First( TYPE( SwTxtNode ));
+ pTNd; pTNd = (SwTxtNode*)aIter.Next() )
+ if( pTNd->GetNodes().IsDocNodes() )
+ pOutlNds->Insert( pTNd );
+
+ if( !pOutlNds->Count() )
+ {
+ delete pOutlNds;
+ return sal_False;
+ }
+ }
+ }
+ else
+ {
+ // dann suche die Gliederungs - Vorlage, der 1. Ebene
+ const SwTxtFmtColls& rFmtColls =*GetTxtFmtColls();
+ for( sal_uInt16 n = rFmtColls.Count(); n; )
+ //if( !rFmtColls[ --n ]->GetOutlineLevel() )//#outline level,zhaojianwei
+ if ( rFmtColls[ --n ]->GetAttrOutlineLevel() == 1 )//<-end,zhaojianwei
+ {
+ pSplitColl = rFmtColls[ n ];
+ break;
+ }
+
+ if( !pSplitColl )
+ return sal_False;
+ }
+
+ const SfxFilter* pFilter;
+ switch( eDocType )
+ {
+ case SPLITDOC_TO_HTML:
+ pFilter = SwIoSystem::GetFilterOfFormat( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "HTML" )));
+ break;
+
+ default:
+// case SPLITDOC_TO_GLOBALDOC:
+ pFilter = SwIoSystem::GetFilterOfFormat(
+ String::CreateFromAscii( FILTER_XML ));
+ eDocType = SPLITDOC_TO_GLOBALDOC;
+ break;
+ }
+
+ if( !pFilter )
+ return sal_False;
+
+ // Undo/Redline aufjedenfall abschalten
+ GetIDocumentUndoRedo().DoUndo(false);
+ SetRedlineMode_intern( (RedlineMode_t)(GetRedlineMode() & ~nsRedlineMode_t::REDLINE_ON));
+
+ String sExt( pFilter->GetSuffixes().GetToken(0, ',') );
+ if( !sExt.Len() )
+ sExt.AssignAscii( "sxw" );
+ if( '.' != sExt.GetChar( 0 ) )
+ sExt.Insert( '.', 0 );
+
+ INetURLObject aEntry(rPath);
+ String sLeading(aEntry.GetBase());
+ aEntry.removeSegment();
+ String sPath = aEntry.GetMainURL( INetURLObject::NO_DECODE );
+ utl::TempFile aTemp(sLeading,&sExt,&sPath );
+ aTemp.EnableKillingFile();
+
+ DateTime aTmplDate;
+ {
+ Time a2Min( 0 ); a2Min.SetMin( 2 );
+ aTmplDate += a2Min;
+ }
+
+
+ // alle Ungueltigen ueberspringen
+ while( nOutl < pOutlNds->Count() &&
+ pOutlNds->GetObject( nOutl )->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
+ ++nOutl;
+
+ do {
+ pSttNd = 0;
+
+ SwNodePtr pNd;
+ for( ; nOutl < pOutlNds->Count(); ++nOutl )
+ if( ( pNd = pOutlNds->GetObject( nOutl ))->GetTxtNode()->
+ GetTxtColl() == pSplitColl &&
+ !pNd->FindTableNode() )
+ {
+ pSttNd = pNd;
+ break;
+ }
+
+ if( pSttNd )
+ {
+ SwNodePtr pEndNd = 0;
+ for( ++nOutl; nOutl < pOutlNds->Count(); ++nOutl )
+ {
+ pNd = pOutlNds->GetObject( nOutl );
+ SwTxtFmtColl* pTColl = pNd->GetTxtNode()->GetTxtColl();
+
+ //if( ( pTColl == pSplitColl || //#outline level,zhaojianwei
+ // ( NO_NUMBERING != pSplitColl->GetOutlineLevel() &&
+ // pTColl->GetOutlineLevel() <
+ // pSplitColl->GetOutlineLevel() )) &&
+ // !pNd->FindTableNode() )
+ if( ( pTColl == pSplitColl ||
+ ( pSplitColl->GetAttrOutlineLevel() > 0 &&
+ pTColl->GetAttrOutlineLevel() > 0 &&
+ pTColl->GetAttrOutlineLevel() <
+ pSplitColl->GetAttrOutlineLevel() )) &&
+ !pNd->FindTableNode() ) //<-end,zhaojianwei
+ {
+ pEndNd = pNd;
+
+ break;
+ }
+ }
+ SwNodeIndex aEndIdx( pEndNd ? *pEndNd
+ : GetNodes().GetEndOfContent() );
+
+ // die Nodes komplett rausschreiben
+ String sFileName;
+ if( pSttNd->GetIndex() + 1 < aEndIdx.GetIndex() )
+ {
+ SfxObjectShellLock xDocSh( new SwDocShell( SFX_CREATE_MODE_INTERNAL ));
+ if( xDocSh->DoInitNew( 0 ) )
+ {
+ SwDoc* pDoc = ((SwDocShell*)(&xDocSh))->GetDoc();
+
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ ((SwDocShell*)(&xDocSh))->GetModel(),
+ uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties());
+ DBG_ASSERT(xDocProps.is(), "Doc has no DocumentProperties");
+ // the GlobalDoc is the template
+ xDocProps->setTemplateName(aEmptyStr);
+ ::util::DateTime uDT(aTmplDate.Get100Sec(),
+ aTmplDate.GetSec(), aTmplDate.GetMin(),
+ aTmplDate.GetHour(), aTmplDate.GetDay(),
+ aTmplDate.GetMonth(), aTmplDate.GetYear());
+ xDocProps->setTemplateDate(uDT);
+ xDocProps->setTemplateURL(rPath);
+ //JP 14.06.99: Set the text of the "split para" as title
+ // from the new doc. Is the current doc has
+ // a title, insert it at begin.
+ String sTitle( xDocProps->getTitle() );
+ if( sTitle.Len() )
+ sTitle.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ": " ));
+ sTitle += ((SwTxtNode*)pSttNd)->GetExpandTxt();
+ xDocProps->setTitle( sTitle );
+
+ // Vorlagen ersetzen
+ pDoc->ReplaceStyles( *this );
+
+ // KapitelNumerierung uebernehmen
+ if( pOutlineRule )
+ pDoc->SetOutlineNumRule( *pOutlineRule );
+
+ SwNodeRange aRg( *pSttNd, 0, aEndIdx.GetNode() );
+ SwNodeIndex aTmpIdx( pDoc->GetNodes().GetEndOfContent() );
+ GetNodes()._Copy( aRg, aTmpIdx, sal_False );
+
+ // den initialen TextNode loeschen
+ SwNodeIndex aIdx( pDoc->GetNodes().GetEndOfExtras(), 2 );
+ if( aIdx.GetIndex() + 1 !=
+ pDoc->GetNodes().GetEndOfContent().GetIndex() )
+ pDoc->GetNodes().Delete( aIdx, 1 );
+
+ // alle Flys in dem Bereich
+ CopyFlyInFlyImpl( aRg, 0, aIdx );
+
+
+ // und noch alle Bookmarks
+ // ?????
+
+ utl::TempFile aTempFile2(sLeading,&sExt,&sPath );
+ sFileName = aTempFile2.GetURL();
+ SfxMedium* pTmpMed = new SfxMedium( sFileName,
+ STREAM_STD_READWRITE, sal_True );
+ pTmpMed->SetFilter( pFilter );
+
+ // fuer den HTML-Filter mussen wir aber ein Layout
+ // haben, damit Textrahmen/Controls/OLE-Objecte korrekt
+ // als Grafik exportiert werden koennen.
+ if( SPLITDOC_TO_HTML == eDocType &&
+ pDoc->GetSpzFrmFmts()->Count() )
+ {
+ /* SfxViewFrame* pFrame = */
+ SfxViewFrame::LoadHiddenDocument( *xDocSh, 0 );
+ }
+ xDocSh->DoSaveAs( *pTmpMed );
+ xDocSh->DoSaveCompleted( pTmpMed );
+
+ // beim Fehler wird keine FileLinkSection eingefuegt
+ if( xDocSh->GetError() )
+ sFileName.Erase();
+ }
+ xDocSh->DoClose();
+ }
+
+ // dann koennen ja die Bereiche eingefuegt werden
+ if( sFileName.Len() )
+ {
+ switch( eDocType )
+ {
+ case SPLITDOC_TO_HTML:
+ {
+ // loesche alle Nodes im Bereich und setze im "Start-
+ // Node" den Link auf das gespeicherte Doc
+ sal_uLong nNodeDiff = aEndIdx.GetIndex() -
+ pSttNd->GetIndex() - 1;
+ if( nNodeDiff )
+ {
+ SwPaM aTmp( *pSttNd, aEndIdx.GetNode(), 1, -1 );
+ aTmp.GetPoint()->nContent.Assign( 0, 0 );
+ aTmp.GetMark()->nContent.Assign( 0, 0 );
+ SwNodeIndex aSIdx( aTmp.GetMark()->nNode );
+ SwNodeIndex aEIdx( aTmp.GetPoint()->nNode );
+
+ // versuche hinters Ende zu verschieben
+ if( !aTmp.Move( fnMoveForward, fnGoNode ) )
+ {
+ // na gut, dann an den Anfang
+ aTmp.Exchange();
+ if( !aTmp.Move( fnMoveBackward, fnGoNode ))
+ {
+ ASSERT( sal_False, "kein Node mehr vorhanden" );
+ }
+ }
+ // Bookmarks usw. verschieben
+ CorrAbs( aSIdx, aEIdx, *aTmp.GetPoint(), sal_True);
+
+ // stehen noch FlyFrames rum, loesche auch diese
+ for( sal_uInt16 n = 0; n < GetSpzFrmFmts()->Count(); ++n )
+ {
+ SwFrmFmt* pFly = (*GetSpzFrmFmts())[n];
+ const SwFmtAnchor* pAnchor = &pFly->GetAnchor();
+ SwPosition const*const pAPos =
+ pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
+ (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
+ aSIdx <= pAPos->nNode &&
+ pAPos->nNode < aEIdx )
+ {
+ DelLayoutFmt( pFly );
+ --n;
+ }
+ }
+
+ GetNodes().Delete( aSIdx, nNodeDiff );
+ }
+
+ // dann setze im StartNode noch den Link:
+ SwFmtINetFmt aINet( sFileName , aEmptyStr );
+ SwTxtNode* pTNd = (SwTxtNode*)pSttNd;
+ pTNd->InsertItem( aINet, 0, pTNd->GetTxt().Len() );
+
+ // wenn der nicht mehr gefunden wird, kann das nur
+ // ein Bug sein!
+ if( !pOutlNds->Seek_Entry( pSttNd, &nOutl ))
+ pSttNd = 0;
+ ++nOutl;
+ }
+ break;
+
+ default:
+ {
+ String sNm( INetURLObject( sFileName ).GetName() );
+ SwSectionData aSectData( FILE_LINK_SECTION,
+ GetUniqueSectionName( &sNm ));
+ SwSectionFmt* pFmt = MakeSectionFmt( 0 );
+ aSectData.SetLinkFileName(sFileName);
+ aSectData.SetProtectFlag(true);
+
+ aEndIdx--; // im InsertSection ist Ende inclusive
+ while( aEndIdx.GetNode().IsStartNode() )
+ aEndIdx--;
+
+ // JP 06.07.99 - Bug 67361 - is any Section ends or
+ // starts in the new sectionrange, they must end or
+ // start before or behind the range!
+ SwSectionNode* pSectNd = pSttNd->FindSectionNode();
+ while( pSectNd && pSectNd->EndOfSectionIndex()
+ <= aEndIdx.GetIndex() )
+ {
+ const SwNode* pSectEnd = pSectNd->EndOfSectionNode();
+ if( pSectNd->GetIndex() + 1 ==
+ pSttNd->GetIndex() )
+ {
+ sal_Bool bMvIdx = aEndIdx == *pSectEnd;
+ DelSectionFmt( pSectNd->GetSection().GetFmt() );
+ if( bMvIdx )
+ aEndIdx--;
+ }
+ else
+ {
+ SwNodeRange aRg( *pSttNd, *pSectEnd );
+ SwNodeIndex aIdx( *pSectEnd, 1 );
+ GetNodes()._MoveNodes( aRg, GetNodes(), aIdx );
+ }
+ pSectNd = pSttNd->FindSectionNode();
+ }
+
+ pSectNd = aEndIdx.GetNode().FindSectionNode();
+ while( pSectNd && pSectNd->GetIndex() >
+ pSttNd->GetIndex() )
+ {
+ // #i15712# don't attempt to split sections if
+ // they are fully enclosed in [pSectNd,aEndIdx].
+ if( aEndIdx < pSectNd->EndOfSectionIndex() )
+ {
+ SwNodeRange aRg( *pSectNd, 1, aEndIdx, 1 );
+ SwNodeIndex aIdx( *pSectNd );
+ GetNodes()._MoveNodes( aRg, GetNodes(), aIdx );
+ }
+
+ pSectNd = pSttNd->FindSectionNode();
+ }
+
+ // -> #i26762#
+ // Ensure order of start and end of section is sane.
+ SwNodeIndex aStartIdx(*pSttNd);
+
+ if (aEndIdx >= aStartIdx)
+ {
+ pSectNd = GetNodes().InsertTextSection(aStartIdx,
+ *pFmt, aSectData, 0, &aEndIdx, false);
+ }
+ else
+ {
+ pSectNd = GetNodes().InsertTextSection(aEndIdx,
+ *pFmt, aSectData, 0, &aStartIdx, false);
+ }
+ // <- #i26762#
+
+ pSectNd->GetSection().CreateLink( CREATE_CONNECT );
+ }
+ break;
+ }
+ }
+ }
+ } while( pSttNd );
+
+// if( pOutlNds != (SwOutlineNodes*)&GetNodes().GetOutLineNds();
+ if( pOutlNds != &GetNodes().GetOutLineNds() )
+ delete pOutlNds;
+
+ switch( eDocType )
+ {
+ case SPLITDOC_TO_HTML:
+ if( get(IDocumentSettingAccess::GLOBAL_DOCUMENT) )
+ {
+ // dann alles verbliebenen Bereiche aufheben
+ while( GetSections().Count() )
+ DelSectionFmt( GetSections()[ 0 ] );
+
+ SfxFilterContainer* pFCntnr = pDocShell->GetFactory().GetFilterContainer();
+ pFilter = pFCntnr->GetFilter4EA( pFilter->GetTypeName(), SFX_FILTER_EXPORT );
+ }
+ break;
+
+// case SPLITDOC_TO_GLOBALDOC:
+ default:
+ // dann das Globaldoc speichern
+ set(IDocumentSettingAccess::GLOBAL_DOCUMENT, true);
+ set(IDocumentSettingAccess::GLOBAL_DOCUMENT_SAVE_LINKS, false);
+ }
+
+ // Medium istn't locked after reopen the document. Bug 91462
+ SfxRequest aReq( SID_SAVEASDOC, SFX_CALLMODE_SYNCHRON, GetAttrPool() );
+ aReq.AppendItem( SfxStringItem( SID_FILE_NAME, rPath ) );
+ aReq.AppendItem( SfxBoolItem( SID_SAVETO, sal_True ) );
+ if(pFilter)
+ aReq.AppendItem( SfxStringItem( SID_FILTER_NAME, pFilter->GetName() ) );
+ const SfxBoolItem *pRet = (const SfxBoolItem*)pDocShell->ExecuteSlot( aReq );
+
+ return pRet && pRet->GetValue();
+}
+
+//#outline level,add by zhaojianwei
+sal_Bool SwDoc::SplitDoc( sal_uInt16 eDocType, const String& rPath, int nOutlineLevel )
+{
+ if( !pDocShell || !pDocShell->GetMedium() ||
+ ( SPLITDOC_TO_GLOBALDOC == eDocType && get(IDocumentSettingAccess::GLOBAL_DOCUMENT) ) )
+ return sal_False;
+
+ sal_uInt16 nOutl = 0;
+ SwOutlineNodes* pOutlNds = (SwOutlineNodes*)&GetNodes().GetOutLineNds();
+ SwNodePtr pSttNd;
+
+ const SfxFilter* pFilter;
+ switch( eDocType )
+ {
+ case SPLITDOC_TO_HTML:
+ pFilter = SwIoSystem::GetFilterOfFormat( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "HTML" )));
+ break;
+
+ default:
+// case SPLITDOC_TO_GLOBALDOC:
+ pFilter = SwIoSystem::GetFilterOfFormat(
+ String::CreateFromAscii( FILTER_XML ));
+ eDocType = SPLITDOC_TO_GLOBALDOC;
+ break;
+ }
+
+ if( !pFilter )
+ return sal_False;
+
+ // Undo/Redline aufjedenfall abschalten
+ GetIDocumentUndoRedo().DoUndo(false);
+ SetRedlineMode_intern( (RedlineMode_t)(GetRedlineMode() & ~nsRedlineMode_t::REDLINE_ON));
+
+ String sExt( pFilter->GetSuffixes().GetToken(0, ',') );
+ if( !sExt.Len() )
+ sExt.AssignAscii( "sxw" );
+ if( '.' != sExt.GetChar( 0 ) )
+ sExt.Insert( '.', 0 );
+
+ INetURLObject aEntry(rPath);
+ String sLeading(aEntry.GetBase());
+ aEntry.removeSegment();
+ String sPath = aEntry.GetMainURL( INetURLObject::NO_DECODE );
+ utl::TempFile aTemp(sLeading,&sExt,&sPath );
+ aTemp.EnableKillingFile();
+
+ DateTime aTmplDate;
+ {
+ Time a2Min( 0 ); a2Min.SetMin( 2 );
+ aTmplDate += a2Min;
+ }
+
+
+ // alle Ungueltigen ueberspringen
+ while( nOutl < pOutlNds->Count() &&
+ pOutlNds->GetObject( nOutl )->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
+ ++nOutl;
+
+ do {
+ pSttNd = 0;
+
+ SwNodePtr pNd;
+ for( ; nOutl < pOutlNds->Count(); ++nOutl )
+ if( ( pNd = pOutlNds->GetObject( nOutl ))->GetTxtNode()->GetAttrOutlineLevel() == nOutlineLevel &&
+ !pNd->FindTableNode() )
+ {
+ pSttNd = pNd;
+ break;
+ }
+
+ if( pSttNd )
+ {
+ SwNodePtr pEndNd = 0;
+ for( ++nOutl; nOutl < pOutlNds->Count(); ++nOutl )
+ {
+ pNd = pOutlNds->GetObject( nOutl );
+
+ const int nLevel = pNd->GetTxtNode()->GetAttrOutlineLevel();
+
+ if( ( 0 < nLevel && nLevel <= nOutlineLevel ) &&
+ !pNd->FindTableNode() )
+ {
+ pEndNd = pNd;
+
+ break;
+ }
+ }
+ SwNodeIndex aEndIdx( pEndNd ? *pEndNd
+ : GetNodes().GetEndOfContent() );
+
+ String sFileName;
+ if( pSttNd->GetIndex() + 1 < aEndIdx.GetIndex() )
+ {
+ SfxObjectShellLock xDocSh( new SwDocShell( SFX_CREATE_MODE_INTERNAL ));
+ if( xDocSh->DoInitNew( 0 ) )
+ {
+ SwDoc* pDoc = ((SwDocShell*)(&xDocSh))->GetDoc();
+
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ ((SwDocShell*)(&xDocSh))->GetModel(),
+ uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties());
+ DBG_ASSERT(xDocProps.is(), "Doc has no DocumentProperties");
+ // the GlobalDoc is the template
+ xDocProps->setTemplateName(aEmptyStr);
+ ::util::DateTime uDT(aTmplDate.Get100Sec(),
+ aTmplDate.GetSec(), aTmplDate.GetMin(),
+ aTmplDate.GetHour(), aTmplDate.GetDay(),
+ aTmplDate.GetMonth(), aTmplDate.GetYear());
+ xDocProps->setTemplateDate(uDT);
+ xDocProps->setTemplateURL(rPath);
+ //JP 14.06.99: Set the text of the "split para" as title
+ // from the new doc. Is the current doc has
+ // a title, insert it at begin.
+ String sTitle( xDocProps->getTitle() );
+ if( sTitle.Len() )
+ sTitle.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ": " ));
+ sTitle += ((SwTxtNode*)pSttNd)->GetExpandTxt();
+ xDocProps->setTitle( sTitle );
+
+ // Vorlagen ersetzen
+ pDoc->ReplaceStyles( *this );
+
+ // KapitelNumerierung uebernehmen
+ if( pOutlineRule )
+ pDoc->SetOutlineNumRule( *pOutlineRule );
+
+ SwNodeRange aRg( *pSttNd, 0, aEndIdx.GetNode() );
+ SwNodeIndex aTmpIdx( pDoc->GetNodes().GetEndOfContent() );
+ GetNodes()._Copy( aRg, aTmpIdx, sal_False );
+
+ // den initialen TextNode loeschen
+ SwNodeIndex aIdx( pDoc->GetNodes().GetEndOfExtras(), 2 );
+ if( aIdx.GetIndex() + 1 !=
+ pDoc->GetNodes().GetEndOfContent().GetIndex() )
+ pDoc->GetNodes().Delete( aIdx, 1 );
+
+ // alle Flys in dem Bereich
+ CopyFlyInFlyImpl( aRg, 0, aIdx );
+
+
+ // und noch alle Bookmarks
+ // ?????
+
+ utl::TempFile aTempFile2(sLeading,&sExt,&sPath );
+ sFileName = aTempFile2.GetURL();
+ SfxMedium* pTmpMed = new SfxMedium( sFileName,
+ STREAM_STD_READWRITE, sal_True );
+ pTmpMed->SetFilter( pFilter );
+
+ // fuer den HTML-Filter mussen wir aber ein Layout
+ // haben, damit Textrahmen/Controls/OLE-Objecte korrekt
+ // als Grafik exportiert werden koennen.
+ if( SPLITDOC_TO_HTML == eDocType &&
+ pDoc->GetSpzFrmFmts()->Count() )
+ {
+ /* SfxViewFrame* pFrame = */
+ SfxViewFrame::LoadHiddenDocument( *xDocSh, 0 );
+ }
+ xDocSh->DoSaveAs( *pTmpMed );
+ xDocSh->DoSaveCompleted( pTmpMed );
+
+ // beim Fehler wird keine FileLinkSection eingefuegt
+ if( xDocSh->GetError() )
+ sFileName.Erase();
+ }
+ xDocSh->DoClose();
+ }
+
+ // dann koennen ja die Bereiche eingefuegt werden
+ if( sFileName.Len() )
+ {
+ switch( eDocType )
+ {
+ case SPLITDOC_TO_HTML:
+ {
+ // loesche alle Nodes im Bereich und setze im "Start-
+ // Node" den Link auf das gespeicherte Doc
+ sal_uLong nNodeDiff = aEndIdx.GetIndex() -
+ pSttNd->GetIndex() - 1;
+ if( nNodeDiff )
+ {
+ SwPaM aTmp( *pSttNd, aEndIdx.GetNode(), 1, -1 );
+ aTmp.GetPoint()->nContent.Assign( 0, 0 );
+ aTmp.GetMark()->nContent.Assign( 0, 0 );
+ SwNodeIndex aSIdx( aTmp.GetMark()->nNode );
+ SwNodeIndex aEIdx( aTmp.GetPoint()->nNode );
+
+ // versuche hinters Ende zu verschieben
+ if( !aTmp.Move( fnMoveForward, fnGoNode ) )
+ {
+ // na gut, dann an den Anfang
+ aTmp.Exchange();
+ if( !aTmp.Move( fnMoveBackward, fnGoNode ))
+ {
+ ASSERT( sal_False, "kein Node mehr vorhanden" );
+ }
+ }
+ // Bookmarks usw. verschieben
+ CorrAbs( aSIdx, aEIdx, *aTmp.GetPoint(), sal_True);
+
+ // stehen noch FlyFrames rum, loesche auch diese
+ for( sal_uInt16 n = 0; n < GetSpzFrmFmts()->Count(); ++n )
+ {
+ SwFrmFmt* pFly = (*GetSpzFrmFmts())[n];
+ const SwFmtAnchor* pAnchor = &pFly->GetAnchor();
+ SwPosition const*const pAPos =
+ pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
+ (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
+ aSIdx <= pAPos->nNode &&
+ pAPos->nNode < aEIdx )
+ {
+ DelLayoutFmt( pFly );
+ --n;
+ }
+ }
+
+ GetNodes().Delete( aSIdx, nNodeDiff );
+ }
+
+ // dann setze im StartNode noch den Link:
+ SwFmtINetFmt aINet( sFileName , aEmptyStr );
+ SwTxtNode* pTNd = (SwTxtNode*)pSttNd;
+ pTNd->InsertItem( aINet, 0, pTNd->GetTxt().Len() );
+
+ // wenn der nicht mehr gefunden wird, kann das nur
+ // ein Bug sein!
+ if( !pOutlNds->Seek_Entry( pSttNd, &nOutl ))
+ pSttNd = 0;
+ ++nOutl;
+ }
+ break;
+
+ default:
+ {
+ String sNm( INetURLObject( sFileName ).GetName() );
+ SwSectionData aSectData( FILE_LINK_SECTION,
+ GetUniqueSectionName( &sNm ));
+ SwSectionFmt* pFmt = MakeSectionFmt( 0 );
+ aSectData.SetLinkFileName(sFileName);
+ aSectData.SetProtectFlag(true);
+
+ aEndIdx--; // im InsertSection ist Ende inclusive
+ while( aEndIdx.GetNode().IsStartNode() )
+ aEndIdx--;
+
+ // JP 06.07.99 - Bug 67361 - is any Section ends or
+ // starts in the new sectionrange, they must end or
+ // start before or behind the range!
+ SwSectionNode* pSectNd = pSttNd->FindSectionNode();
+ while( pSectNd && pSectNd->EndOfSectionIndex()
+ <= aEndIdx.GetIndex() )
+ {
+ const SwNode* pSectEnd = pSectNd->EndOfSectionNode();
+ if( pSectNd->GetIndex() + 1 ==
+ pSttNd->GetIndex() )
+ {
+ sal_Bool bMvIdx = aEndIdx == *pSectEnd;
+ DelSectionFmt( pSectNd->GetSection().GetFmt() );
+ if( bMvIdx )
+ aEndIdx--;
+ }
+ else
+ {
+ SwNodeRange aRg( *pSttNd, *pSectEnd );
+ SwNodeIndex aIdx( *pSectEnd, 1 );
+ GetNodes()._MoveNodes( aRg, GetNodes(), aIdx );
+ }
+ pSectNd = pSttNd->FindSectionNode();
+ }
+
+ pSectNd = aEndIdx.GetNode().FindSectionNode();
+ while( pSectNd && pSectNd->GetIndex() >
+ pSttNd->GetIndex() )
+ {
+ if( aEndIdx < pSectNd->EndOfSectionIndex() )
+ {
+ SwNodeRange aRg( *pSectNd, 1, aEndIdx, 1 );
+ SwNodeIndex aIdx( *pSectNd );
+ GetNodes()._MoveNodes( aRg, GetNodes(), aIdx );
+ }
+
+ pSectNd = pSttNd->FindSectionNode();
+ }
+
+ SwNodeIndex aStartIdx(*pSttNd);
+
+ if (aEndIdx >= aStartIdx)
+ {
+ pSectNd = GetNodes().InsertTextSection(aStartIdx,
+ *pFmt, aSectData, 0, &aEndIdx, false);
+ }
+ else
+ {
+ pSectNd = GetNodes().InsertTextSection(aEndIdx,
+ *pFmt, aSectData, 0, &aStartIdx, false);
+ }
+
+ pSectNd->GetSection().CreateLink( CREATE_CONNECT );
+ }
+ break;
+ }
+ }
+ }
+ } while( pSttNd );
+
+ if( pOutlNds != &GetNodes().GetOutLineNds() )
+ delete pOutlNds;
+
+ switch( eDocType )
+ {
+ case SPLITDOC_TO_HTML:
+ if( get(IDocumentSettingAccess::GLOBAL_DOCUMENT) )
+ {
+ while( GetSections().Count() )
+ DelSectionFmt( GetSections()[ 0 ] );
+
+ SfxFilterContainer* pFCntnr = pDocShell->GetFactory().GetFilterContainer();
+ pFilter = pFCntnr->GetFilter4EA( pFilter->GetTypeName(), SFX_FILTER_EXPORT );
+ }
+ break;
+
+// case SPLITDOC_TO_GLOBALDOC:
+ default:
+ set(IDocumentSettingAccess::GLOBAL_DOCUMENT, true);
+ set(IDocumentSettingAccess::GLOBAL_DOCUMENT_SAVE_LINKS, false);
+ }
+
+ SfxRequest aReq( SID_SAVEASDOC, SFX_CALLMODE_SYNCHRON, GetAttrPool() );
+ aReq.AppendItem( SfxStringItem( SID_FILE_NAME, rPath ) );
+ aReq.AppendItem( SfxBoolItem( SID_SAVETO, sal_True ) );
+ if(pFilter)
+ aReq.AppendItem( SfxStringItem( SID_FILTER_NAME, pFilter->GetName() ) );
+ const SfxBoolItem *pRet = (const SfxBoolItem*)pDocShell->ExecuteSlot( aReq );
+
+ return pRet && pRet->GetValue();
+}//<-end,zhaojianwei
+
diff --git a/sw/source/core/doc/docglos.cxx b/sw/source/core/doc/docglos.cxx
new file mode 100644
index 000000000000..610a8fb170b8
--- /dev/null
+++ b/sw/source/core/doc/docglos.cxx
@@ -0,0 +1,203 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <shellio.hxx>
+#include <pam.hxx>
+#include <swundo.hxx>
+#include <ndtxt.hxx>
+#include <acorrect.hxx>
+#include <crsrsh.hxx>
+#include <docsh.hxx>
+
+
+using namespace ::com::sun::star;
+
+
+/// copy document properties via public interface
+static void lcl_copyDocumentProperties(
+ uno::Reference<document::XDocumentProperties> i_xSource,
+ uno::Reference<document::XDocumentProperties> i_xTarget) {
+ DBG_ASSERT(i_xSource.is(), "null reference");
+ DBG_ASSERT(i_xTarget.is(), "null reference");
+
+ i_xTarget->setAuthor(i_xSource->getAuthor());
+ i_xTarget->setGenerator(i_xSource->getGenerator());
+ i_xTarget->setCreationDate(i_xSource->getCreationDate());
+ i_xTarget->setTitle(i_xSource->getTitle());
+ i_xTarget->setSubject(i_xSource->getSubject());
+ i_xTarget->setDescription(i_xSource->getDescription());
+ i_xTarget->setKeywords(i_xSource->getKeywords());
+ i_xTarget->setLanguage(i_xSource->getLanguage());
+ i_xTarget->setModifiedBy(i_xSource->getModifiedBy());
+ i_xTarget->setModificationDate(i_xSource->getModificationDate());
+ i_xTarget->setPrintedBy(i_xSource->getPrintedBy());
+ i_xTarget->setPrintDate(i_xSource->getPrintDate());
+ i_xTarget->setTemplateName(i_xSource->getTemplateName());
+ i_xTarget->setTemplateURL(i_xSource->getTemplateURL());
+ i_xTarget->setTemplateDate(i_xSource->getTemplateDate());
+ i_xTarget->setAutoloadURL(i_xSource->getAutoloadURL());
+ i_xTarget->setAutoloadSecs(i_xSource->getAutoloadSecs());
+ i_xTarget->setDefaultTarget(i_xSource->getDefaultTarget());
+ i_xTarget->setDocumentStatistics(i_xSource->getDocumentStatistics());
+ i_xTarget->setEditingCycles(i_xSource->getEditingCycles());
+ i_xTarget->setEditingDuration(i_xSource->getEditingDuration());
+
+ uno::Reference<beans::XPropertySet> xSourceUDSet(
+ i_xSource->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
+ uno::Reference<beans::XPropertyContainer> xTargetUD(
+ i_xTarget->getUserDefinedProperties());
+ uno::Reference<beans::XPropertySet> xTargetUDSet(xTargetUD,
+ uno::UNO_QUERY_THROW);
+ uno::Sequence<beans::Property> tgtprops
+ = xTargetUDSet->getPropertySetInfo()->getProperties();
+ for (sal_Int32 i = 0; i < tgtprops.getLength(); ++i) {
+ try {
+ xTargetUD->removeProperty(tgtprops [i].Name);
+ } catch (uno::Exception &) {
+ // ignore
+ }
+ }
+ try {
+ uno::Reference<beans::XPropertySetInfo> xSetInfo
+ = xSourceUDSet->getPropertySetInfo();
+ uno::Sequence<beans::Property> srcprops = xSetInfo->getProperties();
+ for (sal_Int32 i = 0; i < srcprops.getLength(); ++i) {
+ ::rtl::OUString name = srcprops[i].Name;
+ xTargetUD->addProperty(name, srcprops[i].Attributes,
+ xSourceUDSet->getPropertyValue(name));
+ }
+ } catch (uno::Exception &) {
+ // ignore
+ }
+}
+
+/* -----------------22.07.99 11:47-------------------
+ Description: inserts an AutoText block
+ --------------------------------------------------*/
+sal_Bool SwDoc::InsertGlossary( SwTextBlocks& rBlock, const String& rEntry,
+ SwPaM& rPaM, SwCrsrShell* pShell )
+{
+ sal_Bool bRet = sal_False;
+ sal_uInt16 nIdx = rBlock.GetIndex( rEntry );
+ if( (sal_uInt16) -1 != nIdx )
+ {
+ // Bug #70238# ask the TextOnly-Flag before BeginGetDoc, because
+ // the method closed the Storage!
+ sal_Bool bSav_IsInsGlossary = mbInsOnlyTxtGlssry;
+ mbInsOnlyTxtGlssry = rBlock.IsOnlyTextBlock( nIdx );
+
+ if( rBlock.BeginGetDoc( nIdx ) )
+ {
+ SwDoc* pGDoc = rBlock.GetDoc();
+
+ // alle FixFelder aktualisieren. Dann aber auch mit der
+ // richtigen DocInfo!
+ // FIXME: UGLY: Because we cannot limit the range in which to do
+ // field updates, we must update the fixed fields at the glossary
+ // entry document.
+ // To be able to do this, we copy the document properties of the
+ // target document to the glossary document
+// DBG_ASSERT(GetDocShell(), "no SwDocShell"); // may be clipboard!
+ DBG_ASSERT(pGDoc->GetDocShell(), "no SwDocShell at glossary");
+ if (GetDocShell() && pGDoc->GetDocShell()) {
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ GetDocShell()->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties() );
+ uno::Reference<document::XDocumentPropertiesSupplier> xGlosDPS(
+ pGDoc->GetDocShell()->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xGlosDocProps(
+ xGlosDPS->getDocumentProperties() );
+ lcl_copyDocumentProperties(xDocProps, xGlosDocProps);
+ }
+ pGDoc->SetFixFields(false, NULL);
+
+ //StartAllAction();
+ LockExpFlds();
+
+ SwNodeIndex aStt( pGDoc->GetNodes().GetEndOfExtras(), 1 );
+ SwCntntNode* pCntntNd = pGDoc->GetNodes().GoNext( &aStt );
+ const SwTableNode* pTblNd = pCntntNd->FindTableNode();
+ SwPaM aCpyPam( pTblNd ? *(SwNode*)pTblNd : *(SwNode*)pCntntNd );
+ aCpyPam.SetMark();
+
+ // dann bis zum Ende vom Nodes Array
+ aCpyPam.GetPoint()->nNode = pGDoc->GetNodes().GetEndOfContent().GetIndex()-1;
+ pCntntNd = aCpyPam.GetCntntNode();
+ aCpyPam.GetPoint()->nContent.Assign( pCntntNd, pCntntNd->Len() );
+
+ GetIDocumentUndoRedo().StartUndo( UNDO_INSGLOSSARY, NULL );
+ SwPaM *_pStartCrsr = &rPaM, *__pStartCrsr = _pStartCrsr;
+ do {
+
+ SwPosition& rInsPos = *_pStartCrsr->GetPoint();
+ SwStartNode* pBoxSttNd = (SwStartNode*)rInsPos.nNode.GetNode().
+ FindTableBoxStartNode();
+
+ if( pBoxSttNd && 2 == pBoxSttNd->EndOfSectionIndex() -
+ pBoxSttNd->GetIndex() &&
+ aCpyPam.GetPoint()->nNode != aCpyPam.GetMark()->nNode )
+ {
+ // es wird mehr als 1 Node in die akt. Box kopiert.
+ // Dann muessen die BoxAttribute aber entfernt werden.
+ ClearBoxNumAttrs( rInsPos.nNode );
+ }
+
+ SwDontExpandItem aACD;
+ aACD.SaveDontExpandItems( rInsPos );
+
+ pGDoc->CopyRange( aCpyPam, rInsPos, false );
+
+ aACD.RestoreDontExpandItems( rInsPos );
+ if( pShell )
+ pShell->SaveTblBoxCntnt( &rInsPos );
+ } while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) !=
+ __pStartCrsr );
+ GetIDocumentUndoRedo().EndUndo( UNDO_INSGLOSSARY, NULL );
+
+ UnlockExpFlds();
+ if( !IsExpFldsLocked() )
+ UpdateExpFlds(NULL, true);
+ bRet = sal_True;
+ }
+ mbInsOnlyTxtGlssry = bSav_IsInsGlossary;
+ }
+ rBlock.EndGetDoc();
+ return bRet;
+}
+
+
diff --git a/sw/source/core/doc/doclay.cxx b/sw/source/core/doc/doclay.cxx
new file mode 100644
index 000000000000..d5e7354df745
--- /dev/null
+++ b/sw/source/core/doc/doclay.cxx
@@ -0,0 +1,2369 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <unotools/linguprops.hxx>
+#include <unotools/lingucfg.hxx>
+#include <com/sun/star/embed/EmbedStates.hpp>
+#include <hintids.hxx>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <sfx2/progress.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/protitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/prntitem.hxx>
+#include <svx/fmglob.hxx>
+#include <svx/svdouno.hxx>
+#include <svx/fmpage.hxx>
+#include <editeng/frmdiritem.hxx>
+
+#include <swmodule.hxx>
+#include <modcfg.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <rtl/logfile.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <fchrfmt.hxx>
+#include <errhdl.hxx>
+#include <frmatr.hxx>
+#include <txatbase.hxx>
+#include <fmtfld.hxx>
+#include <fmtornt.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtfsize.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtflcnt.hxx>
+#include <fmtcnct.hxx>
+#include <frmfmt.hxx>
+#include <dcontact.hxx>
+#include <txtflcnt.hxx>
+#include <docfld.hxx> // fuer Expression-Felder
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <ndnotxt.hxx>
+#include <ndole.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <flyfrm.hxx>
+#include <fesh.hxx>
+#include <docsh.hxx>
+#include <dflyobj.hxx>
+#include <dcontact.hxx>
+#include <swundo.hxx>
+#include <flypos.hxx>
+#include <UndoInsert.hxx>
+#include <expfld.hxx> // InsertLabel
+#include <poolfmt.hxx> // PoolVorlagen-Id's
+#include <docary.hxx>
+#include <swtable.hxx>
+#include <tblsel.hxx>
+#include <viewopt.hxx>
+#include <fldupde.hxx>
+#include <txtftn.hxx>
+#include <ftnidx.hxx>
+#include <ftninfo.hxx>
+#include <pagedesc.hxx>
+#include <PostItMgr.hxx>
+#include <comcore.hrc> // STR-ResId's
+
+// #i11176#
+#include <unoframe.hxx>
+// OD 2004-05-24 #i28701#
+#include <sortedobjs.hxx>
+
+// --> OD 2004-07-26 #i32089#
+#include <vector>
+// <--
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+#define DEF_FLY_WIDTH 2268 //Defaultbreite fuer FlyFrms (2268 == 4cm)
+
+/* #109161# */
+static bool lcl_IsItemSet(const SwCntntNode & rNode, sal_uInt16 which)
+{
+ bool bResult = false;
+
+ if (SFX_ITEM_SET == rNode.GetSwAttrSet().GetItemState(which))
+ bResult = true;
+
+ return bResult;
+}
+
+/*************************************************************************
+|*
+|* SwDoc::MakeLayoutFmt()
+|*
+|* Beschreibung Erzeugt ein neues Format das in seinen Einstellungen
+|* Defaultmaessig zu dem Request passt. Das Format wird in das
+|* entsprechende Formate-Array gestellt.
+|* Wenn bereits ein passendes Format existiert, so wird dies
+|* zurueckgeliefert.
+|* Ersterstellung MA 22. Sep. 92
+|* Letzte Aenderung JP 08.05.98
+|*
+|*************************************************************************/
+
+SwFrmFmt *SwDoc::MakeLayoutFmt( RndStdIds eRequest, const SfxItemSet* pSet )
+{
+ SwFrmFmt *pFmt = 0;
+ const sal_Bool bMod = IsModified();
+ sal_Bool bHeader = sal_False;
+
+ switch ( eRequest )
+ {
+ case RND_STD_HEADER:
+ case RND_STD_HEADERL:
+ case RND_STD_HEADERR:
+ {
+ bHeader = sal_True;
+ // kein break, es geht unten weiter
+ }
+ case RND_STD_FOOTER:
+ case RND_STD_FOOTERL:
+ case RND_STD_FOOTERR:
+ {
+ pFmt = new SwFrmFmt( GetAttrPool(),
+ (bHeader ? "Header" : "Footer"),
+ GetDfltFrmFmt() );
+
+ SwNodeIndex aTmpIdx( GetNodes().GetEndOfAutotext() );
+ SwStartNode* pSttNd =
+ GetNodes().MakeTextSection
+ ( aTmpIdx,
+ bHeader ? SwHeaderStartNode : SwFooterStartNode,
+ GetTxtCollFromPool(static_cast<sal_uInt16>( bHeader
+ ? ( eRequest == RND_STD_HEADERL
+ ? RES_POOLCOLL_HEADERL
+ : eRequest == RND_STD_HEADERR
+ ? RES_POOLCOLL_HEADERR
+ : RES_POOLCOLL_HEADER )
+ : ( eRequest == RND_STD_FOOTERL
+ ? RES_POOLCOLL_FOOTERL
+ : eRequest == RND_STD_FOOTERR
+ ? RES_POOLCOLL_FOOTERR
+ : RES_POOLCOLL_FOOTER )
+ ) ) );
+ pFmt->SetFmtAttr( SwFmtCntnt( pSttNd ));
+
+ if( pSet ) // noch ein paar Attribute setzen ?
+ pFmt->SetFmtAttr( *pSet );
+
+ // JP: warum zuruecksetzen ??? Doc. ist doch veraendert ???
+ // bei den Fly auf jedenfall verkehrt !!
+ if ( !bMod )
+ ResetModified();
+ }
+ break;
+
+ case RND_DRAW_OBJECT:
+ {
+ pFmt = MakeDrawFrmFmt( aEmptyStr, GetDfltFrmFmt() );
+ if( pSet ) // noch ein paar Attribute setzen ?
+ pFmt->SetFmtAttr( *pSet );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(
+ new SwUndoInsLayFmt(pFmt, 0, 0));
+ }
+ }
+ break;
+
+#ifdef DBG_UTIL
+ case FLY_AT_PAGE:
+ case FLY_AT_CHAR:
+ case FLY_AT_FLY:
+ case FLY_AT_PARA:
+ case FLY_AS_CHAR:
+ ASSERT( false, "use new interface instead: SwDoc::MakeFlySection!" );
+ break;
+#endif
+
+ default:
+ ASSERT( !this,
+ "Layoutformat mit ungueltigem Request angefordert." );
+
+ }
+ return pFmt;
+}
+/*************************************************************************
+|*
+|* SwDoc::DelLayoutFmt()
+|*
+|* Beschreibung Loescht das angegebene Format, der Inhalt wird mit
+|* geloescht.
+|* Ersterstellung MA 23. Sep. 92
+|* Letzte Aenderung MA 05. Feb. 93
+|*
+|*************************************************************************/
+
+void SwDoc::DelLayoutFmt( SwFrmFmt *pFmt )
+{
+ //Verkettung von Rahmen muss ggf. zusammengefuehrt werden.
+ //Bevor die Frames vernichtet werden, damit die Inhalte der Rahmen
+ //ggf. entsprechend gerichtet werden.
+ const SwFmtChain &rChain = pFmt->GetChain();
+ if ( rChain.GetPrev() )
+ {
+ SwFmtChain aChain( rChain.GetPrev()->GetChain() );
+ aChain.SetNext( rChain.GetNext() );
+ SetAttr( aChain, *rChain.GetPrev() );
+ }
+ if ( rChain.GetNext() )
+ {
+ SwFmtChain aChain( rChain.GetNext()->GetChain() );
+ aChain.SetPrev( rChain.GetPrev() );
+ SetAttr( aChain, *rChain.GetNext() );
+ }
+
+ const SwNodeIndex* pCntIdx = pFmt->GetCntnt().GetCntntIdx();
+ if (pCntIdx && !GetIDocumentUndoRedo().DoesUndo())
+ {
+ //Verbindung abbauen, falls es sich um ein OLE-Objekt handelt.
+ SwOLENode* pOLENd = GetNodes()[ pCntIdx->GetIndex()+1 ]->GetOLENode();
+ if( pOLENd && pOLENd->GetOLEObj().IsOleRef() )
+ {
+ /*
+ SwDoc* pDoc = (SwDoc*)pFmt->GetDoc();
+ if( pDoc )
+ {
+ SfxObjectShell* p = pDoc->GetPersist();
+ if( p ) // muss da sein
+ {
+ SvInfoObjectRef aRef( p->Find( pOLENd->GetOLEObj().GetName() ) );
+ if( aRef.Is() )
+ aRef->SetObj(0);
+ }
+ } */
+
+ // TODO/MBA: the old object closed the object, cleared all references to it, but didn't remove it from the container.
+ // I have no idea, why, nobody could explain it - so I do my very best to mimic this behavior
+ //uno::Reference < util::XCloseable > xClose( pOLENd->GetOLEObj().GetOleRef(), uno::UNO_QUERY );
+ //if ( xClose.is() )
+ {
+ try
+ {
+ pOLENd->GetOLEObj().GetOleRef()->changeState( embed::EmbedStates::LOADED );
+ }
+ catch ( uno::Exception& )
+ {
+ }
+ }
+
+ //pOLENd->GetOLEObj().GetOleRef() = 0;
+ }
+ }
+
+ //Frms vernichten.
+ pFmt->DelFrms();
+
+ // erstmal sind nur Fly's Undofaehig
+ const sal_uInt16 nWh = pFmt->Which();
+ if (GetIDocumentUndoRedo().DoesUndo() &&
+ (RES_FLYFRMFMT == nWh || RES_DRAWFRMFMT == nWh))
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoDelLayFmt( pFmt ));
+ }
+ else
+ {
+ // --> OD 2004-07-26 #i32089# - delete at-frame anchored objects
+ if ( nWh == RES_FLYFRMFMT )
+ {
+ // determine frame formats of at-frame anchored objects
+ const SwNodeIndex* pCntntIdx = pFmt->GetCntnt().GetCntntIdx();
+ if ( pCntntIdx )
+ {
+ const SwSpzFrmFmts* pTbl = pFmt->GetDoc()->GetSpzFrmFmts();
+ if ( pTbl )
+ {
+ std::vector<SwFrmFmt*> aToDeleteFrmFmts;
+ const sal_uLong nNodeIdxOfFlyFmt( pCntntIdx->GetIndex() );
+
+ for ( sal_uInt16 i = 0; i < pTbl->Count(); ++i )
+ {
+ SwFrmFmt* pTmpFmt = (*pTbl)[i];
+ const SwFmtAnchor &rAnch = pTmpFmt->GetAnchor();
+ if ( rAnch.GetAnchorId() == FLY_AT_FLY &&
+ rAnch.GetCntntAnchor()->nNode.GetIndex() == nNodeIdxOfFlyFmt )
+ {
+ aToDeleteFrmFmts.push_back( pTmpFmt );
+ }
+ }
+
+ // delete found frame formats
+ while ( !aToDeleteFrmFmts.empty() )
+ {
+ SwFrmFmt* pTmpFmt = aToDeleteFrmFmts.back();
+ pFmt->GetDoc()->DelLayoutFmt( pTmpFmt );
+
+ aToDeleteFrmFmts.pop_back();
+ }
+ }
+ }
+ }
+ // <--
+
+ //Inhalt Loeschen.
+ if( pCntIdx )
+ {
+ SwNode *pNode = &pCntIdx->GetNode();
+ ((SwFmtCntnt&)pFmt->GetFmtAttr( RES_CNTNT )).SetNewCntntIdx( 0 );
+ DeleteSection( pNode );
+ }
+
+ // ggfs. bei Zeichengebundenen Flys das Zeichen loeschen
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ if ((FLY_AS_CHAR == rAnchor.GetAnchorId()) && rAnchor.GetCntntAnchor())
+ {
+ const SwPosition* pPos = rAnchor.GetCntntAnchor();
+ SwTxtNode *pTxtNd = pPos->nNode.GetNode().GetTxtNode();
+
+ // attribute is still in text node, delete it
+ if ( pTxtNd )
+ {
+ SwTxtFlyCnt* const pAttr = static_cast<SwTxtFlyCnt*>(
+ pTxtNd->GetTxtAttrForCharAt( pPos->nContent.GetIndex(),
+ RES_TXTATR_FLYCNT ));
+ if ( pAttr && (pAttr->GetFlyCnt().GetFrmFmt() == pFmt) )
+ {
+ // dont delete, set pointer to 0
+ const_cast<SwFmtFlyCnt&>(pAttr->GetFlyCnt()).SetFlyFmt();
+ SwIndex aIdx( pPos->nContent );
+ pTxtNd->EraseText( aIdx, 1 );
+ }
+ }
+ }
+
+ DelFrmFmt( pFmt );
+ }
+ SetModified();
+}
+
+/*************************************************************************
+|*
+|* SwDoc::CopyLayoutFmt()
+|*
+|* Beschreibung Kopiert das angegebene Format pSrc in pDest und
+|* returnt pDest. Wenn es noch kein pDest gibt, wird
+|* eins angelegt.
+|* JP: steht das Source Format in einem anderen
+|* Dokument, so kopiere auch dann noch richtig !!
+|* Vom chaos::Anchor-Attribut wird die Position immer
+|* auf 0 gesetzt !!!
+|*
+|* Ersterstellung BP 18.12.92
+|* Letzte Aenderung MA 17. Jul. 96
+|*
+|*************************************************************************/
+
+SwFrmFmt *SwDoc::CopyLayoutFmt( const SwFrmFmt& rSource,
+ const SwFmtAnchor& rNewAnchor,
+ bool bSetTxtFlyAtt, bool bMakeFrms )
+{
+ const bool bFly = RES_FLYFRMFMT == rSource.Which();
+ const bool bDraw = RES_DRAWFRMFMT == rSource.Which();
+ ASSERT( bFly || bDraw, "this method only works for fly or draw" );
+
+ SwDoc* pSrcDoc = (SwDoc*)rSource.GetDoc();
+
+ // #108784# may we copy this object?
+ // We may, unless it's 1) it's a control (and therfore a draw)
+ // 2) anchored in a header/footer
+ // 3) anchored (to paragraph?)
+ bool bMayNotCopy = false;
+ if( bDraw )
+ {
+ const SwDrawContact* pDrawContact =
+ static_cast<const SwDrawContact*>( rSource.FindContactObj() );
+
+ bMayNotCopy =
+ ((FLY_AT_PARA == rNewAnchor.GetAnchorId()) ||
+ (FLY_AT_FLY == rNewAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rNewAnchor.GetAnchorId())) &&
+ rNewAnchor.GetCntntAnchor() &&
+ IsInHeaderFooter( rNewAnchor.GetCntntAnchor()->nNode ) &&
+ pDrawContact != NULL &&
+ pDrawContact->GetMaster() != NULL &&
+ CheckControlLayer( pDrawContact->GetMaster() );
+ }
+
+ // just return if we can't copy this
+ if( bMayNotCopy )
+ return NULL;
+
+ SwFrmFmt* pDest = GetDfltFrmFmt();
+ if( rSource.GetRegisteredIn() != pSrcDoc->GetDfltFrmFmt() )
+ pDest = CopyFrmFmt( *(SwFrmFmt*)rSource.GetRegisteredIn() );
+ if( bFly )
+ {
+ // #i11176#
+ // To do a correct cloning concerning the ZOrder for all objects
+ // it is necessary to actually create a draw object for fly frames, too.
+ // These are then added to the DrawingLayer (which needs to exist).
+ // Together with correct sorting of all drawinglayer based objects
+ // before cloning ZOrder transfer works correctly then.
+ SwFlyFrmFmt *pFormat = MakeFlyFrmFmt( rSource.GetName(), pDest );
+ pDest = pFormat;
+
+ SwXFrame::GetOrCreateSdrObject(pFormat);
+ }
+ else
+ pDest = MakeDrawFrmFmt( aEmptyStr, pDest );
+
+ // alle anderen/neue Attribute kopieren.
+ pDest->CopyAttrs( rSource );
+
+ //Chains werden nicht kopiert.
+ pDest->ResetFmtAttr( RES_CHAIN );
+
+ if( bFly )
+ {
+ //Der Inhalt wird dupliziert.
+ const SwNode& rCSttNd = rSource.GetCntnt().GetCntntIdx()->GetNode();
+ SwNodeRange aRg( rCSttNd, 1, *rCSttNd.EndOfSectionNode() );
+
+ SwNodeIndex aIdx( GetNodes().GetEndOfAutotext() );
+ SwStartNode* pSttNd = GetNodes().MakeEmptySection( aIdx, SwFlyStartNode );
+
+ // erst den chaos::Anchor/CntntIndex setzen, innerhalb des Kopierens
+ // auf die Werte zugegriffen werden kann (DrawFmt in Kopf-/Fusszeilen)
+ aIdx = *pSttNd;
+ SwFmtCntnt aAttr( rSource.GetCntnt() );
+ aAttr.SetNewCntntIdx( &aIdx );
+ pDest->SetFmtAttr( aAttr );
+ pDest->SetFmtAttr( rNewAnchor );
+
+ if( !mbCopyIsMove || this != pSrcDoc )
+ {
+ if( mbInReading )
+ pDest->SetName( aEmptyStr );
+ else
+ {
+ // Teste erstmal ob der Name schon vergeben ist.
+ // Wenn ja -> neuen generieren
+ sal_Int8 nNdTyp = aRg.aStart.GetNode().GetNodeType();
+
+ String sOld( pDest->GetName() );
+ pDest->SetName( aEmptyStr );
+ if( FindFlyByName( sOld, nNdTyp ) ) // einen gefunden
+ switch( nNdTyp )
+ {
+ case ND_GRFNODE: sOld = GetUniqueGrfName(); break;
+ case ND_OLENODE: sOld = GetUniqueOLEName(); break;
+ default: sOld = GetUniqueFrameName(); break;
+ }
+
+ pDest->SetName( sOld );
+ }
+ }
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(new SwUndoInsLayFmt(pDest,0,0));
+ }
+
+ // sorge dafuer das auch Fly's in Fly's kopiert werden
+ aIdx = *pSttNd->EndOfSectionNode();
+ pSrcDoc->CopyWithFlyInFly( aRg, 0, aIdx, sal_False, sal_True, sal_True );
+ }
+ else
+ {
+ ASSERT( RES_DRAWFRMFMT == rSource.Which(), "Weder Fly noch Draw." );
+ // OD 2005-08-02 #i52780# - Note: moving object to visible layer not needed.
+ SwDrawContact* pSourceContact = (SwDrawContact *)rSource.FindContactObj();
+
+ SwDrawContact* pContact = new SwDrawContact( (SwDrawFrmFmt*)pDest,
+ CloneSdrObj( *pSourceContact->GetMaster(),
+ mbCopyIsMove && this == pSrcDoc ) );
+ // --> OD 2005-05-23 #i49730# - notify draw frame format
+ // that position attributes are already set, if the position attributes
+ // are already set at the source draw frame format.
+ if ( pDest->ISA(SwDrawFrmFmt) &&
+ rSource.ISA(SwDrawFrmFmt) &&
+ static_cast<const SwDrawFrmFmt&>(rSource).IsPosAttrSet() )
+ {
+ static_cast<SwDrawFrmFmt*>(pDest)->PosAttrSet();
+ }
+ // <--
+
+ if( pDest->GetAnchor() == rNewAnchor )
+ {
+ // OD 03.07.2003 #108784# - do *not* connect to layout, if
+ // a <MakeFrms> will not be called.
+ if ( bMakeFrms )
+ {
+ pContact->ConnectToLayout( &rNewAnchor );
+ }
+ }
+ else
+ pDest->SetFmtAttr( rNewAnchor );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(new SwUndoInsLayFmt(pDest,0,0));
+ }
+ }
+
+ if (bSetTxtFlyAtt && (FLY_AS_CHAR == rNewAnchor.GetAnchorId()))
+ {
+ const SwPosition* pPos = rNewAnchor.GetCntntAnchor();
+ SwFmtFlyCnt aFmt( pDest );
+ pPos->nNode.GetNode().GetTxtNode()->InsertItem(
+ aFmt, pPos->nContent.GetIndex(), 0 );
+ }
+
+ if( bMakeFrms )
+ pDest->MakeFrms();
+
+ return pDest;
+}
+
+SdrObject* SwDoc::CloneSdrObj( const SdrObject& rObj, sal_Bool bMoveWithinDoc,
+ sal_Bool bInsInPage )
+{
+ // --> OD 2005-08-08 #i52858# - method name changed
+ SdrPage *pPg = GetOrCreateDrawModel()->GetPage( 0 );
+ // <--
+ if( !pPg )
+ {
+ pPg = GetDrawModel()->AllocPage( sal_False );
+ GetDrawModel()->InsertPage( pPg );
+ }
+
+ SdrObject *pObj = rObj.Clone();
+ if( bMoveWithinDoc && FmFormInventor == pObj->GetObjInventor() )
+ {
+ // bei Controls muss der Name erhalten bleiben
+ uno::Reference< awt::XControlModel > xModel = ((SdrUnoObj*)pObj)->GetUnoControlModel();
+ uno::Any aVal;
+ uno::Reference< beans::XPropertySet > xSet(xModel, uno::UNO_QUERY);
+ OUString sName( rtl::OUString::createFromAscii("Name") );
+ if( xSet.is() )
+ aVal = xSet->getPropertyValue( sName );
+ if( bInsInPage )
+ pPg->InsertObject( pObj );
+ if( xSet.is() )
+ xSet->setPropertyValue( sName, aVal );
+ }
+ else if( bInsInPage )
+ pPg->InsertObject( pObj );
+
+ // OD 02.07.2003 #108784# - for drawing objects: set layer of cloned object
+ // to invisible layer
+ SdrLayerID nLayerIdForClone = rObj.GetLayer();
+ if ( !pObj->ISA(SwFlyDrawObj) &&
+ !pObj->ISA(SwVirtFlyDrawObj) &&
+ !IS_TYPE(SdrObject,pObj) )
+ {
+ if ( IsVisibleLayerId( nLayerIdForClone ) )
+ {
+ nLayerIdForClone = GetInvisibleLayerIdByVisibleOne( nLayerIdForClone );
+ }
+ }
+ pObj->SetLayer( nLayerIdForClone );
+
+
+ return pObj;
+}
+
+SwFlyFrmFmt* SwDoc::_MakeFlySection( const SwPosition& rAnchPos,
+ const SwCntntNode& rNode,
+ RndStdIds eRequestId,
+ const SfxItemSet* pFlySet,
+ SwFrmFmt* pFrmFmt )
+{
+ if( !pFrmFmt )
+ pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_FRAME );
+
+ String sName;
+ if( !mbInReading )
+ switch( rNode.GetNodeType() )
+ {
+ case ND_GRFNODE: sName = GetUniqueGrfName(); break;
+ case ND_OLENODE: sName = GetUniqueOLEName(); break;
+ default: sName = GetUniqueFrameName(); break;
+ }
+ SwFlyFrmFmt* pFmt = MakeFlyFrmFmt( sName, pFrmFmt );
+
+ //Inhalt erzeugen und mit dem Format verbinden.
+ //CntntNode erzeugen und in die Autotextsection stellen
+ SwNodeRange aRange( GetNodes().GetEndOfAutotext(), -1,
+ GetNodes().GetEndOfAutotext() );
+ GetNodes().SectionDown( &aRange, SwFlyStartNode );
+
+ pFmt->SetFmtAttr( SwFmtCntnt( rNode.StartOfSectionNode() ));
+
+
+ const SwFmtAnchor* pAnchor = 0;
+ if( pFlySet )
+ {
+ pFlySet->GetItemState( RES_ANCHOR, sal_False,
+ (const SfxPoolItem**)&pAnchor );
+ if( SFX_ITEM_SET == pFlySet->GetItemState( RES_CNTNT, sal_False ))
+ {
+ SfxItemSet aTmpSet( *pFlySet );
+ aTmpSet.ClearItem( RES_CNTNT );
+ pFmt->SetFmtAttr( aTmpSet );
+ }
+ else
+ pFmt->SetFmtAttr( *pFlySet );
+ }
+
+ // Anker noch nicht gesetzt ?
+ RndStdIds eAnchorId = pAnchor ? pAnchor->GetAnchorId()
+ : pFmt->GetAnchor().GetAnchorId();
+ // --> OD 2010-01-07 #i107811#
+ // Assure that at-page anchored fly frames have a page num or a content anchor set.
+ if ( !pAnchor ||
+ ( FLY_AT_PAGE != pAnchor->GetAnchorId() &&
+ !pAnchor->GetCntntAnchor() ) ||
+ ( FLY_AT_PAGE == pAnchor->GetAnchorId() &&
+ !pAnchor->GetCntntAnchor() &&
+ pAnchor->GetPageNum() == 0 ) )
+ {
+ // dann setze ihn, wird im Undo gebraucht
+ SwFmtAnchor aAnch( pFmt->GetAnchor() );
+ if (pAnchor && (FLY_AT_FLY == pAnchor->GetAnchorId()))
+ {
+ SwPosition aPos( *rAnchPos.nNode.GetNode().FindFlyStartNode() );
+ aAnch.SetAnchor( &aPos );
+ eAnchorId = FLY_AT_FLY;
+ }
+ else
+ {
+ if( eRequestId != aAnch.GetAnchorId() &&
+ SFX_ITEM_SET != pFmt->GetItemState( RES_ANCHOR, sal_True ) )
+ {
+ aAnch.SetType( eRequestId );
+ }
+
+ eAnchorId = aAnch.GetAnchorId();
+ if ( FLY_AT_PAGE != eAnchorId ||
+ ( FLY_AT_PAGE == eAnchorId &&
+ ( !pAnchor ||
+ aAnch.GetPageNum() == 0 ) ) )
+ {
+ aAnch.SetAnchor( &rAnchPos );
+ }
+ }
+ // <--
+ pFmt->SetFmtAttr( aAnch );
+ }
+ else
+ eAnchorId = pFmt->GetAnchor().GetAnchorId();
+
+ if ( FLY_AS_CHAR == eAnchorId )
+ {
+ xub_StrLen nStt = rAnchPos.nContent.GetIndex();
+ SwTxtNode * pTxtNode = rAnchPos.nNode.GetNode().GetTxtNode();
+
+ ASSERT(pTxtNode!= 0, "There should be a SwTxtNode!");
+
+ if (pTxtNode != NULL)
+ {
+ SwFmtFlyCnt aFmt( pFmt );
+ pTxtNode->InsertItem( aFmt, nStt, nStt );
+ }
+ }
+
+ if( SFX_ITEM_SET != pFmt->GetAttrSet().GetItemState( RES_FRM_SIZE ))
+ {
+ SwFmtFrmSize aFmtSize( ATT_VAR_SIZE, 0, DEF_FLY_WIDTH );
+ const SwNoTxtNode* pNoTxtNode = rNode.GetNoTxtNode();
+ if( pNoTxtNode )
+ {
+ //Groesse einstellen.
+ Size aSize( pNoTxtNode->GetTwipSize() );
+ if( MINFLY > aSize.Width() )
+ aSize.Width() = DEF_FLY_WIDTH;
+ aFmtSize.SetWidth( aSize.Width() );
+ if( aSize.Height() )
+ {
+ aFmtSize.SetHeight( aSize.Height() );
+ aFmtSize.SetHeightSizeType( ATT_FIX_SIZE );
+ }
+ }
+ pFmt->SetFmtAttr( aFmtSize );
+ }
+
+ // Frames anlegen
+ if( GetRootFrm() )
+ pFmt->MakeFrms(); // ???
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ sal_uLong nNodeIdx = rAnchPos.nNode.GetIndex();
+ xub_StrLen nCntIdx = rAnchPos.nContent.GetIndex();
+ GetIDocumentUndoRedo().AppendUndo(
+ new SwUndoInsLayFmt( pFmt, nNodeIdx, nCntIdx ));
+ }
+
+ SetModified();
+ return pFmt;
+}
+
+SwFlyFrmFmt* SwDoc::MakeFlySection( RndStdIds eAnchorType,
+ const SwPosition* pAnchorPos,
+ const SfxItemSet* pFlySet,
+ SwFrmFmt* pFrmFmt, sal_Bool bCalledFromShell )
+{
+ SwFlyFrmFmt* pFmt = 0;
+ sal_Bool bCallMake = sal_True;
+ if ( !pAnchorPos && (FLY_AT_PAGE != eAnchorType) )
+ {
+ const SwFmtAnchor* pAnch;
+ if( (pFlySet && SFX_ITEM_SET == pFlySet->GetItemState(
+ RES_ANCHOR, sal_False, (const SfxPoolItem**)&pAnch )) ||
+ ( pFrmFmt && SFX_ITEM_SET == pFrmFmt->GetItemState(
+ RES_ANCHOR, sal_True, (const SfxPoolItem**)&pAnch )) )
+ {
+ if ( (FLY_AT_PAGE != pAnch->GetAnchorId()) )
+ {
+ pAnchorPos = pAnch->GetCntntAnchor();
+ if (pAnchorPos)
+ {
+ bCallMake = sal_False;
+ }
+ }
+ }
+ }
+
+ if( bCallMake )
+ {
+ if( !pFrmFmt )
+ pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_FRAME );
+
+ sal_uInt16 nCollId = static_cast<sal_uInt16>(
+ get(IDocumentSettingAccess::HTML_MODE) ? RES_POOLCOLL_TEXT : RES_POOLCOLL_FRAME );
+
+ /* #109161# If there exists no adjust item in the paragraph
+ style for the content node of the new fly section
+ propagate an existing adjust item at the anchor to the new
+ content node. */
+ SwCntntNode * pNewTxtNd = GetNodes().MakeTxtNode
+ (SwNodeIndex( GetNodes().GetEndOfAutotext()),
+ GetTxtCollFromPool( nCollId ));
+ SwCntntNode * pAnchorNode = pAnchorPos->nNode.GetNode().GetCntntNode();
+
+ const SfxPoolItem * pItem = NULL;
+
+ if (bCalledFromShell && !lcl_IsItemSet(*pNewTxtNd, RES_PARATR_ADJUST) &&
+ SFX_ITEM_SET == pAnchorNode->GetSwAttrSet().
+ GetItemState(RES_PARATR_ADJUST, sal_True, &pItem))
+ static_cast<SwCntntNode *>(pNewTxtNd)->SetAttr(*pItem);
+
+ pFmt = _MakeFlySection( *pAnchorPos, *pNewTxtNd,
+ eAnchorType, pFlySet, pFrmFmt );
+ }
+ return pFmt;
+}
+
+SwFlyFrmFmt* SwDoc::MakeFlyAndMove( const SwPaM& rPam, const SfxItemSet& rSet,
+ const SwSelBoxes* pSelBoxes,
+ SwFrmFmt *pParent )
+{
+ SwFmtAnchor& rAnch = (SwFmtAnchor&)rSet.Get( RES_ANCHOR );
+
+ GetIDocumentUndoRedo().StartUndo( UNDO_INSLAYFMT, NULL );
+
+ SwFlyFrmFmt* pFmt = MakeFlySection( rAnch.GetAnchorId(), rPam.GetPoint(),
+ &rSet, pParent );
+
+ // Wenn Inhalt selektiert ist, so wird dieser jetzt zum Inhalt des
+ // neuen Rahmen. Sprich er wird in die entspr. Sektion des NodesArr
+ //gemoved.
+
+ if( pFmt )
+ {
+ do { // middle check loop
+ const SwFmtCntnt &rCntnt = pFmt->GetCntnt();
+ ASSERT( rCntnt.GetCntntIdx(), "Kein Inhalt vorbereitet." );
+ SwNodeIndex aIndex( *(rCntnt.GetCntntIdx()), 1 );
+ SwCntntNode *pNode = aIndex.GetNode().GetCntntNode();
+
+ // ACHTUNG: nicht einen Index auf dem Stack erzeugen, sonst
+ // kann der CntntnNode am Ende nicht geloscht werden !!
+ SwPosition aPos( aIndex );
+ aPos.nContent.Assign( pNode, 0 );
+
+ if( pSelBoxes && pSelBoxes->Count() )
+ {
+ // Tabellenselection
+ // kopiere Teile aus einer Tabelle: lege eine Tabelle mit der
+ // Breite der Originalen an und move (kopiere/loesche) die
+ // selektierten Boxen. Die Groessen werden prozentual
+ // korrigiert.
+
+ SwTableNode* pTblNd = (SwTableNode*)(*pSelBoxes)[0]->
+ GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ break;
+
+ SwTable& rTbl = pTblNd->GetTable();
+
+ // ist die gesamte Tabelle selektiert ?
+ if( pSelBoxes->Count() == rTbl.GetTabSortBoxes().Count() )
+ {
+ // verschiebe die gesamte Tabelle
+ SwNodeRange aRg( *pTblNd, 0, *pTblNd->EndOfSectionNode(), 1 );
+
+ // wird die gesamte Tabelle verschoben und steht diese
+ // in einem FlyFrame, dann erzeuge dahinter einen neuen
+ // TextNode. Dadurch bleibt dieser Fly erhalten !
+ if( aRg.aEnd.GetNode().IsEndNode() )
+ GetNodes().MakeTxtNode( aRg.aStart,
+ (SwTxtFmtColl*)GetDfltTxtFmtColl() );
+
+ MoveNodeRange( aRg, aPos.nNode, DOC_MOVEDEFAULT );
+ }
+ else
+ {
+ rTbl.MakeCopy( this, aPos, *pSelBoxes );
+ // Don't delete a part of a table with row span!!
+ // You could delete the content instead -> ToDo
+ //rTbl.DeleteSel( this, *pSelBoxes, 0, 0, sal_True, sal_True );
+ }
+
+ // wenn Tabelle im Rahmen, dann ohne nachfolgenden TextNode
+ aIndex = rCntnt.GetCntntIdx()->GetNode().EndOfSectionIndex() - 1;
+ ASSERT( aIndex.GetNode().GetTxtNode(),
+ "hier sollte ein TextNode stehen" );
+ aPos.nContent.Assign( 0, 0 ); // Index abmelden !!
+ GetNodes().Delete( aIndex, 1 );
+
+//JP erstmal ein Hack, solange keine Flys/Headers/Footers Undofaehig sind
+// werden erstmal alle Undo - Objecte geloescht.
+if( GetIDocumentUndoRedo().DoesUndo() )
+{
+ GetIDocumentUndoRedo().DelAllUndoObj();
+}
+
+ }
+ else
+ {
+/*
+ // alle Pams verschieben
+ SwPaM* pTmp = (SwPaM*)&rPam;
+ do {
+ if( pTmp->HasMark() &&
+ *pTmp->GetPoint() != *pTmp->GetMark() )
+ MoveAndJoin( *pTmp, aPos );
+ } while( &rPam != ( pTmp = (SwPaM*)pTmp->GetNext() ) );
+*/
+ // copy all Pams and then delete all
+ SwPaM* pTmp = (SwPaM*)&rPam;
+ sal_Bool bOldFlag = mbCopyIsMove;
+ bool const bOldUndo = GetIDocumentUndoRedo().DoesUndo();
+ mbCopyIsMove = sal_True;
+ GetIDocumentUndoRedo().DoUndo(false);
+ do {
+ if( pTmp->HasMark() &&
+ *pTmp->GetPoint() != *pTmp->GetMark() )
+ {
+ CopyRange( *pTmp, aPos, false );
+ }
+ pTmp = static_cast<SwPaM*>(pTmp->GetNext());
+ } while ( &rPam != pTmp );
+ mbCopyIsMove = bOldFlag;
+ GetIDocumentUndoRedo().DoUndo(bOldUndo);
+
+ pTmp = (SwPaM*)&rPam;
+ do {
+ if( pTmp->HasMark() &&
+ *pTmp->GetPoint() != *pTmp->GetMark() )
+ {
+ DeleteAndJoin( *pTmp );
+ }
+ pTmp = static_cast<SwPaM*>(pTmp->GetNext());
+ } while ( &rPam != pTmp );
+ }
+ } while( sal_False );
+ }
+
+ SetModified();
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_INSLAYFMT, NULL );
+
+ return pFmt;
+}
+
+
+ //Einfuegen eines DrawObjectes. Das Object muss bereits im DrawModel
+ // angemeldet sein.
+SwDrawFrmFmt* SwDoc::Insert( const SwPaM &rRg,
+ SdrObject& rDrawObj,
+ const SfxItemSet* pFlyAttrSet,
+ SwFrmFmt* pDefFmt )
+{
+ SwDrawFrmFmt *pFmt = MakeDrawFrmFmt( aEmptyStr,
+ pDefFmt ? pDefFmt : GetDfltFrmFmt() );
+
+ const SwFmtAnchor* pAnchor = 0;
+ if( pFlyAttrSet )
+ {
+ pFlyAttrSet->GetItemState( RES_ANCHOR, sal_False,
+ (const SfxPoolItem**)&pAnchor );
+ pFmt->SetFmtAttr( *pFlyAttrSet );
+ }
+
+ RndStdIds eAnchorId = pAnchor ? pAnchor->GetAnchorId()
+ : pFmt->GetAnchor().GetAnchorId();
+
+ // Anker noch nicht gesetzt ?
+ // DrawObjecte duerfen niemals in Kopf-/Fusszeilen landen.
+ const bool bIsAtCntnt = (FLY_AT_PAGE != eAnchorId);
+
+ const SwNodeIndex* pChkIdx = 0;
+ if( !pAnchor )
+ {
+ pChkIdx = &rRg.GetPoint()->nNode;
+ }
+ else if( bIsAtCntnt )
+ {
+ pChkIdx = pAnchor->GetCntntAnchor()
+ ? &pAnchor->GetCntntAnchor()->nNode
+ : &rRg.GetPoint()->nNode;
+ }
+
+ // OD 24.06.2003 #108784# - allow drawing objects in header/footer, but
+ // control objects aren't allowed in header/footer.
+ if( pChkIdx &&
+ ::CheckControlLayer( &rDrawObj ) &&
+ IsInHeaderFooter( *pChkIdx ) )
+ {
+ pFmt->SetFmtAttr( SwFmtAnchor( eAnchorId = FLY_AT_PAGE ) );
+ }
+ else if( !pAnchor || (bIsAtCntnt && !pAnchor->GetCntntAnchor() ))
+ {
+ // dann setze ihn, wird im Undo gebraucht
+ SwFmtAnchor aAnch( pAnchor ? *pAnchor : pFmt->GetAnchor() );
+ eAnchorId = aAnch.GetAnchorId();
+ if( FLY_AT_FLY == eAnchorId )
+ {
+ SwPosition aPos( *rRg.GetNode()->FindFlyStartNode() );
+ aAnch.SetAnchor( &aPos );
+ }
+ else
+ {
+ aAnch.SetAnchor( rRg.GetPoint() );
+ if ( FLY_AT_PAGE == eAnchorId )
+ {
+ eAnchorId = rDrawObj.ISA( SdrUnoObj )
+ ? FLY_AS_CHAR : FLY_AT_PARA;
+ aAnch.SetType( eAnchorId );
+ }
+ }
+ pFmt->SetFmtAttr( aAnch );
+ }
+
+ // bei als Zeichen gebundenen Draws das Attribut im Absatz setzen
+ if ( FLY_AS_CHAR == eAnchorId )
+ {
+ xub_StrLen nStt = rRg.GetPoint()->nContent.GetIndex();
+ SwFmtFlyCnt aFmt( pFmt );
+ rRg.GetPoint()->nNode.GetNode().GetTxtNode()->InsertItem(
+ aFmt, nStt, nStt );
+ }
+
+ SwDrawContact* pContact = new SwDrawContact( pFmt, &rDrawObj );
+
+ // ggfs. Frames anlegen
+ if( GetRootFrm() )
+ {
+ pFmt->MakeFrms();
+ // --> OD 2005-02-09 #i42319# - follow-up of #i35635#
+ // move object to visible layer
+ // --> OD 2007-07-10 #i79391#
+ if ( pContact->GetAnchorFrm() )
+ {
+ pContact->MoveObjToVisibleLayer( &rDrawObj );
+ }
+ // <--
+ }
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoInsLayFmt(pFmt, 0, 0) );
+ }
+
+ SetModified();
+ return pFmt;
+}
+
+/*************************************************************************
+|*
+|* SwDoc::GetAllFlyFmts
+|*
+|* Ersterstellung MA 14. Jul. 93
+|* Letzte Aenderung MD 23. Feb. 95
+|*
+|*************************************************************************/
+
+/*sal_Bool TstFlyRange( const SwPaM* pPam, sal_uInt32 nFlyPos )
+{
+ sal_Bool bOk = sal_False;
+ const SwPaM* pTmp = pPam;
+ do {
+ bOk = pTmp->Start()->nNode.GetIndex() < nFlyPos &&
+ pTmp->End()->nNode.GetIndex() > nFlyPos;
+ } while( !bOk && pPam != ( pTmp = (const SwPaM*)pTmp->GetNext() ));
+ return bOk;
+}
+*/
+/* -----------------------------04.04.00 10:55--------------------------------
+ paragraph frames - o.k. if the PaM includes the paragraph from the beginning
+ to the beginning of the next paragraph at least
+ frames at character - o.k. if the pam start at least at the same position
+ as the frame
+ ---------------------------------------------------------------------------*/
+sal_Bool TstFlyRange( const SwPaM* pPam, const SwPosition* pFlyPos,
+ RndStdIds nAnchorId )
+{
+ sal_Bool bOk = sal_False;
+ const SwPaM* pTmp = pPam;
+ do {
+ const sal_uInt32 nFlyIndex = pFlyPos->nNode.GetIndex();
+ const SwPosition* pPaMStart = pTmp->Start();
+ const SwPosition* pPaMEnd = pTmp->End();
+ const sal_uInt32 nPamStartIndex = pPaMStart->nNode.GetIndex();
+ const sal_uInt32 nPamEndIndex = pPaMEnd->nNode.GetIndex();
+ if (FLY_AT_PARA == nAnchorId)
+ bOk = (nPamStartIndex < nFlyIndex && nPamEndIndex > nFlyIndex) ||
+ (((nPamStartIndex == nFlyIndex) && (pPaMStart->nContent.GetIndex() == 0)) &&
+ (nPamEndIndex > nFlyIndex));
+ else
+ {
+ xub_StrLen nFlyContentIndex = pFlyPos->nContent.GetIndex();
+ xub_StrLen nPamEndContentIndex = pPaMEnd->nContent.GetIndex();
+ bOk = (nPamStartIndex < nFlyIndex &&
+ (( nPamEndIndex > nFlyIndex )||
+ ((nPamEndIndex == nFlyIndex) &&
+ (nPamEndContentIndex > nFlyContentIndex))) )
+ ||
+ (((nPamStartIndex == nFlyIndex) &&
+ (pPaMStart->nContent.GetIndex() <= nFlyContentIndex)) &&
+ ((nPamEndIndex > nFlyIndex) ||
+ (nPamEndContentIndex > nFlyContentIndex )));
+ }
+
+ } while( !bOk && pPam != ( pTmp = (const SwPaM*)pTmp->GetNext() ));
+ return bOk;
+}
+
+
+void SwDoc::GetAllFlyFmts( SwPosFlyFrms& rPosFlyFmts,
+ const SwPaM* pCmpRange, sal_Bool bDrawAlso ) const
+{
+ SwPosFlyFrm *pFPos = 0;
+ SwFrmFmt *pFly;
+
+ // erstmal alle Absatzgebundenen einsammeln
+ for( sal_uInt16 n = 0; n < GetSpzFrmFmts()->Count(); ++n )
+ {
+ pFly = (*GetSpzFrmFmts())[ n ];
+ bool bDrawFmt = bDrawAlso ? RES_DRAWFRMFMT == pFly->Which() : false;
+ bool bFlyFmt = RES_FLYFRMFMT == pFly->Which();
+ if( bFlyFmt || bDrawFmt )
+ {
+ const SwFmtAnchor& rAnchor = pFly->GetAnchor();
+ SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
+ (FLY_AT_FLY == rAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rAnchor.GetAnchorId())))
+ {
+ if( pCmpRange &&
+ !TstFlyRange( pCmpRange, pAPos, rAnchor.GetAnchorId() ))
+ continue; // kein gueltiger FlyFrame
+ pFPos = new SwPosFlyFrm( pAPos->nNode, pFly, rPosFlyFmts.Count() );
+ rPosFlyFmts.Insert( pFPos );
+ }
+ }
+ }
+
+ // kein Layout oder nur ein Teil, dann wars das
+ // Seitenbezogen Flys nur, wenn vollstaendig "gewuenscht" wird !
+ if( !GetRootFrm() || pCmpRange )
+ return;
+
+ pFPos = 0;
+ SwPageFrm *pPage = (SwPageFrm*)GetRootFrm()->GetLower();
+ while( pPage )
+ {
+ if( pPage->GetSortedObjs() )
+ {
+ SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ for( sal_uInt16 i = 0; i < rObjs.Count(); ++i)
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ pFly = &(pAnchoredObj->GetFrmFmt());
+ else if ( bDrawAlso )
+ pFly = &(pAnchoredObj->GetFrmFmt());
+ else
+ continue;
+
+ const SwFmtAnchor& rAnchor = pFly->GetAnchor();
+ if ((FLY_AT_PARA != rAnchor.GetAnchorId()) &&
+ (FLY_AT_FLY != rAnchor.GetAnchorId()) &&
+ (FLY_AT_CHAR != rAnchor.GetAnchorId()))
+ {
+ const SwCntntFrm * pCntntFrm = pPage->FindFirstBodyCntnt();
+ if ( !pCntntFrm )
+ {
+ //Oops! Eine leere Seite. Damit der Rahmen nicht ganz
+ //verlorengeht (RTF) suchen wir schnell den letzen
+ //Cntnt der vor der Seite steht.
+ SwPageFrm *pPrv = (SwPageFrm*)pPage->GetPrev();
+ while ( !pCntntFrm && pPrv )
+ {
+ pCntntFrm = pPrv->FindFirstBodyCntnt();
+ pPrv = (SwPageFrm*)pPrv->GetPrev();
+ }
+ }
+ if ( pCntntFrm )
+ {
+ SwNodeIndex aIdx( *pCntntFrm->GetNode() );
+ pFPos = new SwPosFlyFrm( aIdx, pFly, rPosFlyFmts.Count() );
+ }
+ }
+ if ( pFPos )
+ {
+ rPosFlyFmts.Insert( pFPos );
+ pFPos = 0;
+ }
+ }
+ }
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwDoc::InsertLabel()
+|*
+|* Ersterstellung MA 11. Feb. 94
+|* Letzte Aenderung MA 12. Nov. 97
+|*
+|*************************************************************************/
+
+/* #i6447# changed behaviour if lcl_CpyAttr:
+
+ If the old item set contains the item to set (no inheritance) copy the item
+ into the new set.
+
+ If the old item set contains the item by inheritance and the new set
+ contains the item, too:
+ If the two items differ copy the item from the old set to the new set.
+
+ Otherwise the new set will not be changed.
+*/
+
+void lcl_CpyAttr( SfxItemSet &rNewSet, const SfxItemSet &rOldSet, sal_uInt16 nWhich )
+{
+ const SfxPoolItem *pOldItem = NULL, *pNewItem = NULL;
+
+ rOldSet.GetItemState( nWhich, sal_False, &pOldItem);
+ if (pOldItem != NULL)
+ rNewSet.Put( *pOldItem );
+ else
+ {
+ pOldItem = rOldSet.GetItem( nWhich, sal_True);
+ if (pOldItem != NULL)
+ {
+ pNewItem = rNewSet.GetItem( nWhich, sal_True);
+ if (pNewItem != NULL)
+ {
+ if (*pOldItem != *pNewItem)
+ rNewSet.Put( *pOldItem );
+ }
+ else {
+ ASSERT(0, "What am I doing here?");
+ }
+ }
+ else {
+ ASSERT(0, "What am I doing here?");
+ }
+ }
+
+}
+
+
+static SwFlyFrmFmt *
+lcl_InsertLabel(SwDoc & rDoc, SwTxtFmtColls *const pTxtFmtCollTbl,
+ SwUndoInsertLabel *const pUndo,
+ SwLabelType const eType, String const& rTxt, String const& rSeparator,
+ const String& rNumberingSeparator,
+ const sal_Bool bBefore, const sal_uInt16 nId, const sal_uLong nNdIdx,
+ const String& rCharacterStyle,
+ const sal_Bool bCpyBrd )
+{
+ ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
+
+ sal_Bool bTable = sal_False; //Um etwas Code zu sparen.
+
+ //Erstmal das Feld bauen, weil ueber den Namen die TxtColl besorgt werden
+ //muss
+ OSL_ENSURE( nId == USHRT_MAX || nId < rDoc.GetFldTypes()->Count(),
+ "FldType index out of bounds." );
+ SwFieldType *pType = (nId != USHRT_MAX) ? (*rDoc.GetFldTypes())[nId] : NULL;
+ OSL_ENSURE(!pType || pType->Which() == RES_SETEXPFLD, "wrong Id for Label");
+
+ SwTxtFmtColl * pColl = NULL;
+ if( pType )
+ {
+ for( sal_uInt16 i = pTxtFmtCollTbl->Count(); i; )
+ {
+ if( (*pTxtFmtCollTbl)[ --i ]->GetName() == pType->GetName() )
+ {
+ pColl = (*pTxtFmtCollTbl)[i];
+ break;
+ }
+ }
+ DBG_ASSERT( pColl, "no text collection found" );
+ }
+
+ if( !pColl )
+ {
+ pColl = rDoc.GetTxtCollFromPool( RES_POOLCOLL_LABEL );
+ }
+
+ SwTxtNode *pNew = NULL;
+ SwFlyFrmFmt* pNewFmt = NULL;
+
+ switch ( eType )
+ {
+ case LTYPE_TABLE:
+ bTable = sal_True;
+ /* Kein Break hier */
+ case LTYPE_FLY:
+ //Am Anfang/Ende der Fly-Section den entsprechenden Node mit Feld
+ //einfuegen (Frame wird automatisch erzeugt).
+ {
+ SwStartNode *pSttNd = rDoc.GetNodes()[nNdIdx]->GetStartNode();
+ ASSERT( pSttNd, "Kein StartNode in InsertLabel." );
+ sal_uLong nNode;
+ if( bBefore )
+ {
+ nNode = pSttNd->GetIndex();
+ if( !bTable )
+ ++nNode;
+ }
+ else
+ {
+ nNode = pSttNd->EndOfSectionIndex();
+ if( bTable )
+ ++nNode;
+ }
+
+ if( pUndo )
+ pUndo->SetNodePos( nNode );
+
+ //Node fuer Beschriftungsabsatz erzeugen.
+ SwNodeIndex aIdx( rDoc.GetNodes(), nNode );
+ pNew = rDoc.GetNodes().MakeTxtNode( aIdx, pColl );
+ }
+ break;
+
+ case LTYPE_OBJECT:
+ {
+ //Rahmen zerstoeren, neuen Rahmen einfuegen, entsprechenden
+ // Node mit Feld in den neuen Rahmen, den alten Rahmen mit
+ // dem Object (Grafik/Ole) absatzgebunden in den neuen Rahmen,
+ // Frames erzeugen.
+
+ //Erstmal das Format zum Fly besorgen und das Layout entkoppeln.
+ SwFrmFmt *pOldFmt = rDoc.GetNodes()[nNdIdx]->GetFlyFmt();
+ ASSERT( pOldFmt, "Format des Fly nicht gefunden." );
+ // --> OD #i115719#
+ // <title> and <description> attributes are lost when calling <DelFrms()>.
+ // Thus, keep them and restore them after the calling <MakeFrms()>
+ const bool bIsSwFlyFrmFmtInstance( dynamic_cast<SwFlyFrmFmt*>(pOldFmt) != 0 );
+ const String sTitle( bIsSwFlyFrmFmtInstance
+ ? static_cast<SwFlyFrmFmt*>(pOldFmt)->GetObjTitle()
+ : String() );
+ const String sDescription( bIsSwFlyFrmFmtInstance
+ ? static_cast<SwFlyFrmFmt*>(pOldFmt)->GetObjDescription()
+ : String() );
+ // <--
+ pOldFmt->DelFrms();
+
+ pNewFmt = rDoc.MakeFlyFrmFmt( rDoc.GetUniqueFrameName(),
+ rDoc.GetFrmFmtFromPool(RES_POOLFRM_FRAME) );
+
+ /* #i6447#: Only the selected items are copied from the old
+ format. */
+ SfxItemSet* pNewSet = pNewFmt->GetAttrSet().Clone( sal_True );
+
+
+ //Diejenigen Attribute uebertragen die auch gesetzt sind,
+ //andere sollen weiterhin aus den Vorlagen gueltig werden.
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_PRINT );
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_OPAQUE );
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_PROTECT );
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_SURROUND );
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_VERT_ORIENT );
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_HORI_ORIENT );
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_LR_SPACE );
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_UL_SPACE );
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_BACKGROUND );
+ if( bCpyBrd )
+ {
+ // JP 07.07.99: Bug 67029 - if at Grafik no BoxItem but
+ // in the new Format is any, then set the
+ // default item in the new Set. Because
+ // the Size of the Grafik have never been
+ // changed!
+ const SfxPoolItem *pItem;
+ if( SFX_ITEM_SET == pOldFmt->GetAttrSet().
+ GetItemState( RES_BOX, sal_True, &pItem ))
+ pNewSet->Put( *pItem );
+ else if( SFX_ITEM_SET == pNewFmt->GetAttrSet().
+ GetItemState( RES_BOX, sal_True ))
+ pNewSet->Put( *GetDfltAttr( RES_BOX ) );
+
+ if( SFX_ITEM_SET == pOldFmt->GetAttrSet().
+ GetItemState( RES_SHADOW, sal_True, &pItem ))
+ pNewSet->Put( *pItem );
+ else if( SFX_ITEM_SET == pNewFmt->GetAttrSet().
+ GetItemState( RES_SHADOW, sal_True ))
+ pNewSet->Put( *GetDfltAttr( RES_SHADOW ) );
+ }
+ else
+ {
+ //Die Attribute hart setzen, weil sie sonst aus der
+ // Vorlage kommen koenten und dann passt die
+ // Grossenberechnung nicht mehr.
+ pNewSet->Put( SvxBoxItem(RES_BOX) );
+ pNewSet->Put( SvxShadowItem(RES_SHADOW) );
+
+ }
+
+ //Anker immer uebertragen, ist sowieso ein hartes Attribut.
+ pNewSet->Put( pOldFmt->GetAnchor() );
+
+ //In der Hoehe soll der neue Varabel sein!
+ SwFmtFrmSize aFrmSize( pOldFmt->GetFrmSize() );
+ aFrmSize.SetHeightSizeType( ATT_MIN_SIZE );
+ pNewSet->Put( aFrmSize );
+
+ SwStartNode* pSttNd = rDoc.GetNodes().MakeTextSection(
+ SwNodeIndex( rDoc.GetNodes().GetEndOfAutotext() ),
+ SwFlyStartNode, pColl );
+ pNewSet->Put( SwFmtCntnt( pSttNd ));
+
+ pNewFmt->SetFmtAttr( *pNewSet );
+
+ //Bei InCntnt's wird es spannend: Das TxtAttribut muss
+ //vernichtet werden. Leider reisst dies neben den Frms auch
+ //noch das Format mit in sein Grab. Um dass zu unterbinden
+ //loesen wir vorher die Verbindung zwischen Attribut und Format.
+
+ const SwFmtAnchor& rAnchor = pNewFmt->GetAnchor();
+ if ( FLY_AS_CHAR == rAnchor.GetAnchorId() )
+ {
+ const SwPosition *pPos = rAnchor.GetCntntAnchor();
+ SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
+ ASSERT( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
+ const xub_StrLen nIdx = pPos->nContent.GetIndex();
+ SwTxtAttr * const pHnt =
+ pTxtNode->GetTxtAttrForCharAt(nIdx, RES_TXTATR_FLYCNT);
+
+ ASSERT( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
+ "Missing FlyInCnt-Hint." );
+ ASSERT( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pOldFmt,
+ "Wrong TxtFlyCnt-Hint." );
+
+ const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt(
+ pNewFmt );
+ }
+
+
+ //Der Alte soll keinen Umlauf haben, und er soll oben/mittig
+ //ausgerichtet sein.
+ //Ausserdem soll die Breite 100% betragen und bei Aenderungen
+ //Die Hoehe mit anpassen.
+ pNewSet->ClearItem();
+
+ pNewSet->Put( SwFmtSurround( SURROUND_NONE ) );
+ pNewSet->Put( SvxOpaqueItem( RES_OPAQUE, sal_True ) );
+ pNewSet->Put( SwFmtVertOrient( text::VertOrientation::TOP ) );
+ pNewSet->Put( SwFmtHoriOrient( text::HoriOrientation::CENTER ) );
+
+ aFrmSize = pOldFmt->GetFrmSize();
+ aFrmSize.SetWidthPercent( 100 );
+ aFrmSize.SetHeightPercent( 255 );
+ pNewSet->Put( aFrmSize );
+
+ //Die Attribute setzen wir hart, weil sie sonst aus der Vorlage
+ //kommen koenten und dann passt die Grossenberechnung nicht mehr.
+ if( bCpyBrd )
+ {
+ pNewSet->Put( SvxBoxItem(RES_BOX) );
+ pNewSet->Put( SvxShadowItem(RES_SHADOW) );
+ }
+ pNewSet->Put( SvxLRSpaceItem(RES_LR_SPACE) );
+ pNewSet->Put( SvxULSpaceItem(RES_UL_SPACE) );
+
+ //Der Alte ist absatzgebunden, und zwar am Absatz im neuen.
+ SwFmtAnchor aAnch( FLY_AT_PARA );
+ SwNodeIndex aAnchIdx( *pNewFmt->GetCntnt().GetCntntIdx(), 1 );
+ pNew = aAnchIdx.GetNode().GetTxtNode();
+ SwPosition aPos( aAnchIdx );
+ aAnch.SetAnchor( &aPos );
+ pNewSet->Put( aAnch );
+
+ if( pUndo )
+ pUndo->SetFlys( *pOldFmt, *pNewSet, *pNewFmt );
+ else
+ pOldFmt->SetFmtAttr( *pNewSet );
+
+ delete pNewSet;
+
+ //Nun nur noch die Flys erzeugen lassen. Das ueberlassen
+ //wir vorhanden Methoden (insb. fuer InCntFlys etwas aufwendig).
+ pNewFmt->MakeFrms();
+ // --> OD #i115719#
+ if ( bIsSwFlyFrmFmtInstance )
+ {
+ static_cast<SwFlyFrmFmt*>(pOldFmt)->SetObjTitle( sTitle );
+ static_cast<SwFlyFrmFmt*>(pOldFmt)->SetObjDescription( sDescription );
+ }
+ // <--
+ }
+ break;
+
+ default:
+ OSL_ENSURE(false, "unknown LabelType?");
+ }
+ ASSERT( pNew, "No Label inserted" );
+ if( pNew )
+ {
+ //#i61007# order of captions
+ sal_Bool bOrderNumberingFirst = SW_MOD()->GetModuleConfig()->IsCaptionOrderNumberingFirst();
+ //String aufbereiten
+ String aTxt;
+ if( bOrderNumberingFirst )
+ {
+ aTxt = rNumberingSeparator;
+ }
+ if( pType)
+ {
+ aTxt += pType->GetName();
+ if( !bOrderNumberingFirst )
+ aTxt += ' ';
+ }
+ xub_StrLen nIdx = aTxt.Len();
+ if( rTxt.Len() > 0 )
+ {
+ aTxt += rSeparator;
+ }
+ xub_StrLen nSepIdx = aTxt.Len();
+ aTxt += rTxt;
+
+ //String einfuegen
+ SwIndex aIdx( pNew, 0 );
+ pNew->InsertText( aTxt, aIdx );
+
+ //
+ //Feld einfuegen
+ if(pType)
+ {
+ SwSetExpField aFld( (SwSetExpFieldType*)pType, aEmptyStr, SVX_NUM_ARABIC);
+ if( bOrderNumberingFirst )
+ nIdx = 0;
+ SwFmtFld aFmt( aFld );
+ pNew->InsertItem( aFmt, nIdx, nIdx );
+ if(rCharacterStyle.Len())
+ {
+ SwCharFmt* pCharFmt = rDoc.FindCharFmtByName(rCharacterStyle);
+ if( !pCharFmt )
+ {
+ const sal_uInt16 nMyId = SwStyleNameMapper::GetPoolIdFromUIName(rCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT);
+ pCharFmt = rDoc.GetCharFmtFromPool( nMyId );
+ }
+ if (pCharFmt)
+ {
+ SwFmtCharFmt aCharFmt( pCharFmt );
+ pNew->InsertItem( aCharFmt, 0,
+ nSepIdx + 1, nsSetAttrMode::SETATTR_DONTEXPAND );
+ }
+ }
+ }
+
+ if ( bTable )
+ {
+ if ( bBefore )
+ {
+ if ( !pNew->GetSwAttrSet().GetKeep().GetValue() )
+ pNew->SetAttr( SvxFmtKeepItem( sal_True, RES_KEEP ) );
+ }
+ else
+ {
+ SwTableNode *const pNd =
+ rDoc.GetNodes()[nNdIdx]->GetStartNode()->GetTableNode();
+ SwTable &rTbl = pNd->GetTable();
+ if ( !rTbl.GetFrmFmt()->GetKeep().GetValue() )
+ rTbl.GetFrmFmt()->SetFmtAttr( SvxFmtKeepItem( sal_True, RES_KEEP ) );
+ if ( pUndo )
+ pUndo->SetUndoKeep();
+ }
+ }
+ rDoc.SetModified();
+ }
+
+ return pNewFmt;
+}
+
+SwFlyFrmFmt *
+SwDoc::InsertLabel(
+ SwLabelType const eType, String const& rTxt, String const& rSeparator,
+ String const& rNumberingSeparator,
+ sal_Bool const bBefore, sal_uInt16 const nId, sal_uLong const nNdIdx,
+ String const& rCharacterStyle,
+ sal_Bool const bCpyBrd )
+{
+ SwUndoInsertLabel * pUndo(0);
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo = new SwUndoInsertLabel(
+ eType, rTxt, rSeparator, rNumberingSeparator,
+ bBefore, nId, rCharacterStyle, bCpyBrd );
+ }
+
+ SwFlyFrmFmt *const pNewFmt = lcl_InsertLabel(*this, pTxtFmtCollTbl, pUndo,
+ eType, rTxt, rSeparator, rNumberingSeparator, bBefore,
+ nId, nNdIdx, rCharacterStyle, bCpyBrd);
+
+ if (pUndo)
+ {
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ else
+ {
+ GetIDocumentUndoRedo().DelAllUndoObj();
+ }
+
+ return pNewFmt;
+}
+
+
+/*************************************************************************
+|*
+|* SwDoc::InsertDrawLabel()
+|*
+|* Ersterstellung MIB 7. Dez. 98
+|* Letzte Aenderung MIB 7. Dez. 98
+|*
+|*************************************************************************/
+
+static SwFlyFrmFmt *
+lcl_InsertDrawLabel( SwDoc & rDoc, SwTxtFmtColls *const pTxtFmtCollTbl,
+ SwUndoInsertLabel *const pUndo, SwDrawFrmFmt *const pOldFmt,
+ String const& rTxt,
+ const String& rSeparator,
+ const String& rNumberSeparator,
+ const sal_uInt16 nId,
+ const String& rCharacterStyle,
+ SdrObject& rSdrObj )
+{
+ ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
+ ::sw::DrawUndoGuard const drawUndoGuard(rDoc.GetIDocumentUndoRedo());
+
+ // Erstmal das Feld bauen, weil ueber den Namen die TxtColl besorgt
+ // werden muss
+ OSL_ENSURE( nId == USHRT_MAX || nId < rDoc.GetFldTypes()->Count(),
+ "FldType index out of bounds" );
+ SwFieldType *pType = nId != USHRT_MAX ? (*rDoc.GetFldTypes())[nId] : 0;
+ OSL_ENSURE( !pType || pType->Which() == RES_SETEXPFLD, "Wrong label id" );
+
+ SwTxtFmtColl *pColl = NULL;
+ if( pType )
+ {
+ for( sal_uInt16 i = pTxtFmtCollTbl->Count(); i; )
+ {
+ if( (*pTxtFmtCollTbl)[ --i ]->GetName() == pType->GetName() )
+ {
+ pColl = (*pTxtFmtCollTbl)[i];
+ break;
+ }
+ }
+ DBG_ASSERT( pColl, "no text collection found" );
+ }
+
+ if( !pColl )
+ {
+ pColl = rDoc.GetTxtCollFromPool( RES_POOLCOLL_LABEL );
+ }
+
+ SwTxtNode* pNew = NULL;
+ SwFlyFrmFmt* pNewFmt = NULL;
+
+ // Rahmen zerstoeren, neuen Rahmen einfuegen, entsprechenden
+ // Node mit Feld in den neuen Rahmen, den alten Rahmen mit
+ // dem Object (Grafik/Ole) absatzgebunden in den neuen Rahmen,
+ // Frames erzeugen.
+
+ // OD 27.11.2003 #112045# - Keep layer ID of drawing object before removing
+ // its frames.
+ // Note: The layer ID is passed to the undo and have to be the correct value.
+ // Removing the frames of the drawing object changes its layer.
+ const SdrLayerID nLayerId = rSdrObj.GetLayer();
+
+ pOldFmt->DelFrms();
+
+ //Bei InCntnt's wird es spannend: Das TxtAttribut muss
+ //vernichtet werden. Leider reisst dies neben den Frms auch
+ //noch das Format mit in sein Grab. Um dass zu unterbinden
+ //loesen wir vorher die Verbindung zwischen Attribut und Format.
+ SfxItemSet* pNewSet = pOldFmt->GetAttrSet().Clone( sal_False );
+
+ // Ggf. Groesse und Position des Rahmens schuetzen
+ if ( rSdrObj.IsMoveProtect() || rSdrObj.IsResizeProtect() )
+ {
+ SvxProtectItem aProtect(RES_PROTECT);
+ aProtect.SetCntntProtect( sal_False );
+ aProtect.SetPosProtect( rSdrObj.IsMoveProtect() );
+ aProtect.SetSizeProtect( rSdrObj.IsResizeProtect() );
+ pNewSet->Put( aProtect );
+ }
+
+ // Umlauf uebernehmen
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_SURROUND );
+
+ // Den Rahmen ggf. in den Hintergrund schicken.
+ // OD 02.07.2003 #108784# - consider 'invisible' hell layer.
+ if ( rDoc.GetHellId() != nLayerId &&
+ rDoc.GetInvisibleHellId() != nLayerId )
+ {
+ SvxOpaqueItem aOpaque( RES_OPAQUE );
+ aOpaque.SetValue( sal_True );
+ pNewSet->Put( aOpaque );
+ }
+
+ // Position uebernehmen
+ // OD 2004-04-15 #i26791# - use directly the positioning attributes of
+ // the drawing object.
+ pNewSet->Put( pOldFmt->GetHoriOrient() );
+ pNewSet->Put( pOldFmt->GetVertOrient() );
+
+ pNewSet->Put( pOldFmt->GetAnchor() );
+
+ //In der Hoehe soll der neue Varabel sein!
+ Size aSz( rSdrObj.GetCurrentBoundRect().GetSize() );
+ SwFmtFrmSize aFrmSize( ATT_MIN_SIZE, aSz.Width(), aSz.Height() );
+ pNewSet->Put( aFrmSize );
+
+ // Abstaende auf den neuen Rahmen uebertragen. Eine Umrandung
+ // gibt es beu Zeichen-Objekten nicht, also muss sie geloescht
+ // werden.
+ // MA: Falsch sie wird nicht gesetzt, denn die aus der Vorlage
+ // soll ruhig wirksam werden
+ pNewSet->Put( pOldFmt->GetLRSpace() );
+ pNewSet->Put( pOldFmt->GetULSpace() );
+
+ SwStartNode* pSttNd =
+ rDoc.GetNodes().MakeTextSection(
+ SwNodeIndex( rDoc.GetNodes().GetEndOfAutotext() ),
+ SwFlyStartNode, pColl );
+
+ pNewFmt = rDoc.MakeFlyFrmFmt( rDoc.GetUniqueFrameName(),
+ rDoc.GetFrmFmtFromPool( RES_POOLFRM_FRAME ) );
+
+ // JP 28.10.99: Bug 69487 - set border and shadow to default if the
+ // template contains any.
+ if( SFX_ITEM_SET == pNewFmt->GetAttrSet().GetItemState( RES_BOX, sal_True ))
+ pNewSet->Put( *GetDfltAttr( RES_BOX ) );
+
+ if( SFX_ITEM_SET == pNewFmt->GetAttrSet().GetItemState(RES_SHADOW,sal_True))
+ pNewSet->Put( *GetDfltAttr( RES_SHADOW ) );
+
+ pNewFmt->SetFmtAttr( SwFmtCntnt( pSttNd ));
+ pNewFmt->SetFmtAttr( *pNewSet );
+
+ const SwFmtAnchor& rAnchor = pNewFmt->GetAnchor();
+ if ( FLY_AS_CHAR == rAnchor.GetAnchorId() )
+ {
+ const SwPosition *pPos = rAnchor.GetCntntAnchor();
+ SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
+ ASSERT( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
+ const xub_StrLen nIdx = pPos->nContent.GetIndex();
+ SwTxtAttr * const pHnt =
+ pTxtNode->GetTxtAttrForCharAt( nIdx, RES_TXTATR_FLYCNT );
+
+#ifdef DBG_UTIL
+ ASSERT( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
+ "Missing FlyInCnt-Hint." );
+ ASSERT( pHnt && ((SwFmtFlyCnt&)pHnt->GetFlyCnt()).
+ GetFrmFmt() == (SwFrmFmt*)pOldFmt,
+ "Wrong TxtFlyCnt-Hint." );
+#endif
+ const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt( pNewFmt );
+ }
+
+
+ //Der Alte soll keinen Umlauf haben, und er soll oben/mittig
+ //ausgerichtet sein.
+ pNewSet->ClearItem();
+
+ pNewSet->Put( SwFmtSurround( SURROUND_NONE ) );
+ if (nLayerId == rDoc.GetHellId())
+ {
+ rSdrObj.SetLayer( rDoc.GetHeavenId() );
+ }
+ // OD 02.07.2003 #108784# - consider drawing objects in 'invisible' hell layer
+ else if (nLayerId == rDoc.GetInvisibleHellId())
+ {
+ rSdrObj.SetLayer( rDoc.GetInvisibleHeavenId() );
+ }
+ pNewSet->Put( SvxLRSpaceItem( RES_LR_SPACE ) );
+ pNewSet->Put( SvxULSpaceItem( RES_UL_SPACE ) );
+
+ // OD 2004-04-15 #i26791# - set position of the drawing object, which is labeled.
+ pNewSet->Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ) );
+ pNewSet->Put( SwFmtHoriOrient( 0, text::HoriOrientation::CENTER, text::RelOrientation::FRAME ) );
+
+ //Der Alte ist absatzgebunden, und zwar am Absatz im neuen.
+ SwFmtAnchor aAnch( FLY_AT_PARA );
+ SwNodeIndex aAnchIdx( *pNewFmt->GetCntnt().GetCntntIdx(), 1 );
+ pNew = aAnchIdx.GetNode().GetTxtNode();
+ SwPosition aPos( aAnchIdx );
+ aAnch.SetAnchor( &aPos );
+ pNewSet->Put( aAnch );
+
+ if( pUndo )
+ {
+ pUndo->SetFlys( *pOldFmt, *pNewSet, *pNewFmt );
+ // OD 2004-04-15 #i26791# - position no longer needed
+ pUndo->SetDrawObj( nLayerId );
+ }
+ else
+ pOldFmt->SetFmtAttr( *pNewSet );
+
+ delete pNewSet;
+
+ //Nun nur noch die Flys erzeugen lassen. Das ueberlassen
+ //wir vorhanden Methoden (insb. fuer InCntFlys etwas aufwendig).
+ pNewFmt->MakeFrms();
+
+ ASSERT( pNew, "No Label inserted" );
+
+ if( pNew )
+ {
+ //#i61007# order of captions
+ sal_Bool bOrderNumberingFirst = SW_MOD()->GetModuleConfig()->IsCaptionOrderNumberingFirst();
+
+ // prepare string
+ String aTxt;
+ if( bOrderNumberingFirst )
+ {
+ aTxt = rNumberSeparator;
+ }
+ if ( pType )
+ {
+ aTxt += pType->GetName();
+ if( !bOrderNumberingFirst )
+ aTxt += ' ';
+ }
+ xub_StrLen nIdx = aTxt.Len();
+ aTxt += rSeparator;
+ xub_StrLen nSepIdx = aTxt.Len();
+ aTxt += rTxt;
+
+ // insert text
+ SwIndex aIdx( pNew, 0 );
+ pNew->InsertText( aTxt, aIdx );
+
+ // insert field
+ if ( pType )
+ {
+ SwSetExpField aFld( (SwSetExpFieldType*)pType, aEmptyStr, SVX_NUM_ARABIC );
+ if( bOrderNumberingFirst )
+ nIdx = 0;
+ SwFmtFld aFmt( aFld );
+ pNew->InsertItem( aFmt, nIdx, nIdx );
+ if ( rCharacterStyle.Len() )
+ {
+ SwCharFmt * pCharFmt = rDoc.FindCharFmtByName(rCharacterStyle);
+ if ( !pCharFmt )
+ {
+ const sal_uInt16 nMyId = SwStyleNameMapper::GetPoolIdFromUIName( rCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
+ pCharFmt = rDoc.GetCharFmtFromPool( nMyId );
+ }
+ if ( pCharFmt )
+ {
+ SwFmtCharFmt aCharFmt( pCharFmt );
+ pNew->InsertItem( aCharFmt, 0, nSepIdx + 1,
+ nsSetAttrMode::SETATTR_DONTEXPAND );
+ }
+ }
+ }
+ }
+
+ return pNewFmt;
+}
+
+SwFlyFrmFmt* SwDoc::InsertDrawLabel(
+ String const& rTxt,
+ String const& rSeparator,
+ String const& rNumberSeparator,
+ sal_uInt16 const nId,
+ String const& rCharacterStyle,
+ SdrObject& rSdrObj )
+{
+ SwDrawContact *const pContact =
+ static_cast<SwDrawContact*>(GetUserCall( &rSdrObj ));
+ OSL_ENSURE( RES_DRAWFRMFMT == pContact->GetFmt()->Which(),
+ "InsertDrawLabel(): not a DrawFrmFmt" );
+ if (!pContact)
+ return 0;
+
+ SwDrawFrmFmt* pOldFmt = (SwDrawFrmFmt *)pContact->GetFmt();
+ if (!pOldFmt)
+ return 0;
+
+ SwUndoInsertLabel * pUndo = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ pUndo = new SwUndoInsertLabel(
+ LTYPE_DRAW, rTxt, rSeparator, rNumberSeparator, sal_False,
+ nId, rCharacterStyle, sal_False );
+ }
+
+ SwFlyFrmFmt *const pNewFmt = lcl_InsertDrawLabel(
+ *this, pTxtFmtCollTbl, pUndo, pOldFmt,
+ rTxt, rSeparator, rNumberSeparator, nId, rCharacterStyle, rSdrObj);
+
+ if (pUndo)
+ {
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ else
+ {
+ GetIDocumentUndoRedo().DelAllUndoObj();
+ }
+
+ return pNewFmt;
+}
+
+
+/*************************************************************************
+|*
+|* IDocumentTimerAccess-methods
+|*
+|*************************************************************************/
+
+void SwDoc::StartIdling()
+{
+ mbStartIdleTimer = sal_True;
+ if( !mIdleBlockCount )
+ aIdleTimer.Start();
+}
+
+void SwDoc::StopIdling()
+{
+ mbStartIdleTimer = sal_False;
+ aIdleTimer.Stop();
+}
+
+void SwDoc::BlockIdling()
+{
+ aIdleTimer.Stop();
+ ++mIdleBlockCount;
+}
+
+void SwDoc::UnblockIdling()
+{
+ --mIdleBlockCount;
+ if( !mIdleBlockCount && mbStartIdleTimer && !aIdleTimer.IsActive() )
+ aIdleTimer.Start();
+}
+
+
+/*************************************************************************
+|*
+|* SwDoc::DoIdleJobs()
+|*
+|* Ersterstellung OK 30.03.94
+|* Letzte Aenderung MA 09. Jun. 95
+|*
+|*************************************************************************/
+
+IMPL_LINK( SwDoc, DoIdleJobs, Timer *, pTimer )
+{
+#ifdef TIMELOG
+ static ::rtl::Logfile* pModLogFile = 0;
+ if( !pModLogFile )
+ pModLogFile = new ::rtl::Logfile( "First DoIdleJobs" );
+#endif
+
+ if( GetRootFrm() && GetRootFrm()->GetCurrShell() &&
+ !SfxProgress::GetActiveProgress( pDocShell ) )
+ {
+ ViewShell *pSh, *pStartSh;
+ pSh = pStartSh = GetRootFrm()->GetCurrShell();
+ do {
+ if( pSh->ActionPend() )
+ {
+ if( pTimer )
+ pTimer->Start();
+ return 0;
+ }
+ pSh = (ViewShell*)pSh->GetNext();
+ } while( pSh != pStartSh );
+
+ if (GetRootFrm()->IsNeedGrammarCheck())
+ {
+ sal_Bool bIsOnlineSpell = pSh->GetViewOptions()->IsOnlineSpell();
+
+ sal_Bool bIsAutoGrammar = sal_False;
+ SvtLinguConfig().GetProperty( ::rtl::OUString::createFromAscii(
+ UPN_IS_GRAMMAR_AUTO ) ) >>= bIsAutoGrammar;
+
+ if (bIsOnlineSpell && bIsAutoGrammar)
+ StartGrammarChecking( *this );
+ }
+
+ sal_uInt16 nFldUpdFlag;
+ if( GetRootFrm()->IsIdleFormat() )
+ GetRootFrm()->GetCurrShell()->LayoutIdle();
+ else if( ( AUTOUPD_FIELD_ONLY ==
+ ( nFldUpdFlag = static_cast<sal_uInt16>(getFieldUpdateFlags(true)) )
+ || AUTOUPD_FIELD_AND_CHARTS == nFldUpdFlag ) &&
+ GetUpdtFlds().IsFieldsDirty() &&
+ !GetUpdtFlds().IsInUpdateFlds() &&
+ !IsExpFldsLocked()
+ // das umschalten der Feldname fuehrt zu keinem Update der
+ // Felder, also der "Hintergrund-Update" immer erfolgen
+ /* && !pStartSh->GetViewOptions()->IsFldName()*/ )
+ {
+ // chaos::Action-Klammerung!
+ GetUpdtFlds().SetInUpdateFlds( sal_True );
+
+ GetRootFrm()->StartAllAction();
+
+ // no jump on update of fields #i85168#
+ const sal_Bool bOldLockView = pStartSh->IsViewLocked();
+ pStartSh->LockView( sal_True );
+
+ GetSysFldType( RES_CHAPTERFLD )->Modify( 0, 0 ); // KapitelFld
+ UpdateExpFlds( 0, sal_False ); // Expression-Felder Updaten
+ UpdateTblFlds(NULL); // Tabellen
+ UpdateRefFlds(NULL); // Referenzen
+
+ GetRootFrm()->EndAllAction();
+
+ pStartSh->LockView( bOldLockView );
+
+ GetUpdtFlds().SetInUpdateFlds( sal_False );
+ GetUpdtFlds().SetFieldsDirty( sal_False );
+ }
+ }
+#ifdef TIMELOG
+ if( pModLogFile && 1 != (long)pModLogFile )
+ delete pModLogFile, ((long&)pModLogFile) = 1;
+#endif
+ if( pTimer )
+ pTimer->Start();
+ return 0;
+}
+
+IMPL_STATIC_LINK( SwDoc, BackgroundDone, SvxBrushItem*, EMPTYARG )
+{
+ ViewShell *pSh, *pStartSh;
+ pSh = pStartSh = pThis->GetRootFrm()->GetCurrShell();
+ if( pStartSh )
+ do {
+ if( pSh->GetWin() )
+ {
+ //Fuer Repaint mir virtuellen Device sorgen.
+ pSh->LockPaint();
+ pSh->UnlockPaint( sal_True );
+ }
+ pSh = (ViewShell*)pSh->GetNext();
+ } while( pSh != pStartSh );
+ return 0;
+}
+
+static String lcl_GetUniqueFlyName( const SwDoc* pDoc, sal_uInt16 nDefStrId )
+{
+ ResId aId( nDefStrId, *pSwResMgr );
+ String aName( aId );
+ xub_StrLen nNmLen = aName.Len();
+
+ const SwSpzFrmFmts& rFmts = *pDoc->GetSpzFrmFmts();
+
+ sal_uInt16 nNum, nTmp, nFlagSize = ( rFmts.Count() / 8 ) +2;
+ sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
+ sal_uInt16 n;
+
+ memset( pSetFlags, 0, nFlagSize );
+
+ for( n = 0; n < rFmts.Count(); ++n )
+ {
+ const SwFrmFmt* pFlyFmt = rFmts[ n ];
+ if( RES_FLYFRMFMT == pFlyFmt->Which() &&
+ pFlyFmt->GetName().Match( aName ) == nNmLen )
+ {
+ // Nummer bestimmen und das Flag setzen
+ nNum = static_cast< sal_uInt16 >( pFlyFmt->GetName().Copy( nNmLen ).ToInt32() );
+ if( nNum-- && nNum < rFmts.Count() )
+ pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
+ }
+ }
+
+ // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
+ nNum = rFmts.Count();
+ for( n = 0; n < nFlagSize; ++n )
+ if( 0xff != ( nTmp = pSetFlags[ n ] ))
+ {
+ // also die Nummer bestimmen
+ nNum = n * 8;
+ while( nTmp & 1 )
+ ++nNum, nTmp >>= 1;
+ break;
+ }
+
+ delete [] pSetFlags;
+ return aName += String::CreateFromInt32( ++nNum );
+}
+
+String SwDoc::GetUniqueGrfName() const
+{
+ return lcl_GetUniqueFlyName( this, STR_GRAPHIC_DEFNAME );
+}
+
+String SwDoc::GetUniqueOLEName() const
+{
+ return lcl_GetUniqueFlyName( this, STR_OBJECT_DEFNAME );
+}
+
+String SwDoc::GetUniqueFrameName() const
+{
+ return lcl_GetUniqueFlyName( this, STR_FRAME_DEFNAME );
+}
+
+const SwFlyFrmFmt* SwDoc::FindFlyByName( const String& rName, sal_Int8 nNdTyp ) const
+{
+ const SwSpzFrmFmts& rFmts = *GetSpzFrmFmts();
+ for( sal_uInt16 n = rFmts.Count(); n; )
+ {
+ const SwFrmFmt* pFlyFmt = rFmts[ --n ];
+ const SwNodeIndex* pIdx;
+ if( RES_FLYFRMFMT == pFlyFmt->Which() && pFlyFmt->GetName() == rName &&
+ 0 != ( pIdx = pFlyFmt->GetCntnt().GetCntntIdx() ) &&
+ pIdx->GetNode().GetNodes().IsDocNodes() )
+ {
+ if( nNdTyp )
+ {
+ // dann noch auf den richtigen Node-Typ abfragen
+ const SwNode* pNd = GetNodes()[ pIdx->GetIndex()+1 ];
+ if( nNdTyp == ND_TEXTNODE
+ ? !pNd->IsNoTxtNode()
+ : nNdTyp == pNd->GetNodeType() )
+ return (SwFlyFrmFmt*)pFlyFmt;
+ }
+ else
+ return (SwFlyFrmFmt*)pFlyFmt;
+ }
+ }
+ return 0;
+}
+
+void SwDoc::SetFlyName( SwFlyFrmFmt& rFmt, const String& rName )
+{
+ String sName( rName );
+ if( !rName.Len() || FindFlyByName( rName ) )
+ {
+ sal_uInt16 nTyp = STR_FRAME_DEFNAME;
+ const SwNodeIndex* pIdx = rFmt.GetCntnt().GetCntntIdx();
+ if( pIdx && pIdx->GetNode().GetNodes().IsDocNodes() )
+ switch( GetNodes()[ pIdx->GetIndex() + 1 ]->GetNodeType() )
+ {
+ case ND_GRFNODE: nTyp = STR_GRAPHIC_DEFNAME; break;
+ case ND_OLENODE: nTyp = STR_OBJECT_DEFNAME; break;
+ }
+ sName = lcl_GetUniqueFlyName( this, nTyp );
+ }
+ rFmt.SetName( sName, sal_True );
+ SetModified();
+}
+
+void SwDoc::SetAllUniqueFlyNames()
+{
+ sal_uInt16 n, nFlyNum = 0, nGrfNum = 0, nOLENum = 0;
+
+ ResId nFrmId( STR_FRAME_DEFNAME, *pSwResMgr ),
+ nGrfId( STR_GRAPHIC_DEFNAME, *pSwResMgr ),
+ nOLEId( STR_OBJECT_DEFNAME, *pSwResMgr );
+ String sFlyNm( nFrmId );
+ String sGrfNm( nGrfId );
+ String sOLENm( nOLEId );
+
+ if( 255 < ( n = GetSpzFrmFmts()->Count() ))
+ n = 255;
+ SwSpzFrmFmts aArr( (sal_Int8)n, 10 );
+ SwFrmFmtPtr pFlyFmt;
+ sal_Bool bLoadedFlag = sal_True; // noch etwas fuers Layout
+
+ for( n = GetSpzFrmFmts()->Count(); n; )
+ {
+ if( RES_FLYFRMFMT == (pFlyFmt = (*GetSpzFrmFmts())[ --n ])->Which() )
+ {
+ sal_uInt16 *pNum = 0;
+ xub_StrLen nLen;
+ const String& rNm = pFlyFmt->GetName();
+ if( rNm.Len() )
+ {
+ if( rNm.Match( sGrfNm ) == ( nLen = sGrfNm.Len() ))
+ pNum = &nGrfNum;
+ else if( rNm.Match( sFlyNm ) == ( nLen = sFlyNm.Len() ))
+ pNum = &nFlyNum;
+ else if( rNm.Match( sOLENm ) == ( nLen = sOLENm.Len() ))
+ pNum = &nOLENum;
+
+ if ( pNum && *pNum < ( nLen = static_cast< xub_StrLen >( rNm.Copy( nLen ).ToInt32() ) ) )
+ *pNum = nLen;
+ }
+ else
+ // das wollen wir nachher setzen
+ aArr.Insert( pFlyFmt, aArr.Count() );
+
+ }
+ if( bLoadedFlag )
+ {
+ const SwFmtAnchor& rAnchor = pFlyFmt->GetAnchor();
+ if (((FLY_AT_PAGE == rAnchor.GetAnchorId()) &&
+ rAnchor.GetCntntAnchor()) ||
+ // oder werden DrawObjecte rel. zu irgendetwas ausgerichtet?
+ ( RES_DRAWFRMFMT == pFlyFmt->Which() && (
+ SFX_ITEM_SET == pFlyFmt->GetItemState(
+ RES_VERT_ORIENT )||
+ SFX_ITEM_SET == pFlyFmt->GetItemState(
+ RES_HORI_ORIENT ))) )
+ {
+ bLoadedFlag = sal_False;
+ }
+ }
+ }
+
+ const SwNodeIndex* pIdx;
+
+ for( n = aArr.Count(); n; )
+ if( 0 != ( pIdx = ( pFlyFmt = aArr[ --n ])->GetCntnt().GetCntntIdx() )
+ && pIdx->GetNode().GetNodes().IsDocNodes() )
+ {
+ sal_uInt16 nNum;
+ String sNm;
+ switch( GetNodes()[ pIdx->GetIndex() + 1 ]->GetNodeType() )
+ {
+ case ND_GRFNODE:
+ sNm = sGrfNm;
+ nNum = ++nGrfNum;
+ break;
+ case ND_OLENODE:
+ sNm = sOLENm;
+ nNum = ++nOLENum;
+ break;
+ default:
+ sNm = sFlyNm;
+ nNum = ++nFlyNum;
+ break;
+ }
+ pFlyFmt->SetName( sNm += String::CreateFromInt32( nNum ));
+ }
+ aArr.Remove( 0, aArr.Count() );
+
+ if( GetFtnIdxs().Count() )
+ {
+ SwTxtFtn::SetUniqueSeqRefNo( *this );
+ // --> FME 2005-08-02 #i52775# Chapter footnotes did not
+ // get updated correctly. Calling UpdateAllFtn() instead of
+ // UpdateFtn() solves this problem, but I do not dare to
+ // call UpdateAllFtn() in all cases: Safety first.
+ if ( FTNNUM_CHAPTER == GetFtnInfo().eNum )
+ {
+ GetFtnIdxs().UpdateAllFtn();
+ }
+ // <--
+ else
+ {
+ SwNodeIndex aTmp( GetNodes() );
+ GetFtnIdxs().UpdateFtn( aTmp );
+ }
+ }
+
+ // neues Document und keine seitengebundenen Rahmen/DrawObjecte gefunden,
+ // die an einem Node verankert sind.
+ if( bLoadedFlag )
+ SetLoaded( sal_True );
+}
+
+sal_Bool SwDoc::IsInHeaderFooter( const SwNodeIndex& rIdx ) const
+{
+ // gibt es ein Layout, dann ueber das laufen!!
+ // (Das kann dann auch Fly in Fly in Kopfzeile !)
+ // MIB 9.2.98: Wird auch vom sw3io benutzt, um festzustellen, ob sich
+ // ein Redline-Objekt in einer Kopf- oder Fusszeile befindet. Da
+ // Redlines auch an Start- und Endnodes haengen, muss der Index nicht
+ // unbedingt der eines Content-Nodes sein.
+ SwNode* pNd = &rIdx.GetNode();
+ if( pNd->IsCntntNode() && pLayout )
+ {
+ const SwFrm *pFrm = pNd->GetCntntNode()->GetFrm();
+ if( pFrm )
+ {
+ const SwFrm *pUp = pFrm->GetUpper();
+ while ( pUp && !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
+ {
+ if ( pUp->IsFlyFrm() )
+ pUp = ((SwFlyFrm*)pUp)->GetAnchorFrm();
+ pUp = pUp->GetUpper();
+ }
+ if ( pUp )
+ return sal_True;
+
+ return sal_False;
+ }
+ }
+
+
+ const SwNode* pFlyNd = pNd->FindFlyStartNode();
+ while( pFlyNd )
+ {
+ // dann ueber den Anker nach oben "hangeln"
+ sal_uInt16 n;
+ for( n = 0; n < GetSpzFrmFmts()->Count(); ++n )
+ {
+ const SwFrmFmt* pFmt = (*GetSpzFrmFmts())[ n ];
+ const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+ if( pIdx && pFlyNd == &pIdx->GetNode() )
+ {
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ if ((FLY_AT_PAGE == rAnchor.GetAnchorId()) ||
+ !rAnchor.GetCntntAnchor() )
+ {
+ return sal_False;
+ }
+
+ pNd = &rAnchor.GetCntntAnchor()->nNode.GetNode();
+ pFlyNd = pNd->FindFlyStartNode();
+ break;
+ }
+ }
+ if( n >= GetSpzFrmFmts()->Count() )
+ {
+ ASSERT( mbInReading, "Fly-Section aber kein Format gefunden" );
+ return sal_False;
+ }
+ }
+
+ return 0 != pNd->FindHeaderStartNode() ||
+ 0 != pNd->FindFooterStartNode();
+}
+
+short SwDoc::GetTextDirection( const SwPosition& rPos,
+ const Point* pPt ) const
+{
+ short nRet = -1;
+
+ SwCntntNode *pNd = rPos.nNode.GetNode().GetCntntNode();
+
+ // --> OD 2005-02-21 #i42921# - use new method <SwCntntNode::GetTextDirection(..)>
+ if ( pNd )
+ {
+ nRet = pNd->GetTextDirection( rPos, pPt );
+ }
+ if ( nRet == -1 )
+ // <--
+ {
+ const SvxFrameDirectionItem* pItem = 0;
+ if( pNd )
+ {
+ // in a flyframe? Then look at that for the correct attribute
+ const SwFrmFmt* pFlyFmt = pNd->GetFlyFmt();
+ while( pFlyFmt )
+ {
+ pItem = &pFlyFmt->GetFrmDir();
+ if( FRMDIR_ENVIRONMENT == pItem->GetValue() )
+ {
+ pItem = 0;
+ const SwFmtAnchor* pAnchor = &pFlyFmt->GetAnchor();
+ if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
+ pAnchor->GetCntntAnchor())
+ {
+ pFlyFmt = pAnchor->GetCntntAnchor()->nNode.
+ GetNode().GetFlyFmt();
+ }
+ else
+ pFlyFmt = 0;
+ }
+ else
+ pFlyFmt = 0;
+ }
+
+ if( !pItem )
+ {
+ const SwPageDesc* pPgDsc = pNd->FindPageDesc( sal_False );
+ if( pPgDsc )
+ pItem = &pPgDsc->GetMaster().GetFrmDir();
+ }
+ }
+ if( !pItem )
+ pItem = (SvxFrameDirectionItem*)&GetAttrPool().GetDefaultItem(
+ RES_FRAMEDIR );
+ nRet = pItem->GetValue();
+ }
+ return nRet;
+}
+
+sal_Bool SwDoc::IsInVerticalText( const SwPosition& rPos, const Point* pPt ) const
+{
+ const short nDir = GetTextDirection( rPos, pPt );
+ return FRMDIR_VERT_TOP_RIGHT == nDir || FRMDIR_VERT_TOP_LEFT == nDir;
+}
+
+const SwRootFrm* SwDoc::GetRootFrm() const { return pLayout; }
+SwRootFrm* SwDoc::GetRootFrm() { return pLayout; }
+void SwDoc::SetRootFrm( SwRootFrm* pNew ) { pLayout = pNew; }
+SwLayouter* SwDoc::GetLayouter() { return pLayouter; }
+const SwLayouter* SwDoc::GetLayouter() const { return pLayouter; }
+void SwDoc::SetLayouter( SwLayouter* pNew ) { pLayouter = pNew; }
diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
new file mode 100644
index 000000000000..cdf031aeb923
--- /dev/null
+++ b/sw/source/core/doc/docnew.cxx
@@ -0,0 +1,1275 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#define ROLBCK_HISTORY_ONLY // Der Kampf gegen die CLOOK's
+#include <doc.hxx>
+#include <dcontact.hxx>
+#include <com/sun/star/document/PrinterIndependentLayout.hpp>
+#include <com/sun/star/document/UpdateDocMode.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/linguistic2/XProofreadingIterator.hpp>
+#include <com/sun/star/text/XFlatParagraphIteratorProvider.hpp>
+
+#include <unotools/processfactory.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/virdev.hxx>
+#include <rtl/logfile.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/frame.hxx>
+#include <sfx2/viewfrm.hxx>
+
+#include <svl/macitem.hxx>
+#include <svx/svxids.hrc>
+#include <svx/svdogrp.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <editeng/forbiddencharacterstable.hxx>
+#include <svl/zforlist.hxx>
+#include <unotools/compatibility.hxx>
+#include <unotools/lingucfg.hxx>
+#include <svx/svdpage.hxx>
+#include <paratr.hxx>
+#include <fchrfmt.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtfsize.hxx>
+#include <fmtfordr.hxx>
+#include <fmtpdsc.hxx>
+#include <pvprtdat.hxx>
+#include <rootfrm.hxx> //Damit der RootDtor gerufen wird.
+#include <layouter.hxx>
+#include <pagedesc.hxx> //Damit die PageDescs zerstoert werden koennen.
+#include <ndtxt.hxx>
+#include <printdata.hxx>
+#include <docfld.hxx>
+#include <ftninfo.hxx>
+#include <ftnidx.hxx>
+#include <docstat.hxx>
+#include <charfmt.hxx>
+#include <frmfmt.hxx>
+#include <rolbck.hxx> // Undo-Attr, SwHistory
+#include <poolfmt.hxx> // fuer die Pool-Vorlage
+#include <dbmgr.hxx>
+#include <docsh.hxx>
+#include <acorrect.hxx> // fuer die autom. Aufnahme von Ausnahmen
+#include <visiturl.hxx> // fuer die URL-Change Benachrichtigung
+#include <docary.hxx>
+#include <lineinfo.hxx>
+#include <drawdoc.hxx>
+#include <linkenum.hxx>
+#include <fldupde.hxx>
+#include <extinput.hxx>
+#include <viewsh.hxx>
+#include <doctxm.hxx>
+#include <shellres.hxx>
+#include <breakit.hxx>
+#include <laycache.hxx>
+#include <mvsave.hxx>
+#include <istyleaccess.hxx>
+#include <swstylemanager.hxx>
+#include <IGrammarContact.hxx>
+#include <tblsel.hxx>
+#include <MarkManager.hxx>
+#include <UndoManager.hxx>
+#include <unochart.hxx>
+
+#include <cmdid.h> // fuer den dflt - Printer in SetJob
+
+
+// --> OD 2006-04-19 #b6375613#
+#include <com/sun/star/document/XDocumentInfoSupplier.hpp>
+#include <com/sun/star/beans/XPropertyContainer.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+// <--
+
+// --> OD 2007-03-16 #i73788#
+#include <pausethreadstarting.hxx>
+// <--
+#include <numrule.hxx>
+// --> OD 2008-03-13 #refactorlists#
+#include <list.hxx>
+#include <listfunc.hxx>
+// <--
+
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+
+#include <sfx2/Metadatable.hxx>
+#include <fmtmeta.hxx> // MetaFieldManager
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::document;
+
+const sal_Char __FAR_DATA sFrmFmtStr[] = "Frameformat";
+const sal_Char __FAR_DATA sEmptyPageStr[] = "Empty Page";
+const sal_Char __FAR_DATA sColumnCntStr[] = "Columncontainer";
+const sal_Char __FAR_DATA sCharFmtStr[] = "Zeichenformat";
+const sal_Char __FAR_DATA sTxtCollStr[] = "Textformatvorlage";
+const sal_Char __FAR_DATA sGrfCollStr[] = "Graphikformatvorlage";
+
+SV_IMPL_PTRARR( SwNumRuleTbl, SwNumRulePtr)
+SV_IMPL_PTRARR( SwTxtFmtColls, SwTxtFmtCollPtr)
+SV_IMPL_PTRARR( SwGrfFmtColls, SwGrfFmtCollPtr)
+
+/*
+ * global functions...
+ */
+
+ uno::Reference< linguistic2::XProofreadingIterator > SwDoc::GetGCIterator() const
+{
+ if (!m_xGCIterator.is() && SvtLinguConfig().HasGrammarChecker())
+ {
+ uno::Reference< lang::XMultiServiceFactory > xMgr( utl::getProcessServiceFactory() );
+ if (xMgr.is())
+ {
+ try
+ {
+ rtl::OUString aServiceName( rtl::OUString::createFromAscii("com.sun.star.linguistic2.ProofreadingIterator") );
+ m_xGCIterator = uno::Reference< linguistic2::XProofreadingIterator >
+ ( xMgr->createInstance( aServiceName ), uno::UNO_QUERY_THROW );
+ }
+ catch (uno::Exception &)
+ {
+ DBG_ERROR( "No GCIterator" );
+ }
+ }
+ }
+
+ return m_xGCIterator;
+}
+
+void StartGrammarChecking( SwDoc &rDoc )
+{
+ // check for a visible view
+ bool bVisible = false;
+ const SwDocShell *pDocShell = rDoc.GetDocShell();
+ SfxViewFrame *pFrame = SfxViewFrame::GetFirst( pDocShell, sal_False );
+ while (pFrame && !bVisible)
+ {
+ if (pFrame->IsVisible())
+ bVisible = true;
+ pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell, sal_False );
+ }
+
+ //!! only documents with visible views need to be checked
+ //!! (E.g. don't check temporary documents created for printing, see printing of notes and selections.
+ //!! Those get created on the fly and get hard deleted a bit later as well, and no one should have
+ //!! a uno reference to them)
+ if (bVisible)
+ {
+ uno::Reference< linguistic2::XProofreadingIterator > xGCIterator( rDoc.GetGCIterator() );
+ if ( xGCIterator.is() )
+ {
+ uno::Reference< lang::XComponent > xDoc( rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY );
+ uno::Reference< text::XFlatParagraphIteratorProvider > xFPIP( xDoc, uno::UNO_QUERY );
+
+ // start automatic background checking if not active already
+ if ( xFPIP.is() && !xGCIterator->isProofreading( xDoc ) )
+ xGCIterator->startProofreading( xDoc, xFPIP );
+ }
+ }
+}
+
+/*
+ * interne Funktionen
+ */
+
+
+
+sal_Bool lcl_DelFmtIndizes( const SwFrmFmtPtr& rpFmt, void* )
+{
+ SwFmtCntnt &rFmtCntnt = (SwFmtCntnt&)rpFmt->GetCntnt();
+ if ( rFmtCntnt.GetCntntIdx() )
+ rFmtCntnt.SetNewCntntIdx( 0 );
+ SwFmtAnchor &rFmtAnchor = (SwFmtAnchor&)rpFmt->GetAnchor();
+ if ( rFmtAnchor.GetCntntAnchor() )
+ rFmtAnchor.SetAnchor( 0 );
+ return sal_True;
+}
+
+/*
+ * exportierte Methoden
+ */
+
+SwDoc::SwDoc()
+ : m_pNodes( new SwNodes(this) )
+ ,
+ mpAttrPool(new SwAttrPool(this)),
+ pMarkManager(new ::sw::mark::MarkManager(*this)),
+ m_pMetaFieldManager(new ::sw::MetaFieldManager()),
+ m_pUndoManager(new ::sw::UndoManager(
+ ::std::auto_ptr<SwNodes>(new SwNodes(this)), *this, *this, *this)),
+ pDfltFrmFmt( new SwFrmFmt( GetAttrPool(), sFrmFmtStr, 0 ) ),
+ pEmptyPageFmt( new SwFrmFmt( GetAttrPool(), sEmptyPageStr, pDfltFrmFmt ) ),
+ pColumnContFmt( new SwFrmFmt( GetAttrPool(), sColumnCntStr, pDfltFrmFmt ) ),
+ pDfltCharFmt( new SwCharFmt( GetAttrPool(), sCharFmtStr, 0 ) ),
+ pDfltTxtFmtColl( new SwTxtFmtColl( GetAttrPool(), sTxtCollStr ) ),
+ pDfltGrfFmtColl( new SwGrfFmtColl( GetAttrPool(), sGrfCollStr ) ),
+ pFrmFmtTbl( new SwFrmFmts() ),
+ pCharFmtTbl( new SwCharFmts() ),
+ pSpzFrmFmtTbl( new SwSpzFrmFmts() ),
+ pSectionFmtTbl( new SwSectionFmts() ),
+ pTblFrmFmtTbl( new SwFrmFmts() ),
+ pTxtFmtCollTbl( new SwTxtFmtColls() ),
+ pGrfFmtCollTbl( new SwGrfFmtColls() ),
+ pTOXTypes( new SwTOXTypes() ),
+ pDefTOXBases( new SwDefTOXBase_Impl() ),
+ pLayout( 0 ), // Rootframe des spezifischen Layouts.
+ pDrawModel( 0 ),
+ pUpdtFlds( new SwDocUpdtFld() ),
+ pFldTypes( new SwFldTypes() ),
+ pVirDev( 0 ),
+ pPrt( 0 ),
+ pPrtData( 0 ),
+ pGlossaryDoc( 0 ),
+ pOutlineRule( 0 ),
+ pFtnInfo( new SwFtnInfo ),
+ pEndNoteInfo( new SwEndNoteInfo ),
+ pLineNumberInfo( new SwLineNumberInfo ),
+ pFtnIdxs( new SwFtnIdxs ),
+ pDocStat( new SwDocStat ),
+ pDocShell( 0 ),
+ pLinkMgr( new sfx2::LinkManager( 0 ) ),
+ pACEWord( 0 ),
+ pURLStateChgd( 0 ),
+ pNumberFormatter( 0 ),
+ pNumRuleTbl( new SwNumRuleTbl ),
+ // --> OD 2008-03-26 #refactorlists#
+ maLists(),
+ maListStyleLists(),
+ // <--
+ pRedlineTbl( new SwRedlineTbl ),
+ pAutoFmtRedlnComment( 0 ),
+ pUnoCrsrTbl( new SwUnoCrsrTbl( 0, 16 ) ),
+ pPgPViewPrtData( 0 ),
+ pExtInputRing( 0 ),
+ pLayouter( 0 ),
+ // --> OD 2008-03-07 #refactorlists#
+ pStyleAccess( 0 ),
+ // <--
+ pLayoutCache( 0 ),
+ pUnoCallBack(new SwModify(0)),
+ mpGrammarContact( 0 ),
+ aChartDataProviderImplRef(),
+ pChartControllerHelper( 0 ),
+ // --> OD 2007-10-31 #i83479#
+ mpListItemsList( new tImplSortedNodeNumList() ),
+ // <--
+ m_pXmlIdRegistry(),
+ nAutoFmtRedlnCommentNo( 0 ),
+ nLinkUpdMode( GLOBALSETTING ),
+ eFldUpdMode( AUTOUPD_GLOBALSETTING ),
+ eRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE)),
+ eChrCmprType( CHARCOMPRESS_NONE ),
+ mReferenceCount(0),
+ mIdleBlockCount(0),
+ nLockExpFld( 0 ),
+ mbReadlineChecked(false),
+ // --> OD 2005-02-11 #i38810#
+ mbLinksUpdated( sal_False ),
+ mbClipBoard( false ),
+ mbColumnSelection( false ),
+ // i#78591#
+ mbProtectForm(false),
+ n32DummyCompatabilityOptions1(0),
+ n32DummyCompatabilityOptions2(0),
+ mbStartIdleTimer(sal_False)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLog, "SW", "JP93722", "SwDoc::SwDoc" );
+
+ mbGlossDoc =
+ mbModified =
+ mbDtor =
+ mbPageNums =
+ mbLoaded =
+ mbUpdateExpFld =
+ mbNewDoc =
+ mbCopyIsMove =
+ mbBrowseMode =
+ mbInReading =
+ mbInXMLImport =
+ mbUpdateTOX =
+ mbInLoadAsynchron =
+ mbHTMLMode =
+ mbInCallModified =
+ mbIsGlobalDoc =
+ mbGlblDocSaveLinks =
+ mbIsLabelDoc =
+ mbIsAutoFmtRedline =
+ mbOLEPrtNotifyPending =
+ mbAllOLENotify =
+ mbIsRedlineMove =
+ mbInsOnlyTxtGlssry =
+ mbContains_MSVBasic =
+ mbKernAsianPunctuation =
+#ifdef DBG_UTIL
+ mbXMLExport =
+#endif
+ // --> OD 2006-03-21 #b6375613#
+ mbApplyWorkaroundForB6375613 =
+ // <--
+ false;
+
+ mbNewFldLst =
+ mbVisibleLinks =
+ mbPurgeOLE =
+ true;
+
+ //
+ // COMPATIBILITY FLAGS START
+ //
+
+ // Note: Any non-hidden compatibility flag should obtain its default
+ // by asking SvtCompatibilityOptions, see below.
+ //
+ const SvtCompatibilityOptions aOptions;
+ mbParaSpaceMax = aOptions.IsAddSpacing();
+ mbParaSpaceMaxAtPages = aOptions.IsAddSpacingAtPages();
+ mbTabCompat = !aOptions.IsUseOurTabStops();
+ mbUseVirtualDevice = !aOptions.IsUsePrtDevice();
+ mbAddExternalLeading = !aOptions.IsNoExtLeading();
+ mbOldLineSpacing = aOptions.IsUseLineSpacing();
+ mbAddParaSpacingToTableCells = aOptions.IsAddTableSpacing();
+ mbUseFormerObjectPos = aOptions.IsUseObjectPositioning();
+ mbUseFormerTextWrapping = aOptions.IsUseOurTextWrapping();
+ mbConsiderWrapOnObjPos = aOptions.IsConsiderWrappingStyle();
+ mbMathBaselineAlignment = false; // default for *old* documents is 'off'
+ mbAddFlyOffsets = false; // hidden
+ mbOldNumbering = false; // hidden
+ mbUseHiResolutionVirtualDevice = true; // hidden
+ mbIgnoreFirstLineIndentInNumbering = false; // hidden
+ mbDoNotJustifyLinesWithManualBreak = !aOptions.IsExpandWordSpace();
+ mbDoNotResetParaAttrsForNumFont = false; // hidden
+ mbOutlineLevelYieldsOutlineRule = false; // hidden
+ mbTableRowKeep = false; // hidden
+ mbIgnoreTabsAndBlanksForLineCalculation = false; // hidden
+ mbDoNotCaptureDrawObjsOnPage = false; // hidden
+ mbClipAsCharacterAnchoredWriterFlyFrames= false; // hidden
+ mbUnixForceZeroExtLeading = false; // hidden
+ mbOldPrinterMetrics = false; // hidden
+ mbTabRelativeToIndent = true; // hidden
+ // --> OD 2008-06-05 #i89181#
+ mbTabAtLeftIndentForParagraphsInList = false; // hidden
+ // <--
+
+ //
+ // COMPATIBILITY FLAGS END
+ //
+
+ pMacroTable = new SvxMacroTableDtor;
+
+ mpGrammarContact = ::createGrammarContact();
+
+ /*
+ * Defaultformate und DefaultFormatsammlungen (FmtColl)
+ * werden an der Position 0 in das jeweilige Array eingetragen.
+ * Die Formate der FmtColls sind von den Defaultformaten
+ * abgeleitet und stehen auch in der Liste.
+ */
+ /* Formate */
+ pFrmFmtTbl->Insert(pDfltFrmFmt, 0 );
+ pCharFmtTbl->Insert(pDfltCharFmt, 0 );
+
+ /* FmtColls */
+ // TXT
+ pTxtFmtCollTbl->Insert(pDfltTxtFmtColl, 0 );
+ // GRF
+ pGrfFmtCollTbl->Insert(pDfltGrfFmtColl, 0 );
+
+ // PageDesc, EmptyPageFmt und ColumnFmt anlegen
+ if ( !aPageDescs.Count() )
+ GetPageDescFromPool( RES_POOLPAGE_STANDARD );
+
+ //Leere Seite Einstellen.
+ pEmptyPageFmt->SetFmtAttr( SwFmtFrmSize( ATT_FIX_SIZE ) );
+ //BodyFmt fuer Spalten Einstellen.
+ pColumnContFmt->SetFmtAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT ) );
+
+ _InitFieldTypes();
+
+ // lege (fuer die Filter) eine Default-OutlineNumRule an
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ pOutlineRule = new SwNumRule( String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ),
+ // --> OD 2008-06-06 #i89178#
+ numfunc::GetDefaultPositionAndSpaceMode(),
+ // <--
+ OUTLINE_RULE );
+ // <--
+ // #115901#
+ AddNumRule(pOutlineRule);
+ // --> OD 2005-10-21 - counting of phantoms depends on <IsOldNumbering()>
+ pOutlineRule->SetCountPhantoms( !get(IDocumentSettingAccess::OLD_NUMBERING) );
+ // <--
+
+ new SwTxtNode(
+ SwNodeIndex(GetUndoManager().GetUndoNodes().GetEndOfContent()),
+ pDfltTxtFmtColl );
+ new SwTxtNode( SwNodeIndex( GetNodes().GetEndOfContent() ),
+ GetTxtCollFromPool( RES_POOLCOLL_STANDARD ));
+
+ // den eigenen IdleTimer setzen
+ aIdleTimer.SetTimeout( 600 );
+ aIdleTimer.SetTimeoutHdl( LINK(this, SwDoc, DoIdleJobs) );
+
+ aOLEModifiedTimer.SetTimeout( 1000 );
+ aOLEModifiedTimer.SetTimeoutHdl( LINK( this, SwDoc, DoUpdateModifiedOLE ));
+
+ // DBMgr anlegen
+ pNewDBMgr = new SwNewDBMgr;
+
+ // create TOXTypes
+ InitTOXTypes();
+
+ // --> OD 2008-03-07 #refactorlists#
+ // pass empty item set containing the paragraph's list attributes
+ // as ignorable items to the stype manager.
+ {
+ SfxItemSet aIgnorableParagraphItems( GetAttrPool(),
+ RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
+ 0 );
+ pStyleAccess = createStyleManager( &aIgnorableParagraphItems );
+ }
+ // <--
+
+ ResetModified();
+}
+
+/*
+ * Besonderheiten: an der Position 0 des Arrays der Formate und
+ * der GDI-Objekte befindet sich ein Member der Klasse SwDoc.
+ * Dieser darf also keinesfalls durch delete geloescht
+ * werden!!!!!!!!!!
+ */
+
+
+SwDoc::~SwDoc()
+{
+ // nothing here should create Undo actions!
+ GetIDocumentUndoRedo().DoUndo(false);
+
+ if (pDocShell)
+ {
+ pDocShell->SetUndoManager(0);
+ }
+
+ // --> OD 2007-03-16 #i73788#
+ SwPauseThreadStarting aPauseThreadStarting;
+ // <--
+
+ // --> OD 2007-11-01 #i83479#
+ delete mpListItemsList;
+ mpListItemsList = 0;
+ // <--
+
+ // clean up chart related structures...
+ // Note: the chart data provider gets already diposed in ~SwDocShell
+ // since all UNO API related functionality requires an existing SwDocShell
+ // this assures that dipose gets called if there is need for it.
+ aChartDataProviderImplRef.reset();
+ delete pChartControllerHelper;
+
+ delete mpGrammarContact;
+ mpGrammarContact = 0;
+
+ //!! needs to be done to destroy a possible SwFmtDrop format that may
+ //!! be connected to a char format which may not otherwise be removed
+ //!! and thus would leave a unremoved SwFmt object. (TL)
+ //!! (this is case is not possible via UI but via API...)
+ SwFmtDrop aDrop;
+ SetDefault(aDrop);
+ //!! same for SwFmtCharFmt
+ SwFmtCharFmt aCharFmt(NULL);
+ SetDefault(aCharFmt);
+
+ StopIdling(); // stop idle timer
+
+ delete pUnoCallBack, pUnoCallBack = 0;
+ delete pURLStateChgd;
+
+ delete pLayouter;
+ // --> OD 2005-09-05 #125370#
+ pLayouter = 0L;
+ // <--
+
+ // Undo-Benachrichtigung vom Draw abschalten
+ if( pDrawModel )
+ {
+ DrawNotifyUndoHdl();
+ ClrContourCache();
+ }
+
+ delete pPgPViewPrtData;
+
+ mbDtor = sal_True;
+
+ DELETEZ( pLayout );
+
+ delete pRedlineTbl;
+ delete pUnoCrsrTbl;
+ delete pAutoFmtRedlnComment;
+
+ if( pUpdtFlds )
+ delete pUpdtFlds;
+
+ if( pACEWord )
+ delete pACEWord;
+
+ // die BaseLinks freigeben.
+ {
+ for( sal_uInt16 n = pLinkMgr->GetServers().Count(); n; )
+ pLinkMgr->GetServers()[ --n ]->Closed();
+
+ if( pLinkMgr->GetLinks().Count() )
+ pLinkMgr->Remove( 0, pLinkMgr->GetLinks().Count() );
+ }
+
+ // die KapitelNummern / Nummern muessen vor den Vorlage geloescht werden
+ // ansonsten wird noch staendig geupdatet !!!
+ m_pNodes->pOutlineNds->Remove(sal_uInt16(0), m_pNodes->pOutlineNds->Count());
+ SwNodes & rUndoNodes( GetUndoManager().GetUndoNodes() );
+ rUndoNodes.pOutlineNds->Remove(sal_uInt16(0), rUndoNodes.pOutlineNds->Count());
+
+ pFtnIdxs->Remove( sal_uInt16(0), pFtnIdxs->Count() );
+
+ // indices could be registered in attributes
+ m_pUndoManager->DelAllUndoObj();
+
+ // in den BookMarks sind Indizies auf den Content. Diese muessen vorm
+ // loesche der Nodes geloescht werden.
+ pMarkManager->clearAllMarks();
+ DELETEZ( pMacroTable );
+
+ if( pExtInputRing )
+ {
+ Ring* pTmp = pExtInputRing;
+ pExtInputRing = 0;
+ while( pTmp->GetNext() != pTmp )
+ delete pTmp->GetNext();
+ delete pTmp;
+ }
+
+//JP: alt - loeschen ohne Flag ist teuer; Modify wird verschickt!
+// aTOXTypes.DeleteAndDestroy( 0, aTOXTypes.Count() );
+ {
+ for( sal_uInt16 n = pTOXTypes->Count(); n; )
+ {
+ (*pTOXTypes)[ --n ]->SetInDocDTOR();
+ delete (*pTOXTypes)[ n ];
+ }
+ pTOXTypes->Remove( 0, pTOXTypes->Count() );
+ }
+ delete pDefTOXBases;
+
+ //Im einen oder anderen FrmFormat koennen noch Indizes angemeldet sein,
+ //Diese muessen spaetestens jetzt zerstoert werden.
+ pFrmFmtTbl->ForEach( &lcl_DelFmtIndizes, this );
+ pSpzFrmFmtTbl->ForEach( &lcl_DelFmtIndizes, this );
+ ((SwFrmFmts&)*pSectionFmtTbl).ForEach( &lcl_DelFmtIndizes, this );
+
+ //Die Formate, die hier hinter stehen sind von den DefaultFormaten
+ //abhaengig. Erst nach dem Loeschen der FmtIndizes weil der Inhalt von
+ //Kopf-/Fussbereichen geloescht wird. Wenn dort noch Indizes von Flys
+ //angemeldet sind gibts was an die Ohren.
+ aPageDescs.DeleteAndDestroy( 0, aPageDescs.Count() );
+
+ // Inhaltssections loeschen
+ // nicht erst durch den SwNodes-DTOR, damit Formate
+ // keine Abhaengigen mehr haben.
+ m_pNodes->DelNodes( SwNodeIndex(*m_pNodes), m_pNodes->Count() );
+ rUndoNodes.DelNodes( SwNodeIndex( rUndoNodes ), rUndoNodes.Count() );
+
+ // Formate loeschen, spaeter mal permanent machen.
+
+ // Delete fuer Collections
+ // damit die Abhaengigen wech sind
+ SwTxtFmtColl *pFtnColl = pFtnInfo->GetFtnTxtColl();
+ if ( pFtnColl ) pFtnColl->Remove(pFtnInfo);
+ pFtnColl = pEndNoteInfo->GetFtnTxtColl();
+ if ( pFtnColl ) pFtnColl->Remove(pEndNoteInfo);
+
+ ASSERT( pDfltTxtFmtColl == (*pTxtFmtCollTbl)[0],
+ "Default-Text-Collection muss immer am Anfang stehen" );
+
+ // JP 27.01.98: opt.: ausgehend davon, das Standard als 2. im Array
+ // steht, sollte das als letztes geloescht werden, damit
+ // die ganze Umhaengerei der Formate vermieden wird!
+ if( 2 < pTxtFmtCollTbl->Count() )
+ pTxtFmtCollTbl->DeleteAndDestroy( 2, pTxtFmtCollTbl->Count()-2 );
+ pTxtFmtCollTbl->DeleteAndDestroy( 1, pTxtFmtCollTbl->Count()-1 );
+ delete pTxtFmtCollTbl;
+
+ ASSERT( pDfltGrfFmtColl == (*pGrfFmtCollTbl)[0],
+ "Default-Grf-Collection muss immer am Anfang stehen" );
+
+ pGrfFmtCollTbl->DeleteAndDestroy( 1, pGrfFmtCollTbl->Count()-1 );
+// ergibt sich automatisch - kein _DEL Array!
+// pGrfFmtCollTbl->Remove( 0, n );
+ delete pGrfFmtCollTbl;
+
+ /*
+ * Defaultformate und DefaultFormatsammlungen (FmtColl)
+ * sind an der Position 0 der jeweiligen Arrays eingetragen.
+ * Damit sie nicht vom DTOR der Array's zum 2.mal geloescht werden,
+ * nehme sie aus dem Array.
+ */
+ pFrmFmtTbl->Remove( 0 );
+ pCharFmtTbl->Remove( 0 );
+
+ // Delete fuer pPrt
+ DELETEZ( pPrt );
+ DELETEZ( pNewDBMgr );
+
+ // Alle Flys muessen vor dem Drawing Model zerstoert werden,
+ // da Flys noch DrawContacts enthalten koennen, wenn wegen
+ // eines Lesefehlers kein Layout aufgebaut wurde.
+ pSpzFrmFmtTbl->DeleteAndDestroy( 0, pSpzFrmFmtTbl->Count() );
+
+ //Erst jetzt das Model zerstoeren, die Zeichenobjekte - die ja auch
+ //im Undo herumlungern - wollen noch ihre Attribute beim Model entfernen.
+ //Ausserdem koennen vorher noch DrawContacts existieren.
+ ReleaseDrawModel();
+ //JP 28.01.99: DrawModel vorm LinkManager zerstoeren, da am DrawModel
+ // dieser immer gesetzt ist.
+ DELETEZ( pLinkMgr );
+
+ //Tables vor dem loeschen der Defaults leeren, sonst GPF wegen Def-Abhaengigen.
+ //Die Arrays sollten (wegen includes) bei Gelegenheit auch zu Pointern werden.
+ delete pFrmFmtTbl;
+ delete pSpzFrmFmtTbl;
+
+ delete pStyleAccess;
+
+ delete pCharFmtTbl;
+ delete pSectionFmtTbl;
+ delete pTblFrmFmtTbl;
+ delete pDfltTxtFmtColl;
+ delete pDfltGrfFmtColl;
+ delete pNumRuleTbl;
+
+ // --> OD 2008-03-26 #refactorlists#
+ {
+ for ( std::hash_map< String, SwList*, StringHash >::iterator
+ aListIter = maLists.begin();
+ aListIter != maLists.end();
+ ++aListIter )
+ {
+ delete (*aListIter).second;
+ }
+ maLists.clear();
+ }
+ maListStyleLists.clear();
+ // <--
+
+ delete pPrtData;
+ delete pNumberFormatter;
+ delete pFtnInfo;
+ delete pEndNoteInfo;
+ delete pLineNumberInfo;
+ delete pFtnIdxs;
+ delete pFldTypes;
+ delete pTOXTypes;
+ delete pDocStat;
+ delete pEmptyPageFmt;
+ delete pColumnContFmt;
+ delete pDfltCharFmt;
+ delete pDfltFrmFmt;
+ delete pLayoutCache;
+ delete pVirDev;
+
+ SfxItemPool::Free(mpAttrPool);
+}
+
+//---------------------------------------------------
+
+VirtualDevice& SwDoc::CreateVirtualDevice_() const
+{
+ VirtualDevice* pNewVir = new VirtualDevice( 1 );
+
+ // <--
+ pNewVir->SetReferenceDevice( VirtualDevice::REFDEV_MODE_MSO1 );
+
+ // --> FME 2006-10-09 #i60945# External leading compatibility for unix systems.
+ if ( get(IDocumentSettingAccess::UNIX_FORCE_ZERO_EXT_LEADING ) )
+ pNewVir->Compat_ZeroExtleadBug();
+ // <--
+
+ MapMode aMapMode( pNewVir->GetMapMode() );
+ aMapMode.SetMapUnit( MAP_TWIP );
+ pNewVir->SetMapMode( aMapMode );
+
+ const_cast<SwDoc*>(this)->setVirtualDevice( pNewVir, true, true );
+ return *pVirDev;
+}
+
+//---------------------------------------------------
+
+SfxPrinter& SwDoc::CreatePrinter_() const
+{
+ ASSERT( ! pPrt, "Do not call CreatePrinter_(), call getPrinter() instead" )
+
+#if OSL_DEBUG_LEVEL > 1
+ ASSERT( false, "Printer will be created!" )
+#endif
+
+ // wir erzeugen einen default SfxPrinter.
+ // Das ItemSet wird vom Sfx geloescht!
+ SfxItemSet *pSet = new SfxItemSet( ((SwDoc*)this)->GetAttrPool(),
+ FN_PARAM_ADDPRINTER, FN_PARAM_ADDPRINTER,
+ SID_HTML_MODE, SID_HTML_MODE,
+ SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
+ SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
+ 0 );
+
+ SfxPrinter* pNewPrt = new SfxPrinter( pSet );
+ const_cast<SwDoc*>(this)->setPrinter( pNewPrt, true, true );
+ return *pPrt;
+}
+//---------------------------------------------------
+
+void SwDoc::SetDocShell( SwDocShell* pDSh )
+{
+ if( pDocShell != pDSh )
+ {
+ if (pDocShell)
+ {
+ pDocShell->SetUndoManager(0);
+ }
+ pDocShell = pDSh;
+ if (pDocShell)
+ {
+ pDocShell->SetUndoManager(& GetUndoManager());
+ }
+
+ pLinkMgr->SetPersist( pDocShell );
+ //JP 27.08.98: Bug 55570 - DocShell Pointer auch am DrawModel setzen
+ if( pDrawModel )
+ {
+ ((SwDrawDocument*)pDrawModel)->SetObjectShell( pDocShell );
+ pDrawModel->SetPersist( pDocShell );
+ ASSERT( pDrawModel->GetPersist() == GetPersist(),
+ "draw model's persist is out of sync" );
+ }
+ }
+}
+
+
+// Convenience-Methode, um uebermaessige Includes von docsh.hxx
+// zu vermeiden
+
+
+
+uno::Reference < embed::XStorage > SwDoc::GetDocStorage()
+{
+ if( pDocShell )
+ return pDocShell->GetStorage();
+ if( pLinkMgr->GetPersist() )
+ return pLinkMgr->GetPersist()->GetStorage();
+ return NULL;
+}
+
+
+
+SfxObjectShell* SwDoc::GetPersist() const
+{
+ return pDocShell ? pDocShell : pLinkMgr->GetPersist();
+}
+
+
+void SwDoc::ClearDoc()
+{
+ GetIDocumentUndoRedo().DelAllUndoObj();
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ // Undo-Benachrichtigung vom Draw abschalten
+ if( pDrawModel )
+ {
+ DrawNotifyUndoHdl();
+ ClrContourCache();
+ }
+
+ // stehen noch FlyFrames rum, loesche auch diese
+ sal_uInt16 n;
+ while ( 0 != (n = GetSpzFrmFmts()->Count()) )
+ DelLayoutFmt((*pSpzFrmFmtTbl)[n-1]);
+ ASSERT( !pDrawModel || !pDrawModel->GetPage(0)->GetObjCount(),
+ "not all DrawObjects removed from the page" );
+
+ pRedlineTbl->DeleteAndDestroy( 0, pRedlineTbl->Count() );
+
+ if( pACEWord )
+ delete pACEWord;
+
+ // in den BookMarks sind Indizies auf den Content. Diese muessen vorm
+ // loesche der Nodes geloescht werden.
+ pMarkManager->clearAllMarks();
+ InitTOXTypes();
+
+ // create a dummy pagedesc for the layout
+ sal_uInt16 nDummyPgDsc = MakePageDesc( String::CreateFromAscii( "?DUMMY?" ));
+ SwPageDesc* pDummyPgDsc = aPageDescs[ nDummyPgDsc ];
+
+ SwNodeIndex aSttIdx( *GetNodes().GetEndOfContent().StartOfSectionNode(), 1 );
+ // den ersten immer wieder neu anlegen (ohne Attribute/Vorlagen/...)
+ SwTxtNode* pFirstNd = GetNodes().MakeTxtNode( aSttIdx, pDfltTxtFmtColl );
+
+ if( pLayout )
+ {
+ // set the layout to the dummy pagedesc
+ pFirstNd->SetAttr( SwFmtPageDesc( pDummyPgDsc ));
+
+ SwPosition aPos( *pFirstNd, SwIndex( pFirstNd ));
+ SwPaM const tmpPaM(aSttIdx, SwNodeIndex(GetNodes().GetEndOfContent()));
+ ::PaMCorrAbs(tmpPaM, aPos);
+ }
+
+ GetNodes().Delete( aSttIdx,
+ GetNodes().GetEndOfContent().GetIndex() - aSttIdx.GetIndex() );
+
+ // --> OD 2006-02-28 #i62440#
+ // destruction of numbering rules and creation of new outline rule
+ // *after* the document nodes are deleted.
+ pOutlineRule = NULL;
+ pNumRuleTbl->DeleteAndDestroy( 0, pNumRuleTbl->Count() );
+ // creation of new outline numbering rule
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ pOutlineRule = new SwNumRule( String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ),
+ // --> OD 2008-06-06 #i89178#
+ numfunc::GetDefaultPositionAndSpaceMode(),
+ // <--
+ OUTLINE_RULE );
+ // <--
+ AddNumRule(pOutlineRule);
+ // --> OD 2005-10-21 - counting of phantoms depends on <IsOldNumbering()>
+ pOutlineRule->SetCountPhantoms( !get(IDocumentSettingAccess::OLD_NUMBERING) );
+ // <--
+ // <--
+
+ //remove the dummy pagedec from the array and delete all the old ones
+ aPageDescs.Remove( nDummyPgDsc );
+ aPageDescs.DeleteAndDestroy( 0, aPageDescs.Count() );
+
+ // Delete fuer Collections
+ // damit die Abhaengigen wech sind
+ SwTxtFmtColl* pFtnColl = pFtnInfo->GetFtnTxtColl();
+ if( pFtnColl ) pFtnColl->Remove( pFtnInfo );
+ pFtnColl = pEndNoteInfo->GetFtnTxtColl();
+ if( pFtnColl ) pFtnColl->Remove( pEndNoteInfo );
+
+ // JP 27.01.98: opt.: ausgehend davon, das Standard als 2. im Array
+ // steht, sollte das als letztes geloescht werden, damit
+ // die ganze Umhaengerei der Formate vermieden wird!
+ if( 2 < pTxtFmtCollTbl->Count() )
+ pTxtFmtCollTbl->DeleteAndDestroy( 2, pTxtFmtCollTbl->Count()-2 );
+ pTxtFmtCollTbl->DeleteAndDestroy( 1, pTxtFmtCollTbl->Count()-1 );
+ pGrfFmtCollTbl->DeleteAndDestroy( 1, pGrfFmtCollTbl->Count()-1 );
+ pCharFmtTbl->DeleteAndDestroy( 1, pCharFmtTbl->Count()-1 );
+
+ if( pLayout )
+ {
+ // search the FrameFormat of the root frm. This is not allowed to delete
+ pFrmFmtTbl->Remove( pFrmFmtTbl->GetPos( pLayout->GetFmt() ) );
+ pFrmFmtTbl->DeleteAndDestroy( 1, pFrmFmtTbl->Count()-1 );
+ pFrmFmtTbl->Insert( pLayout->GetFmt(), pFrmFmtTbl->Count() );
+ }
+ else
+ pFrmFmtTbl->DeleteAndDestroy( 1, pFrmFmtTbl->Count()-1 );
+
+ xForbiddenCharsTable.unbind();
+
+ pFldTypes->DeleteAndDestroy( INIT_FLDTYPES,
+ pFldTypes->Count() - INIT_FLDTYPES );
+
+ delete pNumberFormatter, pNumberFormatter = 0;
+
+ GetPageDescFromPool( RES_POOLPAGE_STANDARD );
+ pFirstNd->ChgFmtColl( GetTxtCollFromPool( RES_POOLCOLL_STANDARD ));
+ nDummyPgDsc = aPageDescs.Count();
+ aPageDescs.Insert( pDummyPgDsc, nDummyPgDsc );
+ // set the layout back to the new standard pagedesc
+ pFirstNd->ResetAllAttr();
+ // delete now the dummy pagedesc
+ DelPageDesc( nDummyPgDsc );
+}
+
+void SwDoc::SetPreViewPrtData( const SwPagePreViewPrtData* pNew )
+{
+ if( pNew )
+ {
+ if( pPgPViewPrtData )
+ *pPgPViewPrtData = *pNew;
+ else
+ pPgPViewPrtData = new SwPagePreViewPrtData( *pNew );
+ }
+ else if( pPgPViewPrtData )
+ DELETEZ( pPgPViewPrtData );
+ SetModified();
+}
+/* -----------------------------06.01.00 14:03--------------------------------
+
+ ---------------------------------------------------------------------------*/
+SwModify* SwDoc::GetUnoCallBack() const
+{
+ return pUnoCallBack;
+}
+
+/*-----------------28.5.2001 10:06------------------
+ * SwDoc:
+ * Reading and writing of the layout cache.
+ *--------------------------------------------------*/
+
+void SwDoc::ReadLayoutCache( SvStream& rStream )
+{
+ if( !pLayoutCache )
+ pLayoutCache = new SwLayoutCache();
+ if( !pLayoutCache->IsLocked() )
+ {
+ pLayoutCache->GetLockCount() |= 0x8000;
+ pLayoutCache->Read( rStream );
+ pLayoutCache->GetLockCount() &= 0x7fff;
+ }
+}
+
+void SwDoc::WriteLayoutCache( SvStream& rStream )
+{
+ pLayoutCache->Write( rStream, *this );
+}
+
+IGrammarContact* getGrammarContact( const SwTxtNode& rTxtNode )
+{
+ const SwDoc* pDoc = rTxtNode.GetDoc();
+ if( !pDoc || pDoc->IsInDtor() )
+ return 0;
+ return pDoc->getGrammarContact();
+}
+
+// --> FME 2005-02-25 #i42634# Moved common code of SwReader::Read() and
+// SwDocShell::UpdateLinks() to new SwDoc::UpdateLinks():
+void SwDoc::UpdateLinks( sal_Bool bUI )
+{
+ SfxObjectCreateMode eMode;
+ sal_uInt16 nLinkMode = getLinkUpdateMode( true );
+ sal_uInt16 nUpdateDocMode = GetDocShell()->GetUpdateDocMode();
+ if( GetDocShell() &&
+ (nLinkMode != NEVER || document::UpdateDocMode::FULL_UPDATE == nUpdateDocMode) &&
+ GetLinkManager().GetLinks().Count() &&
+ SFX_CREATE_MODE_INTERNAL !=
+ ( eMode = GetDocShell()->GetCreateMode()) &&
+ SFX_CREATE_MODE_ORGANIZER != eMode &&
+ SFX_CREATE_MODE_PREVIEW != eMode &&
+ !GetDocShell()->IsPreview() )
+ {
+ ViewShell* pVSh = 0;
+ sal_Bool bAskUpdate = nLinkMode == MANUAL;
+ sal_Bool bUpdate = sal_True;
+ switch(nUpdateDocMode)
+ {
+ case document::UpdateDocMode::NO_UPDATE: bUpdate = sal_False;break;
+ case document::UpdateDocMode::QUIET_UPDATE:bAskUpdate = sal_False; break;
+ case document::UpdateDocMode::FULL_UPDATE: bAskUpdate = sal_True; break;
+ }
+ if( bUpdate && (bUI || !bAskUpdate) )
+ {
+ SfxMedium* pMedium = GetDocShell()->GetMedium();
+ SfxFrame* pFrm = pMedium ? pMedium->GetLoadTargetFrame() : 0;
+ Window* pDlgParent = pFrm ? &pFrm->GetWindow() : 0;
+ if( GetRootFrm() && !GetEditShell( &pVSh ) && !pVSh )
+ {
+ ViewShell aVSh( *this, 0, 0 );
+
+ SET_CURR_SHELL( &aVSh );
+ GetLinkManager().UpdateAllLinks( bAskUpdate , sal_True, sal_False, pDlgParent );
+ }
+ else
+ GetLinkManager().UpdateAllLinks( bAskUpdate, sal_True, sal_False, pDlgParent );
+ }
+ }
+
+}
+// <--
+// --> OD 2006-04-19 #b6375613#
+void SwDoc::SetApplyWorkaroundForB6375613( bool p_bApplyWorkaroundForB6375613 )
+{
+ if ( mbApplyWorkaroundForB6375613 != p_bApplyWorkaroundForB6375613 )
+ {
+ mbApplyWorkaroundForB6375613 = p_bApplyWorkaroundForB6375613;
+
+ uno::Reference< document::XDocumentInfoSupplier > xDoc(
+ GetDocShell()->GetBaseModel(),
+ uno::UNO_QUERY);
+ if ( xDoc.is() )
+ {
+ uno::Reference< beans::XPropertyContainer > xDocInfo(
+ xDoc->getDocumentInfo(),
+ uno::UNO_QUERY );
+ if ( xDocInfo.is() )
+ {
+ try
+ {
+ if ( mbApplyWorkaroundForB6375613 )
+ {
+ xDocInfo->addProperty(
+ rtl::OUString::createFromAscii("WorkaroundForB6375613Applied"),
+ beans::PropertyAttribute::TRANSIENT | beans::PropertyAttribute::REMOVABLE,
+ uno::makeAny( false ) );
+ }
+ else
+ {
+ xDocInfo->removeProperty( rtl::OUString::createFromAscii("WorkaroundForB6375613Applied") );
+ }
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+ }
+ }
+}
+// <--
+
+::sfx2::IXmlIdRegistry&
+SwDoc::GetXmlIdRegistry()
+{
+ // UGLY: this relies on SetClipBoard being called before GetXmlIdRegistry!
+ if (!m_pXmlIdRegistry.get())
+ {
+ m_pXmlIdRegistry.reset( ::sfx2::createXmlIdRegistry( IsClipBoard() ) );
+ }
+ return *m_pXmlIdRegistry;
+}
+
+::sw::MetaFieldManager &
+SwDoc::GetMetaFieldManager()
+{
+ return *m_pMetaFieldManager;
+}
+
+::sw::UndoManager &
+SwDoc::GetUndoManager()
+{
+ return *m_pUndoManager;
+}
+
+::sw::UndoManager const&
+SwDoc::GetUndoManager() const
+{
+ return *m_pUndoManager;
+}
+
+IDocumentUndoRedo &
+SwDoc::GetIDocumentUndoRedo()
+{
+ return *m_pUndoManager;
+}
+
+IDocumentUndoRedo const&
+SwDoc::GetIDocumentUndoRedo() const
+{
+ return *m_pUndoManager;
+}
+
+void SwDoc::InitTOXTypes()
+{
+ ShellResource* pShellRes = ViewShell::GetShellRes();
+ SwTOXType * pNew = new SwTOXType(TOX_CONTENT, pShellRes->aTOXContentName );
+ pTOXTypes->Insert( pNew, pTOXTypes->Count() );
+ pNew = new SwTOXType(TOX_INDEX, pShellRes->aTOXIndexName );
+ pTOXTypes->Insert( pNew, pTOXTypes->Count() );
+ pNew = new SwTOXType(TOX_USER, pShellRes->aTOXUserName );
+ pTOXTypes->Insert( pNew, pTOXTypes->Count() );
+ pNew = new SwTOXType(TOX_ILLUSTRATIONS, pShellRes->aTOXIllustrationsName );
+ pTOXTypes->Insert( pNew, pTOXTypes->Count() );
+ pNew = new SwTOXType(TOX_OBJECTS, pShellRes->aTOXObjectsName );
+ pTOXTypes->Insert( pNew, pTOXTypes->Count() );
+ pNew = new SwTOXType(TOX_TABLES, pShellRes->aTOXTablesName );
+ pTOXTypes->Insert( pNew, pTOXTypes->Count() );
+ pNew = new SwTOXType(TOX_AUTHORITIES, pShellRes->aTOXAuthoritiesName );
+ pTOXTypes->Insert( pNew, pTOXTypes->Count() );
+}
+
+/*-- 08.05.2009 10:07:57---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
+{
+ SwDoc* pRet = new SwDoc;
+ //copy settings
+ sal_uInt16 __FAR_DATA aRangeOfDefaults[] = {
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_PARATR_BEGIN, RES_PARATR_END-1,
+ // --> OD 2008-02-25 #refactorlists##
+ RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
+ // <--
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0
+ };
+
+ SfxItemSet aNewDefaults( pRet->GetAttrPool(), aRangeOfDefaults );
+
+ sal_uInt16 nWhich;
+ sal_uInt16 nRange = 0;
+ while( aRangeOfDefaults[nRange] != 0)
+ {
+ for( nWhich = aRangeOfDefaults[nRange]; nWhich < aRangeOfDefaults[nRange + 1]; ++nWhich )
+ {
+ const SfxPoolItem& rSourceAttr = mpAttrPool->GetDefaultItem( nWhich );
+ if( rSourceAttr != pRet->mpAttrPool->GetDefaultItem( nWhich ) )
+ aNewDefaults.Put( rSourceAttr );
+ }
+ nRange += 2;
+ }
+ if( aNewDefaults.Count() )
+ pRet->SetDefault( aNewDefaults );
+
+ pRet->n32DummyCompatabilityOptions1 = n32DummyCompatabilityOptions1;
+ pRet->n32DummyCompatabilityOptions2 = n32DummyCompatabilityOptions2;
+ pRet->mbParaSpaceMax = mbParaSpaceMax ;
+ pRet->mbParaSpaceMaxAtPages = mbParaSpaceMaxAtPages ;
+ pRet->mbTabCompat = mbTabCompat ;
+ pRet->mbUseVirtualDevice = mbUseVirtualDevice ;
+ pRet->mbAddExternalLeading = mbAddExternalLeading ;
+ pRet->mbOldLineSpacing = mbOldLineSpacing ;
+ pRet->mbAddParaSpacingToTableCells = mbAddParaSpacingToTableCells ;
+ pRet->mbUseFormerObjectPos = mbUseFormerObjectPos ;
+ pRet->mbUseFormerTextWrapping = mbUseFormerTextWrapping ;
+ pRet->mbConsiderWrapOnObjPos = mbConsiderWrapOnObjPos ;
+ pRet->mbAddFlyOffsets = mbAddFlyOffsets ;
+ pRet->mbOldNumbering = mbOldNumbering ;
+ pRet->mbUseHiResolutionVirtualDevice = mbUseHiResolutionVirtualDevice ;
+ pRet->mbIgnoreFirstLineIndentInNumbering = mbIgnoreFirstLineIndentInNumbering ;
+ pRet->mbDoNotJustifyLinesWithManualBreak = mbDoNotJustifyLinesWithManualBreak ;
+ pRet->mbDoNotResetParaAttrsForNumFont = mbDoNotResetParaAttrsForNumFont ;
+ pRet->mbOutlineLevelYieldsOutlineRule = mbOutlineLevelYieldsOutlineRule ;
+ pRet->mbTableRowKeep = mbTableRowKeep ;
+ pRet->mbIgnoreTabsAndBlanksForLineCalculation = mbIgnoreTabsAndBlanksForLineCalculation ;
+ pRet->mbDoNotCaptureDrawObjsOnPage = mbDoNotCaptureDrawObjsOnPage ;
+ pRet->mbClipAsCharacterAnchoredWriterFlyFrames= mbClipAsCharacterAnchoredWriterFlyFrames;
+ pRet->mbUnixForceZeroExtLeading = mbUnixForceZeroExtLeading ;
+ pRet->mbOldPrinterMetrics = mbOldPrinterMetrics ;
+ pRet->mbTabRelativeToIndent = mbTabRelativeToIndent ;
+ pRet->mbTabAtLeftIndentForParagraphsInList = mbTabAtLeftIndentForParagraphsInList ;
+
+ //
+ // COMPATIBILITY FLAGS END
+ //
+ pRet->ReplaceStyles( * const_cast< SwDoc*>( this ));
+
+ // we have to use pointer here, since the callee has to decide whether SfxObjectShellLock or SfxObjectShellRef should be used
+ // sometimes the object will be returned with refcount set to 0 ( if no DoInitNew is done )
+ SfxObjectShell* pRetShell = new SwDocShell( pRet, SFX_CREATE_MODE_STANDARD );
+ if( bCallInitNew )
+ {
+ // it could happen that DoInitNew creates model, that increases the refcount of the object
+ pRetShell->DoInitNew();
+ }
+
+ //copy content
+ pRet->Paste( *this );
+
+ // remove the temporary shell if it is there as it was done before
+ pRet->SetTmpDocShell( (SfxObjectShell*)NULL );
+
+ return pRetShell;
+}
+/*-- 08.05.2009 10:52:40---------------------------------------------------
+ copy document content - code from SwFEShell::Paste( SwDoc* , sal_Bool )
+ -----------------------------------------------------------------------*/
+void SwDoc::Paste( const SwDoc& rSource )
+{
+// this has to be empty const sal_uInt16 nStartPageNumber = GetPhyPageNum();
+ // until the end of the NodesArray
+ SwNodeIndex aSourceIdx( rSource.GetNodes().GetEndOfExtras(), 2 );
+ SwPaM aCpyPam( aSourceIdx ); //DocStart
+ SwNodeIndex aTargetIdx( GetNodes().GetEndOfExtras(), 2 );
+ SwPaM aInsertPam( aTargetIdx ); //replaces PCURCRSR from SwFEShell::Paste()
+
+
+ aCpyPam.SetMark();
+ aCpyPam.Move( fnMoveForward, fnGoDoc );
+
+ this->GetIDocumentUndoRedo().StartUndo( UNDO_INSGLOSSARY, NULL );
+ this->LockExpFlds();
+
+ {
+ SwPosition& rInsPos = *aInsertPam.GetPoint();
+ //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);
+
+ aIndexBefore--;
+
+ rSource.CopyRange( aCpyPam, rInsPos, true );
+
+ {
+ aIndexBefore++;
+ SwPaM aPaM(SwPosition(aIndexBefore),
+ SwPosition(rInsPos.nNode));
+
+ MakeUniqueNumRules(aPaM);
+ }
+ }
+
+ //TODO: Is this necessary here? SaveTblBoxCntnt( &rInsPos );
+ if(/*bIncludingPageFrames && */bStartWithTable)
+ {
+ //remove the paragraph in front of the table
+ SwPaM aPara(aInsertPosition);
+ this->DelFullPara(aPara);
+ }
+ //additionally copy page bound frames
+ if( /*bIncludingPageFrames && */rSource.GetSpzFrmFmts()->Count() )
+ {
+ for ( sal_uInt16 i = 0; i < rSource.GetSpzFrmFmts()->Count(); ++i )
+ {
+ sal_Bool bInsWithFmt = sal_True;
+ const SwFrmFmt& rCpyFmt = *(*rSource.GetSpzFrmFmts())[i];
+ if( bInsWithFmt )
+ {
+ SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() );
+ if (FLY_AT_PAGE == aAnchor.GetAnchorId())
+ {
+ aAnchor.SetPageNum( aAnchor.GetPageNum() /*+ nStartPageNumber - */);
+ }
+ else
+ continue;
+ this->CopyLayoutFmt( rCpyFmt, aAnchor, true, true );
+ }
+ }
+ }
+ }
+
+ this->GetIDocumentUndoRedo().EndUndo( UNDO_INSGLOSSARY, NULL );
+
+ UnlockExpFlds();
+ UpdateFlds(NULL, false);
+}
diff --git a/sw/source/core/doc/docnum.cxx b/sw/source/core/doc/docnum.cxx
new file mode 100644
index 000000000000..5a559c022c7b
--- /dev/null
+++ b/sw/source/core/doc/docnum.cxx
@@ -0,0 +1,2972 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <tools/date.hxx>
+#include <tools/time.hxx>
+#include <tools/resid.hxx>
+#include <editeng/lrspitem.hxx>
+#include <ftninfo.hxx>
+#include <ftnidx.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <doctxm.hxx> // pTOXBaseRing
+#include <poolfmt.hxx>
+#include <UndoCore.hxx>
+#include <UndoRedline.hxx>
+#include <UndoNumbering.hxx>
+#include <swundo.hxx>
+#include <SwUndoFmt.hxx>
+#include <rolbck.hxx>
+#include <paratr.hxx>
+#include <docary.hxx>
+#include <mvsave.hxx>
+#include <txtfrm.hxx>
+#include <pamtyp.hxx>
+#include <redline.hxx>
+#include <comcore.hrc>
+#include <editeng/adjitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <frmatr.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <SwNodeNum.hxx>
+// --> OD 2008-03-13 #refactorlists#
+#include <list.hxx>
+#include <listfunc.hxx>
+// <--
+
+#include <map>
+
+inline sal_uInt8 GetUpperLvlChg( sal_uInt8 nCurLvl, sal_uInt8 nLevel, sal_uInt16 nMask )
+{
+ if( 1 < nLevel )
+ {
+ if( nCurLvl + 1 >= nLevel )
+ nCurLvl -= nLevel - 1;
+ else
+ nCurLvl = 0;
+ }
+ return static_cast<sal_uInt8>((nMask - 1) & ~(( 1 << nCurLvl ) - 1));
+}
+
+void SwDoc::SetOutlineNumRule( const SwNumRule& rRule )
+{
+ if( pOutlineRule )
+ (*pOutlineRule) = rRule;
+ else
+ {
+ pOutlineRule = new SwNumRule( rRule );
+
+ AddNumRule(pOutlineRule); // #i36749#
+ }
+
+ pOutlineRule->SetRuleType( OUTLINE_RULE );
+ // --> OD 2008-07-08 #i91400#
+ pOutlineRule->SetName( String::CreateFromAscii(
+ SwNumRule::GetOutlineRuleName() ),
+ *this);
+ // <--
+ // --> OD 2006-09-21 #i69522#
+ // assure that the outline numbering rule is an automatic rule
+ pOutlineRule->SetAutoRule( sal_True );
+ // <--
+
+ // teste ob die evt. gesetzen CharFormate in diesem Document
+ // definiert sind
+ pOutlineRule->CheckCharFmts( this );
+
+ // --> OD 2008-05-13 #refactorlists#
+ // notify text nodes, which are registered at the outline style, about the
+ // changed outline style
+ SwNumRule::tTxtNodeList aTxtNodeList;
+ pOutlineRule->GetTxtNodeList( aTxtNodeList );
+ for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
+ aIter != aTxtNodeList.end(); ++aIter )
+ {
+ SwTxtNode* pTxtNd = *aIter;
+ pTxtNd->NumRuleChgd();
+ // --> OD 2009-01-20 #i94152#
+ // assure that list level corresponds to outline level
+ if ( pTxtNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle() &&
+ pTxtNd->GetAttrListLevel() != pTxtNd->GetTxtColl()->GetAssignedOutlineStyleLevel() )
+ {
+ pTxtNd->SetAttrListLevel( pTxtNd->GetTxtColl()->GetAssignedOutlineStyleLevel() );
+ }
+ // <--
+ }
+ // <--
+
+ PropagateOutlineRule();
+ pOutlineRule->SetInvalidRule(sal_True);
+ UpdateNumRule();
+
+ // gibt es Fussnoten && gilt Kapitelweises Nummerieren, dann updaten
+ if( GetFtnIdxs().Count() && FTNNUM_CHAPTER == GetFtnInfo().eNum )
+ GetFtnIdxs().UpdateAllFtn();
+
+ UpdateExpFlds(NULL, true);
+
+ SetModified();
+}
+
+void SwDoc::PropagateOutlineRule()
+{
+ for (sal_uInt16 n = 0; n < pTxtFmtCollTbl->Count(); n++)
+ {
+ SwTxtFmtColl *pColl = (*pTxtFmtCollTbl)[n];
+
+ // if (NO_NUMBERING != pColl->GetOutlineLevel())//#outline level,zhaojianwei
+ if(pColl->IsAssignedToListLevelOfOutlineStyle())//<-end,zhaojianwei
+ {
+ SwClientIter aIter(*pColl);
+
+ // --> OD 2006-11-20 #i71764#
+ // Check only the list style, which is set at the paragraph style
+ const SwNumRuleItem & rCollRuleItem = pColl->GetNumRule( sal_False );
+ // <--
+
+ // --> OD 2006-11-20 #i71764#
+ // Check on document setting OUTLINE_LEVEL_YIELDS_OUTLINE_RULE no longer needed.
+ if ( rCollRuleItem.GetValue().Len() == 0 )
+ // <--
+ {
+ SwNumRule * pMyOutlineRule = GetOutlineNumRule();
+
+ if (pMyOutlineRule)
+ {
+ SwNumRuleItem aNumItem( pMyOutlineRule->GetName() );
+
+ pColl->SetFmtAttr(aNumItem);
+ }
+ }
+ }
+ }
+}
+
+ // Hoch-/Runterstufen
+sal_Bool SwDoc::OutlineUpDown( const SwPaM& rPam, short nOffset )
+{
+ if( !GetNodes().GetOutLineNds().Count() || !nOffset )
+ return sal_False;
+
+ // den Bereich feststellen
+ const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
+ const SwNodePtr pSttNd = (SwNodePtr)&rPam.Start()->nNode.GetNode();
+ const SwNodePtr pEndNd = (SwNodePtr)&rPam.End()->nNode.GetNode();
+ sal_uInt16 nSttPos, nEndPos;
+
+ if( !rOutlNds.Seek_Entry( pSttNd, &nSttPos ) &&
+ !nSttPos-- )
+ // wir stehen in keiner "Outline-Section"
+ return sal_False;
+
+ if( rOutlNds.Seek_Entry( pEndNd, &nEndPos ) )
+ ++nEndPos;
+
+ // jetzt haben wir unseren Bereich im OutlineNodes-Array
+ // dann prufe ersmal, ob nicht unterebenen aufgehoben werden
+ // (Stufung ueber die Grenzen)
+ sal_uInt16 n;
+
+ // so, dann koennen wir:
+ // 1. Vorlagen-Array anlegen
+ SwTxtFmtColl* aCollArr[ MAXLEVEL ];
+ memset( aCollArr, 0, sizeof( SwTxtFmtColl* ) * MAXLEVEL );
+
+ for( n = 0; n < pTxtFmtCollTbl->Count(); ++n )
+ {
+ //sal_uInt8 nLevel = (*pTxtFmtCollTbl)[ n ]->GetOutlineLevel();//#outline level,zhaojianwei
+ //if( nLevel < MAXLEVEL )
+ // aCollArr[ nLevel ] = (*pTxtFmtCollTbl)[ n ];
+ if((*pTxtFmtCollTbl)[ n ]->IsAssignedToListLevelOfOutlineStyle())
+ {
+ const int nLevel = (*pTxtFmtCollTbl)[ n ]->GetAssignedOutlineStyleLevel();
+ aCollArr[ nLevel ] = (*pTxtFmtCollTbl)[ n ];
+ }//<-end,zhaojianwei
+ }
+
+ /* --> #111107# */
+ /* Find the last occupied level (backward). */
+ for (n = MAXLEVEL - 1; n > 0; n--)
+ {
+ if (aCollArr[n] != 0)
+ break;
+ }
+
+ /* If an occupied level is found, choose next level (which IS
+ unoccupied) until a valid level is found. If no occupied level
+ was found n is 0 and aCollArr[0] is 0. In this case no demoting
+ is possible. */
+ if (aCollArr[n] != 0)
+ {
+ while (n < MAXLEVEL - 1)
+ {
+ n++;
+
+ SwTxtFmtColl *aTmpColl =
+ GetTxtCollFromPool(static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + n));
+
+ //if (aTmpColl->GetOutlineLevel() == n)//#outline level,zhaojianwei
+ if( aTmpColl->IsAssignedToListLevelOfOutlineStyle() &&
+ aTmpColl->GetAssignedOutlineStyleLevel() == n )//<-end,zhaojianwei
+ {
+ aCollArr[n] = aTmpColl;
+ break;
+ }
+ }
+ }
+
+ /* Find the first occupied level (forward). */
+ for (n = 0; n < MAXLEVEL - 1; n++)
+ {
+ if (aCollArr[n] != 0)
+ break;
+ }
+
+ /* If an occupied level is found, choose previous level (which IS
+ unoccupied) until a valid level is found. If no occupied level
+ was found n is MAXLEVEL - 1 and aCollArr[MAXLEVEL - 1] is 0. In
+ this case no demoting is possible. */
+ if (aCollArr[n] != 0)
+ {
+ while (n > 0)
+ {
+ n--;
+
+ SwTxtFmtColl *aTmpColl =
+ GetTxtCollFromPool(static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + n));
+
+ //if (aTmpColl->GetOutlineLevel() == n)//#outline level,zhaojianwei
+ if( aTmpColl->IsAssignedToListLevelOfOutlineStyle() &&
+ aTmpColl->GetAssignedOutlineStyleLevel() == n )//<-end,zhaojianwei
+ {
+ aCollArr[n] = aTmpColl;
+ break;
+ }
+ }
+ }
+ /* <-- #111107# */
+
+ /* --> #i13747#
+
+ Build a move table that states from which level an outline will
+
+ be moved to which other level. */
+
+ /* the move table
+
+ aMoveArr[n] = m: replace aCollArr[n] with aCollArr[m]
+ */
+ int aMoveArr[MAXLEVEL];
+ int nStep; // step size for searching in aCollArr: -1 or 1
+ int nNum; // amount of steps for stepping in aCollArr
+
+ if (nOffset < 0)
+ {
+ nStep = -1;
+ nNum = -nOffset;
+ }
+ else
+ {
+ nStep = 1;
+ nNum = nOffset;
+ }
+
+ /* traverse aCollArr */
+ for (n = 0; n < MAXLEVEL; n++)
+ {
+ /* If outline level n has an assigned paragraph style step
+ nNum steps forwards (nStep == 1) or backwards (nStep ==
+ -1). One step is to go to the next non-null entry in
+ aCollArr in the selected direction. If nNum steps were
+ possible write the index of the entry found to aCollArr[n],
+ i.e. outline level n will be replaced by outline level
+ aCollArr[n].
+
+ If outline level n has no assigned paragraph style
+ aMoveArr[n] is set to -1.
+ */
+ if (aCollArr[n] != NULL)
+ {
+ sal_uInt16 m = n;
+ int nCount = nNum;
+
+ while (nCount > 0 && m + nStep >= 0 && m + nStep < MAXLEVEL)
+ {
+ m = static_cast<sal_uInt16>(m + nStep);
+
+ if (aCollArr[m] != NULL)
+ nCount--;
+ }
+
+ if (nCount == 0)
+ aMoveArr[n] = m;
+ else
+ aMoveArr[n] = -1;
+
+ }
+ else
+ aMoveArr[n] = -1;
+ }
+
+ /* If moving of the outline levels is applicable, i.e. for all
+ outline levels occuring in the document there has to be a valid
+ target outline level implied by aMoveArr. */
+ bool bMoveApplicable = true;
+ for (n = nSttPos; n < nEndPos; n++)
+ {
+ SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
+ SwTxtFmtColl* pColl = pTxtNd->GetTxtColl();
+// int nLevel = pColl->GetOutlineLevel();//#outline level,zhaojianwei
+// if (aMoveArr[nLevel] == -1)
+// bMoveApplicable = false;
+ if( pColl->IsAssignedToListLevelOfOutlineStyle() )
+ {
+ const int nLevel = pColl->GetAssignedOutlineStyleLevel();
+ if (aMoveArr[nLevel] == -1)
+ bMoveApplicable = false;
+ }//<-end,zhaojianwei
+ // --> OD 2008-12-16 #i70748#
+ // Check on outline level attribute of text node, if text node is
+ // not an outline via a to outline style assigned paragraph style.
+ else
+ {
+ const int nNewOutlineLevel = pTxtNd->GetAttrOutlineLevel() + nOffset;
+ if ( nNewOutlineLevel < 1 || nNewOutlineLevel > MAXLEVEL )
+ {
+ bMoveApplicable = false;
+ }
+ }
+ // <--
+ }
+
+ if (! bMoveApplicable )
+ return sal_False;
+
+ /* <-- #i13747 # */
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().StartUndo(UNDO_OUTLINE_LR, NULL);
+ SwUndo *const pUndoOLR( new SwUndoOutlineLeftRight( rPam, nOffset ) );
+ GetIDocumentUndoRedo().AppendUndo(pUndoOLR);
+ }
+
+ // 2. allen Nodes die neue Vorlage zuweisen
+
+ n = nSttPos;
+ while( n < nEndPos)
+ {
+ SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
+ SwTxtFmtColl* pColl = pTxtNd->GetTxtColl();
+
+ if( pColl->IsAssignedToListLevelOfOutlineStyle() )
+ {
+ // ASSERT(pColl->GetOutlineLevel() < MAXLEVEL, //#outline level,removed by zhaojianwei
+ // "non outline node in outline nodes?");
+ //int nLevel = pColl->GetOutlineLevel();
+ const int nLevel = pColl->GetAssignedOutlineStyleLevel();//#outline level,add by zhaojianwei
+
+ ASSERT(aMoveArr[nLevel] >= 0,
+ "move table: current TxtColl not found when building table!");
+
+
+ if (nLevel < MAXLEVEL && aMoveArr[nLevel] >= 0)
+ {
+ pColl = aCollArr[ aMoveArr[nLevel] ];
+
+ if (pColl != NULL)
+ pColl = (SwTxtFmtColl*)pTxtNd->ChgFmtColl( pColl );
+ }
+
+ }
+ else if( pTxtNd->GetAttrOutlineLevel() > 0) //#outline level,add by zhaojianwei
+ {
+ int nLevel = pTxtNd->GetAttrOutlineLevel() + nOffset;
+ if( 0 <= nLevel && nLevel <= MAXLEVEL)
+ pTxtNd->SetAttrOutlineLevel( nLevel );
+
+ }//<-end,zhaojianwei
+
+ n++;
+ // Undo ???
+ }
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().EndUndo(UNDO_OUTLINE_LR, NULL);
+ }
+
+ ChkCondColls();
+ SetModified();
+
+ return sal_True;
+}
+
+
+
+ // Hoch-/Runter - Verschieben !
+sal_Bool SwDoc::MoveOutlinePara( const SwPaM& rPam, short nOffset )
+{
+ // kein Verschiebung in den Sonderbereichen
+ const SwPosition& rStt = *rPam.Start(),
+ & rEnd = &rStt == rPam.GetPoint() ? *rPam.GetMark()
+ : *rPam.GetPoint();
+ if( !GetNodes().GetOutLineNds().Count() || !nOffset ||
+ (rStt.nNode.GetIndex() < GetNodes().GetEndOfExtras().GetIndex()) ||
+ (rEnd.nNode.GetIndex() < GetNodes().GetEndOfExtras().GetIndex()))
+ {
+ return sal_False;
+ }
+
+ sal_uInt16 nAktPos = 0;
+ SwNodeIndex aSttRg( rStt.nNode ), aEndRg( rEnd.nNode );
+
+ //sal_uInt8 nOutLineLevel = NO_NUMBERING; //#outline level,zhaojianwei
+ int nOutLineLevel = MAXLEVEL; //<-end,zhaojianwei
+ SwNode* pSrch = &aSttRg.GetNode();
+ //if( pSrch->IsTxtNode() ) //#outline level,zhaojianwei
+ // nOutLineLevel = static_cast<sal_uInt8>(((SwTxtNode*)pSrch)->GetOutlineLevel());
+ if( pSrch->IsTxtNode())
+ nOutLineLevel = static_cast<sal_uInt8>(((SwTxtNode*)pSrch)->GetAttrOutlineLevel()-1);//<-end,zhaojianwei
+ SwNode* pEndSrch = &aEndRg.GetNode();
+ if( !GetNodes().GetOutLineNds().Seek_Entry( pSrch, &nAktPos ) )
+ {
+ if( !nAktPos )
+ return sal_False; // Promoting or demoting before the first outline => no.
+ if( --nAktPos )
+ aSttRg = *GetNodes().GetOutLineNds()[ nAktPos ];
+ else if( 0 > nOffset )
+ return sal_False; // Promoting at the top of document?!
+ else
+ aSttRg = *GetNodes().GetEndOfContent().StartOfSectionNode();
+ }
+ sal_uInt16 nTmpPos = 0;
+ // If the given range ends at an outlined text node we have to decide if it has to be a part of
+ // the moving range or not. Normally it will be a sub outline of our chapter
+ // and has to be moved, too. But if the chapter ends with a table(or a section end),
+ // the next text node will be choosen and this could be the next outline of the same level.
+ // The criteria has to be the outline level: sub level => incorporate, same/higher level => no.
+ if( GetNodes().GetOutLineNds().Seek_Entry( pEndSrch, &nTmpPos ) )
+ {
+ if( !pEndSrch->IsTxtNode() || pEndSrch == pSrch ||
+ //nOutLineLevel < ((SwTxtNode*)pEndSrch)->GetOutlineLevel() )//#outline level,zhaojianwei
+ nOutLineLevel < ((SwTxtNode*)pEndSrch)->GetAttrOutlineLevel()-1 )//<-end,zhaojianwei
+ ++nTmpPos; // For sub outlines only!
+ }
+
+ aEndRg = nTmpPos < GetNodes().GetOutLineNds().Count()
+ ? *GetNodes().GetOutLineNds()[ nTmpPos ]
+ : GetNodes().GetEndOfContent();
+ if( nOffset >= 0 )
+ nAktPos = nTmpPos;
+ if( aEndRg == aSttRg )
+ {
+ ASSERT( false, "Moving outlines: Surprising selection" );
+ aEndRg++;
+ }
+
+ const SwNode* pNd;
+ // The following code corrects the range to handle sections (start/end nodes)
+ // The range will be extended if the least node before the range is a start node
+ // which ends inside the range => The complete section will be moved.
+ // The range will be shrinked if the last position is a start node.
+ // The range will be shrinked if the last node is an end node which starts before the range.
+ aSttRg--;
+ while( aSttRg.GetNode().IsStartNode() )
+ {
+ pNd = aSttRg.GetNode().EndOfSectionNode();
+ if( pNd->GetIndex() >= aEndRg.GetIndex() )
+ break;
+ aSttRg--;
+ }
+ aSttRg++;
+
+ aEndRg--;
+ while( aEndRg.GetNode().IsStartNode() )
+ aEndRg--;
+ while( aEndRg.GetNode().IsEndNode() )
+ {
+ pNd = aEndRg.GetNode().StartOfSectionNode();
+ if( pNd->GetIndex() >= aSttRg.GetIndex() )
+ break;
+ aEndRg--;
+ }
+ aEndRg++;
+
+ // calculation of the new position
+ if( nOffset < 0 && nAktPos < sal_uInt16(-nOffset) )
+ pNd = GetNodes().GetEndOfContent().StartOfSectionNode();
+ else if( nAktPos + nOffset >= GetNodes().GetOutLineNds().Count() )
+ pNd = &GetNodes().GetEndOfContent();
+ else
+ pNd = GetNodes().GetOutLineNds()[ nAktPos + nOffset ];
+
+ sal_uLong nNewPos = pNd->GetIndex();
+
+ // And now a correction of the insert position if necessary...
+ SwNodeIndex aInsertPos( *pNd, -1 );
+ while( aInsertPos.GetNode().IsStartNode() )
+ {
+ // Just before the insert position starts a section:
+ // when I'm moving forward I do not want to enter the section,
+ // when I'm moving backward I want to stay in the section if I'm already a part of,
+ // I want to stay outside if I was outside before.
+ if( nOffset < 0 )
+ {
+ pNd = aInsertPos.GetNode().EndOfSectionNode();
+ if( pNd->GetIndex() >= aEndRg.GetIndex() )
+ break;
+ }
+ aInsertPos--;
+ --nNewPos;
+ }
+ if( nOffset >= 0 )
+ {
+ // When just before the insert position a section ends, it is okay when I'm moving backward
+ // because I want to stay outside the section.
+ // When moving forward I've to check if I started inside or outside the section
+ // because I don't want to enter of leave such a section
+ while( aInsertPos.GetNode().IsEndNode() )
+ {
+ pNd = aInsertPos.GetNode().StartOfSectionNode();
+ if( pNd->GetIndex() >= aSttRg.GetIndex() )
+ break;
+ aInsertPos--;
+ --nNewPos;
+ }
+ }
+ // We do not want to move into tables (at the moment)
+ aInsertPos++;
+ pNd = &aInsertPos.GetNode();
+ if( pNd->IsTableNode() )
+ pNd = pNd->StartOfSectionNode();
+ if( pNd->FindTableNode() )
+ return sal_False;
+
+ ASSERT( aSttRg.GetIndex() > nNewPos || nNewPos >= aEndRg.GetIndex(),
+ "Position liegt im MoveBereich" );
+
+ // wurde ein Position in den Sonderbereichen errechnet, dann
+ // setze die Position auf den Dokumentanfang.
+ // Sollten da Bereiche oder Tabellen stehen, so werden sie nach
+ // hinten verschoben.
+ nNewPos = Max( nNewPos, GetNodes().GetEndOfExtras().GetIndex() + 2 );
+
+ long nOffs = nNewPos - ( 0 < nOffset ? aEndRg.GetIndex() : aSttRg.GetIndex());
+ SwPaM aPam( aSttRg, aEndRg, 0, -1 );
+ return MoveParagraph( aPam, nOffs, sal_True );
+}
+
+
+sal_uInt16 lcl_FindOutlineName( const SwNodes& rNds, const String& rName,
+ sal_Bool bExact )
+{
+ sal_uInt16 nSavePos = USHRT_MAX;
+ const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
+ for( sal_uInt16 n = 0; n < rOutlNds.Count(); ++n )
+ {
+ SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
+ String sTxt( pTxtNd->GetExpandTxt() );
+ if( sTxt.Equals( rName ) )
+ {
+ // "exact" gefunden, setze Pos auf den Node
+ nSavePos = n;
+ break;
+ }
+ else if( !bExact && USHRT_MAX == nSavePos &&
+ COMPARE_EQUAL == sTxt.CompareTo( rName, rName.Len()) )
+ {
+ // dann vielleicht nur den den 1.Teil vom Text gefunden
+ nSavePos = n;
+ }
+ }
+
+ return nSavePos;
+}
+
+
+
+sal_uInt16 lcl_FindOutlineNum( const SwNodes& rNds, String& rName )
+{
+ // Gueltig Nummern sind (immer nur Offsets!!!):
+ // ([Nummer]+\.)+ (als regulaerer Ausdruck!)
+ // (Nummer gefolgt von Punkt, zum 5 Wiederholungen)
+ // also: "1.1.", "1.", "1.1.1."
+ xub_StrLen nPos = 0;
+ String sNum = rName.GetToken( 0, '.', nPos );
+ if( STRING_NOTFOUND == nPos )
+ return USHRT_MAX; // ungueltige Nummer!!!
+
+ sal_uInt16 nLevelVal[ MAXLEVEL ]; // Nummern aller Levels
+ memset( nLevelVal, 0, MAXLEVEL * sizeof( nLevelVal[0] ));
+ sal_uInt8 nLevel = 0;
+ String sName( rName );
+
+ while( STRING_NOTFOUND != nPos )
+ {
+ sal_uInt16 nVal = 0;
+ sal_Unicode c;
+ for( sal_uInt16 n = 0; n < sNum.Len(); ++n )
+ if( '0' <= ( c = sNum.GetChar( n )) && c <= '9' )
+ {
+ nVal *= 10; nVal += c - '0';
+ }
+ else if( nLevel )
+ break; // "fast" gueltige Nummer
+ else
+ return USHRT_MAX; // ungueltige Nummer!!!
+
+ if( MAXLEVEL > nLevel )
+ nLevelVal[ nLevel++ ] = nVal;
+
+ sName.Erase( 0, nPos );
+ nPos = 0;
+ sNum = sName.GetToken( 0, '.', nPos );
+ // #i4533# without this check all parts delimited by a dot are treated as outline numbers
+ if(!ByteString(sNum, gsl_getSystemTextEncoding()).IsNumericAscii())
+ nPos = STRING_NOTFOUND;
+ }
+ rName = sName; // das ist der nachfolgende Text.
+
+ // alle Levels gelesen, dann suche mal im Document nach dieser
+ // Gliederung:
+ const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
+ // OS: ohne OutlineNodes lohnt die Suche nicht
+ // und man spart sich einen Absturz #42958#
+ if(!rOutlNds.Count())
+ return USHRT_MAX;
+ SwTxtNode* pNd;
+ nPos = 0;
+ //search in the existing outline nodes for the required outline num array
+ for( ; nPos < rOutlNds.Count(); ++nPos )
+ {
+ pNd = rOutlNds[ nPos ]->GetTxtNode();
+ //sal_uInt8 nLvl = pNd->GetTxtColl()->GetOutlineLevel(); //#outline level,zhaojianwei
+ const int nLvl = pNd->GetAttrOutlineLevel()-1; //<-end,zhaojianwei
+ if( nLvl == nLevel - 1)
+ {
+ // check for the outline num
+ // --> OD 2005-11-02 #i51089 - TUNING#
+ // --> OD 2006-09-22 #i68289#
+ // Assure, that text node has the correct numbering level. Otherwise,
+ // its number vector will not fit to the searched level.
+// if ( pNd->GetNum() )
+ if ( pNd->GetNum() &&
+ pNd->GetActualListLevel() == ( nLevel - 1 ) )
+ // <--
+ {
+ const SwNodeNum & rNdNum = *(pNd->GetNum());
+ SwNumberTree::tNumberVector aLevelVal = rNdNum.GetNumberVector();
+ //now compare with the one searched for
+ bool bEqual = true;
+ for( sal_uInt8 n = 0; (n < nLevel) && bEqual; ++n )
+ {
+ bEqual = aLevelVal[n] == nLevelVal[n];
+ }
+ if(bEqual)
+ {
+ break;
+ }
+ }
+ else
+ {
+ // --> OD 2006-01-12 #126588#
+ // A text node, which has an outline paragraph style applied and
+ // has as hard attribute 'no numbering' set, has an outline level,
+ // but no numbering tree node. Thus, consider this situation in
+ // the assertion condition.
+ ASSERT( !pNd->GetNumRule(),
+ "<lcl_FindOutlineNum(..)> - text node with outline level and numbering rule, but without numbering tree node. This is a serious defect -> inform OD" );
+ }
+ }
+ }
+ if( nPos >= rOutlNds.Count() )
+ nPos = USHRT_MAX;
+ return nPos;
+}
+
+ // zu diesem Gliederungspunkt
+
+
+ // JP 13.06.96:
+ // im Namen kann eine Nummer oder/und der Text stehen.
+ // zuerst wird ueber die Nummer versucht den richtigen Eintrag zu finden.
+ // Gibt es diesen, dann wird ueber den Text verglichen, od es der
+ // gewuenschte ist. Ist das nicht der Fall, wird noch mal nur ueber den
+ // Text gesucht. Wird dieser gefunden ist es der Eintrag. Ansonsten der,
+ // der ueber die Nummer gefunden wurde.
+ // Ist keine Nummer angegeben, dann nur den Text suchen.
+
+sal_Bool SwDoc::GotoOutline( SwPosition& rPos, const String& rName ) const
+{
+ if( rName.Len() )
+ {
+ const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
+
+ // 1. Schritt: ueber die Nummer:
+ String sName( rName );
+ sal_uInt16 nFndPos = ::lcl_FindOutlineNum( GetNodes(), sName );
+ if( USHRT_MAX != nFndPos )
+ {
+ SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode();
+ String sExpandedText = pNd->GetExpandTxt();
+ //#i4533# leading numbers followed by a dot have been remove while
+ //searching for the outline position
+ //to compensate this they must be removed from the paragraphs text content, too
+ sal_uInt16 nPos = 0;
+ String sTempNum;
+ while(sExpandedText.Len() && (sTempNum = sExpandedText.GetToken(0, '.', nPos)).Len() &&
+ STRING_NOTFOUND != nPos &&
+ ByteString(sTempNum, gsl_getSystemTextEncoding()).IsNumericAscii())
+ {
+ sExpandedText.Erase(0, nPos);
+ nPos = 0;
+ }
+
+ if( !sExpandedText.Equals( sName ) )
+ {
+ sal_uInt16 nTmp = ::lcl_FindOutlineName( GetNodes(), sName, sal_True );
+ if( USHRT_MAX != nTmp ) // ueber den Namen gefunden
+ {
+ nFndPos = nTmp;
+ pNd = rOutlNds[ nFndPos ]->GetTxtNode();
+ }
+ }
+ rPos.nNode = *pNd;
+ rPos.nContent.Assign( pNd, 0 );
+ return sal_True;
+ }
+
+ nFndPos = ::lcl_FindOutlineName( GetNodes(), rName, sal_False );
+ if( USHRT_MAX != nFndPos )
+ {
+ SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode();
+ rPos.nNode = *pNd;
+ rPos.nContent.Assign( pNd, 0 );
+ return sal_True;
+ }
+
+ // --> OD 2006-09-22 #i68289#
+ // additional search on hyperlink URL without its outline numbering part
+ if ( !sName.Equals( rName ) )
+ {
+ nFndPos = ::lcl_FindOutlineName( GetNodes(), sName, sal_False );
+ if( USHRT_MAX != nFndPos )
+ {
+ SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode();
+ rPos.nNode = *pNd;
+ rPos.nContent.Assign( pNd, 0 );
+ return sal_True;
+ }
+ }
+ // <--
+ }
+ return sal_False;
+}
+
+/* */
+
+// --- Nummerierung -----------------------------------------
+
+// --> OD 2008-02-19 #refactorlists#
+//void SwNumRuleInfo::MakeList( SwDoc& rDoc, sal_Bool )
+//{
+// SwNumRule* pRule = rDoc.FindNumRulePtr(rName);
+
+// // no rule, no fun.
+// if ( !pRule )
+// return;
+
+// //
+// // 1. Case: Information already available at pRule:
+// //
+// if (pRule->GetTxtNodeList())
+// {
+// // copy list to own pList pointer:
+// aList = *pRule->GetTxtNodeList();
+// return;
+// }
+
+// //
+// // 2. Case: Information has to be generated from scratch:
+// //
+
+// if (pRule->IsOutlineRule())
+// {
+// const SwOutlineNodes & rOutlineNodes = rDoc.GetNodes().GetOutLineNds();
+
+// for (sal_uInt16 i = 0; i < rOutlineNodes.Count(); ++i)
+// {
+// SwTxtNode & aNode = *((SwTxtNode *) rOutlineNodes[i]);
+
+// if (pRule == aNode.GetNumRule())
+// AddNode(aNode);
+// }
+// }
+// {
+// SwModify* pMod;
+// const SfxPoolItem* pItem;
+// sal_uInt16 i, nMaxItems = rDoc.GetAttrPool().GetItemCount
+// ( RES_PARATR_NUMRULE);
+// for( i = 0; i < nMaxItems; ++i )
+// {
+// pItem = rDoc.GetAttrPool().GetItem( RES_PARATR_NUMRULE, i );
+// if( 0 != pItem)
+// {
+// pMod = (SwModify*)((SwNumRuleItem*)pItem)->GetDefinedIn();
+// if (0 != pMod &&
+// ((SwNumRuleItem*)pItem)->GetValue().Len() &&
+// ((SwNumRuleItem*)pItem)->GetValue() == rName )
+// {
+// if( pMod->IsA( TYPE( SwFmt )) )
+// pMod->GetInfo( *this );
+// else
+// {
+// SwTxtNode* pModTxtNode = (SwTxtNode*)pMod;
+
+// // #115901#
+// if( pModTxtNode->GetNodes().IsDocNodes())
+// {
+// AddNode( *pModTxtNode );
+// }
+// }
+// }
+// }
+// }
+// }
+
+// // --> FME 2004-11-03 #i36571# The numrule and this info structure should
+// // have different instances of the list:
+// // --> OD 2006-09-12 #i69145#
+// // method <SwNumRule::SetList(..)> copies content of list provided by the parameter
+// pRule->SetTxtNodeList( aList );
+// // <--
+//}
+// <--
+
+
+void lcl_ChgNumRule( SwDoc& rDoc, const SwNumRule& rRule )
+{
+ SwNumRule* pOld = rDoc.FindNumRulePtr( rRule.GetName() );
+ ASSERT( pOld, "ohne die alte NumRule geht gar nichts" );
+
+ sal_uInt16 nChgFmtLevel = 0, nMask = 1;
+ sal_uInt8 n;
+
+ for( n = 0; n < MAXLEVEL; ++n, nMask <<= 1 )
+ {
+ const SwNumFmt& rOldFmt = pOld->Get( n ),
+ & rNewFmt = rRule.Get( n );
+
+ if( rOldFmt != rNewFmt )
+ {
+ nChgFmtLevel |= nMask;
+ }
+ else if( SVX_NUM_NUMBER_NONE > rNewFmt.GetNumberingType() && 1 < rNewFmt.GetIncludeUpperLevels() &&
+ 0 != (nChgFmtLevel & GetUpperLvlChg( n, rNewFmt.GetIncludeUpperLevels(),nMask )) )
+ nChgFmtLevel |= nMask;
+ }
+
+ if( !nChgFmtLevel ) // es wurde nichts veraendert?
+ {
+ // --> OD 2006-04-27 #i64311#
+ const bool bInvalidateNumRule( pOld->IsContinusNum() != rRule.IsContinusNum() );
+ // <--
+ pOld->CheckCharFmts( &rDoc );
+ pOld->SetContinusNum( rRule.IsContinusNum() );
+ // --> OD 2008-06-17 #i87166#
+ // Do NOT change list style type
+// pOld->SetRuleType( rRule.GetRuleType() );
+ // <--
+ // --> OD 2006-04-27 #i64311#
+ if ( bInvalidateNumRule )
+ {
+ pOld->SetInvalidRule(sal_True);
+ }
+ // <--
+ return ;
+ }
+
+ // --> OD 2008-02-19 #refactorlists#
+// SwNumRuleInfo* pUpd = new SwNumRuleInfo( rRule.GetName() );
+// pUpd->MakeList( rDoc );
+
+// sal_uInt8 nLvl;
+// for( sal_uLong nFirst = 0, nLast = pUpd->GetList().Count();
+// nFirst < nLast; ++nFirst )
+// {
+// SwTxtNode* pTxtNd = pUpd->GetList().GetObject( nFirst );
+// nLvl = static_cast<sal_uInt8>(pTxtNd->GetLevel());
+
+// if( nLvl < MAXLEVEL )
+// {
+// if( nChgFmtLevel & ( 1 << nLvl ))
+// {
+// pTxtNd->NumRuleChgd();
+// }
+// }
+// }
+ SwNumRule::tTxtNodeList aTxtNodeList;
+ pOld->GetTxtNodeList( aTxtNodeList );
+ sal_uInt8 nLvl( 0 );
+ for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
+ aIter != aTxtNodeList.end(); ++aIter )
+ {
+ SwTxtNode* pTxtNd = *aIter;
+ nLvl = static_cast<sal_uInt8>(pTxtNd->GetActualListLevel());
+
+ if( nLvl < MAXLEVEL )
+ {
+ if( nChgFmtLevel & ( 1 << nLvl ))
+ {
+ pTxtNd->NumRuleChgd();
+ }
+ }
+ }
+ // <--
+
+ for( n = 0; n < MAXLEVEL; ++n )
+ if( nChgFmtLevel & ( 1 << n ))
+ pOld->Set( n, rRule.GetNumFmt( n ));
+
+ pOld->CheckCharFmts( &rDoc );
+ pOld->SetInvalidRule(sal_True);
+ pOld->SetContinusNum( rRule.IsContinusNum() );
+ // --> OD 2008-06-17 #i87166#
+ // Do NOT change list style type
+// pOld->SetRuleType( rRule.GetRuleType() );
+ // <--
+
+ // --> OD 2008-02-19 #refactorlists#
+// delete pUpd;
+ // <--
+
+ rDoc.UpdateNumRule();
+}
+
+// OD 2008-02-08 #newlistlevelattrs# - add handling of parameter <bResetIndentAttrs>
+// --> OD 2008-03-17 #refactorlists#
+void SwDoc::SetNumRule( const SwPaM& rPam,
+ const SwNumRule& rRule,
+ const bool bCreateNewList,
+ const String sContinuedListId,
+ sal_Bool bSetItem,
+ const bool bResetIndentAttrs )
+{
+ SwUndoInsNum * pUndo = NULL;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // Start/End for attributes!
+ GetIDocumentUndoRedo().StartUndo( UNDO_INSNUM, NULL );
+ pUndo = new SwUndoInsNum( rPam, rRule );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ SwNumRule * pNew = FindNumRulePtr( rRule.GetName() );
+ bool bUpdateRule = false;
+
+ if( !pNew )
+ {
+ pNew = (*pNumRuleTbl)[ MakeNumRule( rRule.GetName(), &rRule ) ];
+ }
+ else if (rRule != *pNew)
+ {
+ bUpdateRule = true;
+ }
+
+ if (bUpdateRule)
+ {
+ if( pUndo )
+ {
+ pUndo->SaveOldNumRule( *pNew );
+ ::lcl_ChgNumRule( *this, rRule );
+ pUndo->SetLRSpaceEndPos();
+ }
+ else
+ {
+ ::lcl_ChgNumRule( *this, rRule );
+ }
+ }
+
+ // --> OD 2008-03-17 #refactorlists#
+ if ( bSetItem )
+ {
+ if ( bCreateNewList )
+ {
+ String sListId;
+ if ( !bUpdateRule )
+ {
+ // apply list id of list, which has been created for the new list style
+ sListId = pNew->GetDefaultListId();
+ }
+ else
+ {
+ // create new list and apply its list id
+ SwList* pNewList = createList( String(), pNew->GetName() );
+ ASSERT( pNewList,
+ "<SwDoc::SetNumRule(..)> - could not create new list. Serious defect -> please inform OD." );
+ sListId = pNewList->GetListId();
+ }
+ InsertPoolItem( rPam,
+ SfxStringItem( RES_PARATR_LIST_ID, sListId ), 0 );
+ }
+ else if ( sContinuedListId.Len() > 0 )
+ {
+ // apply given list id
+ InsertPoolItem( rPam,
+ SfxStringItem( RES_PARATR_LIST_ID, sContinuedListId ), 0 );
+ }
+ }
+ // <--
+
+ if ( ! rPam.HasMark())
+ {
+ SwTxtNode * pTxtNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
+ // --> OD 2006-10-19 #134160#
+ // consider case that the PaM doesn't denote a text node - e.g. it denotes a graphic node
+ if ( pTxtNd )
+ {
+ SwNumRule * pRule = pTxtNd->GetNumRule();
+
+ if (pRule && pRule->GetName() == pNew->GetName())
+ {
+ bSetItem = sal_False;
+ // --> OD 2008-06-02 #refactorlists#
+ if ( !pTxtNd->IsInList() )
+ {
+ pTxtNd->AddToList();
+ }
+ // <--
+ }
+ // --> OD 2005-10-26 #b6340308# - only clear numbering attribute at
+ // text node, if at paragraph style the new numbering rule is found.
+ else if ( !pRule )
+ {
+ SwTxtFmtColl* pColl = pTxtNd->GetTxtColl();
+ if ( pColl )
+ {
+ SwNumRule* pCollRule = FindNumRulePtr(pColl->GetNumRule().GetValue());
+ if ( pCollRule && pCollRule->GetName() == pNew->GetName() )
+ {
+ pTxtNd->ResetAttr( RES_PARATR_NUMRULE );
+ bSetItem = sal_False;
+ }
+ }
+ }
+ // <--
+ }
+ // <--
+ }
+
+ // --> OD 2009-08-18 #i103817#
+ if ( bSetItem )
+ // <--
+ {
+ InsertPoolItem( rPam, SwNumRuleItem( pNew->GetName() ), 0 );
+ }
+
+ // --> OD 2008-02-08 #newlistlevelattrs#
+ if ( bResetIndentAttrs &&
+ pNew && pNew->Get( 0 ).GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ SvUShortsSort aResetAttrsArray;
+ aResetAttrsArray.Insert( RES_LR_SPACE );
+ // --> OD 2010-10-05 #i114929#
+ // On a selection setup a corresponding Point-and-Mark in order to get
+ // the indentation attribute reset on all paragraphs touched by the selection
+ if ( rPam.HasMark() &&
+ rPam.End()->nNode.GetNode().GetTxtNode() )
+ {
+ SwPaM aPam( rPam.Start()->nNode,
+ rPam.End()->nNode );
+ aPam.Start()->nContent = 0;
+ aPam.End()->nContent = rPam.End()->nNode.GetNode().GetTxtNode()->Len();
+ ResetAttrs( aPam, sal_False, &aResetAttrsArray );
+ }
+ else
+ {
+ ResetAttrs( rPam, sal_False, &aResetAttrsArray );
+ }
+ // <--
+ }
+ // <--
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().EndUndo( UNDO_INSNUM, NULL );
+ }
+
+ SetModified();
+}
+
+void SwDoc::SetCounted(const SwPaM & rPam, bool bCounted)
+{
+ if ( bCounted )
+ {
+ SvUShortsSort aResetAttrsArray;
+ aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED );
+ // --> OD 2010-10-05 #i114929#
+ // On a selection setup a corresponding Point-and-Mark in order to get
+ // the list-is-counted attribute reset on all paragraphs touched by the selection
+ if ( rPam.HasMark() &&
+ rPam.End()->nNode.GetNode().GetTxtNode() )
+ {
+ SwPaM aPam( rPam.Start()->nNode,
+ rPam.End()->nNode );
+ aPam.Start()->nContent = 0;
+ aPam.End()->nContent = rPam.End()->nNode.GetNode().GetTxtNode()->Len();
+ ResetAttrs( aPam, sal_False, &aResetAttrsArray );
+ }
+ else
+ {
+ ResetAttrs( rPam, sal_False, &aResetAttrsArray );
+ }
+ // <--
+ }
+ else
+ {
+ InsertPoolItem( rPam,
+ SfxBoolItem( RES_PARATR_LIST_ISCOUNTED, sal_False ), 0 );
+ }
+}
+
+void SwDoc::SetNumRuleStart( const SwPosition& rPos, sal_Bool bFlag )
+{
+ SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+
+ if (pTxtNd)
+ {
+ const SwNumRule* pRule = pTxtNd->GetNumRule();
+ if( pRule && !bFlag != !pTxtNd->IsListRestart())
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo( new SwUndoNumRuleStart(rPos, bFlag) );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ pTxtNd->SetListRestart(bFlag ? true : false);
+
+ SetModified();
+ }
+ }
+}
+
+void SwDoc::SetNodeNumStart( const SwPosition& rPos, sal_uInt16 nStt )
+{
+ SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+
+ if (pTxtNd)
+ {
+ // --> OD 2008-02-27 #refactorlists#
+// const SwNumRule* pRule = pTxtNd->GetNumRule();
+// if( pRule && nStt != pTxtNd->GetListRestartValue() )
+// {
+// if( DoesUndo() )
+// {
+// ClearRedo();
+// AppendUndo( new SwUndoNumRuleStart( rPos, nStt ));
+// }
+// }
+// pTxtNd->SetListRestartValue(nStt);
+
+// SetModified();
+ if ( !pTxtNd->HasAttrListRestartValue() ||
+ pTxtNd->GetAttrListRestartValue() != nStt )
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo( new SwUndoNumRuleStart(rPos, nStt) );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ pTxtNd->SetAttrListRestartValue( nStt );
+
+ SetModified();
+ }
+ // <--
+ }
+}
+
+ // loeschen geht nur, wenn die Rule niemand benutzt!
+sal_Bool SwDoc::DelNumRule( const String& rName, sal_Bool bBroadcast )
+{
+ sal_uInt16 nPos = FindNumRule( rName );
+
+ // --> OD 2007-12-17 #151213#
+ if ( (*pNumRuleTbl)[ nPos ] == GetOutlineNumRule() )
+ {
+ ASSERT( false,
+ "<SwDoc::DelNumRule(..)> - No deletion of outline list style. This is serious defect - please inform OD" );
+ return sal_False;
+ }
+ // <--
+
+ if( USHRT_MAX != nPos && !IsUsed( *(*pNumRuleTbl)[ nPos ] ))
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo =
+ new SwUndoNumruleDelete(*(*pNumRuleTbl)[nPos], this);
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ if (bBroadcast)
+ BroadcastStyleOperation(rName, SFX_STYLE_FAMILY_PSEUDO,
+ SFX_STYLESHEET_ERASED);
+
+ // --> OD 2008-04-02 #refactorlists#
+ deleteListForListStyle( rName );
+ {
+ // delete further list, which have the deleted list style as default list style
+ std::vector< SwList* > aListsForDeletion;
+ tHashMapForLists::iterator aListIter = maLists.begin();
+ while ( aListIter != maLists.end() )
+ {
+ SwList* pList = (*aListIter).second;
+ if ( pList->GetDefaultListStyleName() == rName )
+ {
+ aListsForDeletion.push_back( pList );
+ }
+
+ ++aListIter;
+ }
+ while ( aListsForDeletion.size() > 0 )
+ {
+ SwList* pList = aListsForDeletion.back();
+ aListsForDeletion.pop_back();
+ deleteList( pList->GetListId() );
+ }
+ }
+ // <--
+ // --> FME 2004-11-02 #i34097# DeleteAndDestroy deletes rName if
+ // rName is directly taken from the numrule.
+ const String aTmpName( rName );
+ // <--
+ pNumRuleTbl->DeleteAndDestroy( nPos );
+ maNumRuleMap.erase(aTmpName);
+
+ SetModified();
+ return sal_True;
+ }
+ return sal_False;
+}
+
+// #106897#
+void SwDoc::ChgNumRuleFmts( const SwNumRule& rRule, const String * pName )
+{
+ // #106897#
+ SwNumRule* pRule = FindNumRulePtr( pName ? *pName : rRule.GetName() );
+ if( pRule )
+ {
+ SwUndoInsNum* pUndo = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo = new SwUndoInsNum( *pRule, rRule );
+ pUndo->GetHistory();
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ ::lcl_ChgNumRule( *this, rRule );
+
+ if( pUndo )
+ pUndo->SetLRSpaceEndPos();
+
+ SetModified();
+ }
+}
+
+sal_Bool SwDoc::RenameNumRule(const String & rOldName, const String & rNewName,
+ sal_Bool bBroadcast)
+{
+ sal_Bool bResult = sal_False;
+ SwNumRule * pNumRule = FindNumRulePtr(rOldName);
+
+ if (pNumRule)
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo = new SwUndoNumruleRename(rOldName, rNewName, this);
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ // --> OD 2008-02-19 #refactorlists#
+// SwNumRuleInfo aInfo(rOldName);
+// aInfo.MakeList(*this);
+ SwNumRule::tTxtNodeList aTxtNodeList;
+ pNumRule->GetTxtNodeList( aTxtNodeList );
+ // <--
+
+ // --> OD 2008-07-08 #i91400#
+ pNumRule->SetName( rNewName, *this );
+ // <--
+
+ SwNumRuleItem aItem(rNewName);
+ // --> OD 2008-02-19 #refactorlists#
+// for (sal_uLong nI = 0; nI < aInfo.GetList().Count(); ++nI)
+// {
+// SwTxtNode * pTxtNd = aInfo.GetList().GetObject(nI);
+// pTxtNd->SwCntntNode::SetAttr(aItem);
+// }
+ for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
+ aIter != aTxtNodeList.end(); ++aIter )
+ {
+ SwTxtNode * pTxtNd = *aIter;
+ pTxtNd->SetAttr(aItem);
+ }
+ // <--
+
+ bResult = sal_True;
+
+ if (bBroadcast)
+ BroadcastStyleOperation(rOldName, SFX_STYLE_FAMILY_PSEUDO,
+ SFX_STYLESHEET_MODIFIED);
+ }
+
+ return bResult;
+}
+
+void SwDoc::StopNumRuleAnimations( OutputDevice* pOut )
+{
+ for( sal_uInt16 n = GetNumRuleTbl().Count(); n; )
+ {
+ // --> OD 2008-02-19 #refactorlists#
+// SwNumRuleInfo aUpd( GetNumRuleTbl()[ --n ]->GetName() );
+// aUpd.MakeList( *this );
+
+// for( sal_uLong nFirst = 0, nLast = aUpd.GetList().Count();
+// nFirst < nLast; ++nFirst )
+// {
+// SwTxtNode* pTNd = aUpd.GetList().GetObject( nFirst );
+// SwClientIter aIter( *pTNd );
+// for( SwFrm* pFrm = (SwFrm*)aIter.First( TYPE(SwFrm) );
+// pFrm; pFrm = (SwFrm*)aIter.Next() )
+// if( ((SwTxtFrm*)pFrm)->HasAnimation() )
+// ((SwTxtFrm*)pFrm)->StopAnimation( pOut );
+// }
+ SwNumRule::tTxtNodeList aTxtNodeList;
+ GetNumRuleTbl()[ --n ]->GetTxtNodeList( aTxtNodeList );
+ for ( SwNumRule::tTxtNodeList::iterator aTxtNodeIter = aTxtNodeList.begin();
+ aTxtNodeIter != aTxtNodeList.end(); ++aTxtNodeIter )
+ {
+ SwTxtNode* pTNd = *aTxtNodeIter;
+ SwClientIter aIter( *pTNd );
+ for( SwFrm* pFrm = (SwFrm*)aIter.First( TYPE(SwFrm) );
+ pFrm; pFrm = (SwFrm*)aIter.Next() )
+ if( ((SwTxtFrm*)pFrm)->HasAnimation() )
+ ((SwTxtFrm*)pFrm)->StopAnimation( pOut );
+ }
+ // <--
+ }
+}
+
+sal_Bool SwDoc::ReplaceNumRule( const SwPosition& rPos,
+ const String& rOldRule, const String& rNewRule )
+{
+ sal_Bool bRet = sal_False;
+ SwNumRule *pOldRule = FindNumRulePtr( rOldRule ),
+ *pNewRule = FindNumRulePtr( rNewRule );
+ if( pOldRule && pNewRule && pOldRule != pNewRule )
+ {
+ // --> OD 2008-02-19 #refactorlists#
+ SwUndoInsNum* pUndo = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // Start/End for attributes!
+ GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ pUndo = new SwUndoInsNum( rPos, *pNewRule, rOldRule );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ // --> OD 2008-02-19 #refactorlists#
+ // apply new list style <pNewRule> to all text nodes, which have the
+ // old list style <pOldNRule> applied and belong to the same list as
+ // the text node of the given <SwPosition>.
+// SwNumRuleInfo aUpd( rOldRule );
+// aUpd.MakeList( *this );
+
+// if (aUpd.GetList().Count() > 0) // #106897#
+ SwNumRule::tTxtNodeList aTxtNodeList;
+ pOldRule->GetTxtNodeList( aTxtNodeList );
+ if ( aTxtNodeList.size() > 0 )
+ {
+// // Position suchen und bestimme ob ein Node davor oder dahinter
+// // einen Start erzwingt
+// SwTxtNode* pTxtNd;
+// sal_uLong nFndPos, nFirst, nLast;
+
+// if( TABLE_ENTRY_NOTFOUND != aUpd.GetList().SearchKey(
+// rPos.nNode.GetIndex(), &nFndPos ))
+// ++nFndPos;
+
+// for( nLast = nFndPos; nLast < aUpd.GetList().Count(); ++nLast )
+// {
+// pTxtNd = aUpd.GetList().GetObject( nLast );
+// if(pTxtNd->IsRestart())
+// break;
+// }
+// for( nFirst = nFndPos; nFirst; )
+// {
+// pTxtNd = aUpd.GetList().GetObject( --nFirst );
+// if( pTxtNd->IsRestart() )
+// break;
+// }
+// // dann neue Numerierung ueber diesen Bereich
+// // definieren und den Start am Anfang/Ende zurueck setzen
+// pTxtNd = aUpd.GetList().GetObject( nFirst );
+// if( pTxtNd->IsRestart() )
+// {
+// pTxtNd->SetRestart(false);
+// if( pUndo )
+// pUndo->SetSttNum( pTxtNd->GetIndex() );
+// }
+
+ SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 );
+ sal_uInt16 nChgFmtLevel = 0;
+ for( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
+ {
+ const SwNumFmt& rOldFmt = pOldRule->Get( n ),
+ & rNewFmt = pNewRule->Get( n );
+
+ if( rOldFmt.GetAbsLSpace() != rNewFmt.GetAbsLSpace() ||
+ rOldFmt.GetFirstLineOffset() != rNewFmt.GetFirstLineOffset() )
+ nChgFmtLevel |= ( 1 << n );
+ }
+
+ const SwTxtNode* pGivenTxtNode = rPos.nNode.GetNode().GetTxtNode();
+ SwNumRuleItem aRule( rNewRule );
+// for( ; nFirst < nLast; ++nFirst )
+// {
+// pTxtNd = aUpd.GetList().GetObject( nFirst );
+
+// aRegH.RegisterInModify( pTxtNd, *pTxtNd );
+
+// pTxtNd->SwCntntNode::SetAttr( aRule );
+// pTxtNd->NumRuleChgd();
+// }
+ for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
+ aIter != aTxtNodeList.end(); ++aIter )
+ {
+ SwTxtNode* pTxtNd = *aIter;
+
+ if ( pGivenTxtNode &&
+ pGivenTxtNode->GetListId() == pTxtNd->GetListId() )
+ {
+ aRegH.RegisterInModify( pTxtNd, *pTxtNd );
+
+ pTxtNd->SetAttr( aRule );
+ pTxtNd->NumRuleChgd();
+ }
+ }
+ GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ SetModified();
+
+ bRet = sal_True; // #106897#
+ }
+ }
+
+ return bRet;
+}
+
+// --> OD 2008-03-18 #refactorlists#
+namespace
+{
+ struct ListStyleData
+ {
+ SwNumRule* pReplaceNumRule;
+ bool bCreateNewList;
+ String sListId;
+
+ ListStyleData()
+ : pReplaceNumRule( 0 ),
+ bCreateNewList( false ),
+ sListId()
+ {}
+ };
+}
+// <--
+
+void SwDoc::MakeUniqueNumRules(const SwPaM & rPaM)
+{
+ ASSERT( rPaM.GetDoc() == this, "need same doc" );
+
+ // --> OD 2008-03-18 #refactorlists#
+// map<SwNumRule *, SwNumRule *> aMyNumRuleMap;
+ ::std::map<SwNumRule *, ListStyleData> aMyNumRuleMap;
+ // <--
+
+ sal_uLong nStt = rPaM.Start()->nNode.GetIndex();
+ sal_uLong nEnd = rPaM.End()->nNode.GetIndex();
+
+ bool bFirst = true;
+
+ for (sal_uLong n = nStt; n <= nEnd; n++)
+ {
+ SwTxtNode * pCNd = GetNodes()[n]->GetTxtNode();
+
+ if (pCNd)
+ {
+ SwNumRule * pRule = pCNd->GetNumRule();
+
+ if (pRule && pRule->IsAutoRule() && ! pRule->IsOutlineRule())
+ {
+ // --> OD 2008-03-18 #refactorlists#
+// SwNumRule * pReplaceNumRule = aMyNumRuleMap[pRule];
+ ListStyleData aListStyleData = aMyNumRuleMap[pRule];
+
+// if (! pReplaceNumRule)
+ if ( aListStyleData.pReplaceNumRule == 0 )
+ {
+ if (bFirst)
+ {
+ SwPosition aPos(*pCNd);
+ aListStyleData.pReplaceNumRule =
+ const_cast<SwNumRule *>
+ (SearchNumRule( aPos, false, pCNd->HasNumber(),
+ false, 0,
+ aListStyleData.sListId, true ));
+ }
+
+// if (! pReplaceNumRule)
+ if ( aListStyleData.pReplaceNumRule == 0 )
+ {
+// pReplaceNumRule = new SwNumRule(*pRule);
+// pReplaceNumRule->SetName(GetUniqueNumRuleName());
+ aListStyleData.pReplaceNumRule = new SwNumRule(*pRule);
+ // --> OD 2008-07-08 #i91400#
+ aListStyleData.pReplaceNumRule->SetName(
+ GetUniqueNumRuleName(), *this );
+ // <--
+ aListStyleData.bCreateNewList = true;
+ }
+
+// aMyNumRuleMap[pRule] = pReplaceNumRule;
+ aMyNumRuleMap[pRule] = aListStyleData;
+ }
+
+ SwPaM aPam(*pCNd);
+
+ SetNumRule( aPam, *aListStyleData.pReplaceNumRule,
+ aListStyleData.bCreateNewList,
+ aListStyleData.sListId );
+ if ( aListStyleData.bCreateNewList )
+ {
+ aListStyleData.bCreateNewList = false;
+ aListStyleData.sListId = pCNd->GetListId();
+ aMyNumRuleMap[pRule] = aListStyleData;
+ }
+ // <--
+
+ bFirst = false;
+ }
+ }
+ }
+}
+
+sal_Bool SwDoc::NoNum( const SwPaM& rPam )
+{
+
+ sal_Bool bRet = SplitNode( *rPam.GetPoint(), false );
+ // ist ueberhaupt Nummerierung im Spiel ?
+ if( bRet )
+ {
+ // NoNum setzen und Upaten
+ const SwNodeIndex& rIdx = rPam.GetPoint()->nNode;
+ SwTxtNode* pNd = rIdx.GetNode().GetTxtNode();
+ const SwNumRule* pRule = pNd->GetNumRule();
+ if( pRule )
+ {
+ pNd->SetCountedInList(false);
+
+ SetModified();
+ }
+ else
+ bRet = sal_False; // keine Nummerierung , ?? oder immer sal_True ??
+ }
+ return bRet;
+}
+
+void SwDoc::DelNumRules( const SwPaM& rPam )
+{
+ sal_uLong nStt = rPam.GetPoint()->nNode.GetIndex(),
+ nEnd = rPam.GetMark()->nNode.GetIndex();
+ if( nStt > nEnd )
+ {
+ sal_uLong nTmp = nStt; nStt = nEnd; nEnd = nTmp;
+ }
+
+ SwUndoDelNum* pUndo;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo = new SwUndoDelNum( rPam );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ else
+ pUndo = 0;
+
+ SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 );
+
+ SwNumRuleItem aEmptyRule( aEmptyStr );
+ const SwNode* pOutlNd = 0;
+ for( ; nStt <= nEnd; ++nStt )
+ {
+ SwTxtNode* pTNd = GetNodes()[ nStt ]->GetTxtNode();
+ // --> OD 2008-03-13 #refactorlists#
+// if( pTNd && 0 != ( pItem = pTNd->GetNoCondAttr(
+// RES_PARATR_NUMRULE, sal_True ) ) &&
+// ( pName = &((SwNumRuleItem*)pItem)->GetValue())->Len() )
+ SwNumRule* pNumRuleOfTxtNode = pTNd ? pTNd->GetNumRule() : 0;
+ if ( pTNd && pNumRuleOfTxtNode )
+ // <--
+ {
+ // recognize changes of attribute for undo
+ aRegH.RegisterInModify( pTNd, *pTNd );
+
+ if( pUndo )
+ pUndo->AddNode( *pTNd, sal_False );
+
+ // directly set list style attribute is reset, otherwise empty
+ // list style is applied
+ const SfxItemSet* pAttrSet = pTNd->GetpSwAttrSet();
+ if ( pAttrSet &&
+ pAttrSet->GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET )
+ pTNd->ResetAttr( RES_PARATR_NUMRULE );
+ else
+ pTNd->SetAttr( aEmptyRule );
+
+ // --> OD 2008-03-26 #refactorlists#
+ pTNd->ResetAttr( RES_PARATR_LIST_ID );
+ pTNd->ResetAttr( RES_PARATR_LIST_LEVEL );
+ pTNd->ResetAttr( RES_PARATR_LIST_ISRESTART );
+ pTNd->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
+ pTNd->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
+ // <--
+
+ if( RES_CONDTXTFMTCOLL == pTNd->GetFmtColl()->Which() )
+ pTNd->ChkCondColl();
+ //else if( !pOutlNd && NO_NUMBERING != //#outline level,zhaojianwei
+ // ((SwTxtFmtColl*)pTNd->GetFmtColl())->GetOutlineLevel() )
+ else if( !pOutlNd &&
+ ((SwTxtFmtColl*)pTNd->GetFmtColl())->IsAssignedToListLevelOfOutlineStyle() )//<-end,zhaojianwei
+ pOutlNd = pTNd;
+ }
+ }
+
+ // dann noch alle Updaten
+ UpdateNumRule();
+
+ if( pOutlNd )
+ GetNodes().UpdtOutlineIdx( *pOutlNd );
+}
+
+void SwDoc::InvalidateNumRules()
+{
+ for (sal_uInt16 n = 0; n < pNumRuleTbl->Count(); ++n)
+ (*pNumRuleTbl)[n]->SetInvalidRule(sal_True);
+}
+
+ // zum naechsten/vorhergehenden Punkt auf gleicher Ebene
+
+sal_Bool lcl_IsNumOk( sal_uInt8 nSrchNum, sal_uInt8& rLower, sal_uInt8& rUpper,
+ sal_Bool bOverUpper, sal_uInt8 nNumber )
+{
+ // --> OD 2008-04-02 #refactorlists#
+ ASSERT( nNumber < MAXLEVEL,
+ "<lcl_IsNumOk(..)> - misusage of method" );
+ // <--
+
+ sal_Bool bRet = sal_False;
+ {
+ if( bOverUpper ? nSrchNum == nNumber : nSrchNum >= nNumber )
+ bRet = sal_True;
+ else if( nNumber > rLower )
+ rLower = nNumber;
+ else if( nNumber < rUpper )
+ rUpper = nNumber;
+ }
+ return bRet;
+}
+
+sal_Bool lcl_IsValidPrevNextNumNode( const SwNodeIndex& rIdx )
+{
+ sal_Bool bRet = sal_False;
+ const SwNode& rNd = rIdx.GetNode();
+ switch( rNd.GetNodeType() )
+ {
+ case ND_ENDNODE:
+ bRet = SwTableBoxStartNode == rNd.StartOfSectionNode()->GetStartNodeType() ||
+ rNd.StartOfSectionNode()->IsSectionNode();
+ break;
+
+ case ND_STARTNODE:
+ bRet = SwTableBoxStartNode == ((SwStartNode&)rNd).GetStartNodeType();
+ break;
+
+ case ND_SECTIONNODE: // der ist erlaubt, also weiter
+ bRet = sal_True;
+ break;
+ }
+ return bRet;
+}
+
+sal_Bool lcl_GotoNextPrevNum( SwPosition& rPos, sal_Bool bNext,
+ sal_Bool bOverUpper, sal_uInt8* pUpper, sal_uInt8* pLower )
+{
+ const SwTxtNode* pNd = rPos.nNode.GetNode().GetTxtNode();
+ const SwNumRule* pRule;
+ if( !pNd || 0 == ( pRule = pNd->GetNumRule()))
+ return sal_False;
+
+ sal_uInt8 nSrchNum = static_cast<sal_uInt8>(pNd->GetActualListLevel());
+
+ SwNodeIndex aIdx( rPos.nNode );
+ if( ! pNd->IsCountedInList() )
+ {
+ // falls gerade mal NO_NUMLEVEL an ist, so such den vorherigen Node
+ // mit Nummerierung
+ sal_Bool bError = sal_False;
+ do {
+ aIdx--;
+ if( aIdx.GetNode().IsTxtNode() )
+ {
+ pNd = aIdx.GetNode().GetTxtNode();
+ pRule = pNd->GetNumRule();
+
+ sal_uInt8 nTmpNum;
+
+ if( pRule )
+ {
+ nTmpNum = static_cast<sal_uInt8>(pNd->GetActualListLevel());
+ if( !( ! pNd->IsCountedInList() &&
+ (nTmpNum >= nSrchNum )) )
+ break; // gefunden
+ }
+ else
+ bError = sal_True;
+ }
+ else
+ bError = !lcl_IsValidPrevNextNumNode( aIdx );
+
+ } while( !bError );
+ if( bError )
+ return sal_False;
+ }
+
+ sal_uInt8 nLower = nSrchNum, nUpper = nSrchNum;
+ sal_Bool bRet = sal_False;
+
+ const SwTxtNode* pLast;
+ if( bNext )
+ aIdx++, pLast = pNd;
+ else
+ aIdx--, pLast = 0;
+
+ while( bNext ? ( aIdx.GetIndex() < aIdx.GetNodes().Count() - 1 )
+ : aIdx.GetIndex() )
+ {
+ if( aIdx.GetNode().IsTxtNode() )
+ {
+ pNd = aIdx.GetNode().GetTxtNode();
+ pRule = pNd->GetNumRule();
+ if( pRule )
+ {
+ if( ::lcl_IsNumOk( nSrchNum, nLower, nUpper, bOverUpper,
+ static_cast<sal_uInt8>(pNd->GetActualListLevel()) ))
+ {
+ rPos.nNode = aIdx;
+ rPos.nContent.Assign( (SwTxtNode*)pNd, 0 );
+ bRet = sal_True;
+ break;
+ }
+ else
+ pLast = pNd;
+ }
+ else
+ break;
+ }
+ else if( !lcl_IsValidPrevNextNumNode( aIdx ))
+ break;
+
+ if( bNext )
+ aIdx++;
+ else
+ aIdx--;
+ }
+
+ if( !bRet && !bOverUpper && pLast ) // nicht ueber hoehere Nummmern, aber bis Ende
+ {
+ if( bNext )
+ {
+ rPos.nNode = aIdx;
+ if( aIdx.GetNode().IsCntntNode() )
+ rPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), 0 );
+ }
+ else
+ {
+ rPos.nNode.Assign( *pLast );
+ rPos.nContent.Assign( (SwTxtNode*)pLast, 0 );
+ }
+ bRet = sal_True;
+ }
+
+ if( bRet )
+ {
+ if( pUpper )
+ *pUpper = nUpper;
+ if( pLower )
+ *pLower = nLower;
+ }
+ return bRet;
+}
+
+sal_Bool SwDoc::GotoNextNum( SwPosition& rPos, sal_Bool bOverUpper,
+ sal_uInt8* pUpper, sal_uInt8* pLower )
+{
+ return ::lcl_GotoNextPrevNum( rPos, sal_True, bOverUpper, pUpper, pLower );
+}
+
+// -> #i23731#
+// --> OD 2008-03-18 #refactorlists# - add output parameter <sListId>
+const SwNumRule * SwDoc::SearchNumRule(const SwPosition & rPos,
+ const bool bForward,
+ const bool bNum,
+ const bool bOutline,
+ int nNonEmptyAllowed,
+ String& sListId,
+ const bool bInvestigateStartNode)
+{
+ const SwNumRule * pResult = NULL;
+ SwTxtNode * pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ SwNode * pStartFromNode = pTxtNd;
+
+ if (pTxtNd)
+ {
+ SwNodeIndex aIdx(rPos.nNode);
+
+ // --> OD 2005-10-20 #i55391#
+ // - the start node has also been investigated, if requested.
+ const SwNode * pNode = NULL;
+ do
+ {
+ // --> OD 2005-10-20 #i55391#
+ if ( !bInvestigateStartNode )
+ {
+ if (bForward)
+ aIdx++;
+ else
+ aIdx--;
+ }
+ // <--
+ if (aIdx.GetNode().IsTxtNode())
+ {
+ pTxtNd = aIdx.GetNode().GetTxtNode();
+
+ const SwNumRule * pNumRule = pTxtNd->GetNumRule();
+ if (pNumRule)
+ {
+ if ( ( pNumRule->IsOutlineRule() == ( bOutline ? sal_True : sal_False ) ) && // #115901#
+ ( ( bNum && pNumRule->Get(0).IsEnumeration()) ||
+ ( !bNum && pNumRule->Get(0).IsItemize() ) ) ) // #i22362#, #i29560#
+ {
+ pResult = pTxtNd->GetNumRule();
+ // --> OD 2008-03-18 #refactorlists#
+ // provide also the list id, to which the text node belongs.
+ sListId = pTxtNd->GetListId();
+ }
+
+ break;
+ }
+ else if (pTxtNd->Len() > 0 || NULL != pTxtNd->GetNumRule())
+ {
+ if (nNonEmptyAllowed == 0)
+ break;
+
+ nNonEmptyAllowed--;
+
+ if (nNonEmptyAllowed < 0)
+ nNonEmptyAllowed = -1;
+ }
+ }
+
+ // --> OD 2005-10-20 #i55391#
+ if ( bInvestigateStartNode )
+ {
+ if (bForward)
+ aIdx++;
+ else
+ aIdx--;
+ }
+ // <--
+
+ pNode = &aIdx.GetNode();
+ }
+ while (!(pNode == GetNodes().DocumentSectionStartNode(pStartFromNode) ||
+ pNode == GetNodes().DocumentSectionEndNode(pStartFromNode)));
+ // <--
+ }
+
+ return pResult;
+}
+// <- #i23731#
+
+sal_Bool SwDoc::GotoPrevNum( SwPosition& rPos, sal_Bool bOverUpper,
+ sal_uInt8* pUpper, sal_uInt8* pLower )
+{
+ return ::lcl_GotoNextPrevNum( rPos, sal_False, bOverUpper, pUpper, pLower );
+}
+
+sal_Bool SwDoc::NumUpDown( const SwPaM& rPam, sal_Bool bDown )
+{
+ sal_uLong nStt = rPam.GetPoint()->nNode.GetIndex(),
+ nEnd = rPam.GetMark()->nNode.GetIndex();
+ if( nStt > nEnd )
+ {
+ sal_uLong nTmp = nStt; nStt = nEnd; nEnd = nTmp;
+ }
+
+ // -> #115901# outline nodes are promoted or demoted differently
+ bool bOnlyOutline = true;
+ bool bOnlyNonOutline = true;
+ for (sal_uLong n = nStt; n <= nEnd; n++)
+ {
+ SwTxtNode * pTxtNd = GetNodes()[n]->GetTxtNode();
+
+ if (pTxtNd)
+ {
+ SwNumRule * pRule = pTxtNd->GetNumRule();
+
+ if (pRule)
+ {
+ if (pRule->IsOutlineRule())
+ bOnlyNonOutline = false;
+ else
+ bOnlyOutline = false;
+ }
+ }
+ }
+ // <- #115901#
+
+ sal_Bool bRet = sal_True;
+ char nDiff = bDown ? 1 : -1;
+
+ // ->#115901#
+ if (bOnlyOutline)
+ bRet = OutlineUpDown(rPam, nDiff);
+ else if (bOnlyNonOutline)
+ {
+ /* --> #i24560#
+
+ Only promote or demote if all selected paragraphs are
+ promotable resp. demotable.
+
+ */
+ for (sal_uLong nTmp = nStt; nTmp <= nEnd; ++nTmp)
+ {
+ SwTxtNode* pTNd = GetNodes()[ nTmp ]->GetTxtNode();
+
+ // --> OD 2006-10-19 #134160# - make code robust:
+ // consider case that the node doesn't denote a text node.
+ if ( pTNd )
+ {
+ SwNumRule * pRule = pTNd->GetNumRule();
+
+ if (pRule)
+ {
+ sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel());
+ if( (-1 == nDiff && 0 >= nLevel) ||
+ (1 == nDiff && MAXLEVEL - 1 <= nLevel))
+ bRet = sal_False;
+ }
+ }
+ // <--
+ }
+
+ if( bRet )
+ {
+ /* <-- #i24560# */
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo( new SwUndoNumUpDown(rPam, nDiff) );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ String sNumRule;
+
+ for(sal_uLong nTmp = nStt; nTmp <= nEnd; ++nTmp )
+ {
+ SwTxtNode* pTNd = GetNodes()[ nTmp ]->GetTxtNode();
+
+ if( pTNd)
+ {
+ SwNumRule * pRule = pTNd->GetNumRule();
+
+ if (pRule)
+ {
+ sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel());
+ nLevel = nLevel + nDiff;
+
+ pTNd->SetAttrListLevel(nLevel);
+ }
+ }
+ }
+
+ ChkCondColls();
+ SetModified();
+ }
+ }
+
+ return bRet;
+}
+
+sal_Bool SwDoc::MoveParagraph( const SwPaM& rPam, long nOffset, sal_Bool bIsOutlMv )
+{
+ const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
+
+ sal_uLong nStIdx = pStt->nNode.GetIndex();
+ sal_uLong nEndIdx = pEnd->nNode.GetIndex();
+
+ // Here are some sophisticated checks whether the wished PaM will be moved or not.
+ // For moving outlines (bIsOutlMv) I've already done some checks, so here are two different
+ // checks...
+ SwNode *pTmp1;
+ SwNode *pTmp2;
+ if( bIsOutlMv )
+ {
+ // For moving chapters (outline) the following reason will deny the move:
+ // if a start node is inside the moved area and its end node outside or vice versa.
+ // If a start node is the first moved paragraph, its end node has to be within the moved
+ // area, too (e.g. as last node).
+ // If an end node is the last node of the moved area, its start node has to be a part of
+ // the moved section, too.
+ pTmp1 = GetNodes()[ nStIdx ];
+ if( pTmp1->IsStartNode() )
+ { // First is a start node
+ pTmp2 = pTmp1->EndOfSectionNode();
+ if( pTmp2->GetIndex() > nEndIdx )
+ return sal_False; // Its end node is behind the moved range
+ }
+ pTmp1 = pTmp1->StartOfSectionNode()->EndOfSectionNode();
+ if( pTmp1->GetIndex() <= nEndIdx )
+ return sal_False; // End node inside but start node before moved range => no.
+ pTmp1 = GetNodes()[ nEndIdx ];
+ if( pTmp1->IsEndNode() )
+ { // The last one is an end node
+ pTmp1 = pTmp1->StartOfSectionNode();
+ if( pTmp1->GetIndex() < nStIdx )
+ return sal_False; // Its start node is before the moved range.
+ }
+ pTmp1 = pTmp1->StartOfSectionNode();
+ if( pTmp1->GetIndex() >= nStIdx )
+ return sal_False; // A start node which ends behind the moved area => no.
+ }
+
+ sal_uLong nInStIdx, nInEndIdx;
+ long nOffs = nOffset;
+ if( nOffset > 0 )
+ {
+ nInEndIdx = nEndIdx;
+ nEndIdx += nOffset;
+ ++nOffs;
+ }
+ else
+ {
+ //Impossible to move to negative index
+ if( sal_uLong(abs( nOffset )) > nStIdx)
+ return sal_False;
+
+ nInEndIdx = nStIdx - 1;
+ nStIdx += nOffset;
+ }
+ nInStIdx = nInEndIdx + 1;
+ // Folgende Absatzbloecke sollen vertauscht werden:
+ // [ nStIdx, nInEndIdx ] mit [ nInStIdx, nEndIdx ]
+
+ if( nEndIdx >= GetNodes().GetEndOfContent().GetIndex() )
+ return sal_False;
+
+ if( !bIsOutlMv )
+ { // And here the restrictions for moving paragraphs other than chapters (outlines)
+ // The plan is to exchange [nStIdx,nInEndIdx] and [nStartIdx,nEndIdx]
+ // It will checked if the both "start" nodes as well as the both "end" notes belongs to
+ // the same start-end-section. This is more restrictive than the conditions checked above.
+ // E.g. a paragraph will not escape from a section or be inserted to another section.
+ pTmp1 = GetNodes()[ nStIdx ]->StartOfSectionNode();
+ pTmp2 = GetNodes()[ nInStIdx ]->StartOfSectionNode();
+ if( pTmp1 != pTmp2 )
+ return sal_False; // "start" nodes in different sections
+ pTmp1 = GetNodes()[ nEndIdx ];
+ bool bIsEndNode = pTmp1->IsEndNode();
+ if( !pTmp1->IsStartNode() )
+ {
+ pTmp1 = pTmp1->StartOfSectionNode();
+ if( bIsEndNode ) // For end nodes the first start node is of course inside the range,
+ pTmp1 = pTmp1->StartOfSectionNode(); // I've to check the start node of the start node.
+ }
+ pTmp1 = pTmp1->EndOfSectionNode();
+ pTmp2 = GetNodes()[ nInEndIdx ];
+ if( !pTmp2->IsStartNode() )
+ {
+ bIsEndNode = pTmp2->IsEndNode();
+ pTmp2 = pTmp2->StartOfSectionNode();
+ if( bIsEndNode )
+ pTmp2 = pTmp2->StartOfSectionNode();
+ }
+ pTmp2 = pTmp2->EndOfSectionNode();
+ if( pTmp1 != pTmp2 )
+ return sal_False; // The "end" notes are in different sections
+ }
+
+ // auf Redlining testen - darf die Selektion ueberhaupt verschoben
+ // werden?
+ if( !IsIgnoreRedline() )
+ {
+ sal_uInt16 nRedlPos = GetRedlinePos( pStt->nNode.GetNode(), nsRedlineType_t::REDLINE_DELETE );
+ if( USHRT_MAX != nRedlPos )
+ {
+ SwPosition aStPos( *pStt ), aEndPos( *pEnd );
+ aStPos.nContent = 0;
+ SwCntntNode* pCNd = pEnd->nNode.GetNode().GetCntntNode();
+ aEndPos.nContent = pCNd ? pCNd->Len() : 1;
+ sal_Bool bCheckDel = sal_True;
+
+ // es existiert fuer den Bereich irgendein Redline-Delete-Object
+ for( ; nRedlPos < GetRedlineTbl().Count(); ++nRedlPos )
+ {
+ const SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
+ if( !bCheckDel || nsRedlineType_t::REDLINE_DELETE == pTmp->GetType() )
+ {
+ const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
+ switch( ComparePosition( *pRStt, *pREnd, aStPos, aEndPos ))
+ {
+ case POS_COLLIDE_START:
+ case POS_BEHIND: // Pos1 liegt hinter Pos2
+ nRedlPos = GetRedlineTbl().Count();
+ break;
+
+ case POS_COLLIDE_END:
+ case POS_BEFORE: // Pos1 liegt vor Pos2
+ break;
+ case POS_INSIDE: // Pos1 liegt vollstaendig in Pos2
+ // ist erlaubt, aber checke dann alle nachfolgenden
+ // auf Ueberlappungen
+ bCheckDel = sal_False;
+ break;
+
+ case POS_OUTSIDE: // Pos2 liegt vollstaendig in Pos1
+ case POS_EQUAL: // Pos1 ist genauso gross wie Pos2
+ case POS_OVERLAP_BEFORE: // Pos1 ueberlappt Pos2 am Anfang
+ case POS_OVERLAP_BEHIND: // Pos1 ueberlappt Pos2 am Ende
+ return sal_False;
+ }
+ }
+ }
+ }
+ }
+
+ {
+ // DataChanged vorm verschieben verschicken, dann bekommt
+ // man noch mit, welche Objecte sich im Bereich befinden.
+ // Danach koennen sie vor/hinter der Position befinden.
+ SwDataChanged aTmp( rPam, 0 );
+ }
+
+ SwNodeIndex aIdx( nOffset > 0 ? pEnd->nNode : pStt->nNode, nOffs );
+ SwNodeRange aMvRg( pStt->nNode, 0, pEnd->nNode, +1 );
+
+ SwRedline* pOwnRedl = 0;
+ if( IsRedlineOn() )
+ {
+ // wenn der Bereich komplett im eigenen Redline liegt, kann es
+ // verschoben werden!
+ sal_uInt16 nRedlPos = GetRedlinePos( pStt->nNode.GetNode(), nsRedlineType_t::REDLINE_INSERT );
+ if( USHRT_MAX != nRedlPos )
+ {
+ SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
+ const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
+ SwRedline aTmpRedl( nsRedlineType_t::REDLINE_INSERT, rPam );
+ const SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
+ // liegt komplett im Bereich, und ist auch der eigene Redline?
+ if( aTmpRedl.IsOwnRedline( *pTmp ) &&
+ (pRStt->nNode < pStt->nNode ||
+ (pRStt->nNode == pStt->nNode && !pRStt->nContent.GetIndex()) ) &&
+ (pEnd->nNode < pREnd->nNode ||
+ (pEnd->nNode == pREnd->nNode &&
+ pCEndNd ? pREnd->nContent.GetIndex() == pCEndNd->Len()
+ : !pREnd->nContent.GetIndex() )) )
+ {
+ pOwnRedl = pTmp;
+ if( nRedlPos + 1 < GetRedlineTbl().Count() )
+ {
+ pTmp = GetRedlineTbl()[ nRedlPos+1 ];
+ if( *pTmp->Start() == *pREnd )
+ // dann doch nicht!
+ pOwnRedl = 0;
+ }
+
+ if( pOwnRedl &&
+ !( pRStt->nNode <= aIdx && aIdx <= pREnd->nNode ))
+ {
+ // nicht in sich selbst, dann auch nicht moven
+ pOwnRedl = 0;
+ }
+ }
+ }
+
+ if( !pOwnRedl )
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+
+ // zuerst das Insert, dann das Loeschen
+ SwPosition aInsPos( aIdx );
+ aInsPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), 0 );
+
+ SwPaM aPam( pStt->nNode, aMvRg.aEnd );
+
+ SwPaM& rOrigPam = (SwPaM&)rPam;
+ rOrigPam.DeleteMark();
+ rOrigPam.GetPoint()->nNode = aIdx.GetIndex() - 1;
+
+ sal_Bool bDelLastPara = !aInsPos.nNode.GetNode().IsCntntNode();
+
+ /* #101076# When copying to a non-content node Copy will
+ insert a paragraph before that node and insert before
+ that inserted node. Copy creates an SwUndoInserts that
+ does not cover the extra paragraph. Thus we insert the
+ extra paragraph ourselves, _with_ correct undo
+ information. */
+ if (bDelLastPara)
+ {
+ /* aInsPos points to the non-content node. Move it to
+ the previous content node. */
+ SwPaM aInsPam(aInsPos);
+ sal_Bool bMoved = aInsPam.Move(fnMoveBackward);
+ ASSERT(bMoved, "No content node found!");
+
+ if (bMoved)
+ {
+ /* Append the new node after the content node
+ found. The new position to insert the moved
+ paragraph at is before the inserted
+ paragraph. */
+ AppendTxtNode(*aInsPam.GetPoint());
+ aInsPos = *aInsPam.GetPoint();
+ }
+ }
+
+ CopyRange( aPam, aInsPos, false );
+ if( bDelLastPara )
+ {
+ // dann muss der letzte leere Node wieder entfernt werden
+ aIdx = aInsPos.nNode;
+ SwCntntNode* pCNd = GetNodes().GoPrevious( &aInsPos.nNode );
+ xub_StrLen nCLen = 0; if( pCNd ) nCLen = pCNd->Len();
+ aInsPos.nContent.Assign( pCNd, nCLen );
+
+ // alle die im zu loeschenden Node stehen, mussen auf den
+ // naechsten umgestezt werden
+ SwPosition* pPos;
+ for( sal_uInt16 n = 0; n < GetRedlineTbl().Count(); ++n )
+ {
+ SwRedline* pTmp = GetRedlineTbl()[ n ];
+ if( ( pPos = &pTmp->GetBound(sal_True))->nNode == aIdx )
+ {
+ pPos->nNode++;
+ pPos->nContent.Assign( pPos->nNode.GetNode().GetCntntNode(),0);
+ }
+ if( ( pPos = &pTmp->GetBound(sal_False))->nNode == aIdx )
+ {
+ pPos->nNode++;
+ pPos->nContent.Assign( pPos->nNode.GetNode().GetCntntNode(),0);
+ }
+ }
+ CorrRel( aIdx, aInsPos, 0, sal_False );
+
+ pCNd->JoinNext();
+ }
+
+ rOrigPam.GetPoint()->nNode++;
+ rOrigPam.GetPoint()->nContent.Assign( rOrigPam.GetCntntNode(), 0 );
+
+ RedlineMode_t eOld = GetRedlineMode();
+ checkRedlining(eOld);
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ //JP 06.01.98: MUSS noch optimiert werden!!!
+ SetRedlineMode(
+ (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE));
+ SwUndo *const pUndo(new SwUndoRedlineDelete(aPam, UNDO_DELETE));
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ SwRedline* pNewRedline = new SwRedline( nsRedlineType_t::REDLINE_DELETE, aPam );
+
+ // #101654# prevent assertion from aPam's target being deleted
+ // (Alternatively, one could just let aPam go out of scope, but
+ // that requires touching a lot of code.)
+ aPam.GetBound(sal_True).nContent.Assign( NULL, 0 );
+ aPam.GetBound(sal_False).nContent.Assign( NULL, 0 );
+
+ AppendRedline( pNewRedline, true );
+
+//JP 06.01.98: MUSS noch optimiert werden!!!
+SetRedlineMode( eOld );
+ GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ SetModified();
+
+ return sal_True;
+ }
+ }
+
+ if( !pOwnRedl && !IsIgnoreRedline() && GetRedlineTbl().Count() )
+ {
+ SwPaM aTemp(aIdx);
+ SplitRedline(aTemp);
+ }
+
+ sal_uLong nRedlSttNd(0), nRedlEndNd(0);
+ if( pOwnRedl )
+ {
+ const SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End();
+ nRedlSttNd = pRStt->nNode.GetIndex();
+ nRedlEndNd = pREnd->nNode.GetIndex();
+ }
+
+ SwUndoMoveNum* pUndo = 0;
+ sal_uLong nMoved = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo = new SwUndoMoveNum( rPam, nOffset, bIsOutlMv );
+ nMoved = rPam.End()->nNode.GetIndex() - rPam.Start()->nNode.GetIndex() + 1;
+ }
+
+
+ MoveNodeRange( aMvRg, aIdx, DOC_MOVEREDLINES );
+
+ if( pUndo )
+ {
+ // i57907: Under circumstances (sections at the end of a chapter)
+ // the rPam.Start() is not moved to the new position.
+ // But aIdx should be at the new end position and as long as the number of moved paragraphs
+ // is nMoved, I know, where the new position is.
+ pUndo->SetStartNode( aIdx.GetIndex() - nMoved );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ if( pOwnRedl )
+ {
+ SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End();
+ if( pRStt->nNode.GetIndex() != nRedlSttNd )
+ {
+ pRStt->nNode = nRedlSttNd;
+ pRStt->nContent.Assign( pRStt->nNode.GetNode().GetCntntNode(),0);
+ }
+ if( pREnd->nNode.GetIndex() != nRedlEndNd )
+ {
+ pREnd->nNode = nRedlEndNd;
+ SwCntntNode* pCNd = pREnd->nNode.GetNode().GetCntntNode();
+ xub_StrLen nL = 0; if( pCNd ) nL = pCNd->Len();
+ pREnd->nContent.Assign( pCNd, nL );
+ }
+ }
+
+ SetModified();
+ return sal_True;
+}
+
+sal_Bool SwDoc::NumOrNoNum( const SwNodeIndex& rIdx, sal_Bool bDel )
+{
+ sal_Bool bResult = sal_False;
+ SwTxtNode * pTxtNd = rIdx.GetNode().GetTxtNode();
+
+ if (pTxtNd && pTxtNd->GetNumRule() != NULL &&
+ (pTxtNd->HasNumber() || pTxtNd->HasBullet()))
+ {
+ if ( !pTxtNd->IsCountedInList() == !bDel)
+ {
+ sal_Bool bOldNum = bDel; // == pTxtNd->IsCounted();
+ sal_Bool bNewNum = bDel ? sal_False : sal_True;
+ pTxtNd->SetCountedInList(bNewNum ? true : false);
+
+ SetModified();
+
+ bResult = sal_True;
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoNumOrNoNum * pUndo =
+ new SwUndoNumOrNoNum(rIdx, bOldNum, bNewNum);
+
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ }
+ else if (bDel && pTxtNd->GetNumRule(sal_False) &&
+ pTxtNd->GetActualListLevel() >= 0 &&
+ pTxtNd->GetActualListLevel() < MAXLEVEL)
+ {
+ SwPaM aPam(*pTxtNd);
+
+ DelNumRules(aPam);
+
+ bResult = sal_True;
+ }
+ }
+
+ return bResult;
+}
+
+SwNumRule* SwDoc::GetCurrNumRule( const SwPosition& rPos ) const
+{
+ SwNumRule* pRet = 0;
+ SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
+
+ if( pTNd )
+ {
+ // --> OD 2008-02-20 #refactorlists#
+// pTNd->SyncNumberAndNumRule();
+ // <--
+ pRet = pTNd->GetNumRule();
+ }
+
+ return pRet;
+}
+
+sal_uInt16 SwDoc::FindNumRule( const String& rName ) const
+{
+ for( sal_uInt16 n = pNumRuleTbl->Count(); n; )
+ if( (*pNumRuleTbl)[ --n ]->GetName() == rName )
+ return n;
+
+ return USHRT_MAX;
+}
+
+SwNumRule* SwDoc::FindNumRulePtr( const String& rName ) const
+{
+ SwNumRule * pResult = 0;
+
+ pResult = maNumRuleMap[rName];
+
+ if ( !pResult )
+ {
+ for (sal_uInt16 n = 0; n < pNumRuleTbl->Count(); ++n)
+ {
+ if ((*pNumRuleTbl)[n]->GetName() == rName)
+ {
+ pResult = (*pNumRuleTbl)[n];
+
+ break;
+ }
+ }
+ }
+
+ return pResult;
+}
+
+// #i36749#
+void SwDoc::AddNumRule(SwNumRule * pRule)
+{
+ pNumRuleTbl->Insert(pRule, pNumRuleTbl->Count());
+ maNumRuleMap[pRule->GetName()] = pRule;
+ pRule->SetNumRuleMap(&maNumRuleMap);
+
+ // --> OD 2008-03-26 #refactorlists#
+ createListForListStyle( pRule->GetName() );
+ // <--
+}
+
+// --> OD 2008-02-11 #newlistlevelattrs#
+sal_uInt16 SwDoc::MakeNumRule( const String &rName,
+ const SwNumRule* pCpy,
+ sal_Bool bBroadcast,
+ const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode )
+{
+ SwNumRule* pNew;
+ if( pCpy )
+ {
+ pNew = new SwNumRule( *pCpy );
+
+ // --> OD 2008-07-08 #i91400#
+ pNew->SetName( GetUniqueNumRuleName( &rName ), *this );
+ // <--
+ if( pNew->GetName() != rName )
+ {
+ pNew->SetPoolFmtId( USHRT_MAX );
+ pNew->SetPoolHelpId( USHRT_MAX );
+ pNew->SetPoolHlpFileId( UCHAR_MAX );
+ // --> OD 2008-04-03 #refactorlists#
+ pNew->SetDefaultListId( String() );
+ // <--
+ }
+ pNew->CheckCharFmts( this );
+ }
+ else
+ {
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ pNew = new SwNumRule( GetUniqueNumRuleName( &rName ),
+ eDefaultNumberFormatPositionAndSpaceMode );
+ // <--
+ }
+
+ sal_uInt16 nRet = pNumRuleTbl->Count();
+
+ AddNumRule(pNew); // #i36749#
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo = new SwUndoNumruleCreate(pNew, this);
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ if (bBroadcast)
+ BroadcastStyleOperation(pNew->GetName(), SFX_STYLE_FAMILY_PSEUDO,
+ SFX_STYLESHEET_CREATED);
+
+ return nRet;
+}
+
+String SwDoc::GetUniqueNumRuleName( const String* pChkStr, sal_Bool bAutoNum ) const
+{
+ String aName;
+ if( bAutoNum )
+ {
+ long n = Time().GetTime();
+ n += Date().GetDate();
+ aName = String::CreateFromInt32( n );
+ if( pChkStr && !pChkStr->Len() )
+ pChkStr = 0;
+ }
+ else if( pChkStr && pChkStr->Len() )
+ aName = *pChkStr;
+ else
+ {
+ pChkStr = 0;
+ aName = SW_RESSTR( STR_NUMRULE_DEFNAME );
+ }
+
+ sal_uInt16 nNum(0), nTmp, nFlagSize = ( pNumRuleTbl->Count() / 8 ) +2;
+ sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
+ memset( pSetFlags, 0, nFlagSize );
+
+ xub_StrLen nNmLen = aName.Len();
+ if( !bAutoNum && pChkStr )
+ {
+ while( nNmLen-- && '0' <= aName.GetChar( nNmLen ) &&
+ '9' >= aName.GetChar( nNmLen ) )
+ ; //nop
+
+ if( ++nNmLen < aName.Len() )
+ {
+ aName.Erase( nNmLen );
+ pChkStr = 0;
+ }
+ }
+
+ const SwNumRule* pNumRule;
+ sal_uInt16 n;
+
+ for( n = 0; n < pNumRuleTbl->Count(); ++n )
+ if( 0 != ( pNumRule = (*pNumRuleTbl)[ n ] ) )
+ {
+ const String& rNm = pNumRule->GetName();
+ if( rNm.Match( aName ) == nNmLen )
+ {
+ // Nummer bestimmen und das Flag setzen
+ nNum = (sal_uInt16)rNm.Copy( nNmLen ).ToInt32();
+ if( nNum-- && nNum < pNumRuleTbl->Count() )
+ pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
+ }
+ if( pChkStr && pChkStr->Equals( rNm ) )
+ pChkStr = 0;
+ }
+
+ if( !pChkStr )
+ {
+ // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
+ nNum = pNumRuleTbl->Count();
+ for( n = 0; n < nFlagSize; ++n )
+ if( 0xff != ( nTmp = pSetFlags[ n ] ))
+ {
+ // also die Nummer bestimmen
+ nNum = n * 8;
+ while( nTmp & 1 )
+ ++nNum, nTmp >>= 1;
+ break;
+ }
+
+ }
+ delete [] pSetFlags;
+ if( pChkStr && pChkStr->Len() )
+ return *pChkStr;
+ return aName += String::CreateFromInt32( ++nNum );
+}
+
+void SwDoc::UpdateNumRule()
+{
+ const SwNumRuleTbl& rNmTbl = GetNumRuleTbl();
+ for( sal_uInt16 n = 0; n < rNmTbl.Count(); ++n )
+ if( rNmTbl[ n ]->IsInvalidRule() )
+ rNmTbl[ n ]->Validate();
+}
+
+// --> OD 2008-04-02 #refactorlists#
+void SwDoc::MarkListLevel( const String& sListId,
+ const int nListLevel,
+ const sal_Bool bValue )
+{
+ SwList* pList = getListByName( sListId );
+
+ if ( pList )
+ {
+ MarkListLevel( *pList, nListLevel, bValue );
+ }
+}
+
+void SwDoc::MarkListLevel( SwList& rList,
+ const int nListLevel,
+ const sal_Bool bValue )
+{
+ // Set new marked list level and notify all affected nodes of the changed mark.
+ rList.MarkListLevel( nListLevel, bValue );
+}
+// <- #i27615#
+// <--
+
+// #i23726#
+sal_Bool SwDoc::IsFirstOfNumRule(SwPosition & rPos)
+{
+ sal_Bool bResult = sal_False;
+ SwTxtNode * pTxtNode = rPos.nNode.GetNode().GetTxtNode();
+
+ if (pTxtNode)
+ {
+ SwNumRule * pNumRule = pTxtNode->GetNumRule();
+
+ if (pNumRule)
+ bResult = pTxtNode->IsFirstOfNumRule();
+ }
+
+ return bResult;
+}
+
+// --> OD 2007-10-26 #i83479#
+// implementation for interface <IDocumentListItems>
+bool SwDoc::lessThanNodeNum::operator()( const SwNodeNum* pNodeNumOne,
+ const SwNodeNum* pNodeNumTwo ) const
+{
+ return pNodeNumOne->LessThan( *pNodeNumTwo );
+}
+
+void SwDoc::addListItem( const SwNodeNum& rNodeNum )
+{
+ if ( mpListItemsList == 0 )
+ {
+ return;
+ }
+
+ const bool bAlreadyInserted(
+ mpListItemsList->find( &rNodeNum ) != mpListItemsList->end() );
+ ASSERT( !bAlreadyInserted,
+ "<SwDoc::InsertListItem(..)> - <SwNodeNum> instance already registered as numbered item!" );
+ if ( !bAlreadyInserted )
+ {
+ mpListItemsList->insert( &rNodeNum );
+ }
+}
+
+void SwDoc::removeListItem( const SwNodeNum& rNodeNum )
+{
+ if ( mpListItemsList == 0 )
+ {
+ return;
+ }
+
+ const tImplSortedNodeNumList::size_type nDeleted = mpListItemsList->erase( &rNodeNum );
+ if ( nDeleted > 1 )
+ {
+ ASSERT( false,
+ "<SwDoc::RemoveListItem(..)> - <SwNodeNum> was registered more than once as numbered item!" );
+ }
+}
+
+String SwDoc::getListItemText( const SwNodeNum& rNodeNum,
+ const bool bWithNumber,
+ const bool bWithSpacesForLevel ) const
+{
+ return rNodeNum.GetTxtNode()
+ ? rNodeNum.GetTxtNode()->GetExpandTxt( 0, STRING_LEN, bWithNumber,
+ bWithNumber, bWithSpacesForLevel )
+ : String();
+}
+
+void SwDoc::getListItems( tSortedNodeNumList& orNodeNumList ) const
+{
+ orNodeNumList.clear();
+ orNodeNumList.reserve( mpListItemsList->size() );
+
+ tImplSortedNodeNumList::iterator aIter;
+ tImplSortedNodeNumList::iterator aEndIter = mpListItemsList->end();
+ for ( aIter = mpListItemsList->begin(); aIter != aEndIter; ++aIter )
+ {
+ orNodeNumList.push_back( (*aIter) );
+ }
+}
+
+void SwDoc::getNumItems( tSortedNodeNumList& orNodeNumList ) const
+{
+ orNodeNumList.clear();
+ orNodeNumList.reserve( mpListItemsList->size() );
+
+ tImplSortedNodeNumList::iterator aIter;
+ tImplSortedNodeNumList::iterator aEndIter = mpListItemsList->end();
+ for ( aIter = mpListItemsList->begin(); aIter != aEndIter; ++aIter )
+ {
+ const SwNodeNum* pNodeNum = (*aIter);
+ if ( pNodeNum->IsCounted() &&
+ pNodeNum->GetTxtNode() && pNodeNum->GetTxtNode()->HasNumber() )
+ {
+ orNodeNumList.push_back( pNodeNum );
+ }
+ }
+}
+// <--
+
+// --> OD 2007-11-15 #i83479#
+// implementation for interface <IDocumentOutlineNodes>
+sal_Int32 SwDoc::getOutlineNodesCount() const
+{
+ return GetNodes().GetOutLineNds().Count();
+}
+
+int SwDoc::getOutlineLevel( const sal_Int32 nIdx ) const
+{
+ return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]->
+ // GetTxtNode()->GetOutlineLevel(); //#outline level,zhaojianwei
+ GetTxtNode()->GetAttrOutlineLevel()-1; //<-end,zhaojianwei
+}
+
+String SwDoc::getOutlineText( const sal_Int32 nIdx,
+ const bool bWithNumber,
+ const bool bWithSpacesForLevel ) const
+{
+ return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]->
+ GetTxtNode()->GetExpandTxt( 0, STRING_LEN, bWithNumber,
+ bWithNumber, bWithSpacesForLevel );
+}
+
+SwTxtNode* SwDoc::getOutlineNode( const sal_Int32 nIdx ) const
+{
+ return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]->GetTxtNode();
+}
+
+void SwDoc::getOutlineNodes( IDocumentOutlineNodes::tSortedOutlineNodeList& orOutlineNodeList ) const
+{
+ orOutlineNodeList.clear();
+ orOutlineNodeList.reserve( getOutlineNodesCount() );
+
+ const sal_uInt16 nOutlCount( static_cast<sal_uInt16>(getOutlineNodesCount()) );
+ for ( sal_uInt16 i = 0; i < nOutlCount; ++i )
+ {
+ orOutlineNodeList.push_back(
+ GetNodes().GetOutLineNds()[i]->GetTxtNode() );
+ }
+}
+// <--
+
+// --> OD 2008-03-26 #refactorlists#
+// implementation of interface IDocumentListsAccess
+SwList* SwDoc::createList( String sListId,
+ const String sDefaultListStyleName )
+{
+ if ( sListId.Len() == 0 )
+ {
+ sListId = listfunc::CreateUniqueListId( *this );
+ }
+
+ if ( getListByName( sListId ) )
+ {
+ ASSERT( false,
+ "<SwDoc::createList(..)> - provided list id already used. Serious defect -> please inform OD." );
+ return 0;
+ }
+
+ SwNumRule* pDefaultNumRuleForNewList = FindNumRulePtr( sDefaultListStyleName );
+ if ( !pDefaultNumRuleForNewList )
+ {
+ ASSERT( false,
+ "<SwDoc::createList(..)> - for provided default list style name no list style is found. Serious defect -> please inform OD." );
+ return 0;
+ }
+
+ SwList* pNewList = new SwList( sListId, *pDefaultNumRuleForNewList, GetNodes() );
+ maLists[sListId] = pNewList;
+
+ return pNewList;
+}
+
+void SwDoc::deleteList( const String sListId )
+{
+ SwList* pList = getListByName( sListId );
+ if ( pList )
+ {
+ maLists.erase( sListId );
+ delete pList;
+ }
+}
+
+SwList* SwDoc::getListByName( const String sListId ) const
+{
+ SwList* pList = 0;
+
+ std::hash_map< String, SwList*, StringHash >::const_iterator
+ aListIter = maLists.find( sListId );
+ if ( aListIter != maLists.end() )
+ {
+ pList = (*aListIter).second;
+ }
+
+ return pList;
+}
+
+SwList* SwDoc::createListForListStyle( const String sListStyleName )
+{
+ if ( sListStyleName.Len() == 0 )
+ {
+ ASSERT( false,
+ "<SwDoc::createListForListStyle(..)> - no list style name provided. Serious defect -> please inform OD." );
+ return 0;
+ }
+
+ if ( getListForListStyle( sListStyleName ) )
+ {
+ ASSERT( false,
+ "<SwDoc::createListForListStyle(..)> - a list for the provided list style name already exists. Serious defect -> please inform OD." );
+ return 0;
+ }
+
+ SwNumRule* pNumRule = FindNumRulePtr( sListStyleName );
+ if ( !pNumRule )
+ {
+ ASSERT( false,
+ "<SwDoc::createListForListStyle(..)> - for provided list style name no list style is found. Serious defect -> please inform OD." );
+ return 0;
+ }
+
+ String sListId( pNumRule->GetDefaultListId() ); // can be empty String
+ if ( getListByName( sListId ) )
+ {
+ sListId = String();
+ }
+ SwList* pNewList = createList( sListId, sListStyleName );
+ maListStyleLists[sListStyleName] = pNewList;
+ pNumRule->SetDefaultListId( pNewList->GetListId() );
+
+ return pNewList;
+}
+
+SwList* SwDoc::getListForListStyle( const String sListStyleName ) const
+{
+ SwList* pList = 0;
+
+ std::hash_map< String, SwList*, StringHash >::const_iterator
+ aListIter = maListStyleLists.find( sListStyleName );
+ if ( aListIter != maListStyleLists.end() )
+ {
+ pList = (*aListIter).second;
+ }
+
+ return pList;
+}
+
+void SwDoc::deleteListForListStyle( const String sListStyleName )
+{
+ String sListId;
+ {
+ SwList* pList = getListForListStyle( sListStyleName );
+ ASSERT( pList,
+ "<SwDoc::deleteListForListStyle(..)> - misusage of method: no list found for given list style name" );
+ if ( pList )
+ {
+ sListId = pList->GetListId();
+ }
+ }
+ if ( sListId.Len() > 0 )
+ {
+ maListStyleLists.erase( sListStyleName );
+ deleteList( sListId );
+ }
+}
+// <--
+// --> OD 2008-07-08 #i91400#
+void SwDoc::trackChangeOfListStyleName( const String sListStyleName,
+ const String sNewListStyleName )
+{
+ SwList* pList = getListForListStyle( sListStyleName );
+ ASSERT( pList,
+ "<SwDoc::changeOfListStyleName(..)> - misusage of method: no list found for given list style name" );
+
+ if ( pList != 0 )
+ {
+ maListStyleLists.erase( sListStyleName );
+ maListStyleLists[sNewListStyleName] = pList;
+ }
+}
+// <--
+
+// --> OD 2008-03-13 #refactorlists#
+namespace listfunc
+{
+ const String MakeListIdUnique( const SwDoc& rDoc,
+ const String aSuggestedUniqueListId )
+ {
+ long nHitCount = 0;
+ String aTmpStr = aSuggestedUniqueListId;
+ while ( rDoc.getListByName( aTmpStr ) )
+ {
+ ++nHitCount;
+ aTmpStr = aSuggestedUniqueListId;
+ aTmpStr += String::CreateFromInt32( nHitCount );
+ }
+
+ return aTmpStr;
+ }
+ const String CreateUniqueListId( const SwDoc& rDoc )
+ {
+ // --> OD 2008-08-06 #i92478#
+ String aNewListId = String::CreateFromAscii( "list" );
+ // <--
+ sal_Int64 n = Time().GetTime();
+ n += Date().GetDate();
+ n += rand();
+ // --> OD 2008-08-06 #i92478#
+ aNewListId += String::CreateFromInt64( n );
+ // <--
+
+ return MakeListIdUnique( rDoc, aNewListId );
+ }
+}
+// <--
diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx
new file mode 100644
index 000000000000..d18d2166dd96
--- /dev/null
+++ b/sw/source/core/doc/docredln.cxx
@@ -0,0 +1,3868 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <tools/shl.hxx>
+#include <svl/itemiter.hxx>
+#include <sfx2/app.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/crsditem.hxx>
+#include <swmodule.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <ndtxt.hxx>
+#include <redline.hxx>
+#include <swundo.hxx>
+#include <UndoCore.hxx>
+#include <UndoRedline.hxx>
+#include <hints.hxx>
+#include <pamtyp.hxx>
+#include <poolfmt.hxx>
+#include <viewsh.hxx>
+#include <rootfrm.hxx>
+
+#include <comcore.hrc>
+
+using namespace com::sun::star;
+
+TYPEINIT1(SwRedlineHint, SfxHint);
+
+#ifndef DBG_UTIL
+
+ #define _CHECK_REDLINE( pDoc )
+ #define _DEBUG_REDLINE( pDoc )
+
+#else
+
+#define _ERROR_PREFIX "redline table corrupted: "
+
+ // helper function for lcl_CheckRedline
+ // 1. make sure that pPos->nContent points into pPos->nNode
+ // (or into the 'special' no-content-node-IndexReg)
+ // 2. check that position is valid and doesn't point behind text
+ void lcl_CheckPosition( const SwPosition* pPos )
+ {
+ SwPosition aComparePos( *pPos );
+ aComparePos.nContent.Assign(
+ aComparePos.nNode.GetNode().GetCntntNode(), 0 );
+ DBG_ASSERT( pPos->nContent.GetIdxReg() ==
+ aComparePos.nContent.GetIdxReg(),
+ _ERROR_PREFIX "illegal position" );
+
+ SwTxtNode* pTxtNode = pPos->nNode.GetNode().GetTxtNode();
+ if( pTxtNode == NULL )
+ {
+ DBG_ASSERT( pPos->nContent == 0,
+ _ERROR_PREFIX "non-text-node with content" );
+ }
+ else
+ {
+ DBG_ASSERT( pPos->nContent >= 0 &&
+ pPos->nContent <= pTxtNode->Len(),
+ _ERROR_PREFIX "index behind text" );
+ }
+ }
+
+ void lcl_CheckPam( const SwPaM* pPam )
+ {
+ DBG_ASSERT( pPam != NULL, _ERROR_PREFIX "illegal argument" );
+ lcl_CheckPosition( pPam->GetPoint() );
+ lcl_CheckPosition( pPam->GetMark() );
+ }
+
+ // check validity of the redline table. Checks redline bounds, and make
+ // sure the redlines are sorted and non-overlapping.
+ void lcl_CheckRedline( const SwDoc* pDoc )
+ {
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+
+ // verify valid redline positions
+ for( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
+ lcl_CheckPam( rTbl[ i ] );
+
+ for( sal_uInt16 j = 0; j < rTbl.Count(); ++j )
+ {
+ // check for empty redlines
+ DBG_ASSERT( ( *(rTbl[j]->GetPoint()) != *(rTbl[j]->GetMark()) ) ||
+ ( rTbl[j]->GetContentIdx() != NULL ),
+ _ERROR_PREFIX "empty redline" );
+ }
+
+ // verify proper redline sorting
+ for( sal_uInt16 n = 1; n < rTbl.Count(); ++n )
+ {
+ const SwRedline* pPrev = rTbl[ n-1 ];
+ const SwRedline* pCurrent = rTbl[ n ];
+
+ // check redline sorting
+ DBG_ASSERT( *pPrev->Start() <= *pCurrent->Start(),
+ _ERROR_PREFIX "not sorted correctly" );
+
+ // check for overlapping redlines
+ DBG_ASSERT( *pPrev->End() <= *pCurrent->Start(),
+ _ERROR_PREFIX "overlapping redlines" );
+ }
+ }
+
+ #define _CHECK_REDLINE( pDoc ) lcl_CheckRedline( pDoc );
+
+ void lcl_DebugRedline( const SwDoc* pDoc )
+ {
+ static sal_uInt16 nWatch = 0;
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ sal_uInt16 nDummy = 0;
+ const SwRedline* pCurrent = rTbl[ n ];
+ const SwRedline* pNext = n+1 < rTbl.Count() ? rTbl[ n+1 ] : 0;
+ if( pCurrent == pNext )
+ ++nDummy;
+ if( n == nWatch )
+ ++nDummy; // Possible debugger breakpoint
+ }
+ }
+
+ #define _DEBUG_REDLINE( pDoc ) lcl_DebugRedline( pDoc );
+
+#endif
+
+SV_IMPL_OP_PTRARR_SORT( _SwRedlineTbl, SwRedlinePtr )
+
+RedlineMode_t SwDoc::GetRedlineMode() const
+{
+ return eRedlineMode;
+}
+
+void SwDoc::SetRedlineMode( RedlineMode_t eMode )
+{
+ if( eRedlineMode != eMode )
+ {
+ if( (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) != (nsRedlineMode_t::REDLINE_SHOW_MASK & eMode)
+ || 0 == (nsRedlineMode_t::REDLINE_SHOW_MASK & eMode) )
+ {
+ bool bSaveInXMLImportFlag = IsInXMLImport();
+ SetInXMLImport( false );
+ // und dann alles verstecken, anzeigen
+ void (SwRedline::*pFnc)( sal_uInt16 ) = 0;
+
+ switch( nsRedlineMode_t::REDLINE_SHOW_MASK & eMode )
+ {
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE :
+ pFnc = &SwRedline::Show;
+ break;
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT:
+ pFnc = &SwRedline::Hide;
+ break;
+ case nsRedlineMode_t::REDLINE_SHOW_DELETE:
+ pFnc = &SwRedline::ShowOriginal;
+ break;
+
+ default:
+ pFnc = &SwRedline::Hide;
+ eMode = (RedlineMode_t)(eMode | nsRedlineMode_t::REDLINE_SHOW_INSERT);
+ break;
+ }
+
+ _CHECK_REDLINE( this )
+
+ if( pFnc )
+ for( sal_uInt16 nLoop = 1; nLoop <= 2; ++nLoop )
+ for( sal_uInt16 i = 0; i < pRedlineTbl->Count(); ++i )
+ ((*pRedlineTbl)[ i ]->*pFnc)( nLoop );
+ _CHECK_REDLINE( this )
+ SetInXMLImport( bSaveInXMLImportFlag );
+ }
+ eRedlineMode = eMode;
+ SetModified();
+ }
+}
+
+bool SwDoc::IsRedlineOn() const
+{
+ return IDocumentRedlineAccess::IsRedlineOn(eRedlineMode);
+}
+
+bool SwDoc::IsIgnoreRedline() const
+{
+ return (nsRedlineMode_t::REDLINE_IGNORE & eRedlineMode);
+}
+
+void SwDoc::SetRedlineMode_intern(RedlineMode_t eMode)
+{
+ eRedlineMode = eMode;
+}
+
+const SwRedlineTbl& SwDoc::GetRedlineTbl() const
+{
+ return *pRedlineTbl;
+}
+
+bool SwDoc::IsRedlineMove() const
+{
+ return mbIsRedlineMove;
+}
+
+void SwDoc::SetRedlineMove(bool bFlag)
+{
+ mbIsRedlineMove = bFlag;
+}
+
+const uno::Sequence <sal_Int8>& SwDoc::GetRedlinePassword() const
+{
+ return aRedlinePasswd;
+}
+
+inline bool IsPrevPos( const SwPosition rPos1, const SwPosition rPos2 )
+{
+ const SwCntntNode* pCNd;
+ return 0 == rPos2.nContent.GetIndex() &&
+ rPos2.nNode.GetIndex() - 1 == rPos1.nNode.GetIndex() &&
+ 0 != ( pCNd = rPos1.nNode.GetNode().GetCntntNode() )
+ ? rPos1.nContent.GetIndex() == pCNd->Len()
+ : false;
+}
+
+#ifdef DEBUG
+bool CheckPosition( const SwPosition* pStt, const SwPosition* pEnd )
+{
+ int nError = 0;
+ SwNode* pSttNode = &pStt->nNode.GetNode();
+ SwNode* pEndNode = &pEnd->nNode.GetNode();
+ SwNode* pSttTab = pSttNode->StartOfSectionNode()->FindTableNode();
+ SwNode* pEndTab = pEndNode->StartOfSectionNode()->FindTableNode();
+ SwNode* pSttStart = pSttNode;
+ while( pSttStart && (!pSttStart->IsStartNode() || pSttStart->IsSectionNode() ||
+ pSttStart->IsTableNode() ) )
+ pSttStart = pSttStart->StartOfSectionNode();
+ SwNode* pEndStart = pEndNode;
+ while( pEndStart && (!pEndStart->IsStartNode() || pEndStart->IsSectionNode() ||
+ pEndStart->IsTableNode() ) )
+ pEndStart = pEndStart->StartOfSectionNode();
+ if( pSttTab != pEndTab )
+ nError = 1;
+ if( !pSttTab && pSttStart != pEndStart )
+ nError |= 2;
+ if( nError )
+ nError += 10;
+ return nError != 0;
+}
+#endif
+
+/*
+
+Text heisst, nicht von Redline "verseuchter" Text.
+
+Verhalten von Insert-Redline:
+ - im Text - Redline Object einfuegen
+ - im InsertRedline (eigenes) - ignorieren, bestehendes wird
+ aufgespannt
+ - im InsertRedline (andere) - Insert Redline aufsplitten
+ Redline Object einfuegen
+ - in DeleteRedline - Delete Redline aufsplitten oder
+ am Ende/Anfang verschieben
+
+Verhalten von Delete-Redline:
+ - im Text - Redline Object einfuegen
+ - im DeleteRedline (eigenes/andere) - ignorieren
+ - im InsertRedline (eigenes) - ignorieren, Zeichen aber loeschen
+ - im InsertRedline (andere) - Insert Redline aufsplitten
+ Redline Object einfuegen
+ - Ueberlappung von Text und - Text in eigenen Insert loeschen,
+ eigenem Insert im andereren Text aufspannen (bis
+ zum Insert!
+ - Ueberlappung von Text und - Redline Object einfuegen, der
+ anderem Insert andere Insert wird vom Delete
+ ueberlappt
+*/
+
+bool SwDoc::AppendRedline( SwRedline* pNewRedl, bool bCallDelete )
+{
+#if 0
+// #i93179# disabled: ASSERT in ~SwIndexReg #ifdef DBG_UTIL
+ SwRedline aCopy( *pNewRedl );
+#endif
+ bool bError = true;
+ _CHECK_REDLINE( this )
+
+ if( IsRedlineOn() && !IsShowOriginal( eRedlineMode ) &&
+ pNewRedl->GetAuthorString().Len() )
+ {
+ pNewRedl->InvalidateRange();
+
+ if( mbIsAutoFmtRedline )
+ {
+ pNewRedl->SetAutoFmtFlag();
+ if( pAutoFmtRedlnComment && pAutoFmtRedlnComment->Len() )
+ {
+ pNewRedl->SetComment( *pAutoFmtRedlnComment );
+ pNewRedl->SetSeqNo( nAutoFmtRedlnCommentNo );
+ }
+ }
+
+ SwPosition* pStt = pNewRedl->Start(),
+ * pEnd = pStt == pNewRedl->GetPoint() ? pNewRedl->GetMark()
+ : pNewRedl->GetPoint();
+ {
+ SwTxtNode* pTxtNode = pStt->nNode.GetNode().GetTxtNode();
+ if( pTxtNode == NULL )
+ {
+ if( pStt->nContent > 0 )
+ {
+ DBG_ASSERT( false, "Redline start: non-text-node with content" );
+ pStt->nContent = 0;
+ }
+ }
+ else
+ {
+ if( pStt->nContent > pTxtNode->Len() )
+ {
+ DBG_ASSERT( false, "Redline start: index behind text" );
+ pStt->nContent = pTxtNode->Len();
+ }
+ }
+ pTxtNode = pEnd->nNode.GetNode().GetTxtNode();
+ if( pTxtNode == NULL )
+ {
+ if( pEnd->nContent > 0 )
+ {
+ DBG_ASSERT( false, "Redline end: non-text-node with content" );
+ pEnd->nContent = 0;
+ }
+ }
+ else
+ {
+ if( pEnd->nContent > pTxtNode->Len() )
+ {
+ DBG_ASSERT( false, "Redline end: index behind text" );
+ pEnd->nContent = pTxtNode->Len();
+ }
+ }
+ }
+ if( ( *pStt == *pEnd ) &&
+ ( pNewRedl->GetContentIdx() == NULL ) )
+ { // Do not insert empty redlines
+ delete pNewRedl;
+ return sal_False;
+ }
+ sal_Bool bCompress = sal_False;
+ sal_uInt16 n = 0;
+ // zur StartPos das erste Redline suchen
+ if( !GetRedline( *pStt, &n ) && n )
+ --n;
+ bool bDec = false;
+
+ for( ; pNewRedl && n < pRedlineTbl->Count(); bDec ? n : ++n )
+ {
+ bDec = false;
+#ifdef DVO_TEST
+ _CHECK_REDLINE( this )
+#endif
+
+ SwRedline* pRedl = (*pRedlineTbl)[ n ];
+ SwPosition* pRStt = pRedl->Start(),
+ * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark()
+ : pRedl->GetPoint();
+
+ // #i8518# remove empty redlines while we're at it
+ if( ( *pRStt == *pREnd ) &&
+ ( pRedl->GetContentIdx() == NULL ) )
+ {
+ pRedlineTbl->DeleteAndDestroy(n);
+ continue;
+ }
+
+ SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd );
+
+ switch( pNewRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ switch( pRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ if( pRedl->IsOwnRedline( *pNewRedl ) )
+ {
+ bool bDelete = false;
+
+ // ggfs. verschmelzen?
+ if( (( POS_BEHIND == eCmpPos &&
+ IsPrevPos( *pREnd, *pStt ) ) ||
+ ( POS_COLLIDE_START == eCmpPos ) ||
+ ( POS_OVERLAP_BEHIND == eCmpPos ) ) &&
+ pRedl->CanCombine( *pNewRedl ) &&
+ ( n+1 >= pRedlineTbl->Count() ||
+ ( *(*pRedlineTbl)[ n+1 ]->Start() >= *pEnd &&
+ *(*pRedlineTbl)[ n+1 ]->Start() != *pREnd ) ) )
+ {
+ pRedl->SetEnd( *pEnd, pREnd );
+ if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ }
+
+ bError = false;
+ bDelete = true;
+ }
+ else if( (( POS_BEFORE == eCmpPos &&
+ IsPrevPos( *pEnd, *pRStt ) ) ||
+ ( POS_COLLIDE_END == eCmpPos ) ||
+ ( POS_OVERLAP_BEFORE == eCmpPos ) ) &&
+ pRedl->CanCombine( *pNewRedl ) &&
+ ( !n ||
+ *(*pRedlineTbl)[ n-1 ]->End() != *pRStt ))
+ {
+ pRedl->SetStart( *pStt, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+
+ bError = false;
+ bDelete = true;
+ }
+ else if ( POS_OUTSIDE == eCmpPos )
+ {
+ // #107164# own insert-over-insert
+ // redlines: just scrap the inside ones
+ pRedlineTbl->Remove( n );
+ bDec = true;
+ }
+ // <- #107164#
+ else if( POS_OVERLAP_BEHIND == eCmpPos )
+ {
+ *pStt = *pREnd;
+ if( ( *pStt == *pEnd ) &&
+ ( pNewRedl->GetContentIdx() == NULL ) )
+ bDelete = true;
+ }
+ else if( POS_OVERLAP_BEFORE == eCmpPos )
+ {
+ *pEnd = *pRStt;
+ if( ( *pStt == *pEnd ) &&
+ ( pNewRedl->GetContentIdx() == NULL ) )
+ bDelete = true;
+ }
+ else if( POS_INSIDE == eCmpPos || POS_EQUAL == eCmpPos)
+ bDelete = true;
+
+ if( bDelete )
+ {
+ delete pNewRedl, pNewRedl = 0;
+ bCompress = sal_True;
+ }
+ }
+ else if( POS_INSIDE == eCmpPos )
+ {
+ // aufsplitten
+ if( *pEnd != *pREnd )
+ {
+ SwRedline* pCpy = new SwRedline( *pRedl );
+ pCpy->SetStart( *pEnd );
+ pRedlineTbl->Insert( pCpy );
+ }
+ pRedl->SetEnd( *pStt, pREnd );
+ if( ( *pStt == *pRStt ) &&
+ ( pRedl->GetContentIdx() == NULL ) )
+ {
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ else if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ }
+ }
+ else if ( POS_OUTSIDE == eCmpPos )
+ {
+ // #102366# handle overlapping redlines in broken
+ // documents
+
+ // split up the new redline, since it covers the
+ // existing redline. Insert the first part, and
+ // progress with the remainder as usual
+ SwRedline* pSplit = new SwRedline( *pNewRedl );
+ pSplit->SetEnd( *pRStt );
+ pNewRedl->SetStart( *pREnd );
+ pRedlineTbl->Insert( pSplit );
+ if( *pStt == *pEnd && pNewRedl->GetContentIdx() == NULL )
+ {
+ delete pNewRedl;
+ pNewRedl = 0;
+ bCompress = true;
+ }
+ }
+ else if ( POS_OVERLAP_BEHIND == eCmpPos )
+ {
+ // #107164# handle overlapping redlines in broken
+ // documents
+ pNewRedl->SetStart( *pREnd );
+ }
+ else if ( POS_OVERLAP_BEFORE == eCmpPos )
+ {
+ // #107164# handle overlapping redlines in broken
+ // documents
+ *pEnd = *pRStt;
+ if( ( *pStt == *pEnd ) &&
+ ( pNewRedl->GetContentIdx() == NULL ) )
+ {
+ delete pNewRedl;
+ pNewRedl = 0;
+ bCompress = true;
+ }
+ }
+ break;
+ case nsRedlineType_t::REDLINE_DELETE:
+ if( POS_INSIDE == eCmpPos )
+ {
+ // aufsplitten
+ if( *pEnd != *pREnd )
+ {
+ SwRedline* pCpy = new SwRedline( *pRedl );
+ pCpy->SetStart( *pEnd );
+ pRedlineTbl->Insert( pCpy );
+ }
+ pRedl->SetEnd( *pStt, pREnd );
+ if( ( *pStt == *pRStt ) &&
+ ( pRedl->GetContentIdx() == NULL ) )
+ {
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ else if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ }
+ }
+ else if ( POS_OUTSIDE == eCmpPos )
+ {
+ // #102366# handle overlapping redlines in broken
+ // documents
+
+ // split up the new redline, since it covers the
+ // existing redline. Insert the first part, and
+ // progress with the remainder as usual
+ SwRedline* pSplit = new SwRedline( *pNewRedl );
+ pSplit->SetEnd( *pRStt );
+ pNewRedl->SetStart( *pREnd );
+ pRedlineTbl->Insert( pSplit );
+ if( *pStt == *pEnd && pNewRedl->GetContentIdx() == NULL )
+ {
+ delete pNewRedl;
+ pNewRedl = 0;
+ bCompress = true;
+ }
+ }
+ else if ( POS_EQUAL == eCmpPos )
+ {
+ // #112895# handle identical redlines in broken
+ // documents - delete old (delete) redline
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ else if ( POS_OVERLAP_BEHIND == eCmpPos )
+ { // Another workaround for broken redlines (#107164#)
+ pNewRedl->SetStart( *pREnd );
+ }
+ break;
+ case nsRedlineType_t::REDLINE_FORMAT:
+ switch( eCmpPos )
+ {
+ case POS_OVERLAP_BEFORE:
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ bDec = true;
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ pRedl->SetEnd( *pStt, pREnd );
+ if( *pStt == *pRStt && pRedl->GetContentIdx() == NULL )
+ {
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ break;
+
+ case POS_EQUAL:
+ case POS_OUTSIDE:
+ // ueberlappt den akt. komplett oder hat gleiche
+ // Ausdehung, dann muss der alte geloescht werden
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ break;
+
+ case POS_INSIDE:
+ // ueberlappt den akt. komplett, dann muss
+ // der neue gesplittet oder verkuertzt werden
+ if( *pEnd != *pREnd )
+ {
+ if( *pEnd != *pRStt )
+ {
+ SwRedline* pNew = new SwRedline( *pRedl );
+ pNew->SetStart( *pEnd );
+ pRedl->SetEnd( *pStt, pREnd );
+ if( *pStt == *pRStt && pRedl->GetContentIdx() == NULL )
+ pRedlineTbl->DeleteAndDestroy( n );
+ AppendRedline( pNew, bCallDelete );
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ }
+ else
+ pRedl->SetEnd( *pStt, pREnd );
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_DELETE:
+ switch( pRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_DELETE:
+ switch( eCmpPos )
+ {
+ case POS_OUTSIDE:
+ {
+ // ueberlappt den akt. komplett
+ // dann muss der neue gesplittet werden
+ if( *pEnd != *pREnd )
+ {
+ SwRedline* pNew = new SwRedline( *pNewRedl );
+ pNew->SetStart( *pREnd );
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ AppendRedline( pNew, bCallDelete );
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ else
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ }
+ break;
+
+ case POS_INSIDE:
+ case POS_EQUAL:
+ delete pNewRedl, pNewRedl = 0;
+ bCompress = sal_True;
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ case POS_OVERLAP_BEHIND:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+// 1 == pRedl->GetStackCount() &&
+ pRedl->CanCombine( *pNewRedl ))
+ {
+ // dann kann das zusammengefasst werden, sprich
+ // der neue deckt das schon ab.
+ if( POS_OVERLAP_BEHIND == eCmpPos )
+ pNewRedl->SetStart( *pRStt, pStt );
+ else
+ pNewRedl->SetEnd( *pREnd, pEnd );
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ else if( POS_OVERLAP_BEHIND == eCmpPos )
+ pNewRedl->SetStart( *pREnd, pStt );
+ else
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ break;
+
+ case POS_COLLIDE_START:
+ case POS_COLLIDE_END:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+// 1 == pRedl->GetStackCount() &&
+ pRedl->CanCombine( *pNewRedl ) )
+ {
+ if( IsHideChanges( eRedlineMode ))
+ {
+ // dann erstmal sichtbar machen, bevor
+ // die zusammengefasst werden koennen!
+ // Damit pNew auch beim Verschieben der
+ // Indizies behandelt wird, erstmal
+ // temporaer einfuegen
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ pRedl->Show();
+ pRedlineTbl->Remove( pRedlineTbl->GetPos(pNewRedl ));
+ pRStt = pRedl->Start();
+ pREnd = pRedl->End();
+ }
+
+ // dann kann das zusammengefasst werden, sprich
+ // der neue deckt das schon ab.
+ if( POS_COLLIDE_START == eCmpPos )
+ pNewRedl->SetStart( *pRStt, pStt );
+ else
+ pNewRedl->SetEnd( *pREnd, pEnd );
+
+ // delete current (below), and restart process with
+ // previous
+ sal_uInt16 nToBeDeleted = n;
+ bDec = true;
+
+ // #107359# Do it again, Sam!
+ // If you can do it for them, you can do it for me.
+ if( *(pNewRedl->Start()) <= *pREnd )
+ {
+ // Whoooah, we just extended the new 'redline'
+ // beyond previous redlines, so better start
+ // again. Of course this is not supposed to
+ // happen, and in an ideal world it doesn't,
+ // but unfortunately this code is buggy and
+ // totally rotten so it does happen and we
+ // better fix it.
+ n = 0;
+ bDec = true;
+ }
+
+ pRedlineTbl->DeleteAndDestroy( nToBeDeleted );
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_INSERT:
+ {
+ // b62341295: Do not throw away redlines
+ // even if they are not allowed to be combined
+ RedlineMode_t eOld = eRedlineMode;
+ if( !( eOld & nsRedlineMode_t::REDLINE_DONTCOMBINE_REDLINES ) &&
+ pRedl->IsOwnRedline( *pNewRedl ) )
+ {
+
+// auf NONE setzen, damit das Delete::Redo die RedlineDaten wieder richtig
+// zusammen fasst! Der ShowMode muss erhalten bleiben!
+ eRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE));
+ switch( eCmpPos )
+ {
+ case POS_EQUAL:
+ bCompress = sal_True;
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ // kein break!
+
+ case POS_INSIDE:
+ if( bCallDelete )
+ {
+ eRedlineMode = (RedlineMode_t)(eRedlineMode | nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES);
+
+ // #98863# DeleteAndJoin does not yield the
+ // desired result if there is no paragraph to
+ // join with, i.e. at the end of the document.
+ // For this case, we completely delete the
+ // paragraphs (if, of course, we also start on
+ // a paragraph boundary).
+ if( (pStt->nContent == 0) &&
+ pEnd->nNode.GetNode().IsEndNode() )
+ {
+ pEnd->nNode--;
+ pEnd->nContent.Assign(
+ pEnd->nNode.GetNode().GetTxtNode(), 0);
+ DelFullPara( *pNewRedl );
+ }
+ else
+ DeleteAndJoin( *pNewRedl );
+
+ bCompress = sal_True;
+ }
+ delete pNewRedl, pNewRedl = 0;
+ break;
+
+ case POS_OUTSIDE:
+ {
+ pRedlineTbl->Remove( n );
+ bDec = true;
+ // damit pNew auch beim Verschieben der Indizies
+ // behandelt wird, erstmal temp. einfuegen
+ if( bCallDelete )
+ {
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ DeleteAndJoin( *pRedl );
+ sal_uInt16 nFnd = pRedlineTbl->GetPos(pNewRedl );
+ if( USHRT_MAX != nFnd )
+ pRedlineTbl->Remove( nFnd );
+ else
+ pNewRedl = 0;
+ }
+ delete pRedl;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ {
+ SwPaM aPam( *pRStt, *pEnd );
+
+ if( *pEnd == *pREnd )
+ pRedlineTbl->DeleteAndDestroy( n );
+ else
+ {
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ }
+
+ if( bCallDelete )
+ {
+ // damit pNew auch beim Verschieben der Indizies
+ // behandelt wird, erstmal temp. einfuegen
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ DeleteAndJoin( aPam );
+ sal_uInt16 nFnd = pRedlineTbl->GetPos(pNewRedl );
+ if( USHRT_MAX != nFnd )
+ pRedlineTbl->Remove( nFnd );
+ else
+ pNewRedl = 0;
+ n = 0; // neu Aufsetzen
+ }
+ bDec = true;
+ }
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ {
+ SwPaM aPam( *pStt, *pREnd );
+
+ if( *pStt == *pRStt )
+ {
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ else
+ pRedl->SetEnd( *pStt, pREnd );
+
+ if( bCallDelete )
+ {
+ // damit pNew auch beim Verschieben der Indizies
+ // behandelt wird, erstmal temp. einfuegen
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ DeleteAndJoin( aPam );
+ sal_uInt16 nFnd = pRedlineTbl->GetPos(pNewRedl );
+ if( USHRT_MAX != nFnd )
+ pRedlineTbl->Remove( nFnd );
+ else
+ pNewRedl = 0;
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ eRedlineMode = eOld;
+ }
+ else
+ {
+ // it may be necessary to split the existing redline in
+ // two. In this case, pRedl will be changed to cover
+ // only part of it's former range, and pNew will cover
+ // the remainder.
+ SwRedline* pNew = 0;
+
+ switch( eCmpPos )
+ {
+ case POS_EQUAL:
+ {
+ pRedl->PushData( *pNewRedl );
+ delete pNewRedl, pNewRedl = 0;
+ if( IsHideChanges( eRedlineMode ))
+ pRedl->Hide();
+ bCompress = sal_True;
+ }
+ break;
+
+ case POS_INSIDE:
+ {
+ if( *pRStt == *pStt )
+ {
+ // --> mst 2010-05-17 #i97421#
+ // redline w/out extent loops
+ if (*pStt != *pEnd)
+ // <--
+ {
+ pNewRedl->PushData( *pRedl, sal_False );
+ pRedl->SetStart( *pEnd, pRStt );
+ // re-insert
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ bDec = true;
+ }
+ }
+ else
+ {
+ pNewRedl->PushData( *pRedl, sal_False );
+ if( *pREnd != *pEnd )
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->SetStart( *pEnd );
+ }
+ pRedl->SetEnd( *pStt, pREnd );
+ if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ }
+ }
+ }
+ break;
+
+ case POS_OUTSIDE:
+ {
+ pRedl->PushData( *pNewRedl );
+ if( *pEnd == *pREnd )
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ else
+ {
+ pNew = new SwRedline( *pNewRedl );
+ pNew->SetEnd( *pRStt );
+ pNewRedl->SetStart( *pREnd, pStt );
+ }
+ bCompress = sal_True;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ {
+ if( *pEnd == *pREnd )
+ {
+ pRedl->PushData( *pNewRedl );
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ if( IsHideChanges( eRedlineMode ))
+ {
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ pRedl->Hide();
+ pRedlineTbl->Remove(
+ pRedlineTbl->GetPos(pNewRedl ));
+ }
+ }
+ else
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->PushData( *pNewRedl );
+ pNew->SetEnd( *pEnd );
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ pRedl->SetStart( *pNew->End(), pRStt ) ;
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ bDec = true;
+ }
+ }
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ {
+ if( *pStt == *pRStt )
+ {
+ pRedl->PushData( *pNewRedl );
+ pNewRedl->SetStart( *pREnd, pStt );
+ if( IsHideChanges( eRedlineMode ))
+ {
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ pRedl->Hide();
+ pRedlineTbl->Remove(
+ pRedlineTbl->GetPos(pNewRedl ));
+ }
+ }
+ else
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->PushData( *pNewRedl );
+ pNew->SetStart( *pStt );
+ pNewRedl->SetStart( *pREnd, pStt );
+ pRedl->SetEnd( *pNew->Start(), pREnd );
+ if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ // insert the pNew part (if it exists)
+ if( pNew )
+ {
+ // AppendRedline( pNew, bCallDelete );
+ //sal_Bool bRet =
+ pRedlineTbl->Insert( pNew );
+
+ // pNew must be deleted if Insert() wasn't
+ // successful. But that can't happen, since pNew is
+ // part of the original pRedl redline.
+ // ASSERT( bRet, "Can't insert existing redline?" );
+
+ // restart (now with pRedl being split up)
+ n = 0;
+ bDec = true;
+ }
+ }
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT:
+ switch( eCmpPos )
+ {
+ case POS_OVERLAP_BEFORE:
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ bDec = true;
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ pRedl->SetEnd( *pStt, pREnd );
+ break;
+
+ case POS_EQUAL:
+ case POS_OUTSIDE:
+ // ueberlappt den akt. komplett oder hat gleiche
+ // Ausdehung, dann muss der alte geloescht werden
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ break;
+
+ case POS_INSIDE:
+ // ueberlappt den akt. komplett, dann muss
+ // der neue gesplittet oder verkuertzt werden
+ if( *pEnd != *pREnd )
+ {
+ if( *pEnd != *pRStt )
+ {
+ SwRedline* pNew = new SwRedline( *pRedl );
+ pNew->SetStart( *pEnd );
+ pRedl->SetEnd( *pStt, pREnd );
+ if( ( *pStt == *pRStt ) &&
+ ( pRedl->GetContentIdx() == NULL ) )
+ pRedlineTbl->DeleteAndDestroy( n );
+ AppendRedline( pNew, bCallDelete );
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ }
+ else
+ pRedl->SetEnd( *pStt, pREnd );
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT:
+ switch( pRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ case nsRedlineType_t::REDLINE_DELETE:
+ switch( eCmpPos )
+ {
+ case POS_OVERLAP_BEFORE:
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ pNewRedl->SetStart( *pREnd, pStt );
+ break;
+
+ case POS_EQUAL:
+ case POS_INSIDE:
+ delete pNewRedl, pNewRedl = 0;
+ break;
+
+ case POS_OUTSIDE:
+ // ueberlappt den akt. komplett, dann muss
+ // der neue gesplittet oder verkuerzt werden
+ if( *pEnd != *pREnd )
+ {
+ if( *pEnd != *pRStt )
+ {
+ SwRedline* pNew = new SwRedline( *pNewRedl );
+ pNew->SetStart( *pREnd );
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ AppendRedline( pNew, bCallDelete );
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ }
+ else
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ break;
+ default:
+ break;
+ }
+ break;
+ case nsRedlineType_t::REDLINE_FORMAT:
+ switch( eCmpPos )
+ {
+ case POS_OUTSIDE:
+ case POS_EQUAL:
+ {
+ // ueberlappt den akt. komplett oder hat gleiche
+ // Ausdehnung, dann muss der alte geloescht werden
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ break;
+
+ case POS_INSIDE:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+ pRedl->CanCombine( *pNewRedl ))
+ // ein eigenes kann komplett ignoriert werden
+ delete pNewRedl, pNewRedl = 0;
+
+ else if( *pREnd == *pEnd )
+ // ansonsten nur den akt. verkuerzen
+ pRedl->SetEnd( *pStt, pREnd );
+ else if( *pRStt == *pStt )
+ {
+ // ansonsten nur den akt. verkuerzen
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ bDec = true;
+ }
+ else
+ {
+ // liegt komplett im akt.
+ // dann muss der gesplittet werden
+ SwRedline* pNew = new SwRedline( *pRedl );
+ pNew->SetStart( *pEnd );
+ pRedl->SetEnd( *pStt, pREnd );
+ AppendRedline( pNew, bCallDelete );
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ case POS_OVERLAP_BEHIND:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+ pRedl->CanCombine( *pNewRedl ))
+ {
+ // dann kann das zusammengefasst werden, sprich
+ // der neue deckt das schon ab.
+ if( POS_OVERLAP_BEHIND == eCmpPos )
+ pNewRedl->SetStart( *pRStt, pStt );
+ else
+ pNewRedl->SetEnd( *pREnd, pEnd );
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = 0;
+ }
+ else if( POS_OVERLAP_BEHIND == eCmpPos )
+ pNewRedl->SetStart( *pREnd, pStt );
+ else
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ break;
+
+ case POS_COLLIDE_END:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+ pRedl->CanCombine( *pNewRedl ) && n &&
+ *(*pRedlineTbl)[ n-1 ]->End() < *pStt )
+ {
+ // dann kann das zusammengefasst werden, sprich
+ // der neue deckt das schon ab.
+ pNewRedl->SetEnd( *pREnd, pEnd );
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ break;
+ case POS_COLLIDE_START:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+ pRedl->CanCombine( *pNewRedl ) &&
+ n+1 < pRedlineTbl->Count() &&
+ *(*pRedlineTbl)[ n+1 ]->Start() < *pEnd )
+ {
+ // dann kann das zusammengefasst werden, sprich
+ // der neue deckt das schon ab.
+ pNewRedl->SetStart( *pRStt, pStt );
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+
+ case nsRedlineType_t::REDLINE_FMTCOLL:
+ // wie soll das verhalten sein????
+ // erstmal so einfuegen
+ break;
+ default:
+ break;
+ }
+ }
+
+ if( pNewRedl )
+ {
+ if( ( *pStt == *pEnd ) &&
+ ( pNewRedl->GetContentIdx() == NULL ) )
+ { // Do not insert empty redlines
+ delete pNewRedl;
+ pNewRedl = 0;
+ }
+ else
+ pRedlineTbl->Insert( pNewRedl );
+ }
+
+ if( bCompress )
+ CompressRedlines();
+ }
+ else
+ {
+ if( bCallDelete && nsRedlineType_t::REDLINE_DELETE == pNewRedl->GetType() )
+ {
+ RedlineMode_t eOld = eRedlineMode;
+// auf NONE setzen, damit das Delete::Redo die RedlineDaten wieder richtig
+// zusammen fasst! Der ShowMode muss erhalten bleiben!
+ eRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE));
+ DeleteAndJoin( *pNewRedl );
+ eRedlineMode = eOld;
+ }
+ delete pNewRedl, pNewRedl = 0;
+ }
+ _CHECK_REDLINE( this )
+
+ return ( 0 != pNewRedl ) || !bError;
+}
+
+void SwDoc::CompressRedlines()
+{
+ _CHECK_REDLINE( this )
+
+ void (SwRedline::*pFnc)(sal_uInt16) = 0;
+ switch( nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode )
+ {
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE:
+ pFnc = &SwRedline::Show;
+ break;
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT:
+ pFnc = &SwRedline::Hide;
+ break;
+ }
+
+ // versuche gleiche zusammenzufassen
+ for( sal_uInt16 n = 1; n < pRedlineTbl->Count(); ++n )
+ {
+ SwRedline* pPrev = (*pRedlineTbl)[ n-1 ],
+ * pCur = (*pRedlineTbl)[ n ];
+ const SwPosition* pPrevStt = pPrev->Start(),
+ * pPrevEnd = pPrevStt == pPrev->GetPoint()
+ ? pPrev->GetMark() : pPrev->GetPoint();
+ const SwPosition* pCurStt = pCur->Start(),
+ * pCurEnd = pCurStt == pCur->GetPoint()
+ ? pCur->GetMark() : pCur->GetPoint();
+ if( *pPrevEnd == *pCurStt && pPrev->CanCombine( *pCur ) &&
+ pPrevStt->nNode.GetNode().StartOfSectionNode() ==
+ pCurEnd->nNode.GetNode().StartOfSectionNode() &&
+ !pCurEnd->nNode.GetNode().StartOfSectionNode()->IsTableNode() )
+ {
+ // dann koennen die zusammen gefasst werden
+ pPrev->Show();
+ pCur->Show();
+
+ pPrev->SetEnd( *pCur->End() );
+ pRedlineTbl->DeleteAndDestroy( n );
+ --n;
+ if( pFnc )
+ (pPrev->*pFnc)(0);
+ }
+ }
+ _CHECK_REDLINE( this )
+}
+
+bool SwDoc::SplitRedline( const SwPaM& rRange )
+{
+ sal_Bool bChg = sal_False;
+ sal_uInt16 n = 0;
+ const SwPosition* pStt = rRange.Start(),
+ * pEnd = pStt == rRange.GetPoint() ? rRange.GetMark()
+ : rRange.GetPoint();
+ GetRedline( *pStt, &n );
+ for( ; n < pRedlineTbl->Count() ; ++n )
+ {
+ SwRedline* pTmp = (*pRedlineTbl)[ n ];
+ SwPosition* pTStt = pTmp->Start(),
+ * pTEnd = pTStt == pTmp->GetPoint() ? pTmp->GetMark()
+ : pTmp->GetPoint();
+ if( *pTStt <= *pStt && *pStt <= *pTEnd &&
+ *pTStt <= *pEnd && *pEnd <= *pTEnd )
+ {
+ bChg = sal_True;
+ int nn = 0;
+ if( *pStt == *pTStt )
+ nn += 1;
+ if( *pEnd == *pTEnd )
+ nn += 2;
+
+ SwRedline* pNew = 0;
+ switch( nn )
+ {
+ case 0:
+ pNew = new SwRedline( *pTmp );
+ pTmp->SetEnd( *pStt, pTEnd );
+ pNew->SetStart( *pEnd );
+ break;
+
+ case 1:
+ *pTStt = *pEnd;
+ break;
+
+ case 2:
+ *pTEnd = *pStt;
+ break;
+
+ case 3:
+ pTmp->InvalidateRange();
+ pRedlineTbl->DeleteAndDestroy( n-- );
+ pTmp = 0;
+ break;
+ }
+ if( pTmp && !pTmp->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pTmp, n );
+ }
+ if( pNew )
+ pRedlineTbl->Insert( pNew, n );
+ }
+ else if( *pEnd < *pTStt )
+ break;
+ }
+ return bChg;
+}
+
+bool SwDoc::DeleteRedline( const SwPaM& rRange, bool bSaveInUndo,
+ sal_uInt16 nDelType )
+{
+ if( nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES & eRedlineMode ||
+ !rRange.HasMark() || *rRange.GetMark() == *rRange.GetPoint() )
+ return sal_False;
+
+ sal_Bool bChg = sal_False;
+
+ if (bSaveInUndo && GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoRedline* pUndo = new SwUndoRedline( UNDO_REDLINE, rRange );
+ if( pUndo->GetRedlSaveCount() )
+ {
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ else
+ delete pUndo;
+ }
+
+ const SwPosition* pStt = rRange.Start(),
+ * pEnd = pStt == rRange.GetPoint() ? rRange.GetMark()
+ : rRange.GetPoint();
+ sal_uInt16 n = 0;
+ GetRedline( *pStt, &n );
+ for( ; n < pRedlineTbl->Count() ; ++n )
+ {
+ SwRedline* pRedl = (*pRedlineTbl)[ n ];
+ if( USHRT_MAX != nDelType && nDelType != pRedl->GetType() )
+ continue;
+
+ SwPosition* pRStt = pRedl->Start(),
+ * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark()
+ : pRedl->GetPoint();
+ sal_Bool bDel = sal_False;
+ switch( ComparePosition( *pStt, *pEnd, *pRStt, *pREnd ) )
+ {
+ case POS_EQUAL:
+ case POS_OUTSIDE:
+ bDel = sal_True;
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ if( *pEnd == *pREnd )
+ bDel = sal_True;
+ else
+ {
+ pRedl->InvalidateRange();
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ --n;
+ }
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ if( *pStt == *pRStt )
+ bDel = sal_True;
+ else
+ {
+ pRedl->InvalidateRange();
+ pRedl->SetEnd( *pStt, pREnd );
+ if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ --n;
+ }
+ }
+ break;
+
+ case POS_INSIDE:
+ {
+ // der muss gesplittet werden
+ pRedl->InvalidateRange();
+ if( *pRStt == *pStt )
+ {
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ --n;
+ }
+ else
+ {
+ SwRedline* pCpy;
+ if( *pREnd != *pEnd )
+ {
+ pCpy = new SwRedline( *pRedl );
+ pCpy->SetStart( *pEnd );
+ }
+ else
+ pCpy = 0;
+ pRedl->SetEnd( *pStt, pREnd );
+ if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( pRedlineTbl->GetPos( pRedl ));
+ pRedlineTbl->Insert( pRedl );
+ --n;
+ }
+ if( pCpy )
+ pRedlineTbl->Insert( pCpy );
+ }
+ }
+ break;
+
+ case POS_COLLIDE_END:
+ case POS_BEFORE:
+ n = pRedlineTbl->Count();
+ break;
+ default:
+ break;
+ }
+
+ if( bDel )
+ {
+ pRedl->InvalidateRange();
+ pRedlineTbl->DeleteAndDestroy( n-- );
+ bChg = sal_True;
+ }
+ }
+
+ if( bChg )
+ SetModified();
+
+ return bChg;
+}
+
+bool SwDoc::DeleteRedline( const SwStartNode& rNode, bool bSaveInUndo,
+ sal_uInt16 nDelType )
+{
+ SwPaM aTemp(*rNode.EndOfSectionNode(), rNode);
+ return DeleteRedline(aTemp, bSaveInUndo, nDelType);
+}
+
+sal_uInt16 SwDoc::GetRedlinePos( const SwNode& rNd, sal_uInt16 nType ) const
+{
+ const sal_uLong nNdIdx = rNd.GetIndex();
+ for( sal_uInt16 n = 0; n < pRedlineTbl->Count() ; ++n )
+ {
+ const SwRedline* pTmp = (*pRedlineTbl)[ n ];
+ sal_uLong nPt = pTmp->GetPoint()->nNode.GetIndex(),
+ nMk = pTmp->GetMark()->nNode.GetIndex();
+ if( nPt < nMk ) { long nTmp = nMk; nMk = nPt; nPt = nTmp; }
+
+ if( ( USHRT_MAX == nType || nType == pTmp->GetType()) &&
+ nMk <= nNdIdx && nNdIdx <= nPt )
+ return n;
+
+ if( nMk > nNdIdx )
+ break;
+ }
+ return USHRT_MAX;
+}
+
+const SwRedline* SwDoc::GetRedline( const SwPosition& rPos,
+ sal_uInt16* pFndPos ) const
+{
+ sal_uInt16 nO = pRedlineTbl->Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ const SwRedline* pRedl = (*pRedlineTbl)[ nM ];
+ const SwPosition* pStt = pRedl->Start();
+ const SwPosition* pEnd = pStt == pRedl->GetPoint()
+ ? pRedl->GetMark()
+ : pRedl->GetPoint();
+ if( pEnd == pStt
+ ? *pStt == rPos
+ : ( *pStt <= rPos && rPos < *pEnd ) )
+ {
+ /* #107318# returned wrong redline ???*/
+ while( nM && rPos == *(*pRedlineTbl)[ nM - 1 ]->End() &&
+ rPos == *(*pRedlineTbl)[ nM - 1 ]->Start() )
+ {
+ --nM;
+ pRedl = (*pRedlineTbl)[ nM ];
+ }
+
+ if( pFndPos )
+ *pFndPos = nM;
+ return pRedl;
+ }
+ else if( *pEnd <= rPos )
+ nU = nM + 1;
+ else if( nM == 0 )
+ {
+ if( pFndPos )
+ *pFndPos = nU;
+ return 0;
+ }
+ else
+ nO = nM - 1;
+ }
+ }
+ if( pFndPos )
+ *pFndPos = nU;
+ return 0;
+}
+
+typedef sal_Bool (*Fn_AcceptReject)( SwRedlineTbl& rArr, sal_uInt16& rPos,
+ sal_Bool bCallDelete,
+ const SwPosition* pSttRng,
+ const SwPosition* pEndRng);
+
+sal_Bool lcl_AcceptRedline( SwRedlineTbl& rArr, sal_uInt16& rPos,
+ sal_Bool bCallDelete,
+ const SwPosition* pSttRng = 0,
+ const SwPosition* pEndRng = 0 )
+{
+ sal_Bool bRet = sal_True;
+ SwRedline* pRedl = rArr[ rPos ];
+ SwPosition *pRStt = 0, *pREnd = 0;
+ SwComparePosition eCmp = POS_OUTSIDE;
+ if( pSttRng && pEndRng )
+ {
+ pRStt = pRedl->Start();
+ pREnd = pRedl->End();
+ eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd );
+ }
+
+ pRedl->InvalidateRange();
+
+ switch( pRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ case nsRedlineType_t::REDLINE_FORMAT:
+ {
+ sal_Bool bCheck = sal_False, bReplace = sal_False;
+ switch( eCmp )
+ {
+ case POS_INSIDE:
+ if( *pSttRng == *pRStt )
+ pRedl->SetStart( *pEndRng, pRStt );
+ else
+ {
+ if( *pEndRng != *pREnd )
+ {
+ // aufsplitten
+ SwRedline* pNew = new SwRedline( *pRedl );
+ pNew->SetStart( *pEndRng );
+ rArr.Insert( pNew ); ++rPos;
+ }
+ pRedl->SetEnd( *pSttRng, pREnd );
+ bCheck = sal_True;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ pRedl->SetStart( *pEndRng, pRStt );
+ bReplace = sal_True;
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ pRedl->SetEnd( *pSttRng, pREnd );
+ bCheck = sal_True;
+ break;
+
+ case POS_OUTSIDE:
+ case POS_EQUAL:
+ rArr.DeleteAndDestroy( rPos-- );
+ break;
+
+ default:
+ bRet = sal_False;
+ }
+
+ if( bReplace || ( bCheck && !pRedl->HasValidRange() ))
+ {
+ // neu einsortieren
+ rArr.Remove( rArr.GetPos( pRedl ));
+ rArr.Insert( pRedl );
+ }
+ }
+ break;
+ case nsRedlineType_t::REDLINE_DELETE:
+ {
+ SwDoc& rDoc = *pRedl->GetDoc();
+ const SwPosition *pDelStt = 0, *pDelEnd = 0;
+ sal_Bool bDelRedl = sal_False;
+ switch( eCmp )
+ {
+ case POS_INSIDE:
+ if( bCallDelete )
+ {
+ pDelStt = pSttRng;
+ pDelEnd = pEndRng;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ if( bCallDelete )
+ {
+ pDelStt = pRStt;
+ pDelEnd = pEndRng;
+ }
+ break;
+ case POS_OVERLAP_BEHIND:
+ if( bCallDelete )
+ {
+ pDelStt = pREnd;
+ pDelEnd = pSttRng;
+ }
+ break;
+
+ case POS_OUTSIDE:
+ case POS_EQUAL:
+ {
+ rArr.Remove( rPos-- );
+ bDelRedl = sal_True;
+ if( bCallDelete )
+ {
+ pDelStt = pRedl->Start();
+ pDelEnd = pRedl->End();
+ }
+ }
+ break;
+ default:
+ bRet = sal_False;
+ }
+
+ if( pDelStt && pDelEnd )
+ {
+ SwPaM aPam( *pDelStt, *pDelEnd );
+ SwCntntNode* pCSttNd = pDelStt->nNode.GetNode().GetCntntNode();
+ SwCntntNode* pCEndNd = pDelEnd->nNode.GetNode().GetCntntNode();
+
+ if( bDelRedl )
+ delete pRedl;
+
+ RedlineMode_t eOld = rDoc.GetRedlineMode();
+ rDoc.SetRedlineMode_intern( (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)));
+
+ if( pCSttNd && pCEndNd )
+ rDoc.DeleteAndJoin( aPam );
+ else
+ {
+ rDoc.DeleteRange( aPam );
+
+ if( pCSttNd && !pCEndNd )
+ {
+ aPam.GetBound( sal_True ).nContent.Assign( 0, 0 );
+ aPam.GetBound( sal_False ).nContent.Assign( 0, 0 );
+ aPam.DeleteMark();
+ rDoc.DelFullPara( aPam );
+ }
+ }
+ rDoc.SetRedlineMode_intern( eOld );
+ }
+ else if( bDelRedl )
+ delete pRedl;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_FMTCOLL:
+ rArr.DeleteAndDestroy( rPos-- );
+ break;
+
+ default:
+ bRet = sal_False;
+ }
+ return bRet;
+}
+
+sal_Bool lcl_RejectRedline( SwRedlineTbl& rArr, sal_uInt16& rPos,
+ sal_Bool bCallDelete,
+ const SwPosition* pSttRng = 0,
+ const SwPosition* pEndRng = 0 )
+{
+ sal_Bool bRet = sal_True;
+ SwRedline* pRedl = rArr[ rPos ];
+ SwPosition *pRStt = 0, *pREnd = 0;
+ SwComparePosition eCmp = POS_OUTSIDE;
+ if( pSttRng && pEndRng )
+ {
+ pRStt = pRedl->Start();
+ pREnd = pRedl->End();
+ eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd );
+ }
+
+ pRedl->InvalidateRange();
+
+ switch( pRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ {
+ SwDoc& rDoc = *pRedl->GetDoc();
+ const SwPosition *pDelStt = 0, *pDelEnd = 0;
+ sal_Bool bDelRedl = sal_False;
+ switch( eCmp )
+ {
+ case POS_INSIDE:
+ if( bCallDelete )
+ {
+ pDelStt = pSttRng;
+ pDelEnd = pEndRng;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ if( bCallDelete )
+ {
+ pDelStt = pRStt;
+ pDelEnd = pEndRng;
+ }
+ break;
+ case POS_OVERLAP_BEHIND:
+ if( bCallDelete )
+ {
+ pDelStt = pREnd;
+ pDelEnd = pSttRng;
+ }
+ break;
+ case POS_OUTSIDE:
+ case POS_EQUAL:
+ {
+ // dann den Bereich wieder loeschen
+ rArr.Remove( rPos-- );
+ bDelRedl = sal_True;
+ if( bCallDelete )
+ {
+ pDelStt = pRedl->Start();
+ pDelEnd = pRedl->End();
+ }
+ }
+ break;
+
+ default:
+ bRet = sal_False;
+ }
+ if( pDelStt && pDelEnd )
+ {
+ SwPaM aPam( *pDelStt, *pDelEnd );
+
+ SwCntntNode* pCSttNd = pDelStt->nNode.GetNode().GetCntntNode();
+ SwCntntNode* pCEndNd = pDelEnd->nNode.GetNode().GetCntntNode();
+
+ if( bDelRedl )
+ delete pRedl;
+
+ RedlineMode_t eOld = rDoc.GetRedlineMode();
+ rDoc.SetRedlineMode_intern( (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)));
+
+ if( pCSttNd && pCEndNd )
+ rDoc.DeleteAndJoin( aPam );
+ else
+ {
+ rDoc.DeleteRange( aPam );
+
+ if( pCSttNd && !pCEndNd )
+ {
+ aPam.GetBound( sal_True ).nContent.Assign( 0, 0 );
+ aPam.GetBound( sal_False ).nContent.Assign( 0, 0 );
+ aPam.DeleteMark();
+ rDoc.DelFullPara( aPam );
+ }
+ }
+ rDoc.SetRedlineMode_intern( eOld );
+ }
+ else if( bDelRedl )
+ delete pRedl;
+ }
+ break;
+ case nsRedlineType_t::REDLINE_DELETE:
+ {
+ SwRedline* pNew = 0;
+ sal_Bool bCheck = sal_False, bReplace = sal_False;
+
+ switch( eCmp )
+ {
+ case POS_INSIDE:
+ {
+ if( 1 < pRedl->GetStackCount() )
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->PopData();
+ }
+ if( *pSttRng == *pRStt )
+ {
+ pRedl->SetStart( *pEndRng, pRStt );
+ bReplace = sal_True;
+ if( pNew )
+ pNew->SetEnd( *pEndRng );
+ }
+ else
+ {
+ if( *pEndRng != *pREnd )
+ {
+ // aufsplitten
+ SwRedline* pCpy = new SwRedline( *pRedl );
+ pCpy->SetStart( *pEndRng );
+ rArr.Insert( pCpy ); ++rPos;
+ if( pNew )
+ pNew->SetEnd( *pEndRng );
+ }
+
+ pRedl->SetEnd( *pSttRng, pREnd );
+ bCheck = sal_True;
+ if( pNew )
+ pNew->SetStart( *pSttRng );
+ }
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ if( 1 < pRedl->GetStackCount() )
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->PopData();
+ }
+ pRedl->SetStart( *pEndRng, pRStt );
+ bReplace = sal_True;
+ if( pNew )
+ pNew->SetEnd( *pEndRng );
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ if( 1 < pRedl->GetStackCount() )
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->PopData();
+ }
+ pRedl->SetEnd( *pSttRng, pREnd );
+ bCheck = sal_True;
+ if( pNew )
+ pNew->SetStart( *pSttRng );
+ break;
+
+ case POS_OUTSIDE:
+ case POS_EQUAL:
+ if( !pRedl->PopData() )
+ // das RedlineObject loeschen reicht
+ rArr.DeleteAndDestroy( rPos-- );
+ break;
+
+ default:
+ bRet = sal_False;
+ }
+
+ if( pNew )
+ {
+ rArr.Insert( pNew ); ++rPos;
+ }
+
+ if( bReplace || ( bCheck && !pRedl->HasValidRange() ))
+ {
+ // neu einsortieren
+ rArr.Remove( rArr.GetPos( pRedl ));
+ rArr.Insert( pRedl );
+ }
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT:
+ case nsRedlineType_t::REDLINE_FMTCOLL:
+ {
+ if( pRedl->GetExtraData() )
+ pRedl->GetExtraData()->Reject( *pRedl );
+ rArr.DeleteAndDestroy( rPos-- );
+ }
+ break;
+
+ default:
+ bRet = sal_False;
+ }
+ return bRet;
+}
+
+
+const SwRedline* lcl_FindCurrRedline( const SwPosition& rSttPos,
+ sal_uInt16& rPos,
+ sal_Bool bNext = sal_True )
+{
+ const SwRedline* pFnd = 0;
+ const SwRedlineTbl& rArr = rSttPos.nNode.GetNode().GetDoc()->GetRedlineTbl();
+ for( ; rPos < rArr.Count() ; ++rPos )
+ {
+ const SwRedline* pTmp = rArr[ rPos ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ const SwPosition* pRStt = pTmp->Start(),
+ * pREnd = pRStt == pTmp->GetPoint() ? pTmp->GetMark()
+ : pTmp->GetPoint();
+ if( bNext ? *pRStt <= rSttPos : *pRStt < rSttPos )
+ {
+ if( bNext ? *pREnd > rSttPos : *pREnd >= rSttPos )
+ {
+ pFnd = pTmp;
+ break;
+ }
+ }
+ else
+ break;
+ }
+ }
+ return pFnd;
+}
+
+// #111827#
+int lcl_AcceptRejectRedl( Fn_AcceptReject fn_AcceptReject,
+ SwRedlineTbl& rArr, sal_Bool bCallDelete,
+ const SwPaM& rPam)
+{
+ sal_uInt16 n = 0;
+ int nCount = 0; // #111827#
+
+ const SwPosition* pStt = rPam.Start(),
+ * pEnd = pStt == rPam.GetPoint() ? rPam.GetMark()
+ : rPam.GetPoint();
+ const SwRedline* pFnd = lcl_FindCurrRedline( *pStt, n, sal_True );
+ if( pFnd && // neu ein Teil davon?
+ ( *pFnd->Start() != *pStt || *pFnd->End() > *pEnd ))
+ {
+ // dann nur die TeilSelektion aufheben
+ if( (*fn_AcceptReject)( rArr, n, bCallDelete, pStt, pEnd ))
+ nCount++; // #111827#
+ ++n;
+ }
+
+ for( ; n < rArr.Count(); ++n )
+ {
+ SwRedline* pTmp = rArr[ n ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ if( *pTmp->End() <= *pEnd )
+ {
+ if( (*fn_AcceptReject)( rArr, n, bCallDelete, 0, 0 ))
+ nCount++; // #111827#
+ }
+ else
+ {
+ if( *pTmp->Start() < *pEnd )
+ {
+ // dann nur in der TeilSelektion aufheben
+ if( (*fn_AcceptReject)( rArr, n, bCallDelete, pStt, pEnd ))
+ nCount++; // #111827#
+ }
+ break;
+ }
+ }
+ }
+ return nCount; // #111827#
+}
+
+void lcl_AdjustRedlineRange( SwPaM& rPam )
+{
+ // die Selektion steht nur im ContentBereich. Wenn es aber Redlines
+ // davor oder dahinter auf nicht ContentNodes stehen, dann erweiter die
+ // die Selection auf diese
+ SwPosition* pStt = rPam.Start(),
+ * pEnd = pStt == rPam.GetPoint() ? rPam.GetMark()
+ : rPam.GetPoint();
+ SwDoc* pDoc = rPam.GetDoc();
+ if( !pStt->nContent.GetIndex() &&
+ !pDoc->GetNodes()[ pStt->nNode.GetIndex() - 1 ]->IsCntntNode() )
+ {
+ const SwRedline* pRedl = pDoc->GetRedline( *pStt, 0 );
+ if( pRedl )
+ {
+ const SwPosition* pRStt = pRedl->Start();
+ if( !pRStt->nContent.GetIndex() && pRStt->nNode.GetIndex() ==
+ pStt->nNode.GetIndex() - 1 )
+ *pStt = *pRStt;
+ }
+ }
+ if( pEnd->nNode.GetNode().IsCntntNode() &&
+ !pDoc->GetNodes()[ pEnd->nNode.GetIndex() + 1 ]->IsCntntNode() &&
+ pEnd->nContent.GetIndex() == pEnd->nNode.GetNode().GetCntntNode()->Len() )
+ {
+ const SwRedline* pRedl = pDoc->GetRedline( *pEnd, 0 );
+ if( pRedl )
+ {
+ const SwPosition* pREnd = pRedl->End();
+ if( !pREnd->nContent.GetIndex() && pREnd->nNode.GetIndex() ==
+ pEnd->nNode.GetIndex() + 1 )
+ *pEnd = *pREnd;
+ }
+ }
+}
+
+
+bool SwDoc::AcceptRedline( sal_uInt16 nPos, bool bCallDelete )
+{
+ sal_Bool bRet = sal_False;
+
+ // aufjedenfall auf sichtbar umschalten
+ if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
+ (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) )
+ SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode));
+
+ SwRedline* pTmp = (*pRedlineTbl)[ nPos ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // #111827#
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UNDO_ARG1, pTmp->GetDescr());
+ GetIDocumentUndoRedo().StartUndo(UNDO_ACCEPT_REDLINE, &aRewriter);
+ }
+
+ int nLoopCnt = 2;
+ sal_uInt16 nSeqNo = pTmp->GetSeqNo();
+
+ do {
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo( new SwUndoAcceptRedline(*pTmp) );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ bRet |= lcl_AcceptRedline( *pRedlineTbl, nPos, bCallDelete );
+
+ if( nSeqNo )
+ {
+ if( USHRT_MAX == nPos )
+ nPos = 0;
+ sal_uInt16 nFndPos = 2 == nLoopCnt
+ ? pRedlineTbl->FindNextSeqNo( nSeqNo, nPos )
+ : pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos );
+ if( USHRT_MAX != nFndPos || ( 0 != ( --nLoopCnt ) &&
+ USHRT_MAX != ( nFndPos =
+ pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ))) )
+ pTmp = (*pRedlineTbl)[ nPos = nFndPos ];
+ else
+ nLoopCnt = 0;
+ }
+ else
+ nLoopCnt = 0;
+
+ } while( nLoopCnt );
+
+ if( bRet )
+ {
+ CompressRedlines();
+ SetModified();
+ }
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().EndUndo(UNDO_END, 0);
+ }
+ }
+ return bRet;
+}
+
+bool SwDoc::AcceptRedline( const SwPaM& rPam, bool bCallDelete )
+{
+ // aufjedenfall auf sichtbar umschalten
+ if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
+ (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) )
+ SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode));
+
+ // die Selektion steht nur im ContentBereich. Wenn es aber Redlines
+ // davor oder dahinter auf nicht ContentNodes stehen, dann erweiter die
+ // die Selection auf diese
+ SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
+ lcl_AdjustRedlineRange( aPam );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_ACCEPT_REDLINE, NULL );
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoAcceptRedline( aPam ));
+ }
+
+ // #111827#
+ int nRet = lcl_AcceptRejectRedl( lcl_AcceptRedline, *pRedlineTbl,
+ bCallDelete, aPam );
+ if( nRet > 0 )
+ {
+ CompressRedlines();
+ SetModified();
+ }
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // #111827#
+ String aTmpStr;
+
+ {
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, String::CreateFromInt32(nRet));
+ aTmpStr = aRewriter.Apply(String(SW_RES(STR_N_REDLINES)));
+ }
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, aTmpStr);
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_ACCEPT_REDLINE, &aRewriter );
+ }
+ return nRet != 0;
+}
+
+bool SwDoc::RejectRedline( sal_uInt16 nPos, bool bCallDelete )
+{
+ sal_Bool bRet = sal_False;
+
+ // aufjedenfall auf sichtbar umschalten
+ if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
+ (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) )
+ SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode));
+
+ SwRedline* pTmp = (*pRedlineTbl)[ nPos ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // #111827#
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UNDO_ARG1, pTmp->GetDescr());
+ GetIDocumentUndoRedo().StartUndo(UNDO_REJECT_REDLINE, &aRewriter);
+ }
+
+ int nLoopCnt = 2;
+ sal_uInt16 nSeqNo = pTmp->GetSeqNo();
+
+ do {
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo( new SwUndoRejectRedline( *pTmp ) );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ bRet |= lcl_RejectRedline( *pRedlineTbl, nPos, bCallDelete );
+
+ if( nSeqNo )
+ {
+ if( USHRT_MAX == nPos )
+ nPos = 0;
+ sal_uInt16 nFndPos = 2 == nLoopCnt
+ ? pRedlineTbl->FindNextSeqNo( nSeqNo, nPos )
+ : pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos );
+ if( USHRT_MAX != nFndPos || ( 0 != ( --nLoopCnt ) &&
+ USHRT_MAX != ( nFndPos =
+ pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ))) )
+ pTmp = (*pRedlineTbl)[ nPos = nFndPos ];
+ else
+ nLoopCnt = 0;
+ }
+ else
+ nLoopCnt = 0;
+
+ } while( nLoopCnt );
+
+ if( bRet )
+ {
+ CompressRedlines();
+ SetModified();
+ }
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().EndUndo(UNDO_END, 0);
+ }
+ }
+ return bRet;
+}
+
+bool SwDoc::RejectRedline( const SwPaM& rPam, bool bCallDelete )
+{
+ // aufjedenfall auf sichtbar umschalten
+ if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
+ (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) )
+ SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode));
+
+ // die Selektion steht nur im ContentBereich. Wenn es aber Redlines
+ // davor oder dahinter auf nicht ContentNodes stehen, dann erweiter die
+ // die Selection auf diese
+ SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
+ lcl_AdjustRedlineRange( aPam );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_REJECT_REDLINE, NULL );
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoRejectRedline(aPam) );
+ }
+
+ // #111827#
+ int nRet = lcl_AcceptRejectRedl( lcl_RejectRedline, *pRedlineTbl,
+ bCallDelete, aPam );
+ if( nRet > 0 )
+ {
+ CompressRedlines();
+ SetModified();
+ }
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // #111827#
+ String aTmpStr;
+
+ {
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, String::CreateFromInt32(nRet));
+ aTmpStr = aRewriter.Apply(String(SW_RES(STR_N_REDLINES)));
+ }
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, aTmpStr);
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_REJECT_REDLINE, &aRewriter );
+ }
+
+ return nRet != 0;
+}
+
+const SwRedline* SwDoc::SelNextRedline( SwPaM& rPam ) const
+{
+ rPam.DeleteMark();
+ rPam.SetMark();
+
+ SwPosition& rSttPos = *rPam.GetPoint();
+ SwPosition aSavePos( rSttPos );
+ sal_Bool bRestart;
+
+ // sollte die StartPos auf dem letzen gueligen ContentNode stehen,
+ // dann aufjedenfall das naechste Redline nehmen
+ sal_uInt16 n = 0;
+ const SwRedline* pFnd = lcl_FindCurrRedline( rSttPos, n, sal_True );
+ if( pFnd )
+ {
+ const SwPosition* pEnd = pFnd->End();
+ if( !pEnd->nNode.GetNode().IsCntntNode() )
+ {
+ SwNodeIndex aTmp( pEnd->nNode );
+ SwCntntNode* pCNd = GetNodes().GoPrevSection( &aTmp );
+ if( !pCNd || ( aTmp == rSttPos.nNode &&
+ pCNd->Len() == rSttPos.nContent.GetIndex() ))
+ pFnd = 0;
+ }
+ if( pFnd )
+ rSttPos = *pFnd->End();
+ }
+
+ do {
+ bRestart = sal_False;
+
+ for( ; !pFnd && n < pRedlineTbl->Count(); ++n )
+ {
+ pFnd = (*pRedlineTbl)[ n ];
+ if( pFnd->HasMark() && pFnd->IsVisible() )
+ {
+ *rPam.GetMark() = *pFnd->Start();
+ rSttPos = *pFnd->End();
+ break;
+ }
+ else
+ pFnd = 0;
+ }
+
+ if( pFnd )
+ {
+ // alle vom gleichen Typ und Author, die hinter einander liegen
+ // zu einer Selektion zusammenfassen.
+ const SwPosition* pPrevEnd = pFnd->End();
+ while( ++n < pRedlineTbl->Count() )
+ {
+ const SwRedline* pTmp = (*pRedlineTbl)[ n ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ const SwPosition *pRStt;
+ if( pFnd->GetType() == pTmp->GetType() &&
+ pFnd->GetAuthor() == pTmp->GetAuthor() &&
+ ( *pPrevEnd == *( pRStt = pTmp->Start() ) ||
+ IsPrevPos( *pPrevEnd, *pRStt )) )
+ {
+ pPrevEnd = pTmp->End();
+ rSttPos = *pPrevEnd;
+ }
+ else
+ break;
+ }
+ }
+ }
+
+ if( pFnd )
+ {
+ const SwRedline* pSaveFnd = pFnd;
+
+ SwCntntNode* pCNd;
+ SwNodeIndex* pIdx = &rPam.GetMark()->nNode;
+ if( !pIdx->GetNode().IsCntntNode() &&
+ 0 != ( pCNd = GetNodes().GoNextSection( pIdx )) )
+ {
+ if( *pIdx <= rPam.GetPoint()->nNode )
+ rPam.GetMark()->nContent.Assign( pCNd, 0 );
+ else
+ pFnd = 0;
+ }
+
+ if( pFnd )
+ {
+ pIdx = &rPam.GetPoint()->nNode;
+ if( !pIdx->GetNode().IsCntntNode() &&
+ 0 != ( pCNd = GetNodes().GoPrevSection( pIdx )) )
+ {
+ if( *pIdx >= rPam.GetMark()->nNode )
+ rPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+ else
+ pFnd = 0;
+ }
+ }
+
+ if( !pFnd || *rPam.GetMark() == *rPam.GetPoint() )
+ {
+ if( n < pRedlineTbl->Count() )
+ {
+ bRestart = sal_True;
+ *rPam.GetPoint() = *pSaveFnd->End();
+ }
+ else
+ {
+ rPam.DeleteMark();
+ *rPam.GetPoint() = aSavePos;
+ }
+ pFnd = 0;
+ }
+ }
+ } while( bRestart );
+
+ return pFnd;
+}
+
+const SwRedline* SwDoc::SelPrevRedline( SwPaM& rPam ) const
+{
+ rPam.DeleteMark();
+ rPam.SetMark();
+
+ SwPosition& rSttPos = *rPam.GetPoint();
+ SwPosition aSavePos( rSttPos );
+ sal_Bool bRestart;
+
+ // sollte die StartPos auf dem ersten gueligen ContentNode stehen,
+ // dann aufjedenfall das vorherige Redline nehmen
+ sal_uInt16 n = 0;
+ const SwRedline* pFnd = lcl_FindCurrRedline( rSttPos, n, sal_False );
+ if( pFnd )
+ {
+ const SwPosition* pStt = pFnd->Start();
+ if( !pStt->nNode.GetNode().IsCntntNode() )
+ {
+ SwNodeIndex aTmp( pStt->nNode );
+ SwCntntNode* pCNd = GetNodes().GoNextSection( &aTmp );
+ if( !pCNd || ( aTmp == rSttPos.nNode &&
+ !rSttPos.nContent.GetIndex() ))
+ pFnd = 0;
+ }
+ if( pFnd )
+ rSttPos = *pFnd->Start();
+ }
+
+ do {
+ bRestart = sal_False;
+
+ while( !pFnd && 0 < n )
+ {
+ pFnd = (*pRedlineTbl)[ --n ];
+ if( pFnd->HasMark() && pFnd->IsVisible() )
+ {
+ *rPam.GetMark() = *pFnd->End();
+ rSttPos = *pFnd->Start();
+ }
+ else
+ pFnd = 0;
+ }
+
+ if( pFnd )
+ {
+ // alle vom gleichen Typ und Author, die hinter einander liegen
+ // zu einer Selektion zusammenfassen.
+ const SwPosition* pNextStt = pFnd->Start();
+ while( 0 < n )
+ {
+ const SwRedline* pTmp = (*pRedlineTbl)[ --n ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ const SwPosition *pREnd;
+ if( pFnd->GetType() == pTmp->GetType() &&
+ pFnd->GetAuthor() == pTmp->GetAuthor() &&
+ ( *pNextStt == *( pREnd = pTmp->End() ) ||
+ IsPrevPos( *pREnd, *pNextStt )) )
+ {
+ pNextStt = pTmp->Start();
+ rSttPos = *pNextStt;
+ }
+ else
+ {
+ ++n;
+ break;
+ }
+ }
+ }
+ }
+
+ if( pFnd )
+ {
+ const SwRedline* pSaveFnd = pFnd;
+
+ SwCntntNode* pCNd;
+ SwNodeIndex* pIdx = &rPam.GetMark()->nNode;
+ if( !pIdx->GetNode().IsCntntNode() &&
+ 0 != ( pCNd = GetNodes().GoPrevSection( pIdx )) )
+ {
+ if( *pIdx >= rPam.GetPoint()->nNode )
+ rPam.GetMark()->nContent.Assign( pCNd, pCNd->Len() );
+ else
+ pFnd = 0;
+ }
+
+ if( pFnd )
+ {
+ pIdx = &rPam.GetPoint()->nNode;
+ if( !pIdx->GetNode().IsCntntNode() &&
+ 0 != ( pCNd = GetNodes().GoNextSection( pIdx )) )
+ {
+ if( *pIdx <= rPam.GetMark()->nNode )
+ rPam.GetPoint()->nContent.Assign( pCNd, 0 );
+ else
+ pFnd = 0;
+ }
+ }
+
+ if( !pFnd || *rPam.GetMark() == *rPam.GetPoint() )
+ {
+ if( n )
+ {
+ bRestart = sal_True;
+ *rPam.GetPoint() = *pSaveFnd->Start();
+ }
+ else
+ {
+ rPam.DeleteMark();
+ *rPam.GetPoint() = aSavePos;
+ }
+ pFnd = 0;
+ }
+ }
+ } while( bRestart );
+
+ return pFnd;
+}
+
+// Kommentar am Redline setzen
+bool SwDoc::SetRedlineComment( const SwPaM& rPaM, const String& rS )
+{
+ sal_Bool bRet = sal_False;
+ const SwPosition* pStt = rPaM.Start(),
+ * pEnd = pStt == rPaM.GetPoint() ? rPaM.GetMark()
+ : rPaM.GetPoint();
+ sal_uInt16 n = 0;
+ if( lcl_FindCurrRedline( *pStt, n, sal_True ) )
+ {
+ for( ; n < pRedlineTbl->Count(); ++n )
+ {
+ bRet = sal_True;
+ SwRedline* pTmp = (*pRedlineTbl)[ n ];
+ if( pStt != pEnd && *pTmp->Start() > *pEnd )
+ break;
+
+ pTmp->SetComment( rS );
+ if( *pTmp->End() >= *pEnd )
+ break;
+ }
+ }
+ if( bRet )
+ SetModified();
+
+ return bRet;
+}
+
+// legt gebenenfalls einen neuen Author an
+sal_uInt16 SwDoc::GetRedlineAuthor()
+{
+ return SW_MOD()->GetRedlineAuthor();
+}
+
+ // fuer die Reader usw. - neuen Author in die Tabelle eintragen
+sal_uInt16 SwDoc::InsertRedlineAuthor( const String& rNew )
+{
+ return SW_MOD()->InsertRedlineAuthor(rNew);
+}
+
+void SwDoc::UpdateRedlineAttr()
+{
+ const SwRedlineTbl& rTbl = GetRedlineTbl();
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ SwRedline* pRedl = rTbl[ n ];
+ if( pRedl->IsVisible() )
+ pRedl->InvalidateRange();
+ }
+}
+
+ // setze Kommentar-Text fuers Redline, das dann per AppendRedline
+ // hereinkommt. Wird vom Autoformat benutzt. 0-Pointer setzt den Modus
+ // wieder zurueck. Pointer wird nicht kopiert, muss also gueltig bleiben!
+void SwDoc::SetAutoFmtRedlineComment( const String* pTxt, sal_uInt16 nSeqNo )
+{
+ mbIsAutoFmtRedline = 0 != pTxt;
+ if( pTxt )
+ {
+ if( !pAutoFmtRedlnComment )
+ pAutoFmtRedlnComment = new String( *pTxt );
+ else
+ *pAutoFmtRedlnComment = *pTxt;
+ }
+ else if( pAutoFmtRedlnComment )
+ delete pAutoFmtRedlnComment, pAutoFmtRedlnComment = 0;
+
+ nAutoFmtRedlnCommentNo = nSeqNo;
+}
+
+void SwDoc::SetRedlinePassword(
+ /*[in]*/const uno::Sequence <sal_Int8>& rNewPassword)
+{
+ aRedlinePasswd = rNewPassword;
+ SetModified();
+}
+
+/* */
+
+sal_Bool SwRedlineTbl::Insert( SwRedlinePtr& p, sal_Bool bIns )
+{
+ sal_Bool bRet = sal_False;
+ if( p->HasValidRange() )
+ {
+ bRet = _SwRedlineTbl::Insert( p );
+ p->CallDisplayFunc();
+ }
+ else if( bIns )
+ bRet = InsertWithValidRanges( p );
+ else
+ {
+ ASSERT( !this, "Redline: falscher Bereich" );
+ }
+ return bRet;
+}
+
+sal_Bool SwRedlineTbl::Insert( SwRedlinePtr& p, sal_uInt16& rP, sal_Bool bIns )
+{
+ sal_Bool bRet = sal_False;
+ if( p->HasValidRange() )
+ {
+ bRet = _SwRedlineTbl::Insert( p, rP );
+ p->CallDisplayFunc();
+ }
+ else if( bIns )
+ bRet = InsertWithValidRanges( p, &rP );
+ else
+ {
+ ASSERT( !this, "Redline: falscher Bereich" );
+ }
+ return bRet;
+}
+
+sal_Bool SwRedlineTbl::InsertWithValidRanges( SwRedlinePtr& p, sal_uInt16* pInsPos )
+{
+ // erzeuge aus den Selektion gueltige "Teilbereiche".
+ sal_Bool bAnyIns = sal_False;
+ SwPosition* pStt = p->Start(),
+ * pEnd = pStt == p->GetPoint() ? p->GetMark() : p->GetPoint();
+ SwPosition aNewStt( *pStt );
+ SwNodes& rNds = aNewStt.nNode.GetNodes();
+ SwCntntNode* pC;
+
+ if( !aNewStt.nNode.GetNode().IsCntntNode() )
+ {
+ pC = rNds.GoNext( &aNewStt.nNode );
+ if( pC )
+ aNewStt.nContent.Assign( pC, 0 );
+ else
+ aNewStt.nNode = rNds.GetEndOfContent();
+ }
+
+ SwRedline* pNew = 0;
+ sal_uInt16 nInsPos;
+
+ if( aNewStt < *pEnd )
+ do {
+ if( !pNew )
+ pNew = new SwRedline( p->GetRedlineData(), aNewStt );
+ else
+ {
+ pNew->DeleteMark();
+ *pNew->GetPoint() = aNewStt;
+ }
+
+ pNew->SetMark();
+ GoEndSection( pNew->GetPoint() );
+ // i60396: If the redlines starts before a table but the table is the last member
+ // of the section, the GoEndSection will end inside the table.
+ // This will result in an incorrect redline, so we've to go back
+ SwNode* pTab = pNew->GetPoint()->nNode.GetNode().StartOfSectionNode()->FindTableNode();
+ // We end in a table when pTab != 0
+ if( pTab && !pNew->GetMark()->nNode.GetNode().StartOfSectionNode()->FindTableNode() )
+ { // but our Mark was outside the table => Correction
+ do
+ {
+ // We want to be before the table
+ *pNew->GetPoint() = SwPosition(*pTab);
+ pC = GoPreviousNds( &pNew->GetPoint()->nNode, sal_False ); // here we are.
+ if( pC )
+ pNew->GetPoint()->nContent.Assign( pC, 0 );
+ pTab = pNew->GetPoint()->nNode.GetNode().StartOfSectionNode()->FindTableNode();
+ }while( pTab ); // If there is another table we have to repeat our step backwards
+ }
+
+ if( *pNew->GetPoint() > *pEnd )
+ {
+ pC = 0;
+ if( aNewStt.nNode != pEnd->nNode )
+ do {
+ SwNode& rCurNd = aNewStt.nNode.GetNode();
+ if( rCurNd.IsStartNode() )
+ {
+ if( rCurNd.EndOfSectionIndex() < pEnd->nNode.GetIndex() )
+ aNewStt.nNode = *rCurNd.EndOfSectionNode();
+ else
+ break;
+ }
+ else if( rCurNd.IsCntntNode() )
+ pC = rCurNd.GetCntntNode();
+ aNewStt.nNode++;
+ } while( aNewStt.nNode.GetIndex() < pEnd->nNode.GetIndex() );
+
+ if( aNewStt.nNode == pEnd->nNode )
+ aNewStt.nContent = pEnd->nContent;
+ else if( pC )
+ {
+ aNewStt.nNode = *pC;
+ aNewStt.nContent.Assign( pC, pC->Len() );
+ }
+
+ if( aNewStt <= *pEnd )
+ *pNew->GetPoint() = aNewStt;
+ }
+ else
+ aNewStt = *pNew->GetPoint();
+#ifdef DEBUG
+ CheckPosition( pNew->GetPoint(), pNew->GetMark() );
+#endif
+ if( *pNew->GetPoint() != *pNew->GetMark() &&
+ _SwRedlineTbl::Insert( pNew, nInsPos ) )
+ {
+ pNew->CallDisplayFunc();
+ bAnyIns = sal_True;
+ pNew = 0;
+ if( pInsPos && *pInsPos < nInsPos )
+ *pInsPos = nInsPos;
+ }
+
+ if( aNewStt >= *pEnd ||
+ 0 == (pC = rNds.GoNext( &aNewStt.nNode )) )
+ break;
+
+ aNewStt.nContent.Assign( pC, 0 );
+
+ } while( aNewStt < *pEnd );
+
+ delete pNew;
+ delete p, p = 0;
+ return bAnyIns;
+}
+
+void SwRedlineTbl::Remove( sal_uInt16 nP, sal_uInt16 nL )
+{
+ SwDoc* pDoc = 0;
+ if( !nP && nL && nL == _SwRedlineTbl::Count() )
+ pDoc = _SwRedlineTbl::GetObject( 0 )->GetDoc();
+
+ _SwRedlineTbl::Remove( nP, nL );
+
+ ViewShell* pSh;
+ if( pDoc && !pDoc->IsInDtor() && pDoc->GetRootFrm() &&
+ 0 != ( pSh = pDoc->GetRootFrm()->GetCurrShell()) )
+ pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
+}
+
+void SwRedlineTbl::DeleteAndDestroy( sal_uInt16 nP, sal_uInt16 nL )
+{
+ SwDoc* pDoc = 0;
+ if( !nP && nL && nL == _SwRedlineTbl::Count() )
+ pDoc = _SwRedlineTbl::GetObject( 0 )->GetDoc();
+
+ _SwRedlineTbl::DeleteAndDestroy( nP, nL );
+
+ ViewShell* pSh;
+ if( pDoc && !pDoc->IsInDtor() && pDoc->GetRootFrm() &&
+ 0 != ( pSh = pDoc->GetRootFrm()->GetCurrShell()) )
+ pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
+}
+
+// suche den naechsten oder vorherigen Redline mit dergleichen Seq.No
+// Mit dem Lookahead kann die Suche eingeschraenkt werden. 0 oder
+// USHRT_MAX suchen im gesamten Array.
+sal_uInt16 SwRedlineTbl::FindNextOfSeqNo( sal_uInt16 nSttPos, sal_uInt16 nLookahead ) const
+{
+ return nSttPos + 1 < _SwRedlineTbl::Count()
+ ? FindNextSeqNo( _SwRedlineTbl::GetObject( nSttPos )
+ ->GetSeqNo(), nSttPos+1, nLookahead )
+ : USHRT_MAX;
+}
+
+sal_uInt16 SwRedlineTbl::FindPrevOfSeqNo( sal_uInt16 nSttPos, sal_uInt16 nLookahead ) const
+{
+ return nSttPos ? FindPrevSeqNo( _SwRedlineTbl::GetObject(
+ nSttPos )->GetSeqNo(),
+ nSttPos-1, nLookahead )
+ : USHRT_MAX;
+}
+
+sal_uInt16 SwRedlineTbl::FindNextSeqNo( sal_uInt16 nSeqNo, sal_uInt16 nSttPos,
+ sal_uInt16 nLookahead ) const
+{
+ sal_uInt16 nRet = USHRT_MAX, nEnd;
+ if( nSeqNo && nSttPos < _SwRedlineTbl::Count() )
+ {
+ nEnd = _SwRedlineTbl::Count();
+ if( nLookahead && USHRT_MAX != nLookahead &&
+ nSttPos + nLookahead < _SwRedlineTbl::Count() )
+ nEnd = nSttPos + nLookahead;
+
+ for( ; nSttPos < nEnd; ++nSttPos )
+ if( nSeqNo == _SwRedlineTbl::GetObject( nSttPos )->GetSeqNo() )
+ {
+ nRet = nSttPos;
+ break;
+ }
+ }
+ return nRet;
+}
+
+sal_uInt16 SwRedlineTbl::FindPrevSeqNo( sal_uInt16 nSeqNo, sal_uInt16 nSttPos,
+ sal_uInt16 nLookahead ) const
+{
+ sal_uInt16 nRet = USHRT_MAX, nEnd;
+ if( nSeqNo && nSttPos < _SwRedlineTbl::Count() )
+ {
+ nEnd = 0;
+ if( nLookahead && USHRT_MAX != nLookahead && nSttPos > nLookahead )
+ nEnd = nSttPos - nLookahead;
+
+ ++nSttPos;
+ while( nSttPos > nEnd )
+ if( nSeqNo == _SwRedlineTbl::GetObject( --nSttPos )->GetSeqNo() )
+ {
+ nRet = nSttPos;
+ break;
+ }
+ }
+ return nRet;
+}
+
+/* */
+
+SwRedlineExtraData::~SwRedlineExtraData()
+{
+}
+
+void SwRedlineExtraData::Accept( SwPaM& ) const
+{
+}
+
+void SwRedlineExtraData::Reject( SwPaM& ) const
+{
+}
+
+int SwRedlineExtraData::operator == ( const SwRedlineExtraData& ) const
+{
+ return sal_False;
+}
+
+
+SwRedlineExtraData_FmtColl::SwRedlineExtraData_FmtColl( const String& rColl,
+ sal_uInt16 nPoolFmtId,
+ const SfxItemSet* pItemSet )
+ : sFmtNm(rColl), pSet(0), nPoolId(nPoolFmtId)
+{
+ if( pItemSet && pItemSet->Count() )
+ pSet = new SfxItemSet( *pItemSet );
+}
+
+SwRedlineExtraData_FmtColl::~SwRedlineExtraData_FmtColl()
+{
+ delete pSet;
+}
+
+SwRedlineExtraData* SwRedlineExtraData_FmtColl::CreateNew() const
+{
+ return new SwRedlineExtraData_FmtColl( sFmtNm, nPoolId, pSet );
+}
+
+void SwRedlineExtraData_FmtColl::Reject( SwPaM& rPam ) const
+{
+ SwDoc* pDoc = rPam.GetDoc();
+
+// was ist mit Undo ? ist das abgeschaltet ??
+ SwTxtFmtColl* pColl = USHRT_MAX == nPoolId
+ ? pDoc->FindTxtFmtCollByName( sFmtNm )
+ : pDoc->GetTxtCollFromPool( nPoolId );
+ if( pColl )
+ pDoc->SetTxtFmtColl( rPam, pColl, false );
+
+ if( pSet )
+ {
+ rPam.SetMark();
+ SwPosition& rMark = *rPam.GetMark();
+ SwTxtNode* pTNd = rMark.nNode.GetNode().GetTxtNode();
+ if( pTNd )
+ {
+ rMark.nContent.Assign( pTNd, pTNd->GetTxt().Len() );
+
+ if( pTNd->HasSwAttrSet() )
+ {
+ // nur die setzen, die nicht mehr vorhanden sind. Andere
+ // koennen jetzt veraendert drin stehen, aber die werden
+ // nicht angefasst.
+ SfxItemSet aTmp( *pSet );
+ aTmp.Differentiate( *pTNd->GetpSwAttrSet() );
+ pDoc->InsertItemSet( rPam, aTmp, 0 );
+ }
+ else
+ {
+ pDoc->InsertItemSet( rPam, *pSet, 0 );
+ }
+ }
+ rPam.DeleteMark();
+ }
+}
+
+int SwRedlineExtraData_FmtColl::operator == ( const SwRedlineExtraData& r) const
+{
+ const SwRedlineExtraData_FmtColl& rCmp = (SwRedlineExtraData_FmtColl&)r;
+ return sFmtNm == rCmp.sFmtNm && nPoolId == rCmp.nPoolId &&
+ ( ( !pSet && !rCmp.pSet ) ||
+ ( pSet && rCmp.pSet && *pSet == *rCmp.pSet ) );
+}
+
+void SwRedlineExtraData_FmtColl::SetItemSet( const SfxItemSet& rSet )
+{
+ delete pSet;
+ if( rSet.Count() )
+ pSet = new SfxItemSet( rSet );
+ else
+ pSet = 0;
+}
+
+
+SwRedlineExtraData_Format::SwRedlineExtraData_Format( const SfxItemSet& rSet )
+{
+ SfxItemIter aIter( rSet );
+ const SfxPoolItem* pItem = aIter.FirstItem();
+ while( sal_True )
+ {
+ aWhichIds.Insert( pItem->Which(), aWhichIds.Count() );
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+}
+
+SwRedlineExtraData_Format::SwRedlineExtraData_Format(
+ const SwRedlineExtraData_Format& rCpy )
+ : SwRedlineExtraData(), aWhichIds( (sal_uInt8)rCpy.aWhichIds.Count() )
+{
+ aWhichIds.Insert( &rCpy.aWhichIds, 0 );
+}
+
+SwRedlineExtraData_Format::~SwRedlineExtraData_Format()
+{
+}
+
+SwRedlineExtraData* SwRedlineExtraData_Format::CreateNew() const
+{
+ return new SwRedlineExtraData_Format( *this );
+}
+
+void SwRedlineExtraData_Format::Reject( SwPaM& rPam ) const
+{
+ SwDoc* pDoc = rPam.GetDoc();
+
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)));
+
+ // eigentlich muesste hier das Attribut zurueck gesetzt werden!!!
+ for( sal_uInt16 n = 0, nEnd = aWhichIds.Count(); n < nEnd; ++n )
+ {
+ pDoc->InsertPoolItem( rPam, *GetDfltAttr( aWhichIds[ n ] ),
+ nsSetAttrMode::SETATTR_DONTEXPAND );
+ }
+
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+int SwRedlineExtraData_Format::operator == ( const SwRedlineExtraData& rCmp ) const
+{
+ int nRet = 1;
+ sal_uInt16 n = 0, nEnd = aWhichIds.Count();
+ if( nEnd != ((SwRedlineExtraData_Format&)rCmp).aWhichIds.Count() )
+ nRet = 0;
+ else
+ for( ; n < nEnd; ++n )
+ if( ((SwRedlineExtraData_Format&)rCmp).aWhichIds[n] != aWhichIds[n])
+ {
+ nRet = 0;
+ break;
+ }
+ return nRet;
+}
+
+/* */
+
+SwRedlineData::SwRedlineData( RedlineType_t eT, sal_uInt16 nAut )
+ : pNext( 0 ), pExtraData( 0 ), eType( eT ), nAuthor( nAut ), nSeqNo( 0 )
+{
+ aStamp.SetSec( 0 );
+ aStamp.Set100Sec( 0 );
+}
+
+SwRedlineData::SwRedlineData( const SwRedlineData& rCpy, sal_Bool bCpyNext )
+ :
+ pNext( (bCpyNext && rCpy.pNext) ? new SwRedlineData( *rCpy.pNext ) : 0 ),
+ pExtraData( rCpy.pExtraData ? rCpy.pExtraData->CreateNew() : 0 ),
+ sComment( rCpy.sComment ), aStamp( rCpy.aStamp ), eType( rCpy.eType ),
+ nAuthor( rCpy.nAuthor ), nSeqNo( rCpy.nSeqNo )
+{
+}
+
+ // fuer sw3io: pNext geht in eigenen Besitz ueber!
+SwRedlineData::SwRedlineData(RedlineType_t eT, sal_uInt16 nAut, const DateTime& rDT,
+ const String& rCmnt, SwRedlineData *pNxt, SwRedlineExtraData* pData)
+ : pNext(pNxt), pExtraData(pData), sComment(rCmnt), aStamp(rDT),
+ eType(eT), nAuthor(nAut), nSeqNo(0)
+{
+}
+
+SwRedlineData::~SwRedlineData()
+{
+ delete pExtraData;
+ delete pNext;
+}
+
+ // ExtraData wird kopiert, der Pointer geht also NICHT in den Besitz
+ // des RedlineObjectes!
+void SwRedlineData::SetExtraData( const SwRedlineExtraData* pData )
+{
+ delete pExtraData;
+
+ if( pData )
+ pExtraData = pData->CreateNew();
+ else
+ pExtraData = 0;
+}
+
+// #111827#
+String SwRedlineData::GetDescr() const
+{
+ String aResult;
+
+ aResult += String(SW_RES(STR_REDLINE_INSERT + GetType()));
+
+ return aResult;
+}
+
+/* */
+
+SwRedline::SwRedline(RedlineType_t eTyp, const SwPaM& rPam )
+ : SwPaM( *rPam.GetMark(), *rPam.GetPoint() ),
+ pRedlineData( new SwRedlineData( eTyp, GetDoc()->GetRedlineAuthor() ) ),
+ pCntntSect( 0 )
+{
+ bDelLastPara = bIsLastParaDelete = sal_False;
+ bIsVisible = sal_True;
+ if( !rPam.HasMark() )
+ DeleteMark();
+}
+
+SwRedline::SwRedline( const SwRedlineData& rData, const SwPaM& rPam )
+ : SwPaM( *rPam.GetMark(), *rPam.GetPoint() ),
+ pRedlineData( new SwRedlineData( rData )),
+ pCntntSect( 0 )
+{
+ bDelLastPara = bIsLastParaDelete = sal_False;
+ bIsVisible = sal_True;
+ if( !rPam.HasMark() )
+ DeleteMark();
+}
+
+SwRedline::SwRedline( const SwRedlineData& rData, const SwPosition& rPos )
+ : SwPaM( rPos ),
+ pRedlineData( new SwRedlineData( rData )),
+ pCntntSect( 0 )
+{
+ bDelLastPara = bIsLastParaDelete = sal_False;
+ bIsVisible = sal_True;
+}
+
+SwRedline::SwRedline( const SwRedline& rCpy )
+ : SwPaM( *rCpy.GetMark(), *rCpy.GetPoint() ),
+ pRedlineData( new SwRedlineData( *rCpy.pRedlineData )),
+ pCntntSect( 0 )
+{
+ bDelLastPara = bIsLastParaDelete = sal_False;
+ bIsVisible = sal_True;
+ if( !rCpy.HasMark() )
+ DeleteMark();
+}
+
+SwRedline::~SwRedline()
+{
+ if( pCntntSect )
+ {
+ // dann den Content Bereich loeschen
+ if( !GetDoc()->IsInDtor() )
+ GetDoc()->DeleteSection( &pCntntSect->GetNode() );
+ delete pCntntSect;
+ }
+ delete pRedlineData;
+}
+
+// liegt eine gueltige Selektion vor?
+sal_Bool SwRedline::HasValidRange() const
+{
+ const SwNode* pPtNd = &GetPoint()->nNode.GetNode(),
+ * pMkNd = &GetMark()->nNode.GetNode();
+ if( pPtNd->StartOfSectionNode() == pMkNd->StartOfSectionNode() &&
+ !pPtNd->StartOfSectionNode()->IsTableNode() &&
+ // JP 18.5.2001: Bug 87222 - invalid if points on the end of content
+ // DVO 25.03.2002: #96530# end-of-content only invalid if no content
+ // index exists
+ ( pPtNd != pMkNd || GetContentIdx() != NULL ||
+ pPtNd != &pPtNd->GetNodes().GetEndOfContent() )
+ )
+ return sal_True;
+ return sal_False;
+}
+
+void SwRedline::CallDisplayFunc( sal_uInt16 nLoop )
+{
+ switch( nsRedlineMode_t::REDLINE_SHOW_MASK & GetDoc()->GetRedlineMode() )
+ {
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE:
+ Show( nLoop );
+ break;
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT:
+ Hide( nLoop );
+ break;
+ case nsRedlineMode_t::REDLINE_SHOW_DELETE:
+ ShowOriginal( nLoop );
+ break;
+ }
+}
+
+void SwRedline::Show( sal_uInt16 nLoop )
+{
+ if( 1 <= nLoop )
+ {
+ SwDoc* pDoc = GetDoc();
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ switch( GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt
+ bIsVisible = sal_True;
+ MoveFromSection();
+ break;
+
+ case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht
+ bIsVisible = sal_True;
+ MoveFromSection();
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet
+ case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert
+ InvalidateRange();
+ break;
+ default:
+ break;
+ }
+ pDoc->SetRedlineMode_intern( eOld );
+ }
+}
+
+void SwRedline::Hide( sal_uInt16 nLoop )
+{
+ SwDoc* pDoc = GetDoc();
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ switch( GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt
+ bIsVisible = sal_True;
+ if( 1 <= nLoop )
+ MoveFromSection();
+ break;
+
+ case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht
+ bIsVisible = sal_False;
+ switch( nLoop )
+ {
+ case 0: MoveToSection(); break;
+ case 1: CopyToSection(); break;
+ case 2: DelCopyOfSection(); break;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet
+ case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert
+ if( 1 <= nLoop )
+ InvalidateRange();
+ break;
+ default:
+ break;
+ }
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+void SwRedline::ShowOriginal( sal_uInt16 nLoop )
+{
+ SwDoc* pDoc = GetDoc();
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ SwRedlineData* pCur;
+
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ // bestimme den Type, ist der erste auf Stack
+ for( pCur = pRedlineData; pCur->pNext; )
+ pCur = pCur->pNext;
+
+ switch( pCur->eType )
+ {
+ case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt
+ bIsVisible = sal_False;
+ switch( nLoop )
+ {
+ case 0: MoveToSection(); break;
+ case 1: CopyToSection(); break;
+ case 2: DelCopyOfSection(); break;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht
+ bIsVisible = sal_True;
+ if( 1 <= nLoop )
+ MoveFromSection();
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet
+ case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert
+ if( 1 <= nLoop )
+ InvalidateRange();
+ break;
+ default:
+ break;
+ }
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+
+void SwRedline::InvalidateRange() // das Layout anstossen
+{
+ sal_uLong nSttNd = GetMark()->nNode.GetIndex(),
+ nEndNd = GetPoint()->nNode.GetIndex();
+ sal_uInt16 nSttCnt = GetMark()->nContent.GetIndex(),
+ nEndCnt = GetPoint()->nContent.GetIndex();
+
+ if( nSttNd > nEndNd || ( nSttNd == nEndNd && nSttCnt > nEndCnt ))
+ {
+ sal_uLong nTmp = nSttNd; nSttNd = nEndNd; nEndNd = nTmp;
+ nTmp = nSttCnt; nSttCnt = nEndCnt; nEndCnt = (sal_uInt16)nTmp;
+ }
+
+ SwUpdateAttr aHt( 0, 0, RES_FMT_CHG );
+ SwNodes& rNds = GetDoc()->GetNodes();
+ SwNode* pNd;
+ for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
+ if( ND_TEXTNODE == ( pNd = rNds[ n ] )->GetNodeType() )
+ {
+ aHt.nStart = n == nSttNd ? nSttCnt : 0;
+ aHt.nEnd = n == nEndNd ? nEndCnt : ((SwTxtNode*)pNd)->GetTxt().Len();
+ ((SwTxtNode*)pNd)->Modify( &aHt, &aHt );
+ }
+}
+
+/*************************************************************************
+ * SwRedline::CalcStartEnd()
+ * Calculates the start and end position of the intersection rTmp and
+ * text node nNdIdx
+ *************************************************************************/
+
+void SwRedline::CalcStartEnd( sal_uLong nNdIdx, sal_uInt16& nStart, sal_uInt16& nEnd ) const
+{
+ const SwPosition *pRStt = Start(), *pREnd = End();
+ if( pRStt->nNode < nNdIdx )
+ {
+ if( pREnd->nNode > nNdIdx )
+ {
+ nStart = 0; // Absatz ist komplett enthalten
+ nEnd = STRING_LEN;
+ }
+ else
+ {
+ ASSERT( pREnd->nNode == nNdIdx,
+ "SwRedlineItr::Seek: GetRedlinePos Error" );
+ nStart = 0; // Absatz wird vorne ueberlappt
+ nEnd = pREnd->nContent.GetIndex();
+ }
+ }
+ else if( pRStt->nNode == nNdIdx )
+ {
+ nStart = pRStt->nContent.GetIndex();
+ if( pREnd->nNode == nNdIdx )
+ nEnd = pREnd->nContent.GetIndex(); // Innerhalb des Absatzes
+ else
+ nEnd = STRING_LEN; // Absatz wird hinten ueberlappt
+ }
+ else
+ {
+ nStart = STRING_LEN;
+ nEnd = STRING_LEN;
+ }
+}
+
+void SwRedline::MoveToSection()
+{
+ if( !pCntntSect )
+ {
+ const SwPosition* pStt = Start(),
+ * pEnd = pStt == GetPoint() ? GetMark() : GetPoint();
+
+ SwDoc* pDoc = GetDoc();
+ SwPaM aPam( *pStt, *pEnd );
+ SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode();
+ SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
+
+ if( !pCSttNd )
+ {
+ // damit die Indizies der anderen Redlines nicht mitverschoben
+ // werden, diese aufs Ende setzen (ist exclusive).
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ SwRedline* pRedl = rTbl[ n ];
+ if( pRedl->GetBound(sal_True) == *pStt )
+ pRedl->GetBound(sal_True) = *pEnd;
+ if( pRedl->GetBound(sal_False) == *pStt )
+ pRedl->GetBound(sal_False) = *pEnd;
+ }
+ }
+
+ SwStartNode* pSttNd;
+ SwNodes& rNds = pDoc->GetNodes();
+ if( pCSttNd || pCEndNd )
+ {
+ SwTxtFmtColl* pColl = (pCSttNd && pCSttNd->IsTxtNode() )
+ ? ((SwTxtNode*)pCSttNd)->GetTxtColl()
+ : (pCEndNd && pCEndNd->IsTxtNode() )
+ ? ((SwTxtNode*)pCEndNd)->GetTxtColl()
+ : pDoc->GetTxtCollFromPool(
+ RES_POOLCOLL_STANDARD );
+
+ pSttNd = rNds.MakeTextSection( SwNodeIndex( rNds.GetEndOfRedlines() ),
+ SwNormalStartNode, pColl );
+ SwTxtNode* pTxtNd = rNds[ pSttNd->GetIndex() + 1 ]->GetTxtNode();
+
+ SwNodeIndex aNdIdx( *pTxtNd );
+ SwPosition aPos( aNdIdx, SwIndex( pTxtNd ));
+ if( pCSttNd && pCEndNd )
+ pDoc->MoveAndJoin( aPam, aPos, IDocumentContentOperations::DOC_MOVEDEFAULT );
+ else
+ {
+ if( pCSttNd && !pCEndNd )
+ bDelLastPara = sal_True;
+ pDoc->MoveRange( aPam, aPos,
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+ }
+ }
+ else
+ {
+ pSttNd = rNds.MakeEmptySection( SwNodeIndex( rNds.GetEndOfRedlines() ),
+ SwNormalStartNode );
+
+ SwPosition aPos( *pSttNd->EndOfSectionNode() );
+ pDoc->MoveRange( aPam, aPos,
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+ }
+ pCntntSect = new SwNodeIndex( *pSttNd );
+
+ if( pStt == GetPoint() )
+ Exchange();
+
+ DeleteMark();
+ }
+ else
+ InvalidateRange();
+}
+
+void SwRedline::CopyToSection()
+{
+ if( !pCntntSect )
+ {
+ const SwPosition* pStt = Start(),
+ * pEnd = pStt == GetPoint() ? GetMark() : GetPoint();
+
+ SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode();
+ SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
+
+ SwStartNode* pSttNd;
+ SwDoc* pDoc = GetDoc();
+ SwNodes& rNds = pDoc->GetNodes();
+
+ sal_Bool bSaveCopyFlag = pDoc->IsCopyIsMove(),
+ bSaveRdlMoveFlg = pDoc->IsRedlineMove();
+ pDoc->SetCopyIsMove( sal_True );
+
+ // #100619# The IsRedlineMove() flag causes the behaviour of the
+ // SwDoc::_CopyFlyInFly method to change, which will eventually be
+ // called by the pDoc->Copy line below (through SwDoc::_Copy,
+ // SwDoc::CopyWithFlyInFly). This rather obscure bugfix was introduced
+ // for #63198# and #64896#, and apparently never really worked.
+ pDoc->SetRedlineMove( pStt->nContent == 0 );
+
+ if( pCSttNd )
+ {
+ SwTxtFmtColl* pColl = (pCSttNd && pCSttNd->IsTxtNode() )
+ ? ((SwTxtNode*)pCSttNd)->GetTxtColl()
+ : pDoc->GetTxtCollFromPool(
+ RES_POOLCOLL_STANDARD );
+
+ pSttNd = rNds.MakeTextSection( SwNodeIndex( rNds.GetEndOfRedlines() ),
+ SwNormalStartNode, pColl );
+
+ SwNodeIndex aNdIdx( *pSttNd, 1 );
+ SwTxtNode* pTxtNd = aNdIdx.GetNode().GetTxtNode();
+ SwPosition aPos( aNdIdx, SwIndex( pTxtNd ));
+ pDoc->CopyRange( *this, aPos, false );
+
+ // JP 08.10.98: die Vorlage vom EndNode ggfs. mit uebernehmen
+ // - ist im Doc::Copy nicht erwuenscht
+ if( pCEndNd && pCEndNd != pCSttNd )
+ {
+ SwCntntNode* pDestNd = aPos.nNode.GetNode().GetCntntNode();
+ if( pDestNd )
+ {
+ if( pDestNd->IsTxtNode() && pCEndNd->IsTxtNode() )
+ ((SwTxtNode*)pCEndNd)->CopyCollFmt(
+ *(SwTxtNode*)pDestNd );
+ else
+ pDestNd->ChgFmtColl( pCEndNd->GetFmtColl() );
+ }
+ }
+ }
+ else
+ {
+ pSttNd = rNds.MakeEmptySection( SwNodeIndex( rNds.GetEndOfRedlines() ),
+ SwNormalStartNode );
+
+ if( pCEndNd )
+ {
+ SwPosition aPos( *pSttNd->EndOfSectionNode() );
+ pDoc->CopyRange( *this, aPos, false );
+ }
+ else
+ {
+ SwNodeIndex aInsPos( *pSttNd->EndOfSectionNode() );
+ SwNodeRange aRg( pStt->nNode, 0, pEnd->nNode, 1 );
+ pDoc->CopyWithFlyInFly( aRg, 0, aInsPos );
+ }
+ }
+ pCntntSect = new SwNodeIndex( *pSttNd );
+
+ pDoc->SetCopyIsMove( bSaveCopyFlag );
+ pDoc->SetRedlineMove( bSaveRdlMoveFlg );
+ }
+}
+
+void SwRedline::DelCopyOfSection()
+{
+ if( pCntntSect )
+ {
+ const SwPosition* pStt = Start(),
+ * pEnd = pStt == GetPoint() ? GetMark() : GetPoint();
+
+ SwDoc* pDoc = GetDoc();
+ SwPaM aPam( *pStt, *pEnd );
+ SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode();
+ SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
+
+ if( !pCSttNd )
+ {
+ // damit die Indizies der anderen Redlines nicht mitverschoben
+ // werden, diese aufs Ende setzen (ist exclusive).
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ SwRedline* pRedl = rTbl[ n ];
+ if( pRedl->GetBound(sal_True) == *pStt )
+ pRedl->GetBound(sal_True) = *pEnd;
+ if( pRedl->GetBound(sal_False) == *pStt )
+ pRedl->GetBound(sal_False) = *pEnd;
+ }
+ }
+
+ if( pCSttNd && pCEndNd )
+ {
+ // --> OD 2009-08-20 #i100466#
+ // force a <join next> on <delete and join> operation
+ pDoc->DeleteAndJoin( aPam, true );
+ // <--
+ }
+ else if( pCSttNd || pCEndNd )
+ {
+ if( pCSttNd && !pCEndNd )
+ bDelLastPara = sal_True;
+ pDoc->DeleteRange( aPam );
+
+ if( bDelLastPara )
+ {
+ // #100611# To prevent dangling references to the paragraph to
+ // be deleted, redline that point into this paragraph should be
+ // moved to the new end position. Since redlines in the redline
+ // table are sorted and the pEnd position is an endnode (see
+ // bDelLastPara condition above), only redlines before the
+ // current ones can be affected.
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+ sal_uInt16 n = rTbl.GetPos( this );
+ ASSERT( n != USHRT_MAX, "How strange. We don't exist!" );
+ for( sal_Bool bBreak = sal_False; !bBreak && n > 0; )
+ {
+ --n;
+ bBreak = sal_True;
+ if( rTbl[ n ]->GetBound(sal_True) == *aPam.GetPoint() )
+ {
+ rTbl[ n ]->GetBound(sal_True) = *pEnd;
+ bBreak = sal_False;
+ }
+ if( rTbl[ n ]->GetBound(sal_False) == *aPam.GetPoint() )
+ {
+ rTbl[ n ]->GetBound(sal_False) = *pEnd;
+ bBreak = sal_False;
+ }
+ }
+
+ SwPosition aEnd( *pEnd );
+ *GetPoint() = *pEnd;
+ *GetMark() = *pEnd;
+ DeleteMark();
+
+ aPam.GetBound( sal_True ).nContent.Assign( 0, 0 );
+ aPam.GetBound( sal_False ).nContent.Assign( 0, 0 );
+ aPam.DeleteMark();
+ pDoc->DelFullPara( aPam );
+ }
+ }
+ else
+ {
+ pDoc->DeleteRange( aPam );
+ }
+
+ if( pStt == GetPoint() )
+ Exchange();
+
+ DeleteMark();
+ }
+}
+
+void SwRedline::MoveFromSection()
+{
+ if( pCntntSect )
+ {
+ SwDoc* pDoc = GetDoc();
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+ SvPtrarr aBeforeArr( 16, 16 ), aBehindArr( 16, 16 );
+ sal_uInt16 nMyPos = rTbl.GetPos( this );
+ ASSERT( this, "this nicht im Array?" );
+ sal_Bool bBreak = sal_False;
+ sal_uInt16 n;
+
+ for( n = nMyPos+1; !bBreak && n < rTbl.Count(); ++n )
+ {
+ bBreak = sal_True;
+ if( rTbl[ n ]->GetBound(sal_True) == *GetPoint() )
+ {
+ void* pTmp = &rTbl[ n ]->GetBound(sal_True);
+ aBehindArr.Insert( pTmp, aBehindArr.Count());
+ bBreak = sal_False;
+ }
+ if( rTbl[ n ]->GetBound(sal_False) == *GetPoint() )
+ {
+ void* pTmp = &rTbl[ n ]->GetBound(sal_False);
+ aBehindArr.Insert( pTmp, aBehindArr.Count() );
+ bBreak = sal_False;
+ }
+ }
+ for( bBreak = sal_False, n = nMyPos; !bBreak && n ; )
+ {
+ --n;
+ bBreak = sal_True;
+ if( rTbl[ n ]->GetBound(sal_True) == *GetPoint() )
+ {
+ void* pTmp = &rTbl[ n ]->GetBound(sal_True);
+ aBeforeArr.Insert( pTmp, aBeforeArr.Count() );
+ bBreak = sal_False;
+ }
+ if( rTbl[ n ]->GetBound(sal_False) == *GetPoint() )
+ {
+ void* pTmp = &rTbl[ n ]->GetBound(sal_False);
+ aBeforeArr.Insert( pTmp, aBeforeArr.Count() );
+ bBreak = sal_False;
+ }
+ }
+
+ // --> OD 2009-03-17 #i95711#
+ const SwNode* pKeptCntntSectNode( &pCntntSect->GetNode() );
+ // <--
+ {
+ SwPaM aPam( pCntntSect->GetNode(),
+ *pCntntSect->GetNode().EndOfSectionNode(), 1,
+ ( bDelLastPara ? -2 : -1 ) );
+ SwCntntNode* pCNd = aPam.GetCntntNode();
+ if( pCNd )
+ aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+ else
+ aPam.GetPoint()->nNode++;
+
+ SwFmtColl* pColl = pCNd && pCNd->Len() && aPam.GetPoint()->nNode !=
+ aPam.GetMark()->nNode
+ ? pCNd->GetFmtColl() : 0;
+
+ SwNodeIndex aNdIdx( GetPoint()->nNode, -1 );
+ sal_uInt16 nPos = GetPoint()->nContent.GetIndex();
+
+ SwPosition aPos( *GetPoint() );
+ if( bDelLastPara && *aPam.GetPoint() == *aPam.GetMark() )
+ {
+ aPos.nNode--;
+
+ pDoc->AppendTxtNode( aPos );
+ }
+ else
+ {
+ pDoc->MoveRange( aPam, aPos,
+ IDocumentContentOperations::DOC_MOVEALLFLYS );
+ }
+
+ SetMark();
+ *GetPoint() = aPos;
+ GetMark()->nNode = aNdIdx.GetIndex() + 1;
+ pCNd = GetMark()->nNode.GetNode().GetCntntNode();
+ GetMark()->nContent.Assign( pCNd, nPos );
+
+ if( bDelLastPara )
+ {
+ GetPoint()->nNode++;
+ GetPoint()->nContent.Assign( pCNd = GetCntntNode(), 0 );
+ bDelLastPara = sal_False;
+ }
+ else if( pColl )
+ pCNd = GetCntntNode();
+
+ if( pColl && pCNd )
+ pCNd->ChgFmtColl( pColl );
+ }
+ // --> OD 2009-03-17 #i95771#
+ // Under certain conditions the previous <SwDoc::Move(..)> has already
+ // remove the change tracking section of this <SwRedline> instance from
+ // the change tracking nodes area.
+ // Thus, check, if <pCntntSect> still points to the change tracking section
+ // by comparing it with the "indexed" <SwNode> instance copied before
+ // perform the intrinsic move.
+ // Note: Such condition is e.g. a "delete" change tracking only containing a table.
+ if ( &pCntntSect->GetNode() == pKeptCntntSectNode )
+ {
+ pDoc->DeleteSection( &pCntntSect->GetNode() );
+ }
+ // <--
+ delete pCntntSect, pCntntSect = 0;
+
+ // #100611# adjustment of redline table positions must take start and
+ // end into account, not point and mark.
+ for( n = 0; n < aBeforeArr.Count(); ++n )
+ *(SwPosition*)aBeforeArr[ n ] = *Start();
+ for( n = 0; n < aBehindArr.Count(); ++n )
+ *(SwPosition*)aBehindArr[ n ] = *End();
+ }
+ else
+ InvalidateRange();
+}
+
+// fuers Undo
+void SwRedline::SetContentIdx( const SwNodeIndex* pIdx )
+{
+ if( pIdx && !pCntntSect )
+ {
+ pCntntSect = new SwNodeIndex( *pIdx );
+ bIsVisible = sal_False;
+ }
+ else if( !pIdx && pCntntSect )
+ {
+ delete pCntntSect, pCntntSect = 0;
+ bIsVisible = sal_False;
+ }
+#ifdef DBG_UTIL
+ else
+ ASSERT( !this, "das ist keine gueltige Operation" );
+#endif
+}
+
+sal_Bool SwRedline::CanCombine( const SwRedline& rRedl ) const
+{
+ return IsVisible() && rRedl.IsVisible() &&
+ pRedlineData->CanCombine( *rRedl.pRedlineData );
+}
+
+void SwRedline::PushData( const SwRedline& rRedl, sal_Bool bOwnAsNext )
+{
+// SwRedlineData* pNew = new SwRedlineData( rRedl.GetType(),
+// rRedl.GetAuthor() );
+ SwRedlineData* pNew = new SwRedlineData( *rRedl.pRedlineData, sal_False );
+ if( bOwnAsNext )
+ {
+ pNew->pNext = pRedlineData;
+ pRedlineData = pNew;
+ }
+ else
+ {
+ pNew->pNext = pRedlineData->pNext;
+ pRedlineData->pNext = pNew;
+ }
+}
+
+sal_Bool SwRedline::PopData()
+{
+ if( !pRedlineData->pNext )
+ return sal_False;
+ SwRedlineData* pCur = pRedlineData;
+ pRedlineData = pCur->pNext;
+ pCur->pNext = 0;
+ delete pCur;
+ return sal_True;
+}
+
+sal_uInt16 SwRedline::GetStackCount() const
+{
+ sal_uInt16 nRet = 1;
+ for( SwRedlineData* pCur = pRedlineData; pCur->pNext; ++nRet )
+ pCur = pCur->pNext;
+ return nRet;
+}
+
+// -> #111827#
+sal_uInt16 SwRedline::GetAuthor( sal_uInt16 nPos ) const
+{
+ return GetRedlineData(nPos).nAuthor;
+}
+
+const String& SwRedline::GetAuthorString( sal_uInt16 nPos ) const
+{
+ return SW_MOD()->GetRedlineAuthor(GetRedlineData(nPos).nAuthor);
+}
+
+const DateTime& SwRedline::GetTimeStamp( sal_uInt16 nPos ) const
+{
+ return GetRedlineData(nPos).aStamp;
+}
+
+RedlineType_t SwRedline::GetRealType( sal_uInt16 nPos ) const
+{
+ return GetRedlineData(nPos).eType;
+}
+
+const String& SwRedline::GetComment( sal_uInt16 nPos ) const
+{
+ return GetRedlineData(nPos).sComment;
+}
+// <- #111827#
+
+int SwRedline::operator==( const SwRedline& rCmp ) const
+{
+ return this == &rCmp;
+}
+
+int SwRedline::operator<( const SwRedline& rCmp ) const
+{
+ sal_Bool nResult = sal_False;
+
+ if (*Start() < *rCmp.Start())
+ nResult = sal_True;
+ else if (*Start() == *rCmp.Start())
+ if (*End() < *rCmp.End())
+ nResult = sal_True;
+
+ return nResult;
+}
+
+// -> #111827#
+const SwRedlineData & SwRedline::GetRedlineData(sal_uInt16 nPos) const
+{
+ SwRedlineData * pCur = pRedlineData;
+
+ while (nPos > 0 && NULL != pCur->pNext)
+ {
+ pCur = pCur->pNext;
+
+ nPos--;
+ }
+
+ ASSERT( 0 == nPos, "Pos angabe ist zu gross" );
+
+ return *pCur;
+}
+
+String SwRedline::GetDescr(sal_uInt16 nPos)
+{
+ String aResult;
+
+ // get description of redline data (e.g.: "insert $1")
+ aResult = GetRedlineData(nPos).GetDescr();
+
+ SwPaM * pPaM = NULL;
+ bool bDeletePaM = false;
+
+ // if this redline is visible the content is in this PaM
+ if (NULL == pCntntSect)
+ {
+ pPaM = this;
+ }
+ else // otherwise it is saved in pCntntSect
+ {
+ SwNodeIndex aTmpIdx( *pCntntSect->GetNode().EndOfSectionNode() );
+ pPaM = new SwPaM(*pCntntSect, aTmpIdx );
+ bDeletePaM = true;
+ }
+
+ // replace $1 in description by description of the redlines text
+ String aTmpStr;
+ aTmpStr += String(SW_RES(STR_START_QUOTE));
+ aTmpStr += ShortenString(pPaM->GetTxt(), nUndoStringLength,
+ String(SW_RES(STR_LDOTS)));
+ aTmpStr += String(SW_RES(STR_END_QUOTE));
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, aTmpStr);
+
+ aResult = aRewriter.Apply(aResult);
+
+ if (bDeletePaM)
+ delete pPaM;
+
+ return aResult;
+}
+// <- #111827#
+
+
+bool SwDoc::IsInRedlines(const SwNode & rNode) const
+{
+ SwPosition aPos(rNode);
+ SwNode & rEndOfRedlines = GetNodes().GetEndOfRedlines();
+ SwPaM aPam(SwPosition(*rEndOfRedlines.StartOfSectionNode()),
+ SwPosition(rEndOfRedlines));
+
+ return aPam.ContainsPosition(aPos) ? true : false;
+}
diff --git a/sw/source/core/doc/docruby.cxx b/sw/source/core/doc/docruby.cxx
new file mode 100644
index 000000000000..c8703ab6adcb
--- /dev/null
+++ b/sw/source/core/doc/docruby.cxx
@@ -0,0 +1,361 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <string.h> // fuer strchr()
+
+#include <com/sun/star/i18n/UnicodeType.hdl>
+#include <com/sun/star/i18n/WordType.hdl>
+
+#include <unotools/charclass.hxx>
+
+#include <hintids.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <mvsave.hxx> // Strukturen zum Sichern beim Move/Delete
+#include <ndtxt.hxx>
+#include <txatbase.hxx>
+#include <rubylist.hxx>
+#include <pam.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <breakit.hxx>
+#include <crsskip.hxx>
+
+SV_IMPL_PTRARR( SwRubyList, SwRubyListEntryPtr )
+
+using namespace ::com::sun::star::i18n;
+
+
+/*
+ * Members in the list:
+ * - String - the orig text
+ * - SwFmtRuby - the ruby attribut
+ *
+ *
+ */
+sal_uInt16 SwDoc::FillRubyList( const SwPaM& rPam, SwRubyList& rList,
+ sal_uInt16 nMode )
+{
+ const SwPaM *_pStartCrsr = (SwPaM*)rPam.GetNext(),
+ *__pStartCrsr = _pStartCrsr;
+ sal_Bool bCheckEmpty = &rPam != _pStartCrsr;
+ do {
+ const SwPosition* pStt = _pStartCrsr->Start(),
+ * pEnd = pStt == _pStartCrsr->GetPoint()
+ ? _pStartCrsr->GetMark()
+ : _pStartCrsr->GetPoint();
+ if( !bCheckEmpty || ( pStt != pEnd && *pStt != *pEnd ))
+ {
+ SwPaM aPam( *pStt );
+ do {
+ SwRubyListEntry* pNew = new SwRubyListEntry;
+ if( pEnd != pStt )
+ {
+ aPam.SetMark();
+ *aPam.GetMark() = *pEnd;
+ }
+ if( _SelectNextRubyChars( aPam, *pNew, nMode ))
+ {
+ rList.Insert( pNew, rList.Count() );
+ aPam.DeleteMark();
+ }
+ else
+ {
+ delete pNew;
+ if( *aPam.GetPoint() < *pEnd )
+ {
+ // goto next paragraph
+ aPam.DeleteMark();
+ aPam.Move( fnMoveForward, fnGoNode );
+ }
+ else
+ break;
+ }
+ } while( 30 > rList.Count() && *aPam.GetPoint() < *pEnd );
+ }
+ } while( 30 > rList.Count() &&
+ (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != __pStartCrsr );
+
+ return rList.Count();
+}
+
+sal_uInt16 SwDoc::SetRubyList( const SwPaM& rPam, const SwRubyList& rList,
+ sal_uInt16 nMode )
+{
+ GetIDocumentUndoRedo().StartUndo( UNDO_SETRUBYATTR, NULL );
+ SvUShortsSort aDelArr;
+ aDelArr.Insert( RES_TXTATR_CJK_RUBY );
+
+ sal_uInt16 nListEntry = 0;
+
+ const SwPaM *_pStartCrsr = (SwPaM*)rPam.GetNext(),
+ *__pStartCrsr = _pStartCrsr;
+ sal_Bool bCheckEmpty = &rPam != _pStartCrsr;
+ do {
+ const SwPosition* pStt = _pStartCrsr->Start(),
+ * pEnd = pStt == _pStartCrsr->GetPoint()
+ ? _pStartCrsr->GetMark()
+ : _pStartCrsr->GetPoint();
+ if( !bCheckEmpty || ( pStt != pEnd && *pStt != *pEnd ))
+ {
+
+ SwPaM aPam( *pStt );
+ do {
+ SwRubyListEntry aCheckEntry;
+ if( pEnd != pStt )
+ {
+ aPam.SetMark();
+ *aPam.GetMark() = *pEnd;
+ }
+ if( _SelectNextRubyChars( aPam, aCheckEntry, nMode ))
+ {
+ const SwRubyListEntry* pEntry = rList[ nListEntry++ ];
+ if( aCheckEntry.GetRubyAttr() != pEntry->GetRubyAttr() )
+ {
+ // set/reset the attribut
+ if( pEntry->GetRubyAttr().GetText().Len() )
+ {
+ InsertPoolItem( aPam, pEntry->GetRubyAttr(), 0 );
+ }
+ else
+ {
+ ResetAttrs( aPam, sal_True, &aDelArr );
+ }
+ }
+
+ if( aCheckEntry.GetText() != pEntry->GetText() &&
+ pEntry->GetText().Len() )
+ {
+ // text is changed, so replace the original
+ ReplaceRange( aPam, pEntry->GetText(), false );
+ }
+ aPam.DeleteMark();
+ }
+ else
+ {
+ if( *aPam.GetPoint() < *pEnd )
+ {
+ // goto next paragraph
+ aPam.DeleteMark();
+ aPam.Move( fnMoveForward, fnGoNode );
+ }
+ else
+ {
+ const SwRubyListEntry* pEntry = rList[ nListEntry++ ];
+
+ // set/reset the attribut
+ if( pEntry->GetRubyAttr().GetText().Len() &&
+ pEntry->GetText().Len() )
+ {
+ InsertString( aPam, pEntry->GetText() );
+ aPam.SetMark();
+ aPam.GetMark()->nContent -= pEntry->GetText().Len();
+ InsertPoolItem( aPam, pEntry->GetRubyAttr(),
+ nsSetAttrMode::SETATTR_DONTEXPAND );
+ }
+ else
+ break;
+ aPam.DeleteMark();
+ }
+ }
+ } while( nListEntry < rList.Count() && *aPam.GetPoint() < *pEnd );
+ }
+ } while( 30 > rList.Count() &&
+ (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != __pStartCrsr );
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_SETRUBYATTR, NULL );
+
+ return nListEntry;
+}
+
+sal_Bool SwDoc::_SelectNextRubyChars( SwPaM& rPam, SwRubyListEntry& rEntry, sal_uInt16 )
+{
+ // Point must be the startposition, Mark is optional the end position
+ SwPosition* pPos = rPam.GetPoint();
+ const SwTxtNode* pTNd = pPos->nNode.GetNode().GetTxtNode();
+ const String* pTxt = &pTNd->GetTxt();
+ xub_StrLen nStart = pPos->nContent.GetIndex(), nEnd = pTxt->Len();
+
+ sal_Bool bHasMark = rPam.HasMark();
+ if( bHasMark )
+ {
+ // in the same node?
+ if( rPam.GetMark()->nNode == pPos->nNode )
+ {
+ // then use that end
+ xub_StrLen nTEnd = rPam.GetMark()->nContent.GetIndex();
+ if( nTEnd < nEnd )
+ nEnd = nTEnd;
+ }
+ rPam.DeleteMark();
+ }
+
+ // ----- search the start
+ // --- look where a ruby attribut starts
+ sal_uInt16 nHtIdx = USHRT_MAX;
+ const SwpHints* pHts = pTNd->GetpSwpHints();
+ const SwTxtAttr* pAttr = 0;
+ if( pHts )
+ {
+ const SwTxtAttr* pHt;
+ for( nHtIdx = 0; nHtIdx < pHts->Count(); ++nHtIdx )
+ if( RES_TXTATR_CJK_RUBY == ( pHt = (*pHts)[ nHtIdx ])->Which() &&
+ *pHt->GetAnyEnd() > nStart )
+ {
+ if( *pHt->GetStart() < nEnd )
+ {
+ pAttr = pHt;
+ if( !bHasMark && nStart > *pAttr->GetStart() )
+ {
+ nStart = *pAttr->GetStart();
+ pPos->nContent = nStart;
+ }
+ }
+ break;
+ }
+ }
+
+ if( !bHasMark && nStart && ( !pAttr || nStart != *pAttr->GetStart()) )
+ {
+ // skip to the word begin!
+ long nWordStt = pBreakIt->GetBreakIter()->getWordBoundary(
+ *pTxt, nStart,
+ pBreakIt->GetLocale( pTNd->GetLang( nStart )),
+ WordType::ANYWORD_IGNOREWHITESPACES,
+ sal_True ).startPos;
+ if( nWordStt < nStart && -1 != nWordStt )
+ {
+ nStart = (xub_StrLen)nWordStt;
+ pPos->nContent = nStart;
+ }
+ }
+
+ sal_Bool bAlphaNum = sal_False;
+ long nWordEnd = nEnd;
+ CharClass& rCC = GetAppCharClass();
+ while( nStart < nEnd )
+ {
+ if( pAttr && nStart == *pAttr->GetStart() )
+ {
+ pPos->nContent = nStart;
+ if( !rPam.HasMark() )
+ {
+ rPam.SetMark();
+ pPos->nContent = *pAttr->GetAnyEnd();
+ if( pPos->nContent.GetIndex() > nEnd )
+ pPos->nContent = nEnd;
+ rEntry.SetRubyAttr( pAttr->GetRuby() );
+ }
+ break;
+ }
+
+ sal_Int32 nChType = rCC.getType( *pTxt, nStart );
+ sal_Bool bIgnoreChar = sal_False, bIsAlphaNum = sal_False, bChkNxtWrd = sal_False;
+ switch( nChType )
+ {
+ case UnicodeType::UPPERCASE_LETTER:
+ case UnicodeType::LOWERCASE_LETTER:
+ case UnicodeType::TITLECASE_LETTER:
+ case UnicodeType::DECIMAL_DIGIT_NUMBER:
+ bChkNxtWrd = bIsAlphaNum = sal_True;
+ break;
+
+ case UnicodeType::SPACE_SEPARATOR:
+ case UnicodeType::CONTROL:
+/*??*/ case UnicodeType::PRIVATE_USE:
+ case UnicodeType::START_PUNCTUATION:
+ case UnicodeType::END_PUNCTUATION:
+ bIgnoreChar = sal_True;
+ break;
+
+
+ case UnicodeType::OTHER_LETTER:
+ bChkNxtWrd = sal_True;
+ // no break!
+// case UnicodeType::UNASSIGNED:
+// case UnicodeType::MODIFIER_LETTER:
+// case UnicodeType::NON_SPACING_MARK:
+// case UnicodeType::ENCLOSING_MARK:
+// case UnicodeType::COMBINING_SPACING_MARK:
+// case UnicodeType::LETTER_NUMBER:
+// case UnicodeType::OTHER_NUMBER:
+// case UnicodeType::LINE_SEPARATOR:
+// case UnicodeType::PARAGRAPH_SEPARATOR:
+// case UnicodeType::FORMAT:
+// case UnicodeType::SURROGATE:
+// case UnicodeType::DASH_PUNCTUATION:
+// case UnicodeType::CONNECTOR_PUNCTUATION:
+///*?? */case UnicodeType::OTHER_PUNCTUATION:
+//--> char '!' is to ignore!
+// case UnicodeType::MATH_SYMBOL:
+// case UnicodeType::CURRENCY_SYMBOL:
+// case UnicodeType::MODIFIER_SYMBOL:
+// case UnicodeType::OTHER_SYMBOL:
+// case UnicodeType::INITIAL_PUNCTUATION:
+// case UnicodeType::FINAL_PUNCTUATION:
+ default:
+ bIsAlphaNum = sal_False;
+ break;
+ }
+
+ if( rPam.HasMark() )
+ {
+ if( bIgnoreChar || bIsAlphaNum != bAlphaNum || nStart >= nWordEnd )
+ break;
+ }
+ else if( !bIgnoreChar )
+ {
+ rPam.SetMark();
+ bAlphaNum = bIsAlphaNum;
+ if( bChkNxtWrd && pBreakIt->GetBreakIter().is() )
+ {
+ // search the end of this word
+ nWordEnd = pBreakIt->GetBreakIter()->getWordBoundary(
+ *pTxt, nStart,
+ pBreakIt->GetLocale( pTNd->GetLang( nStart )),
+ WordType::ANYWORD_IGNOREWHITESPACES,
+ sal_True ).endPos;
+ if( 0 > nWordEnd || nWordEnd > nEnd || nWordEnd == nStart )
+ nWordEnd = nEnd;
+ }
+ }
+ pTNd->GoNext( &pPos->nContent, CRSR_SKIP_CHARS );
+ nStart = pPos->nContent.GetIndex();
+ }
+
+ nStart = rPam.GetMark()->nContent.GetIndex();
+ rEntry.SetText( pTxt->Copy( nStart,
+ rPam.GetPoint()->nContent.GetIndex() - nStart ));
+ return rPam.HasMark();
+}
+
+SwRubyListEntry::~SwRubyListEntry()
+{
+}
diff --git a/sw/source/core/doc/docsort.cxx b/sw/source/core/doc/docsort.cxx
new file mode 100644
index 000000000000..497e00b70125
--- /dev/null
+++ b/sw/source/core/doc/docsort.cxx
@@ -0,0 +1,1036 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <rtl/math.hxx>
+#include <unotools/collatorwrapper.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/i18n/CollatorOptions.hpp>
+#include <comphelper/processfactory.hxx>
+#include <editeng/unolingu.hxx>
+#include <docary.hxx>
+#include <fmtanchr.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <node.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <swtable.hxx>
+#include <swundo.hxx>
+#include <sortopt.hxx>
+#include <docsort.hxx>
+#include <UndoSort.hxx>
+#include <UndoRedline.hxx>
+#include <hints.hxx>
+#include <tblsel.hxx>
+#include <cellatr.hxx>
+#include <redline.hxx>
+#include <node2lay.hxx>
+#include <unochart.hxx>
+
+#if OSL_DEBUG_LEVEL > 1
+//nur zum debugen
+#include <cellatr.hxx>
+#endif
+
+using namespace ::com::sun::star::lang;
+
+SwSortOptions* SwSortElement::pOptions = 0;
+SwDoc* SwSortElement::pDoc = 0;
+const FlatFndBox* SwSortElement::pBox = 0;
+CollatorWrapper* SwSortElement::pSortCollator = 0;
+Locale* SwSortElement::pLocale = 0;
+String* SwSortElement::pLastAlgorithm = 0;
+LocaleDataWrapper* SwSortElement::pLclData = 0;
+
+SV_IMPL_OP_PTRARR_SORT( SwSortElements, SwSortElementPtr );
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Ein Sortierelement fuers Sort konstruieren
+ --------------------------------------------------------------------*/
+
+
+void SwSortElement::Init( SwDoc* pD, const SwSortOptions& rOpt,
+ FlatFndBox* pFltBx )
+{
+ ASSERT( !pDoc && !pOptions && !pBox, "wer hat das Finit vergessen?" );
+ pDoc = pD;
+ pOptions = new SwSortOptions( rOpt );
+ pBox = pFltBx;
+
+ LanguageType nLang = rOpt.nLanguage;
+ switch ( nLang )
+ {
+ case LANGUAGE_NONE:
+ case LANGUAGE_DONTKNOW:
+ nLang = (LanguageType)GetAppLanguage();
+ break;
+ }
+ pLocale = new Locale( SvxCreateLocale( nLang ) );
+
+ pSortCollator = new CollatorWrapper(
+ ::comphelper::getProcessServiceFactory() );
+// pSortCollator->loadCollatorAlgorithm( sAlgorithm, aLocale,
+// rOpt.bIgnoreCase ? SW_COLLATOR_IGNORES : 0 );
+}
+
+
+void SwSortElement::Finit()
+{
+ delete pOptions, pOptions = 0;
+ delete pLocale, pLocale = 0;
+ delete pLastAlgorithm, pLastAlgorithm = 0;
+ delete pSortCollator, pSortCollator = 0;
+ delete pLclData, pLclData = 0;
+ pDoc = 0;
+ pBox = 0;
+}
+
+
+SwSortElement::~SwSortElement()
+{
+}
+
+
+double SwSortElement::StrToDouble( const String& rStr ) const
+{
+ if( !pLclData )
+ pLclData = new LocaleDataWrapper(
+ ::comphelper::getProcessServiceFactory(), *pLocale );
+
+ rtl_math_ConversionStatus eStatus;
+ sal_Int32 nEnd;
+ double nRet = ::rtl::math::stringToDouble( rStr,
+ pLclData->getNumDecimalSep().GetChar(0),
+ pLclData->getNumThousandSep().GetChar(0),
+ &eStatus, &nEnd );
+
+ if( rtl_math_ConversionStatus_Ok != eStatus || nEnd == 0 )
+ nRet = 0.0;
+ return nRet;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Operatoren zum Vergleichen
+ --------------------------------------------------------------------*/
+
+
+sal_Bool SwSortElement::operator==(const SwSortElement& )
+{
+ return sal_False;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Kleiner-Operator fuers sortieren
+ --------------------------------------------------------------------*/
+
+sal_Bool SwSortElement::operator<(const SwSortElement& rCmp)
+{
+
+ // der eigentliche Vergleich
+ //
+ for(sal_uInt16 nKey = 0; nKey < pOptions->aKeys.Count(); ++nKey)
+ {
+ const SwSortElement *pOrig, *pCmp;
+
+ const SwSortKey* pSrtKey = pOptions->aKeys[ nKey ];
+ if( pSrtKey->eSortOrder == SRT_ASCENDING )
+ pOrig = this, pCmp = &rCmp;
+ else
+ pOrig = &rCmp, pCmp = this;
+
+ if( pSrtKey->bIsNumeric )
+ {
+ double n1 = pOrig->GetValue( nKey );
+ double n2 = pCmp->GetValue( nKey );
+
+ if( n1 == n2 )
+ continue;
+
+ return n1 < n2;
+ }
+ else
+ {
+ if( !pLastAlgorithm || *pLastAlgorithm != pSrtKey->sSortType )
+ {
+ if( pLastAlgorithm )
+ *pLastAlgorithm = pSrtKey->sSortType;
+ else
+ pLastAlgorithm = new String( pSrtKey->sSortType );
+ pSortCollator->loadCollatorAlgorithm( *pLastAlgorithm,
+ *pLocale,
+ pOptions->bIgnoreCase ? SW_COLLATOR_IGNORES : 0 );
+ }
+
+ sal_Int32 nCmp = pSortCollator->compareString(
+ pOrig->GetKey( nKey ), pCmp->GetKey( nKey ));
+ if( 0 == nCmp )
+ continue;
+
+ return -1 == nCmp;
+ }
+ }
+ return sal_False;
+}
+
+double SwSortElement::GetValue( sal_uInt16 nKey ) const
+{
+ return StrToDouble( GetKey( nKey ));
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: SortierElemente fuer Text
+ --------------------------------------------------------------------*/
+
+
+SwSortTxtElement::SwSortTxtElement(const SwNodeIndex& rPos)
+ : nOrg(rPos.GetIndex()), aPos(rPos)
+{
+}
+
+
+SwSortTxtElement::~SwSortTxtElement()
+{
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Key ermitteln
+ --------------------------------------------------------------------*/
+
+
+String SwSortTxtElement::GetKey(sal_uInt16 nId) const
+{
+ SwTxtNode* pTxtNd = aPos.GetNode().GetTxtNode();
+ if( !pTxtNd )
+ return aEmptyStr;
+
+ // fuer TextNodes
+ const String& rStr = pTxtNd->GetTxt();
+
+ sal_Unicode nDeli = pOptions->cDeli;
+ sal_uInt16 nDCount = pOptions->aKeys[nId]->nColumnId, i = 1;
+ xub_StrLen nStart = 0;
+
+ // Den Delimitter suchen
+ while( nStart != STRING_NOTFOUND && i < nDCount)
+ if( STRING_NOTFOUND != ( nStart = rStr.Search( nDeli, nStart ) ) )
+ {
+ nStart++;
+ i++;
+ }
+
+ // naechsten Delimitter gefunden oder Ende des Strings und Kopieren
+ xub_StrLen nEnd = rStr.Search( nDeli, nStart+1 );
+ return rStr.Copy( nStart, nEnd-nStart );
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Sortier-Elemente fuer Tabellen
+ --------------------------------------------------------------------*/
+
+SwSortBoxElement::SwSortBoxElement( sal_uInt16 nRC )
+ : nRow( nRC )
+{
+}
+
+
+SwSortBoxElement::~SwSortBoxElement()
+{
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Schluessel zu einer Zelle ermitteln
+ --------------------------------------------------------------------*/
+
+
+String SwSortBoxElement::GetKey(sal_uInt16 nKey) const
+{
+ const _FndBox* pFndBox;
+ sal_uInt16 nCol = pOptions->aKeys[nKey]->nColumnId-1;
+
+ if( SRT_ROWS == pOptions->eDirection )
+ pFndBox = pBox->GetBox(nCol, nRow); // Zeilen sortieren
+ else
+ pFndBox = pBox->GetBox(nRow, nCol); // Spalten sortieren
+
+ // Den Text rausfieseln
+ String aRetStr;
+ if( pFndBox )
+ { // StartNode holen und ueberlesen
+ const SwTableBox* pMyBox = pFndBox->GetBox();
+ ASSERT(pMyBox, "Keine atomare Box");
+
+ if( pMyBox->GetSttNd() )
+ {
+ // ueber alle TextNodes der Box
+ const SwNode *pNd = 0, *pEndNd = pMyBox->GetSttNd()->EndOfSectionNode();
+ for( sal_uLong nIdx = pMyBox->GetSttIdx() + 1; pNd != pEndNd; ++nIdx )
+ if( ( pNd = pDoc->GetNodes()[ nIdx ])->IsTxtNode() )
+ aRetStr += ((SwTxtNode*)pNd)->GetTxt();
+ }
+ }
+ return aRetStr;
+}
+
+double SwSortBoxElement::GetValue( sal_uInt16 nKey ) const
+{
+ const _FndBox* pFndBox;
+ sal_uInt16 nCol = pOptions->aKeys[nKey]->nColumnId-1;
+
+ if( SRT_ROWS == pOptions->eDirection )
+ pFndBox = pBox->GetBox(nCol, nRow); // Zeilen sortieren
+ else
+ pFndBox = pBox->GetBox(nRow, nCol); // Spalten sortieren
+
+ double nVal;
+ if( pFndBox )
+ {
+ const SwFmt *pFmt = pFndBox->GetBox()->GetFrmFmt();
+ if (pFmt->GetTblBoxNumFmt().GetValue() & NUMBERFORMAT_TEXT)
+ nVal = SwSortElement::GetValue( nKey );
+ else
+ nVal = pFmt->GetTblBoxValue().GetValue();
+ }
+ else
+ nVal = 0;
+
+ return nVal;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Text sortieren im Document
+ --------------------------------------------------------------------*/
+
+
+sal_Bool SwDoc::SortText(const SwPaM& rPaM, const SwSortOptions& rOpt)
+{
+ // pruefen ob Rahmen im Text
+ const SwPosition *pStart = rPaM.Start(), *pEnd = rPaM.End();
+ // Index auf den Start der Selektion
+
+ for ( sal_uInt16 n = 0; n < GetSpzFrmFmts()->Count(); ++n )
+ {
+ SwFrmFmt *const pFmt = static_cast<SwFrmFmt*>((*GetSpzFrmFmts())[n]);
+ SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+
+ if (pAPos && (FLY_AT_PARA == pAnchor->GetAnchorId()) &&
+ pStart->nNode <= pAPos->nNode && pAPos->nNode <= pEnd->nNode )
+ return sal_False;
+ }
+
+ // pruefe ob nur TextNodes in der Selection liegen
+ {
+ sal_uLong nStart = pStart->nNode.GetIndex(),
+ nEnd = pEnd->nNode.GetIndex();
+ while( nStart <= nEnd )
+ // Iterieren ueber einen selektierten Bereich
+ if( !GetNodes()[ nStart++ ]->IsTxtNode() )
+ return sal_False;
+ }
+
+ bool const bUndo = GetIDocumentUndoRedo().DoesUndo();
+ if( bUndo )
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ }
+
+ SwPaM* pRedlPam = 0;
+ SwUndoRedlineSort* pRedlUndo = 0;
+ SwUndoSort* pUndoSort = 0;
+
+ if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() ))
+ {
+ pRedlPam = new SwPaM( pStart->nNode, pEnd->nNode, -1, 1 );
+ SwCntntNode* pCNd = pRedlPam->GetCntntNode( sal_False );
+ if( pCNd )
+ pRedlPam->GetMark()->nContent = pCNd->Len();
+
+ if( IsRedlineOn() && !IsShowOriginal( GetRedlineMode() ) )
+ {
+ if( bUndo )
+ {
+ pRedlUndo = new SwUndoRedlineSort( *pRedlPam,rOpt );
+ GetIDocumentUndoRedo().DoUndo(false);
+ }
+ // erst den Bereich kopieren, dann
+ SwNodeIndex aEndIdx( pEnd->nNode, 1 );
+ SwNodeRange aRg( pStart->nNode, aEndIdx );
+ GetNodes()._Copy( aRg, aEndIdx );
+
+ // Bereich neu ist von pEnd->nNode+1 bis aEndIdx
+ DeleteRedline( *pRedlPam, true, USHRT_MAX );
+
+ pRedlPam->GetMark()->nNode.Assign( pEnd->nNode.GetNode(), 1 );
+ pCNd = pRedlPam->GetCntntNode( sal_False );
+ pRedlPam->GetMark()->nContent.Assign( pCNd, 0 );
+
+ pRedlPam->GetPoint()->nNode.Assign( aEndIdx.GetNode() );
+ pCNd = pRedlPam->GetCntntNode( sal_True );
+ xub_StrLen nCLen = 0;
+ if( !pCNd &&
+ 0 != (pCNd = GetNodes()[ aEndIdx.GetIndex()-1 ]->GetCntntNode()))
+ {
+ nCLen = pCNd->Len();
+ pRedlPam->GetPoint()->nNode.Assign( *pCNd );
+ }
+ pRedlPam->GetPoint()->nContent.Assign( pCNd, nCLen );
+
+ if( pRedlUndo )
+ pRedlUndo->SetValues( rPaM );
+ }
+ else
+ {
+ DeleteRedline( *pRedlPam, true, USHRT_MAX );
+ delete pRedlPam, pRedlPam = 0;
+ }
+ }
+
+ SwNodeIndex aStart(pStart->nNode);
+ SwSortElement::Init( this, rOpt );
+ SwSortElements aSortArr;
+ while( aStart <= pEnd->nNode )
+ {
+ // Iterieren ueber einen selektierten Bereich
+ SwSortTxtElement* pSE = new SwSortTxtElement( aStart );
+ aSortArr.Insert(pSE);
+ aStart++;
+ }
+
+ // Und jetzt der Akt: Verschieben von Nodes und immer schoen auf UNDO
+ // achten
+ //
+ sal_uLong nBeg = pStart->nNode.GetIndex();
+ SwNodeRange aRg( aStart, aStart );
+
+ if( bUndo && !pRedlUndo )
+ {
+ pUndoSort = new SwUndoSort(rPaM, rOpt);
+ GetIDocumentUndoRedo().AppendUndo(pUndoSort);
+ }
+
+ GetIDocumentUndoRedo().DoUndo(false);
+
+ for ( sal_uInt16 n = 0; n < aSortArr.Count(); ++n )
+ {
+ SwSortTxtElement* pBox = (SwSortTxtElement*)aSortArr[n];
+ aStart = nBeg + n;
+ aRg.aStart = pBox->aPos.GetIndex();
+ aRg.aEnd = aRg.aStart.GetIndex() + 1;
+
+ // Nodes verschieben
+ MoveNodeRange( aRg, aStart,
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+
+ // Undo Verschiebungen einpflegen
+ if(pUndoSort)
+ pUndoSort->Insert(pBox->nOrg, nBeg + n);
+ }
+ // Alle Elemente aus dem SortArray loeschen
+ aSortArr.DeleteAndDestroy(0, aSortArr.Count());
+ SwSortElement::Finit();
+
+ if( pRedlPam )
+ {
+ if( pRedlUndo )
+ {
+ pRedlUndo->SetSaveRange( *pRedlPam );
+ // UGLY: temp. enable Undo
+ GetIDocumentUndoRedo().DoUndo(true);
+ GetIDocumentUndoRedo().AppendUndo( pRedlUndo );
+ GetIDocumentUndoRedo().DoUndo(false);
+ }
+
+ // nBeg is start of sorted range
+ SwNodeIndex aSttIdx( GetNodes(), nBeg );
+
+ // the copied range is deleted
+ SwRedline *const pDeleteRedline(
+ new SwRedline( nsRedlineType_t::REDLINE_DELETE, *pRedlPam ));
+
+ // pRedlPam points to nodes that may be deleted (hidden) by
+ // AppendRedline, so adjust it beforehand to prevent ASSERT
+ pRedlPam->GetPoint()->nNode = aSttIdx;
+ SwCntntNode* pCNd = aSttIdx.GetNode().GetCntntNode();
+ pRedlPam->GetPoint()->nContent.Assign( pCNd, 0 );
+
+ AppendRedline(pDeleteRedline, true);
+
+ // the sorted range is inserted
+ AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, *pRedlPam ), true);
+
+ if( pRedlUndo )
+ {
+ SwNodeIndex aInsEndIdx( pRedlPam->GetMark()->nNode, -1 );
+ pRedlPam->GetMark()->nNode = aInsEndIdx;
+ SwCntntNode *const pPrevNode =
+ pRedlPam->GetMark()->nNode.GetNode().GetCntntNode();
+ pRedlPam->GetMark()->nContent.Assign( pPrevNode, pPrevNode->Len() );
+
+ pRedlUndo->SetValues( *pRedlPam );
+ }
+
+ if( pRedlUndo )
+ pRedlUndo->SetOffset( aSttIdx );
+
+ delete pRedlPam, pRedlPam = 0;
+ }
+ GetIDocumentUndoRedo().DoUndo( bUndo );
+ if( bUndo )
+ {
+ GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ }
+
+ return sal_True;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Tabelle sortieren im Document
+ --------------------------------------------------------------------*/
+
+sal_Bool SwDoc::SortTbl(const SwSelBoxes& rBoxes, const SwSortOptions& rOpt)
+{
+ // uebers SwDoc fuer Undo !!
+ ASSERT( rBoxes.Count(), "keine gueltige Box-Liste" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ // Auf gehts sortieren
+ // suche alle Boxen / Lines
+ _FndBox aFndBox( 0, 0 );
+ {
+ _FndPara aPara( rBoxes, &aFndBox );
+ pTblNd->GetTable().GetTabLines().ForEach( &_FndLineCopyCol, &aPara );;
+ }
+
+ if(!aFndBox.GetLines().Count())
+ return sal_False;
+
+ if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
+ DeleteRedline( *pTblNd, true, USHRT_MAX );
+
+ sal_uInt16 nStart = 0;
+ if( pTblNd->GetTable().GetRowsToRepeat() > 0 && rOpt.eDirection == SRT_ROWS )
+ {
+ // Oberste seleketierte Zeile
+ _FndLines& rLines = aFndBox.GetLines();
+
+ while( nStart < rLines.Count() )
+ {
+ // Verschachtelung durch Split Merge beachten,
+ // die oberste rausholen
+ SwTableLine* pLine = rLines[nStart]->GetLine();
+ while ( pLine->GetUpper() )
+ pLine = pLine->GetUpper()->GetUpper();
+
+ if( pTblNd->GetTable().IsHeadline( *pLine ) )
+ nStart++;
+ else
+ break;
+ }
+ // Alle selektierten in der HeaderLine ? -> kein Offset
+ if( nStart == rLines.Count() )
+ nStart = 0;
+ }
+
+ // umschalten auf relative Formeln
+ SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
+ aMsgHnt.eFlags = TBL_RELBOXNAME;
+ UpdateTblFlds( &aMsgHnt );
+
+ // Tabelle als flache Array-Struktur
+ FlatFndBox aFlatBox(this, aFndBox);
+
+ if(!aFlatBox.IsSymmetric())
+ return sal_False;
+
+ // MIB 9.7.97: HTML-Layout loeschen
+ pTblNd->GetTable().SetHTMLTableLayout( 0 );
+
+ // --> FME 2004-11-26 #i37739# A simple 'MakeFrms' after the node sorting
+ // does not work if the table is inside a frame and has no prev/next.
+ SwNode2Layout aNode2Layout( *pTblNd );
+ // <--
+
+ // loesche die Frames der Tabelle
+ pTblNd->DelFrms();
+ // ? TL_CHART2: ?
+
+ SwUndoSort* pUndoSort = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndoSort = new SwUndoSort( rBoxes[0]->GetSttIdx(),
+ rBoxes[rBoxes.Count()-1]->GetSttIdx(),
+ *pTblNd, rOpt, aFlatBox.HasItemSets() );
+ GetIDocumentUndoRedo().AppendUndo(pUndoSort);
+ }
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ // SchluesselElemente einsortieren
+ sal_uInt16 nCount = (rOpt.eDirection == SRT_ROWS) ?
+ aFlatBox.GetRows() : aFlatBox.GetCols();
+
+ // SortList nach Schluessel sortieren
+ SwSortElement::Init( this, rOpt, &aFlatBox );
+ SwSortElements aSortList;
+
+ // wenn die HeaderLine wiederholt wird und die
+ // Zeilen sortiert werden 1.Zeile nicht mitsortieren
+ sal_uInt16 i;
+
+ for( i = nStart; i < nCount; ++i)
+ {
+ SwSortBoxElement* pEle = new SwSortBoxElement( i );
+ aSortList.Insert(pEle);
+ }
+
+ // nach Sortierung verschieben
+ SwMovedBoxes aMovedList;
+ for(i=0; i < aSortList.Count(); ++i)
+ {
+ SwSortBoxElement* pBox = (SwSortBoxElement*)aSortList[i];
+ if(rOpt.eDirection == SRT_ROWS)
+ MoveRow(this, aFlatBox, pBox->nRow, i + nStart, aMovedList, pUndoSort);
+ else
+ MoveCol(this, aFlatBox, pBox->nRow, i + nStart, aMovedList, pUndoSort);
+ }
+
+ // Restore table frames:
+ // --> FME 2004-11-26 #i37739# A simple 'MakeFrms' after the node sorting
+ // does not work if the table is inside a frame and has no prev/next.
+ const sal_uLong nIdx = pTblNd->GetIndex();
+ aNode2Layout.RestoreUpperFrms( GetNodes(), nIdx, nIdx + 1 );
+ // <--
+
+ // TL_CHART2: need to inform chart of probably changed cell names
+ UpdateCharts( pTblNd->GetTable().GetFrmFmt()->GetName() );
+
+ // Alle Elemente aus dem SortArray loeschen
+ aSortList.DeleteAndDestroy( 0, aSortList.Count() );
+ SwSortElement::Finit();
+
+ SetModified();
+ return sal_True;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Zeilenweise verschieben
+ --------------------------------------------------------------------*/
+
+
+void MoveRow(SwDoc* pDoc, const FlatFndBox& rBox, sal_uInt16 nS, sal_uInt16 nT,
+ SwMovedBoxes& rMovedList, SwUndoSort* pUD)
+{
+ for( sal_uInt16 i=0; i < rBox.GetCols(); ++i )
+ { // Alte Zellen-Pos bestimmen und merken
+ const _FndBox* pSource = rBox.GetBox(i, nS);
+
+ // neue Zellen-Pos
+ const _FndBox* pTarget = rBox.GetBox(i, nT);
+
+ const SwTableBox* pT = pTarget->GetBox();
+ const SwTableBox* pS = pSource->GetBox();
+
+ sal_Bool bMoved = rMovedList.GetPos(pT) != USHRT_MAX;
+
+ // und verschieben
+ MoveCell(pDoc, pS, pT, bMoved, pUD);
+
+ rMovedList.Insert(pS, rMovedList.Count() );
+
+ if( pS != pT )
+ {
+ SwFrmFmt* pTFmt = (SwFrmFmt*)pT->GetFrmFmt();
+ const SfxItemSet* pSSet = rBox.GetItemSet( i, nS );
+
+ if( pSSet ||
+ SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_FORMAT ) ||
+ SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_FORMULA ) ||
+ SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_VALUE ) )
+ {
+ pTFmt = ((SwTableBox*)pT)->ClaimFrmFmt();
+ pTFmt->LockModify();
+ if( pTFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE ) )
+ pTFmt->ResetFmtAttr( RES_VERT_ORIENT );
+
+ if( pSSet )
+ pTFmt->SetFmtAttr( *pSSet );
+ pTFmt->UnlockModify();
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Spaltenweise verschieben
+ --------------------------------------------------------------------*/
+
+
+void MoveCol(SwDoc* pDoc, const FlatFndBox& rBox, sal_uInt16 nS, sal_uInt16 nT,
+ SwMovedBoxes& rMovedList, SwUndoSort* pUD)
+{
+ for(sal_uInt16 i=0; i < rBox.GetRows(); ++i)
+ { // Alte Zellen-Pos bestimmen und merken
+ const _FndBox* pSource = rBox.GetBox(nS, i);
+
+ // neue Zellen-Pos
+ const _FndBox* pTarget = rBox.GetBox(nT, i);
+
+ // und verschieben
+ const SwTableBox* pT = pTarget->GetBox();
+ const SwTableBox* pS = pSource->GetBox();
+
+ // und verschieben
+ sal_Bool bMoved = rMovedList.GetPos(pT) != USHRT_MAX;
+ MoveCell(pDoc, pS, pT, bMoved, pUD);
+
+ rMovedList.Insert(pS, rMovedList.Count() );
+
+ if( pS != pT )
+ {
+ SwFrmFmt* pTFmt = (SwFrmFmt*)pT->GetFrmFmt();
+ const SfxItemSet* pSSet = rBox.GetItemSet( nS, i );
+
+ if( pSSet ||
+ SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_FORMAT ) ||
+ SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_FORMULA ) ||
+ SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_VALUE ) )
+ {
+ pTFmt = ((SwTableBox*)pT)->ClaimFrmFmt();
+ pTFmt->LockModify();
+ if( pTFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE ) )
+ pTFmt->ResetFmtAttr( RES_VERT_ORIENT );
+
+ if( pSSet )
+ pTFmt->SetFmtAttr( *pSSet );
+ pTFmt->UnlockModify();
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Eine einzelne Zelle verschieben
+ --------------------------------------------------------------------*/
+
+
+void MoveCell(SwDoc* pDoc, const SwTableBox* pSource, const SwTableBox* pTar,
+ sal_Bool bMovedBefore, SwUndoSort* pUD)
+{
+ ASSERT(pSource && pTar,"Fehlende Quelle oder Ziel");
+
+ if(pSource == pTar)
+ return;
+
+ if(pUD)
+ pUD->Insert( pSource->GetName(), pTar->GetName() );
+
+ // Pam Quelle auf den ersten ContentNode setzen
+ SwNodeRange aRg( *pSource->GetSttNd(), 0, *pSource->GetSttNd() );
+ SwNode* pNd = pDoc->GetNodes().GoNext( &aRg.aStart );
+
+ // wurde die Zelle (Source) nicht verschoben
+ // -> einen Leer-Node einfuegen und den Rest verschieben
+ // ansonsten steht der Mark auf dem ersten Content-Node
+ if( pNd->StartOfSectionNode() == pSource->GetSttNd() )
+ pNd = pDoc->GetNodes().MakeTxtNode( aRg.aStart,
+ (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
+ aRg.aEnd = *pNd->EndOfSectionNode();
+
+ // Ist das Ziel leer(1 leerer Node vorhanden)
+ // -> diesen loeschen und move
+ // Ziel
+ SwNodeIndex aTar( *pTar->GetSttNd() );
+ pNd = pDoc->GetNodes().GoNext( &aTar ); // naechsten ContentNode
+ sal_uLong nCount = pNd->EndOfSectionIndex() - pNd->StartOfSectionIndex();
+
+ sal_Bool bDelFirst = sal_False;
+ if( nCount == 2 )
+ {
+ ASSERT( pNd->GetCntntNode(), "Kein ContentNode");
+ bDelFirst = !pNd->GetCntntNode()->Len() && bMovedBefore;
+ }
+
+ if(!bDelFirst)
+ { // Es besteht schon Inhalt -> alter I n h a l t Section Down
+ SwNodeRange aRgTar( aTar.GetNode(), 0, *pNd->EndOfSectionNode() );
+ pDoc->GetNodes().SectionDown( &aRgTar );
+ }
+
+ // Einfuegen der Source
+ SwNodeIndex aIns( *pTar->GetSttNd()->EndOfSectionNode() );
+ pDoc->MoveNodeRange( aRg, aIns,
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+
+ // Falls erster Node leer -> weg damit
+ if(bDelFirst)
+ pDoc->GetNodes().Delete( aTar, 1 );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Zweidimensionales Array aus FndBoxes generieren
+ --------------------------------------------------------------------*/
+
+
+FlatFndBox::FlatFndBox(SwDoc* pDocPtr, const _FndBox& rBox) :
+ pDoc(pDocPtr),
+ rBoxRef(rBox),
+ pArr(0),
+ ppItemSets(0),
+ nRow(0),
+ nCol(0)
+{ // Ist das Array symmetrisch
+ if((bSym = CheckLineSymmetry(rBoxRef)) != 0)
+ {
+ // Spalten/Reihen-Anzahl ermitteln
+ nCols = GetColCount(rBoxRef);
+ nRows = GetRowCount(rBoxRef);
+
+ // lineares Array anlegen
+ pArr = new _FndBoxPtr[ nRows * nCols ];
+ _FndBox** ppTmp = (_FndBox**)pArr;
+ memset( ppTmp, 0, sizeof(_FndBoxPtr) * nRows * nCols );
+
+
+ FillFlat( rBoxRef );
+ }
+}
+
+
+FlatFndBox::~FlatFndBox()
+{
+ _FndBox** ppTmp = (_FndBox**)pArr;
+ delete [] ppTmp;
+
+ if( ppItemSets )
+ delete [] ppItemSets;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Alle Lines einer Box muessen gleichviel Boxen haben
+ --------------------------------------------------------------------*/
+
+
+sal_Bool FlatFndBox::CheckLineSymmetry(const _FndBox& rBox)
+{
+ const _FndLines &rLines = rBox.GetLines();
+ sal_uInt16 nBoxes(0);
+
+ // UeberLines iterieren
+ for(sal_uInt16 i=0; i < rLines.Count(); ++i)
+ { // Die Boxen einer Line
+ _FndLine* pLn = rLines[i];
+ const _FndBoxes& rBoxes = pLn->GetBoxes();
+
+ // Anzahl der Boxen aller Lines ungleich -> keine Symmetrie
+ if( i && nBoxes != rBoxes.Count())
+ return sal_False;
+
+ nBoxes = rBoxes.Count();
+ if( !CheckBoxSymmetry( *pLn ) )
+ return sal_False;
+ }
+ return sal_True;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Box auf Symmetrie pruefen
+ Alle Boxen einer Line muessen gleichviele Lines haben
+ --------------------------------------------------------------------*/
+
+
+sal_Bool FlatFndBox::CheckBoxSymmetry(const _FndLine& rLn)
+{
+ const _FndBoxes &rBoxes = rLn.GetBoxes();
+ sal_uInt16 nLines(0);
+
+ // Ueber Boxes iterieren
+ for(sal_uInt16 i=0; i < rBoxes.Count(); ++i)
+ { // Die Boxen einer Line
+ _FndBox* pBox = rBoxes[i];
+ const _FndLines& rLines = pBox->GetLines();
+
+ // Anzahl der Boxen aller Lines ungleich -> keine Symmetrie
+ if( i && nLines != rLines.Count() )
+ return sal_False;
+
+ nLines = rLines.Count();
+ if( nLines && !CheckLineSymmetry( *pBox ) )
+ return sal_False;
+ }
+ return sal_True;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: max Anzahl der Spalten (Boxes)
+ --------------------------------------------------------------------*/
+
+
+sal_uInt16 FlatFndBox::GetColCount(const _FndBox& rBox)
+{
+ const _FndLines& rLines = rBox.GetLines();
+ // Ueber Lines iterieren
+ if( !rLines.Count() )
+ return 1;
+
+ sal_uInt16 nSum = 0;
+ for( sal_uInt16 i=0; i < rLines.Count(); ++i )
+ {
+ // Die Boxen einer Line
+ sal_uInt16 nCount = 0;
+ const _FndBoxes& rBoxes = rLines[i]->GetBoxes();
+ for( sal_uInt16 j=0; j < rBoxes.Count(); ++j )
+ // Rekursiv wirder ueber die Lines Iterieren
+ nCount += rBoxes[j]->GetLines().Count()
+ ? GetColCount(*rBoxes[j]) : 1;
+
+ if( nSum < nCount )
+ nSum = nCount;
+ }
+ return nSum;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: max Anzahl der Zeilen (Lines)
+ --------------------------------------------------------------------*/
+
+
+sal_uInt16 FlatFndBox::GetRowCount(const _FndBox& rBox)
+{
+ const _FndLines& rLines = rBox.GetLines();
+ if( !rLines.Count() )
+ return 1;
+
+ sal_uInt16 nLines = 0;
+ for(sal_uInt16 i=0; i < rLines.Count(); ++i)
+ { // Die Boxen einer Line
+ const _FndBoxes& rBoxes = rLines[i]->GetBoxes();
+ sal_uInt16 nLn = 1;
+ for(sal_uInt16 j=0; j < rBoxes.Count(); ++j)
+ if( rBoxes[j]->GetLines().Count() )
+ // Rekursiv ueber die Lines Iterieren
+ nLn = Max(GetRowCount(*rBoxes[j]), nLn);
+
+ nLines = nLines + nLn;
+ }
+ return nLines;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: lineares Array aus atomaren FndBoxes erzeugen
+ --------------------------------------------------------------------*/
+
+
+void FlatFndBox::FillFlat(const _FndBox& rBox, sal_Bool bLastBox)
+{
+ sal_Bool bModRow = sal_False;
+ const _FndLines& rLines = rBox.GetLines();
+
+ // Ueber Lines iterieren
+ sal_uInt16 nOldRow = nRow;
+ for( sal_uInt16 i=0; i < rLines.Count(); ++i )
+ {
+ // Die Boxen einer Line
+ const _FndBoxes& rBoxes = rLines[i]->GetBoxes();
+ sal_uInt16 nOldCol = nCol;
+ for( sal_uInt16 j = 0; j < rBoxes.Count(); ++j )
+ {
+ // Die Box pruefen ob es eine atomare Box ist
+ const _FndBox* pBox = rBoxes[ j ];
+
+ if( !pBox->GetLines().Count() )
+ {
+ // peichern
+ sal_uInt16 nOff = nRow * nCols + nCol;
+ *(pArr + nOff) = pBox;
+
+ // sicher die Formel/Format/Value Werte
+ const SwFrmFmt* pFmt = pBox->GetBox()->GetFrmFmt();
+ if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMAT ) ||
+ SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMULA ) ||
+ SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_VALUE ) )
+ {
+ SfxItemSet* pSet = new SfxItemSet( pDoc->GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
+ RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
+ pSet->Put( pFmt->GetAttrSet() );
+ if( !ppItemSets )
+ {
+ ppItemSets = new SfxItemSet*[ nRows * nCols ];
+ memset( ppItemSets, 0, sizeof(SfxItemSet*) * nRows * nCols );
+ }
+ *(ppItemSets + nOff ) = pSet;
+ }
+
+ bModRow = sal_True;
+ }
+ else
+ {
+ // Rekursiv wieder ueber die Lines einer Box Iterieren
+ FillFlat( *pBox, ( j == rBoxes.Count()-1 ) );
+ }
+ nCol++;
+ }
+ if(bModRow)
+ nRow++;
+ nCol = nOldCol;
+ }
+ if(!bLastBox)
+ nRow = nOldRow;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Zugriff auf eine bestimmte Zelle
+ --------------------------------------------------------------------*/
+
+
+const _FndBox* FlatFndBox::GetBox(sal_uInt16 n_Col, sal_uInt16 n_Row) const
+{
+ sal_uInt16 nOff = n_Row * nCols + n_Col;
+ const _FndBox* pTmp = *(pArr + nOff);
+
+ ASSERT(n_Col < nCols && n_Row < nRows && pTmp, "unzulaessiger Array-Zugriff");
+ return pTmp;
+}
+
+const SfxItemSet* FlatFndBox::GetItemSet(sal_uInt16 n_Col, sal_uInt16 n_Row) const
+{
+ ASSERT( !ppItemSets || ( n_Col < nCols && n_Row < nRows), "unzulaessiger Array-Zugriff");
+
+ return ppItemSets ? *(ppItemSets + (n_Row * nCols + n_Col )) : 0;
+}
+
+
diff --git a/sw/source/core/doc/docstat.cxx b/sw/source/core/doc/docstat.cxx
new file mode 100644
index 000000000000..ee44bf142de3
--- /dev/null
+++ b/sw/source/core/doc/docstat.cxx
@@ -0,0 +1,67 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <docstat.hxx>
+
+
+/************************************************************************
+ * SwDocStat::SwDocStat()
+ ************************************************************************/
+
+SwDocStat::SwDocStat() :
+ nTbl(0),
+ nGrf(0),
+ nOLE(0),
+ nPage(1),
+ nPara(1),
+ nAllPara(1),
+ nWord(0),
+ nChar(0),
+ bModified(sal_True)
+{}
+
+/************************************************************************
+ * void SwDocStat::Reset()
+ ************************************************************************/
+
+void SwDocStat::Reset()
+{
+ nTbl = 0;
+ nGrf = 0;
+ nOLE = 0;
+ nPage = 1;
+ nPara = 1;
+ nAllPara= 1;
+ nWord = 0;
+ nChar = 0;
+ bModified = sal_True;
+}
+
diff --git a/sw/source/core/doc/doctxm.cxx b/sw/source/core/doc/doctxm.cxx
new file mode 100644
index 000000000000..79fcfc60049d
--- /dev/null
+++ b/sw/source/core/doc/doctxm.cxx
@@ -0,0 +1,2464 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <limits.h>
+#include <hintids.hxx>
+
+#define _SVSTDARR_STRINGSSORT
+#include <svl/svstdarr.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <sot/clsids.hxx>
+#include <docsh.hxx>
+#include <ndole.hxx>
+#include <txttxmrk.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtpdsc.hxx>
+#include <frmfmt.hxx>
+#include <fmtfsize.hxx>
+#include <frmatr.hxx>
+#include <pagedesc.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pagefrm.hxx>
+#include <ndtxt.hxx>
+#include <swtable.hxx>
+#include <doctxm.hxx>
+#include <txmsrt.hxx>
+#include <rolbck.hxx>
+#include <poolfmt.hxx>
+#include <txtfrm.hxx>
+#include <rootfrm.hxx>
+#include <UndoAttribute.hxx>
+#include <swundo.hxx>
+#include <mdiexp.hxx>
+#include <docary.hxx>
+#include <charfmt.hxx>
+#include <fchrfmt.hxx>
+#include <fldbas.hxx>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <expfld.hxx>
+#include <chpfld.hxx>
+#include <mvsave.hxx>
+#include <node2lay.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <breakit.hxx>
+#include <editsh.hxx>
+#include <scriptinfo.hxx>
+
+using namespace ::com::sun::star;
+
+const sal_Unicode cNumRepl = '@';
+const sal_Unicode cEndPageNum = '~';
+const sal_Char __FAR_DATA sPageDeli[] = ", ";
+
+SV_IMPL_PTRARR(SwTOXSortTabBases, SwTOXSortTabBasePtr)
+
+TYPEINIT2( SwTOXBaseSection, SwTOXBase, SwSection ); // fuers RTTI
+
+struct LinkStruct
+{
+ SwFmtINetFmt aINetFmt;
+ xub_StrLen nStartTextPos, nEndTextPos;
+
+ LinkStruct( const String& rURL, xub_StrLen nStart, xub_StrLen nEnd )
+ : aINetFmt( rURL, aEmptyStr),
+ nStartTextPos( nStart),
+ nEndTextPos(nEnd) {}
+};
+
+typedef LinkStruct* LinkStructPtr;
+SV_DECL_PTRARR(LinkStructArr, LinkStructPtr, 0, 5 )
+SV_IMPL_PTRARR(LinkStructArr, LinkStructPtr)
+
+sal_uInt16 SwDoc::GetTOIKeys( SwTOIKeyType eTyp, SvStringsSort& rArr ) const
+{
+ if( rArr.Count() )
+ rArr.Remove( sal_uInt16(0), rArr.Count() );
+
+ // dann mal ueber den Pool und alle Primary oder Secondary heraussuchen
+ const SwTxtTOXMark* pMark;
+ const SfxPoolItem* pItem;
+ const SwTOXType* pTOXType;
+ sal_uInt32 i, nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_TOXMARK );
+ for( i = 0; i < nMaxItems; ++i )
+ if( 0 != (pItem = GetAttrPool().GetItem2( RES_TXTATR_TOXMARK, i ) ) &&
+ 0!= ( pTOXType = ((SwTOXMark*)pItem)->GetTOXType()) &&
+ TOX_INDEX == pTOXType->GetType() &&
+ 0 != ( pMark = ((SwTOXMark*)pItem)->GetTxtTOXMark() ) &&
+ pMark->GetpTxtNd() &&
+ pMark->GetpTxtNd()->GetNodes().IsDocNodes() )
+ {
+ const String* pStr;
+ if( TOI_PRIMARY == eTyp )
+ pStr = &((SwTOXMark*)pItem)->GetPrimaryKey();
+ else
+ pStr = &((SwTOXMark*)pItem)->GetSecondaryKey();
+
+ if( pStr->Len() )
+ rArr.Insert( (StringPtr)pStr );
+ }
+
+ return rArr.Count();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: aktuelle Verzeichnismarkierungen ermitteln
+ --------------------------------------------------------------------*/
+
+
+sal_uInt16 SwDoc::GetCurTOXMark( const SwPosition& rPos,
+ SwTOXMarks& rArr ) const
+{
+ // search on Position rPos for all SwTOXMarks
+ SwTxtNode *const pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ if( !pTxtNd || !pTxtNd->GetpSwpHints() )
+ return 0;
+
+ const SwpHints & rHts = *pTxtNd->GetpSwpHints();
+ const SwTxtAttr* pHt;
+ xub_StrLen nSttIdx;
+ const xub_StrLen *pEndIdx;
+
+ xub_StrLen nAktPos = rPos.nContent.GetIndex();
+
+ for( sal_uInt16 n = 0; n < rHts.Count(); ++n )
+ {
+ if( RES_TXTATR_TOXMARK != (pHt = rHts[n])->Which() )
+ continue;
+ if( ( nSttIdx = *pHt->GetStart() ) < nAktPos )
+ {
+ // pruefe Ende mit ab
+ if( 0 == ( pEndIdx = pHt->GetEnd() ) ||
+ *pEndIdx <= nAktPos )
+ continue; // weiter suchen
+ }
+ else if( nSttIdx > nAktPos )
+ // ist Start vom Hint groesser als rPos, dann abbrechen. Denn
+ // die Attribute sind nach Start sortiert !
+ break;
+
+ const SwTOXMark* pTMark = &pHt->GetTOXMark();
+ rArr.Insert( pTMark, rArr.Count() );
+ }
+ return rArr.Count();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Marke loeschen
+ --------------------------------------------------------------------*/
+
+void SwDoc::DeleteTOXMark( const SwTOXMark* pTOXMark )
+{
+ // hole den TextNode und
+ const SwTxtTOXMark* pTxtTOXMark = pTOXMark->GetTxtTOXMark();
+ ASSERT( pTxtTOXMark, "Kein TxtTOXMark, kann nicht geloescht werden" );
+
+ SwTxtNode& rTxtNd = const_cast<SwTxtNode&>(pTxtTOXMark->GetTxtNode());
+ ASSERT( rTxtNd.GetpSwpHints(), "kann nicht geloescht werden" );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // save attributes for Undo
+ SwUndoResetAttr* pUndo = new SwUndoResetAttr(
+ SwPosition( rTxtNd, SwIndex( &rTxtNd, *pTxtTOXMark->GetStart() ) ),
+ RES_TXTATR_TOXMARK );
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+
+ SwRegHistory aRHst( rTxtNd, &pUndo->GetHistory() );
+ rTxtNd.GetpSwpHints()->Register( &aRHst );
+ }
+
+ rTxtNd.DeleteAttribute( const_cast<SwTxtTOXMark*>(pTxtTOXMark) );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ if( rTxtNd.GetpSwpHints() )
+ rTxtNd.GetpSwpHints()->DeRegister();
+ }
+ SetModified();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Traveln zwischen TOXMarks
+ --------------------------------------------------------------------*/
+
+class CompareNodeCntnt
+{
+ sal_uLong nNode;
+ xub_StrLen nCntnt;
+public:
+ CompareNodeCntnt( sal_uLong nNd, xub_StrLen nCnt )
+ : nNode( nNd ), nCntnt( nCnt ) {}
+
+ int operator==( const CompareNodeCntnt& rCmp )
+ { return nNode == rCmp.nNode && nCntnt == rCmp.nCntnt; }
+ int operator!=( const CompareNodeCntnt& rCmp )
+ { return nNode != rCmp.nNode || nCntnt != rCmp.nCntnt; }
+ int operator< ( const CompareNodeCntnt& rCmp )
+ { return nNode < rCmp.nNode ||
+ ( nNode == rCmp.nNode && nCntnt < rCmp.nCntnt); }
+ int operator<=( const CompareNodeCntnt& rCmp )
+ { return nNode < rCmp.nNode ||
+ ( nNode == rCmp.nNode && nCntnt <= rCmp.nCntnt); }
+ int operator> ( const CompareNodeCntnt& rCmp )
+ { return nNode > rCmp.nNode ||
+ ( nNode == rCmp.nNode && nCntnt > rCmp.nCntnt); }
+ int operator>=( const CompareNodeCntnt& rCmp )
+ { return nNode > rCmp.nNode ||
+ ( nNode == rCmp.nNode && nCntnt >= rCmp.nCntnt); }
+};
+
+const SwTOXMark& SwDoc::GotoTOXMark( const SwTOXMark& rCurTOXMark,
+ SwTOXSearch eDir, sal_Bool bInReadOnly )
+{
+ const SwTxtTOXMark* pMark = rCurTOXMark.GetTxtTOXMark();
+ ASSERT(pMark, "pMark==0 Ungueltige TxtTOXMark");
+
+ const SwTxtNode *pTOXSrc = pMark->GetpTxtNd();
+
+ CompareNodeCntnt aAbsIdx( pTOXSrc->GetIndex(), *pMark->GetStart() );
+ CompareNodeCntnt aPrevPos( 0, 0 );
+ CompareNodeCntnt aNextPos( ULONG_MAX, STRING_NOTFOUND );
+ CompareNodeCntnt aMax( 0, 0 );
+ CompareNodeCntnt aMin( ULONG_MAX, STRING_NOTFOUND );
+
+ const SwTOXMark* pNew = 0;
+ const SwTOXMark* pMax = &rCurTOXMark;
+ const SwTOXMark* pMin = &rCurTOXMark;
+
+ const SwModify* pType = rCurTOXMark.GetRegisteredIn();
+ SwClientIter aIter( *(SwModify*)pType );
+
+ const SwTOXMark* pTOXMark;
+ const SwCntntFrm* pCFrm;
+ Point aPt;
+ for( pTOXMark = (SwTOXMark*)aIter.First( TYPE( SwTOXMark )); pTOXMark;
+ pTOXMark = (SwTOXMark*)aIter.Next() )
+ {
+ if( pTOXMark != &rCurTOXMark &&
+ 0 != ( pMark = pTOXMark->GetTxtTOXMark()) &&
+ 0 != ( pTOXSrc = pMark->GetpTxtNd() ) &&
+ 0 != ( pCFrm = pTOXSrc->GetFrm( &aPt, 0, sal_False )) &&
+ ( bInReadOnly || !pCFrm->IsProtected() ))
+ {
+ CompareNodeCntnt aAbsNew( pTOXSrc->GetIndex(), *pMark->GetStart() );
+ switch( eDir )
+ {
+ //Die untenstehenden etwas komplizierter ausgefallen Ausdruecke
+ //dienen dazu auch ueber Eintraege auf der selben (!) Position
+ //traveln zu koennen. Wenn einer Zeit hat mag er sie mal
+ //optimieren.
+
+ case TOX_SAME_PRV:
+ if( pTOXMark->GetText() != rCurTOXMark.GetText() )
+ break;
+ /* no break here */
+ case TOX_PRV:
+ if ( (aAbsNew < aAbsIdx && aAbsNew > aPrevPos &&
+ aPrevPos != aAbsIdx && aAbsNew != aAbsIdx ) ||
+ (aAbsIdx == aAbsNew &&
+ (sal_uLong(&rCurTOXMark) > sal_uLong(pTOXMark) &&
+ (!pNew ||
+ (pNew && (aPrevPos < aAbsIdx ||
+ sal_uLong(pNew) < sal_uLong(pTOXMark)))))) ||
+ (aPrevPos == aAbsNew && aAbsIdx != aAbsNew &&
+ sal_uLong(pTOXMark) > sal_uLong(pNew)) )
+ {
+ pNew = pTOXMark;
+ aPrevPos = aAbsNew;
+ if ( aAbsNew >= aMax )
+ {
+ aMax = aAbsNew;
+ pMax = pTOXMark;
+ }
+ }
+ break;
+
+ case TOX_SAME_NXT:
+ if( pTOXMark->GetText() != rCurTOXMark.GetText() )
+ break;
+ /* no break here */
+ case TOX_NXT:
+ if ( (aAbsNew > aAbsIdx && aAbsNew < aNextPos &&
+ aNextPos != aAbsIdx && aAbsNew != aAbsIdx ) ||
+ (aAbsIdx == aAbsNew &&
+ (sal_uLong(&rCurTOXMark) < sal_uLong(pTOXMark) &&
+ (!pNew ||
+ (pNew && (aNextPos > aAbsIdx ||
+ sal_uLong(pNew) > sal_uLong(pTOXMark)))))) ||
+ (aNextPos == aAbsNew && aAbsIdx != aAbsNew &&
+ sal_uLong(pTOXMark) < sal_uLong(pNew)) )
+ {
+ pNew = pTOXMark;
+ aNextPos = aAbsNew;
+ if ( aAbsNew <= aMin )
+ {
+ aMin = aAbsNew;
+ pMin = pTOXMark;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+
+ // kein Nachfolger wurde gefunden
+ // Min oder Max benutzen
+ if(!pNew)
+ {
+ switch(eDir)
+ {
+ case TOX_PRV:
+ case TOX_SAME_PRV:
+ pNew = pMax;
+ break;
+ case TOX_NXT:
+ case TOX_SAME_NXT:
+ pNew = pMin;
+ break;
+ default:
+ pNew = &rCurTOXMark;
+ }
+ }
+ return *pNew;
+}
+
+/* */
+
+const SwTOXBaseSection* SwDoc::InsertTableOf( const SwPosition& rPos,
+ const SwTOXBase& rTOX,
+ const SfxItemSet* pSet,
+ sal_Bool bExpand )
+{
+ GetIDocumentUndoRedo().StartUndo( UNDO_INSTOX, NULL );
+
+ String sSectNm( rTOX.GetTOXName() );
+ sSectNm = GetUniqueTOXBaseName( *rTOX.GetTOXType(), &sSectNm );
+ SwPaM aPam( rPos );
+ SwSectionData aSectionData( TOX_CONTENT_SECTION, sSectNm );
+ SwTOXBaseSection *const pNewSection = dynamic_cast<SwTOXBaseSection *>(
+ InsertSwSection( aPam, aSectionData, & rTOX, pSet, false ));
+ if (pNewSection)
+ {
+ SwSectionNode *const pSectNd = pNewSection->GetFmt()->GetSectionNode();
+ pNewSection->SetTOXName(sSectNm); // rTOX may have had no name...
+
+ if( bExpand )
+ {
+ // OD 19.03.2003 #106329# - add value for 2nd parameter = true to
+ // indicate, that a creation of a new table of content has to be performed.
+ // Value of 1st parameter = default value.
+ pNewSection->Update( 0, true );
+ }
+ else if( 1 == rTOX.GetTitle().Len() && IsInReading() )
+ // insert title of TOX
+ {
+ // then insert the headline section
+ SwNodeIndex aIdx( *pSectNd, +1 );
+
+ SwTxtNode* pHeadNd = GetNodes().MakeTxtNode( aIdx,
+ GetTxtCollFromPool( RES_POOLCOLL_STANDARD ) );
+
+ String sNm( pNewSection->GetTOXName() );
+// ??Resource
+sNm.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "_Head" ));
+
+ SwSectionData headerData( TOX_HEADER_SECTION, sNm );
+
+ SwNodeIndex aStt( *pHeadNd ); aIdx--;
+ SwSectionFmt* pSectFmt = MakeSectionFmt( 0 );
+ GetNodes().InsertTextSection(
+ aStt, *pSectFmt, headerData, 0, &aIdx, true, false);
+ }
+ }
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_INSTOX, NULL );
+
+ return pNewSection;
+}
+
+
+
+const SwTOXBaseSection* SwDoc::InsertTableOf( sal_uLong nSttNd, sal_uLong nEndNd,
+ const SwTOXBase& rTOX,
+ const SfxItemSet* pSet )
+{
+ // check for recursiv TOX
+ SwNode* pNd = GetNodes()[ nSttNd ];
+ SwSectionNode* pSectNd = pNd->FindSectionNode();
+ while( pSectNd )
+ {
+ SectionType eT = pSectNd->GetSection().GetType();
+ if( TOX_HEADER_SECTION == eT || TOX_CONTENT_SECTION == eT )
+ return 0;
+ pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode();
+ }
+
+ String sSectNm( rTOX.GetTOXName() );
+ sSectNm = GetUniqueTOXBaseName(*rTOX.GetTOXType(), &sSectNm);
+
+ SwSectionData aSectionData( TOX_CONTENT_SECTION, sSectNm );
+
+ SwNodeIndex aStt( GetNodes(), nSttNd ), aEnd( GetNodes(), nEndNd );
+ SwSectionFmt* pFmt = MakeSectionFmt( 0 );
+ if(pSet)
+ pFmt->SetFmtAttr(*pSet);
+
+// --aEnd; // im InsertSection ist Ende inclusive
+
+ SwSectionNode *const pNewSectionNode =
+ GetNodes().InsertTextSection(aStt, *pFmt, aSectionData, &rTOX, &aEnd);
+ if (!pNewSectionNode)
+ {
+ DelSectionFmt( pFmt );
+ return 0;
+ }
+
+ SwTOXBaseSection *const pNewSection(
+ dynamic_cast<SwTOXBaseSection*>(& pNewSectionNode->GetSection()));
+ pNewSection->SetTOXName(sSectNm); // rTOX may have had no name...
+ return pNewSection;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Aktuelles Verzeichnis ermitteln
+ --------------------------------------------------------------------*/
+
+const SwTOXBase* SwDoc::GetCurTOX( const SwPosition& rPos ) const
+{
+ const SwNode& rNd = rPos.nNode.GetNode();
+ const SwSectionNode* pSectNd = rNd.FindSectionNode();
+ while( pSectNd )
+ {
+ SectionType eT = pSectNd->GetSection().GetType();
+ if( TOX_CONTENT_SECTION == eT )
+ {
+ ASSERT( pSectNd->GetSection().ISA( SwTOXBaseSection ),
+ "keine TOXBaseSection!" );
+ SwTOXBaseSection& rTOXSect = (SwTOXBaseSection&)
+ pSectNd->GetSection();
+ return &rTOXSect;
+ }
+ pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode();
+ }
+ return 0;
+}
+/* -----------------01.09.99 16:01-------------------
+
+ --------------------------------------------------*/
+const SwAttrSet& SwDoc::GetTOXBaseAttrSet(const SwTOXBase& rTOXBase) const
+{
+ ASSERT( rTOXBase.ISA( SwTOXBaseSection ), "no TOXBaseSection!" );
+ const SwTOXBaseSection& rTOXSect = (const SwTOXBaseSection&)rTOXBase;
+ SwSectionFmt* pFmt = rTOXSect.GetFmt();
+ ASSERT( pFmt, "invalid TOXBaseSection!" );
+ return pFmt->GetAttrSet();
+}
+/* -----------------02.09.99 07:48-------------------
+
+ --------------------------------------------------*/
+const SwTOXBase* SwDoc::GetDefaultTOXBase( TOXTypes eTyp, sal_Bool bCreate )
+{
+ SwTOXBase** prBase = 0;
+ switch(eTyp)
+ {
+ case TOX_CONTENT: prBase = &pDefTOXBases->pContBase; break;
+ case TOX_INDEX: prBase = &pDefTOXBases->pIdxBase; break;
+ case TOX_USER: prBase = &pDefTOXBases->pUserBase; break;
+ case TOX_TABLES: prBase = &pDefTOXBases->pTblBase; break;
+ case TOX_OBJECTS: prBase = &pDefTOXBases->pObjBase; break;
+ case TOX_ILLUSTRATIONS: prBase = &pDefTOXBases->pIllBase; break;
+ case TOX_AUTHORITIES: prBase = &pDefTOXBases->pAuthBase; break;
+ }
+ if(!(*prBase) && bCreate)
+ {
+ SwForm aForm(eTyp);
+ const SwTOXType* pType = GetTOXType(eTyp, 0);
+ (*prBase) = new SwTOXBase(pType, aForm, 0, pType->GetTypeName());
+ }
+ return (*prBase);
+}
+/* -----------------02.09.99 08:06-------------------
+
+ --------------------------------------------------*/
+void SwDoc::SetDefaultTOXBase(const SwTOXBase& rBase)
+{
+ SwTOXBase** prBase = 0;
+ switch(rBase.GetType())
+ {
+ case TOX_CONTENT: prBase = &pDefTOXBases->pContBase; break;
+ case TOX_INDEX: prBase = &pDefTOXBases->pIdxBase; break;
+ case TOX_USER: prBase = &pDefTOXBases->pUserBase; break;
+ case TOX_TABLES: prBase = &pDefTOXBases->pTblBase; break;
+ case TOX_OBJECTS: prBase = &pDefTOXBases->pObjBase; break;
+ case TOX_ILLUSTRATIONS: prBase = &pDefTOXBases->pIllBase; break;
+ case TOX_AUTHORITIES: prBase = &pDefTOXBases->pAuthBase; break;
+ }
+ if(*prBase)
+ delete (*prBase);
+ (*prBase) = new SwTOXBase(rBase);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnis loeschen
+ --------------------------------------------------------------------*/
+
+
+sal_Bool SwDoc::DeleteTOX( const SwTOXBase& rTOXBase, sal_Bool bDelNodes )
+{
+ // its only delete the TOX, not the nodes
+ sal_Bool bRet = sal_False;
+ ASSERT( rTOXBase.ISA( SwTOXBaseSection ), "keine TOXBaseSection!" );
+
+ const SwTOXBaseSection& rTOXSect = (const SwTOXBaseSection&)rTOXBase;
+ SwSectionFmt* pFmt = rTOXSect.GetFmt();
+ if( pFmt )
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_CLEARTOXRANGE, NULL );
+
+ /* Save the start node of the TOX' section. */
+ SwSectionNode * pMyNode = pFmt->GetSectionNode();
+ /* Save start node of section's surrounding. */
+ SwNode * pStartNd = pMyNode->StartOfSectionNode();
+
+ /* Look for point where to move the cursors in the area to
+ delete to. This is done by first searching forward from the
+ end of the TOX' section. If no content node is found behind
+ the TOX one is searched before it. If this is not
+ successfull, too, insert new text node behind the end of
+ the TOX' section. The cursors from the TOX' section will be
+ moved to the content node found or the new text node. */
+
+ /* Set PaM to end of TOX' section and search following content node.
+
+ aSearchPam will contain the point where to move the cursors
+ to. */
+ SwPaM aSearchPam(*pMyNode->EndOfSectionNode());
+ SwPosition aEndPos(*pStartNd->EndOfSectionNode());
+ if (! aSearchPam.Move() /* no content node found */
+ || *aSearchPam.GetPoint() >= aEndPos /* content node found
+ outside surrounding */
+ )
+ {
+ /* Set PaM to beginning of TOX' section and search previous
+ content node */
+ SwPaM aTmpPam(*pMyNode);
+ aSearchPam = aTmpPam;
+ SwPosition aStartPos(*pStartNd);
+
+ if ( ! aSearchPam.Move(fnMoveBackward) /* no content node found */
+ || *aSearchPam.GetPoint() <= aStartPos /* content node
+ found outside
+ surrounding */
+ )
+ {
+ /* There is no content node in the surrounding of
+ TOX'. Append text node behind TOX' section. */
+
+ SwPosition aInsPos(*pMyNode->EndOfSectionNode());
+ AppendTxtNode(aInsPos);
+
+ SwPaM aTmpPam1(aInsPos);
+ aSearchPam = aTmpPam1;
+ }
+ }
+
+
+ /* PaM containing the TOX. */
+ SwPaM aPam(*pMyNode->EndOfSectionNode(), *pMyNode);
+
+ /* Move cursors contained in TOX to point determined above. */
+ PaMCorrAbs(aPam, *aSearchPam.GetPoint());
+
+ if( !bDelNodes )
+ {
+ SwSections aArr( 0, 4 );
+ sal_uInt16 nCnt = pFmt->GetChildSections( aArr, SORTSECT_NOT, sal_False );
+ for( sal_uInt16 n = 0; n < nCnt; ++n )
+ {
+ SwSection* pSect = aArr[ n ];
+ if( TOX_HEADER_SECTION == pSect->GetType() )
+ {
+ DelSectionFmt( pSect->GetFmt(), bDelNodes );
+ }
+ }
+ }
+
+ DelSectionFmt( pFmt, bDelNodes );
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_CLEARTOXRANGE, NULL );
+ bRet = sal_True;
+ }
+
+ return bRet;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnistypen verwalten
+ --------------------------------------------------------------------*/
+
+sal_uInt16 SwDoc::GetTOXTypeCount(TOXTypes eTyp) const
+{
+ const SwTOXTypePtr * ppTTypes = pTOXTypes->GetData();
+ sal_uInt16 nCnt = 0;
+ for( sal_uInt16 n = 0; n < pTOXTypes->Count(); ++n, ++ppTTypes )
+ if( eTyp == (*ppTTypes)->GetType() )
+ ++nCnt;
+ return nCnt;
+}
+/*--------------------------------------------------------------------
+
+ --------------------------------------------------------------------*/
+const SwTOXType* SwDoc::GetTOXType( TOXTypes eTyp, sal_uInt16 nId ) const
+{
+ const SwTOXTypePtr * ppTTypes = pTOXTypes->GetData();
+ sal_uInt16 nCnt = 0;
+ for( sal_uInt16 n = 0; n < pTOXTypes->Count(); ++n, ++ppTTypes )
+ if( eTyp == (*ppTTypes)->GetType() && nCnt++ == nId )
+ return (*ppTTypes);
+ return 0;
+}
+
+/*--------------------------------------------------------------------
+
+ --------------------------------------------------------------------*/
+const SwTOXType* SwDoc::InsertTOXType( const SwTOXType& rTyp )
+{
+ SwTOXType * pNew = new SwTOXType( rTyp );
+ pTOXTypes->Insert( pNew, pTOXTypes->Count() );
+ return pNew;
+}
+/*--------------------------------------------------------------------
+
+ --------------------------------------------------------------------*/
+String SwDoc::GetUniqueTOXBaseName( const SwTOXType& rType,
+ const String* pChkStr ) const
+{
+ sal_uInt16 n;
+ const SwSectionNode* pSectNd;
+ const SwSection* pSect;
+
+ if(pChkStr && !pChkStr->Len())
+ pChkStr = 0;
+ String aName( rType.GetTypeName() );
+ xub_StrLen nNmLen = aName.Len();
+
+ sal_uInt16 nNum = 0;
+ sal_uInt16 nTmp = 0;
+ sal_uInt16 nFlagSize = ( pSectionFmtTbl->Count() / 8 ) +2;
+ sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
+ memset( pSetFlags, 0, nFlagSize );
+
+ for( n = 0; n < pSectionFmtTbl->Count(); ++n )
+ if( 0 != ( pSectNd = (*pSectionFmtTbl)[ n ]->GetSectionNode( sal_False ) )&&
+ TOX_CONTENT_SECTION == (pSect = &pSectNd->GetSection())->GetType())
+ {
+ const String& rNm = pSect->GetSectionName();
+ if( rNm.Match( aName ) == nNmLen )
+ {
+ // Nummer bestimmen und das Flag setzen
+ nNum = (sal_uInt16)rNm.Copy( nNmLen ).ToInt32();
+ if( nNum-- && nNum < pSectionFmtTbl->Count() )
+ pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
+ }
+ if( pChkStr && pChkStr->Equals( rNm ) )
+ pChkStr = 0;
+ }
+
+ if( !pChkStr )
+ {
+ // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
+ nNum = pSectionFmtTbl->Count();
+ for( n = 0; n < nFlagSize; ++n )
+ if( 0xff != ( nTmp = pSetFlags[ n ] ))
+ {
+ // also die Nummer bestimmen
+ nNum = n * 8;
+ while( nTmp & 1 )
+ ++nNum, nTmp >>= 1;
+ break;
+ }
+ }
+ delete [] pSetFlags;
+ if( pChkStr )
+ return *pChkStr;
+ return aName += String::CreateFromInt32( ++nNum );
+}
+
+/*--------------------------------------------------------------------
+
+ --------------------------------------------------------------------*/
+sal_Bool SwDoc::SetTOXBaseName(const SwTOXBase& rTOXBase, const String& rName)
+{
+ ASSERT( rTOXBase.ISA( SwTOXBaseSection ),
+ "keine TOXBaseSection!" );
+ SwTOXBaseSection* pTOX = (SwTOXBaseSection*)&rTOXBase;
+
+ String sTmp = GetUniqueTOXBaseName(*rTOXBase.GetTOXType(), &rName);
+ sal_Bool bRet = sTmp == rName;
+ if(bRet)
+ {
+ pTOX->SetTOXName(rName);
+ pTOX->SetSectionName(rName);
+ SetModified();
+ }
+ return bRet;
+}
+
+/* */
+
+const SwTxtNode* lcl_FindChapterNode( const SwNode& rNd, sal_uInt8 nLvl = 0 )
+{
+ const SwNode* pNd = &rNd;
+ if( pNd->GetNodes().GetEndOfExtras().GetIndex() > pNd->GetIndex() )
+ {
+ // then find the "Anchor" (Body) position
+ Point aPt;
+ SwNode2Layout aNode2Layout( *pNd, pNd->GetIndex() );
+ const SwFrm* pFrm = aNode2Layout.GetFrm( &aPt, 0, sal_False );
+
+ if( pFrm )
+ {
+ SwPosition aPos( *pNd );
+ pNd = GetBodyTxtNode( *pNd->GetDoc(), aPos, *pFrm );
+ ASSERT( pNd, "wo steht der Absatz" );
+ }
+ }
+ return pNd ? pNd->FindOutlineNodeOfLevel( nLvl ) : 0;
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnis-Klasse
+ --------------------------------------------------------------------*/
+
+SwTOXBaseSection::SwTOXBaseSection(SwTOXBase const& rBase, SwSectionFmt & rFmt)
+ : SwTOXBase( rBase )
+ , SwSection( TOX_CONTENT_SECTION, aEmptyStr, rFmt )
+{
+ SetProtect( rBase.IsProtected() );
+ SetSectionName( GetTOXName() );
+}
+
+
+SwTOXBaseSection::~SwTOXBaseSection()
+{
+}
+
+
+sal_Bool SwTOXBaseSection::SetPosAtStartEnd( SwPosition& rPos, sal_Bool bAtStart ) const
+{
+ sal_Bool bRet = sal_False;
+ const SwSectionNode* pSectNd = GetFmt()->GetSectionNode();
+ if( pSectNd )
+ {
+ SwCntntNode* pCNd;
+ xub_StrLen nC = 0;
+ if( bAtStart )
+ {
+ rPos.nNode = *pSectNd;
+ pCNd = pSectNd->GetDoc()->GetNodes().GoNext( &rPos.nNode );
+ }
+ else
+ {
+ rPos.nNode = *pSectNd->EndOfSectionNode();
+ pCNd = pSectNd->GetDoc()->GetNodes().GoPrevious( &rPos.nNode );
+ if( pCNd ) nC = pCNd->Len();
+ }
+ rPos.nContent.Assign( pCNd, nC );
+ bRet = sal_True;
+ }
+ return bRet;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnisinhalt zusammensammeln
+ --------------------------------------------------------------------*/
+
+void SwTOXBaseSection::Update(const SfxItemSet* pAttr,
+ const bool _bNewTOX )
+{
+ const SwSectionNode* pSectNd;
+ if( !SwTOXBase::GetRegisteredIn()->GetDepends() ||
+ !GetFmt() || 0 == (pSectNd = GetFmt()->GetSectionNode() ) ||
+ !pSectNd->GetNodes().IsDocNodes() ||
+ IsHiddenFlag() )
+ return;
+
+ SwDoc* pDoc = (SwDoc*)pSectNd->GetDoc();
+
+ DBG_ASSERT(pDoc != NULL, "Where is the document?");
+
+ if(pAttr && pDoc && GetFmt())
+ pDoc->ChgFmt(*GetFmt(), *pAttr);
+
+ // OD 18.03.2003 #106329# - determine default page description, which
+ // will be used by the content nodes, if no approriate one is found.
+ const SwPageDesc* pDefaultPageDesc;
+ {
+ pDefaultPageDesc =
+ pSectNd->GetSection().GetFmt()->GetPageDesc().GetPageDesc();
+ if ( !_bNewTOX && !pDefaultPageDesc )
+ {
+ // determine page description of table-of-content
+ sal_uInt32 nPgDescNdIdx = pSectNd->GetIndex() + 1;
+ sal_uInt32* pPgDescNdIdx = &nPgDescNdIdx;
+ pDefaultPageDesc = pSectNd->FindPageDesc( sal_False, pPgDescNdIdx );
+ if ( nPgDescNdIdx < pSectNd->GetIndex() )
+ {
+ pDefaultPageDesc = 0;
+ }
+ }
+ // OD 28.04.2003 #109166# - consider end node of content section in the
+ // node array.
+ if ( !pDefaultPageDesc &&
+ ( pSectNd->EndOfSectionNode()->GetIndex() <
+ (pSectNd->GetNodes().GetEndOfContent().GetIndex() - 1) )
+ )
+ {
+ // determine page description of content after table-of-content
+ SwNodeIndex aIdx( *(pSectNd->EndOfSectionNode()) );
+ const SwCntntNode* pNdAfterTOX = pSectNd->GetNodes().GoNext( &aIdx );
+ const SwAttrSet& aNdAttrSet = pNdAfterTOX->GetSwAttrSet();
+ const SvxBreak eBreak = aNdAttrSet.GetBreak().GetBreak();
+ if ( !( eBreak == SVX_BREAK_PAGE_BEFORE ||
+ eBreak == SVX_BREAK_PAGE_BOTH )
+ )
+ {
+ pDefaultPageDesc = pNdAfterTOX->FindPageDesc( sal_False );
+ }
+ }
+ // OD 28.04.2003 #109166# - consider start node of content section in
+ // the node array.
+ if ( !pDefaultPageDesc &&
+ ( pSectNd->GetIndex() >
+ (pSectNd->GetNodes().GetEndOfContent().StartOfSectionIndex() + 1) )
+ )
+ {
+ // determine page description of content before table-of-content
+ SwNodeIndex aIdx( *pSectNd );
+ pDefaultPageDesc =
+ pSectNd->GetNodes().GoPrevious( &aIdx )->FindPageDesc( sal_False );
+
+ }
+ if ( !pDefaultPageDesc )
+ {
+ // determine default page description
+ pDefaultPageDesc =
+ &const_cast<const SwDoc *>(pDoc)->GetPageDesc( 0 );
+ }
+ }
+
+ pDoc->SetModified();
+
+ // get current Language
+ SwTOXInternational aIntl( GetLanguage(),
+ TOX_INDEX == GetTOXType()->GetType() ?
+ GetOptions() : 0,
+ GetSortAlgorithm() );
+
+ aSortArr.DeleteAndDestroy( 0, aSortArr.Count() );
+
+ // find the first layout node for this TOX, if it only find the content
+ // in his own chapter
+ const SwTxtNode* pOwnChapterNode = IsFromChapter()
+ ? ::lcl_FindChapterNode( *pSectNd, 0 )
+ : 0;
+
+ SwNode2Layout aN2L( *pSectNd );
+ ((SwSectionNode*)pSectNd)->DelFrms();
+
+ // remove old content an insert one empty textnode (to hold the layout!)
+ SwTxtNode* pFirstEmptyNd;
+ {
+ pDoc->DeleteRedline( *pSectNd, true, USHRT_MAX );
+
+ SwNodeIndex aSttIdx( *pSectNd, +1 );
+ SwNodeIndex aEndIdx( *pSectNd->EndOfSectionNode() );
+ pFirstEmptyNd = pDoc->GetNodes().MakeTxtNode( aEndIdx,
+ pDoc->GetTxtCollFromPool( RES_POOLCOLL_TEXT ) );
+
+ {
+ // Task 70995 - save and restore PageDesc and Break Attributes
+ SwNodeIndex aNxtIdx( aSttIdx );
+ const SwCntntNode* pCNd = aNxtIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = pDoc->GetNodes().GoNext( &aNxtIdx );
+ if( pCNd->HasSwAttrSet() )
+ {
+ SfxItemSet aBrkSet( pDoc->GetAttrPool(), aBreakSetRange );
+ aBrkSet.Put( *pCNd->GetpSwAttrSet() );
+ if( aBrkSet.Count() )
+ pFirstEmptyNd->SetAttr( aBrkSet );
+ }
+ }
+ aEndIdx--;
+ SwPosition aPos( aEndIdx, SwIndex( pFirstEmptyNd, 0 ));
+ pDoc->CorrAbs( aSttIdx, aEndIdx, aPos, sal_True );
+
+ // delete all before
+ DelFlyInRange( aSttIdx, aEndIdx );
+ _DelBookmarks( aSttIdx, aEndIdx );
+
+ pDoc->GetNodes().Delete( aSttIdx, aEndIdx.GetIndex() - aSttIdx.GetIndex() );
+
+ }
+
+ //
+ // insert title of TOX
+ if( GetTitle().Len() )
+ {
+ // then insert the headline section
+ SwNodeIndex aIdx( *pSectNd, +1 );
+
+ SwTxtNode* pHeadNd = pDoc->GetNodes().MakeTxtNode( aIdx,
+ GetTxtFmtColl( FORM_TITLE ) );
+ pHeadNd->InsertText( GetTitle(), SwIndex( pHeadNd ) );
+
+ String sNm( GetTOXName() );
+// ??Resource
+sNm.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "_Head" ));
+
+ SwSectionData headerData( TOX_HEADER_SECTION, sNm );
+
+ SwNodeIndex aStt( *pHeadNd ); aIdx--;
+ SwSectionFmt* pSectFmt = pDoc->MakeSectionFmt( 0 );
+ pDoc->GetNodes().InsertTextSection(
+ aStt, *pSectFmt, headerData, 0, &aIdx, true, false);
+ }
+
+ // jetzt waere ein prima Zeitpunkt, um die Numerierung zu updaten
+ pDoc->UpdateNumRule();
+
+ if( GetCreateType() & nsSwTOXElement::TOX_MARK )
+ UpdateMarks( aIntl, pOwnChapterNode );
+
+ if( GetCreateType() & nsSwTOXElement::TOX_OUTLINELEVEL )
+ UpdateOutline( pOwnChapterNode );
+
+ if( GetCreateType() & nsSwTOXElement::TOX_TEMPLATE )
+ UpdateTemplate( pOwnChapterNode );
+
+ if( GetCreateType() & nsSwTOXElement::TOX_OLE ||
+ TOX_OBJECTS == SwTOXBase::GetType())
+ UpdateCntnt( nsSwTOXElement::TOX_OLE, pOwnChapterNode );
+
+ if( GetCreateType() & nsSwTOXElement::TOX_TABLE ||
+ (TOX_TABLES == SwTOXBase::GetType() && IsFromObjectNames()) )
+ UpdateTable( pOwnChapterNode );
+
+ if( GetCreateType() & nsSwTOXElement::TOX_GRAPHIC ||
+ (TOX_ILLUSTRATIONS == SwTOXBase::GetType() && IsFromObjectNames()))
+ UpdateCntnt( nsSwTOXElement::TOX_GRAPHIC, pOwnChapterNode );
+
+ if( GetSequenceName().Len() && !IsFromObjectNames() &&
+ (TOX_TABLES == SwTOXBase::GetType() ||
+ TOX_ILLUSTRATIONS == SwTOXBase::GetType() ) )
+ UpdateSequence( pOwnChapterNode );
+
+ if( GetCreateType() & nsSwTOXElement::TOX_FRAME )
+ UpdateCntnt( nsSwTOXElement::TOX_FRAME, pOwnChapterNode );
+
+ if(TOX_AUTHORITIES == SwTOXBase::GetType())
+ UpdateAuthorities( aIntl );
+
+ // Bei Bedarf Alphadelimitter einfuegen (nur bei Stichwoertern)
+ //
+ if( TOX_INDEX == SwTOXBase::GetType() &&
+ ( GetOptions() & nsSwTOIOptions::TOI_ALPHA_DELIMITTER ) )
+ InsertAlphaDelimitter( aIntl );
+
+ // sortierte Liste aller Verzeichnismarken und Verzeichnisbereiche
+ void* p = 0;
+ String* pStr = 0;
+ sal_uInt16 nCnt = 0, nFormMax = GetTOXForm().GetFormMax();
+ SvStringsDtor aStrArr( (sal_uInt8)nFormMax );
+ SvPtrarr aCollArr( (sal_uInt8)nFormMax );
+ for( ; nCnt < nFormMax; ++nCnt )
+ {
+ aCollArr.Insert( p, nCnt );
+ aStrArr.Insert( pStr, nCnt );
+ }
+
+ SwNodeIndex aInsPos( *pFirstEmptyNd, 1 );
+ for( nCnt = 0; nCnt < aSortArr.Count(); ++nCnt )
+ {
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ // setze den Text in das Verzeichniss
+ sal_uInt16 nLvl = aSortArr[ nCnt ]->GetLevel();
+ SwTxtFmtColl* pColl = (SwTxtFmtColl*)aCollArr[ nLvl ];
+ if( !pColl )
+ {
+ pColl = GetTxtFmtColl( nLvl );
+ aCollArr.Remove( nLvl );
+ p = pColl;
+ aCollArr.Insert( p , nLvl );
+ }
+
+ // Generierung: dynamische TabStops setzen
+ SwTxtNode* pTOXNd = pDoc->GetNodes().MakeTxtNode( aInsPos , pColl );
+ aSortArr[ nCnt ]->pTOXNd = pTOXNd;
+
+ // Generierung: Form auswerten und Platzhalter
+ // fuer die Seitennummer eintragen
+ //if it is a TOX_INDEX and the SwForm IsCommaSeparated()
+ // then a range of entries must be generated into one paragraph
+ sal_uInt16 nRange = 1;
+ if(TOX_INDEX == SwTOXBase::GetType() &&
+ GetTOXForm().IsCommaSeparated() &&
+ aSortArr[nCnt]->GetType() == TOX_SORT_INDEX)
+ {
+ const SwTOXMark& rMark = aSortArr[nCnt]->pTxtMark->GetTOXMark();
+ const String sPrimKey = rMark.GetPrimaryKey();
+ const String sSecKey = rMark.GetSecondaryKey();
+ const SwTOXMark* pNextMark = 0;
+ while(aSortArr.Count() > (nCnt + nRange)&&
+ aSortArr[nCnt + nRange]->GetType() == TOX_SORT_INDEX &&
+ 0 != (pNextMark = &(aSortArr[nCnt + nRange]->pTxtMark->GetTOXMark())) &&
+ pNextMark->GetPrimaryKey() == sPrimKey &&
+ pNextMark->GetSecondaryKey() == sSecKey)
+ nRange++;
+ }
+ // OD 18.03.2003 #106329# - pass node index of table-of-content section
+ // and default page description to method <GenerateText(..)>.
+ GenerateText( nCnt, nRange, aStrArr, pSectNd->GetIndex(), pDefaultPageDesc );
+ nCnt += nRange - 1;
+ }
+
+ // delete the first dummy node and remove all Cursor into the prev node
+ aInsPos = *pFirstEmptyNd;
+ {
+ SwPaM aCorPam( *pFirstEmptyNd );
+ aCorPam.GetPoint()->nContent.Assign( pFirstEmptyNd, 0 );
+ if( !aCorPam.Move( fnMoveForward ) )
+ aCorPam.Move( fnMoveBackward );
+ SwNodeIndex aEndIdx( aInsPos, 1 );
+ pDoc->CorrAbs( aInsPos, aEndIdx, *aCorPam.GetPoint(), sal_True );
+
+ // Task 70995 - save and restore PageDesc and Break Attributes
+ if( pFirstEmptyNd->HasSwAttrSet() )
+ {
+ if( GetTitle().Len() )
+ aEndIdx = *pSectNd;
+ else
+ aEndIdx = *pFirstEmptyNd;
+ SwCntntNode* pCNd = pDoc->GetNodes().GoNext( &aEndIdx );
+ if( pCNd ) // Robust against defect documents, e.g. i60336
+ pCNd->SetAttr( *pFirstEmptyNd->GetpSwAttrSet() );
+ }
+ }
+
+ // now create the new Frames
+ sal_uLong nIdx = pSectNd->GetIndex();
+ // don't delete if index is empty
+ if(nIdx + 2 < pSectNd->EndOfSectionIndex())
+ pDoc->GetNodes().Delete( aInsPos, 1 );
+
+ aN2L.RestoreUpperFrms( pDoc->GetNodes(), nIdx, nIdx + 1 );
+ if(pDoc->GetRootFrm())
+ SwFrm::CheckPageDescs( (SwPageFrm*)pDoc->GetRootFrm()->Lower() );
+
+ SetProtect( SwTOXBase::IsProtected() );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: AlphaDelimitter einfuegen
+ --------------------------------------------------------------------*/
+
+
+void SwTOXBaseSection::InsertAlphaDelimitter( const SwTOXInternational& rIntl )
+{
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ String sDeli, sLastDeli;
+ sal_uInt16 i = 0;
+ while( i < aSortArr.Count() )
+ {
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ sal_uInt16 nLevel = aSortArr[i]->GetLevel();
+
+ // Alpha-Delimitter ueberlesen
+ if( nLevel == FORM_ALPHA_DELIMITTER )
+ continue;
+
+ String sMyString, sMyStringReading;
+ aSortArr[i]->GetTxt( sMyString, sMyStringReading );
+
+ sDeli = rIntl.GetIndexKey( sMyString, sMyStringReading,
+ aSortArr[i]->GetLocale() );
+
+ // Delimitter schon vorhanden ??
+ if( sDeli.Len() && sLastDeli != sDeli )
+ {
+ // alle kleiner Blank wollen wir nicht haben -> sind Sonderzeichen
+ if( ' ' <= sDeli.GetChar( 0 ) )
+ {
+ SwTOXCustom* pCst = new SwTOXCustom( sDeli, aEmptyStr, FORM_ALPHA_DELIMITTER,
+ rIntl, aSortArr[i]->GetLocale() );
+ aSortArr.Insert( pCst, i++ );
+ }
+ sLastDeli = sDeli;
+ }
+
+ // Skippen bis gleibhes oder kleineres Level erreicht ist
+ do {
+ i++;
+ } while (i < aSortArr.Count() && aSortArr[i]->GetLevel() > nLevel);
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Template auswerten
+ --------------------------------------------------------------------*/
+
+SwTxtFmtColl* SwTOXBaseSection::GetTxtFmtColl( sal_uInt16 nLevel )
+{
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ const String& rName = GetTOXForm().GetTemplate( nLevel );
+ SwTxtFmtColl* pColl = rName.Len() ? pDoc->FindTxtFmtCollByName(rName) :0;
+ if( !pColl )
+ {
+ sal_uInt16 nPoolFmt = 0;
+ const TOXTypes eMyType = SwTOXBase::GetType();
+ switch( eMyType )
+ {
+ case TOX_INDEX: nPoolFmt = RES_POOLCOLL_TOX_IDXH; break;
+ case TOX_USER:
+ if( nLevel < 6 )
+ nPoolFmt = RES_POOLCOLL_TOX_USERH;
+ else
+ nPoolFmt = RES_POOLCOLL_TOX_USER6 - 6;
+ break;
+ case TOX_ILLUSTRATIONS: nPoolFmt = RES_POOLCOLL_TOX_ILLUSH; break;
+ case TOX_OBJECTS: nPoolFmt = RES_POOLCOLL_TOX_OBJECTH; break;
+ case TOX_TABLES: nPoolFmt = RES_POOLCOLL_TOX_TABLESH; break;
+ case TOX_AUTHORITIES: nPoolFmt = RES_POOLCOLL_TOX_AUTHORITIESH; break;
+
+ case TOX_CONTENT:
+ // im Content Bereich gibt es einen Sprung!
+ if( nLevel < 6 )
+ nPoolFmt = RES_POOLCOLL_TOX_CNTNTH;
+ else
+ nPoolFmt = RES_POOLCOLL_TOX_CNTNT6 - 6;
+ break;
+ }
+
+ if(eMyType == TOX_AUTHORITIES && nLevel)
+ nPoolFmt = nPoolFmt + 1;
+ else if(eMyType == TOX_INDEX && nLevel)
+ {
+ //pool: Level 1,2,3, Delimiter
+ //SwForm: Delimiter, Level 1,2,3
+ nPoolFmt += 1 == nLevel ? nLevel + 3 : nLevel - 1;
+ }
+ else
+ nPoolFmt = nPoolFmt + nLevel;
+ pColl = pDoc->GetTxtCollFromPool( nPoolFmt );
+ }
+ return pColl;
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Aus Markierungen erzeugen
+ --------------------------------------------------------------------*/
+
+void SwTOXBaseSection::UpdateMarks( const SwTOXInternational& rIntl,
+ const SwTxtNode* pOwnChapterNode )
+{
+ const SwModify* pType = SwTOXBase::GetRegisteredIn();
+ if( !pType->GetDepends() )
+ return;
+
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ TOXTypes eTOXTyp = GetTOXType()->GetType();
+ SwClientIter aIter( *(SwModify*)pType );
+
+ SwTxtTOXMark* pTxtMark;
+ SwTOXMark* pMark;
+ for( pMark = (SwTOXMark*)aIter.First( TYPE( SwTOXMark )); pMark;
+ pMark = (SwTOXMark*)aIter.Next() )
+ {
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ if( pMark->GetTOXType()->GetType() == eTOXTyp &&
+ 0 != ( pTxtMark = pMark->GetTxtTOXMark() ) )
+ {
+ const SwTxtNode* pTOXSrc = pTxtMark->GetpTxtNd();
+ // nur TOXMarks einfuegen die im Doc stehen
+ // nicht die, die im UNDO stehen
+ //
+ // if selected use marks from the same chapter only
+ if( pTOXSrc->GetNodes().IsDocNodes() &&
+ pTOXSrc->GetTxt().Len() && pTOXSrc->GetDepends() &&
+ pTOXSrc->GetFrm() &&
+ (!IsFromChapter() || ::lcl_FindChapterNode( *pTOXSrc, 0 ) == pOwnChapterNode ) &&
+ !pTOXSrc->HasHiddenParaField() &&
+ !SwScriptInfo::IsInHiddenRange( *pTOXSrc, *pTxtMark->GetStart() ) )
+ {
+ SwTOXSortTabBase* pBase = 0;
+ if(TOX_INDEX == eTOXTyp)
+ {
+ // Stichwortverzeichnismarkierung
+ lang::Locale aLocale;
+ if ( pBreakIt->GetBreakIter().is() )
+ {
+ aLocale = pBreakIt->GetLocale(
+ pTOXSrc->GetLang( *pTxtMark->GetStart() ) );
+ }
+
+ pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
+ GetOptions(), FORM_ENTRY, rIntl, aLocale );
+ InsertSorted(pBase);
+ if(GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY &&
+ pTxtMark->GetTOXMark().GetPrimaryKey().Len())
+ {
+ pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
+ GetOptions(), FORM_PRIMARY_KEY, rIntl, aLocale );
+ InsertSorted(pBase);
+ if(pTxtMark->GetTOXMark().GetSecondaryKey().Len())
+ {
+ pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
+ GetOptions(), FORM_SECONDARY_KEY, rIntl, aLocale );
+ InsertSorted(pBase);
+ }
+ }
+ }
+ else if( TOX_USER == eTOXTyp ||
+ pMark->GetLevel() <= GetLevel())
+ { // Inhaltsberzeichnismarkierung
+ // also used for user marks
+ pBase = new SwTOXContent( *pTOXSrc, pTxtMark, rIntl );
+ InsertSorted(pBase);
+ }
+ }
+ }
+ }
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnisinhalt aus Gliederungsebene generieren
+ --------------------------------------------------------------------*/
+
+
+void SwTOXBaseSection::UpdateOutline( const SwTxtNode* pOwnChapterNode )
+{
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ SwNodes& rNds = pDoc->GetNodes();
+
+ const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
+ for( sal_uInt16 n = 0; n < rOutlNds.Count(); ++n )
+ {
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+ SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
+ if( pTxtNd && pTxtNd->Len() && pTxtNd->GetDepends() &&
+ //sal_uInt16(pTxtNd->GetTxtColl()->GetOutlineLevel()+1) <= GetLevel() && //#outline level,zhaojianwei
+ sal_uInt16( pTxtNd->GetAttrOutlineLevel()) <= GetLevel() && //<-end,zhaojianwei
+ pTxtNd->GetFrm() &&
+ !pTxtNd->HasHiddenParaField() &&
+ !pTxtNd->HasHiddenCharAttribute( true ) &&
+ ( !IsFromChapter() ||
+ ::lcl_FindChapterNode( *pTxtNd, 0 ) == pOwnChapterNode ))
+ {
+ SwTOXPara * pNew = new SwTOXPara( *pTxtNd, nsSwTOXElement::TOX_OUTLINELEVEL );
+ InsertSorted( pNew );
+ }
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnisinhalt aus Vorlagenbereichen generieren
+ --------------------------------------------------------------------*/
+
+void SwTOXBaseSection::UpdateTemplate( const SwTxtNode* pOwnChapterNode )
+{
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
+ {
+ String sTmpStyleNames = GetStyleNames(i);
+ sal_uInt16 nTokenCount = sTmpStyleNames.GetTokenCount(TOX_STYLE_DELIMITER);
+ for( sal_uInt16 nStyle = 0; nStyle < nTokenCount; ++nStyle )
+ {
+ SwTxtFmtColl* pColl = pDoc->FindTxtFmtCollByName(
+ sTmpStyleNames.GetToken( nStyle,
+ TOX_STYLE_DELIMITER ));
+ //TODO: no outline Collections in content indexes if OutlineLevels are already included
+ if( !pColl ||
+ ( TOX_CONTENT == SwTOXBase::GetType() &&
+ GetCreateType() & nsSwTOXElement::TOX_OUTLINELEVEL &&
+ //NO_NUMBERING != pColl->GetOutlineLevel() ) )//#outline level,zhaojianwei
+ pColl->IsAssignedToListLevelOfOutlineStyle()) )//<-end,zhaojianwei
+ continue;
+
+ SwClientIter aIter( *pColl );
+ SwTxtNode* pTxtNd = (SwTxtNode*)aIter.First( TYPE( SwTxtNode ));
+ for( ; pTxtNd; pTxtNd = (SwTxtNode*)aIter.Next() )
+ {
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ if( pTxtNd->GetTxt().Len() && pTxtNd->GetFrm() &&
+ pTxtNd->GetNodes().IsDocNodes() &&
+ ( !IsFromChapter() || pOwnChapterNode ==
+ ::lcl_FindChapterNode( *pTxtNd, 0 ) ) )
+ {
+ SwTOXPara * pNew = new SwTOXPara( *pTxtNd, nsSwTOXElement::TOX_TEMPLATE, i + 1 );
+ InsertSorted(pNew);
+ }
+ }
+ }
+ }
+}
+
+/* -----------------14.07.99 09:59-------------------
+ Description: generate content from sequence fields
+ --------------------------------------------------*/
+void SwTOXBaseSection::UpdateSequence( const SwTxtNode* pOwnChapterNode )
+{
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ SwFieldType* pSeqFld = pDoc->GetFldType(RES_SETEXPFLD, GetSequenceName(), false);
+ if(!pSeqFld)
+ return;
+
+ SwClientIter aIter( *pSeqFld );
+ SwFmtFld* pFmtFld = (SwFmtFld*)aIter.First( TYPE( SwFmtFld ));
+ for( ; pFmtFld; pFmtFld = (SwFmtFld*)aIter.Next() )
+ {
+ const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
+ if(!pTxtFld)
+ continue;
+ const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ if( rTxtNode.GetTxt().Len() && rTxtNode.GetFrm() &&
+ rTxtNode.GetNodes().IsDocNodes() &&
+ ( !IsFromChapter() ||
+ ::lcl_FindChapterNode( rTxtNode, 0 ) == pOwnChapterNode ) )
+ {
+ SwTOXPara * pNew = new SwTOXPara( rTxtNode, nsSwTOXElement::TOX_SEQUENCE, 1 );
+ //set indexes if the number or the reference text are to be displayed
+ if( GetCaptionDisplay() == CAPTION_TEXT )
+ {
+ pNew->SetStartIndex(
+ SwGetExpField::GetReferenceTextPos( *pFmtFld, *pDoc ));
+ }
+ else if(GetCaptionDisplay() == CAPTION_NUMBER)
+ {
+ pNew->SetEndIndex(*pTxtFld->GetStart() + 1);
+ }
+ InsertSorted(pNew);
+ }
+ }
+}
+/* -----------------15.09.99 14:18-------------------
+
+ --------------------------------------------------*/
+void SwTOXBaseSection::UpdateAuthorities( const SwTOXInternational& rIntl )
+{
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ SwFieldType* pAuthFld = pDoc->GetFldType(RES_AUTHORITY, aEmptyStr, false);
+ if(!pAuthFld)
+ return;
+
+ SwClientIter aIter( *pAuthFld );
+ SwFmtFld* pFmtFld = (SwFmtFld*)aIter.First( TYPE( SwFmtFld ));
+ for( ; pFmtFld; pFmtFld = (SwFmtFld*)aIter.Next() )
+ {
+ const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
+ //undo
+ if(!pTxtFld)
+ continue;
+ const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+// const SwTxtNode* pChapterCompareNode = 0;
+
+ if( rTxtNode.GetTxt().Len() && rTxtNode.GetFrm() &&
+ rTxtNode.GetNodes().IsDocNodes() /*&&
+ (!IsFromChapter() || pChapterCompareNode == pOwnChapterNode) */)
+ {
+ //#106485# the body node has to be used!
+ SwCntntFrm *pFrm = rTxtNode.GetFrm();
+ SwPosition aFldPos(rTxtNode);
+ const SwTxtNode* pTxtNode = 0;
+ if(pFrm && !pFrm->IsInDocBody())
+ pTxtNode = GetBodyTxtNode( *pDoc, aFldPos, *pFrm );
+ if(!pTxtNode)
+ pTxtNode = &rTxtNode;
+ SwTOXAuthority* pNew = new SwTOXAuthority( *pTxtNode, *pFmtFld, rIntl );
+
+ InsertSorted(pNew);
+ }
+ }
+}
+
+long lcl_IsSOObject( const SvGlobalName& rFactoryNm )
+{
+ static struct _SoObjType {
+ long nFlag;
+ // GlobalNameId
+ struct _GlobalNameIds {
+ sal_uInt32 n1;
+ sal_uInt16 n2, n3;
+ sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
+ } aGlNmIds[4];
+ } aArr[] = {
+ { nsSwTOOElements::TOO_MATH,
+ { {SO3_SM_CLASSID_60},{SO3_SM_CLASSID_50},
+ {SO3_SM_CLASSID_40},{SO3_SM_CLASSID_30} } },
+ { nsSwTOOElements::TOO_CHART,
+ { {SO3_SCH_CLASSID_60},{SO3_SCH_CLASSID_50},
+ {SO3_SCH_CLASSID_40},{SO3_SCH_CLASSID_30} } },
+ { nsSwTOOElements::TOO_CALC,
+ { {SO3_SC_CLASSID_60},{SO3_SC_CLASSID_50},
+ {SO3_SC_CLASSID_40},{SO3_SC_CLASSID_30} } },
+ { nsSwTOOElements::TOO_DRAW_IMPRESS,
+ { {SO3_SIMPRESS_CLASSID_60},{SO3_SIMPRESS_CLASSID_50},
+ {SO3_SIMPRESS_CLASSID_40},{SO3_SIMPRESS_CLASSID_30} } },
+ { nsSwTOOElements::TOO_DRAW_IMPRESS,
+ { {SO3_SDRAW_CLASSID_60},{SO3_SDRAW_CLASSID_50}}},
+ { 0,{{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0} } }
+ };
+
+ long nRet = 0;
+ for( const _SoObjType* pArr = aArr; !nRet && pArr->nFlag; ++pArr )
+ for ( int n = 0; n < 4; ++n )
+ {
+ const _SoObjType::_GlobalNameIds& rId = pArr->aGlNmIds[ n ];
+ if( !rId.n1 )
+ break;
+ SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3,
+ rId.b8, rId.b9, rId.b10, rId.b11,
+ rId.b12, rId.b13, rId.b14, rId.b15 );
+ if( rFactoryNm == aGlbNm )
+ {
+ nRet = pArr->nFlag;
+ break;
+ }
+ }
+
+ return nRet;
+}
+
+void SwTOXBaseSection::UpdateCntnt( SwTOXElement eMyType,
+ const SwTxtNode* pOwnChapterNode )
+{
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ SwNodes& rNds = pDoc->GetNodes();
+ // auf den 1. Node der 1. Section
+ sal_uLong nIdx = rNds.GetEndOfAutotext().StartOfSectionIndex() + 2,
+ nEndIdx = rNds.GetEndOfAutotext().GetIndex();
+
+ while( nIdx < nEndIdx )
+ {
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ SwNode* pNd = rNds[ nIdx ];
+ SwCntntNode* pCNd = 0;
+ switch( eMyType )
+ {
+ case nsSwTOXElement::TOX_FRAME:
+ if( !pNd->IsNoTxtNode() )
+ {
+ pCNd = pNd->GetCntntNode();
+ if( !pCNd )
+ {
+ SwNodeIndex aTmp( *pNd );
+ pCNd = rNds.GoNext( &aTmp );
+ }
+ }
+ break;
+ case nsSwTOXElement::TOX_GRAPHIC:
+ if( pNd->IsGrfNode() )
+ pCNd = (SwCntntNode*)pNd;
+ break;
+ case nsSwTOXElement::TOX_OLE:
+ if( pNd->IsOLENode() )
+ {
+ sal_Bool bInclude = sal_True;
+ if(TOX_OBJECTS == SwTOXBase::GetType())
+ {
+ SwOLENode* pOLENode = pNd->GetOLENode();
+ long nMyOLEOptions = GetOLEOptions();
+ SwOLEObj& rOLEObj = pOLENode->GetOLEObj();
+
+ if( rOLEObj.IsOleRef() ) //Noch nicht geladen
+ {
+ SvGlobalName aTmpName = SvGlobalName( rOLEObj.GetOleRef()->getClassID() );
+ long nObj = ::lcl_IsSOObject( aTmpName );
+ bInclude = ( (nMyOLEOptions & nsSwTOOElements::TOO_OTHER) && 0 == nObj)
+ || (0 != (nMyOLEOptions & nObj));
+ }
+ else
+ {
+ DBG_ERROR("OLE-object nicht geladen?");
+ bInclude = sal_False;
+ }
+ }
+
+ if(bInclude)
+ pCNd = (SwCntntNode*)pNd;
+ }
+ break;
+ default: break;
+ }
+
+ if( pCNd )
+ {
+ //find node in body text
+ int nSetLevel = USHRT_MAX;
+
+ //#111105# tables of tables|illustrations|objects don't support hierarchies
+ if( IsLevelFromChapter() &&
+ TOX_TABLES != SwTOXBase::GetType() &&
+ TOX_ILLUSTRATIONS != SwTOXBase::GetType() &&
+ TOX_OBJECTS != SwTOXBase::GetType() )
+ {
+ const SwTxtNode* pOutlNd = ::lcl_FindChapterNode( *pCNd,
+ MAXLEVEL - 1 );
+ if( pOutlNd )
+ {
+ //sal_uInt16 nTmp = pOutlNd->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
+ //if( nTmp < NO_NUMBERING )
+ // nSetLevel = nTmp + 1;
+ if( pOutlNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle())
+ nSetLevel = pOutlNd->GetTxtColl()->GetAttrOutlineLevel() ;//<-end,zhaojianwei
+ }
+ }
+
+ if( pCNd->GetFrm() && ( !IsFromChapter() ||
+ ::lcl_FindChapterNode( *pCNd, 0 ) == pOwnChapterNode ))
+ {
+ SwTOXPara * pNew = new SwTOXPara( *pCNd, eMyType,
+ ( USHRT_MAX != nSetLevel )
+ ? static_cast<sal_uInt16>(nSetLevel)
+ : FORM_ALPHA_DELIMITTER );
+ InsertSorted( pNew );
+ }
+ }
+
+ nIdx = pNd->StartOfSectionNode()->EndOfSectionIndex() + 2; // 2 == End-/StartNode
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Tabelleneintraege zusammensuchen
+ --------------------------------------------------------------------*/
+
+void SwTOXBaseSection::UpdateTable( const SwTxtNode* pOwnChapterNode )
+{
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ SwNodes& rNds = pDoc->GetNodes();
+ const SwFrmFmts& rArr = *pDoc->GetTblFrmFmts();
+
+ for( sal_uInt16 n = 0; n < rArr.Count(); ++n )
+ {
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ SwTable* pTmpTbl = SwTable::FindTable( rArr[ n ] );
+ SwTableBox* pFBox;
+ if( pTmpTbl && 0 != (pFBox = pTmpTbl->GetTabSortBoxes()[0] ) &&
+ pFBox->GetSttNd() && pFBox->GetSttNd()->GetNodes().IsDocNodes() )
+ {
+ const SwTableNode* pTblNd = pFBox->GetSttNd()->FindTableNode();
+ SwNodeIndex aCntntIdx( *pTblNd, 1 );
+
+ SwCntntNode* pCNd;
+ while( 0 != ( pCNd = rNds.GoNext( &aCntntIdx ) ) &&
+ aCntntIdx.GetIndex() < pTblNd->EndOfSectionIndex() )
+ {
+ if( pCNd->GetFrm() && (!IsFromChapter() ||
+ ::lcl_FindChapterNode( *pCNd, 0 ) == pOwnChapterNode ))
+ {
+ SwTOXTable * pNew = new SwTOXTable( *pCNd );
+ if( IsLevelFromChapter() && TOX_TABLES != SwTOXBase::GetType())
+ {
+ const SwTxtNode* pOutlNd =
+ ::lcl_FindChapterNode( *pCNd, MAXLEVEL - 1 );
+ if( pOutlNd )
+ {
+ //sal_uInt16 nTmp = pOutlNd->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
+ //if( nTmp < NO_NUMBERING )
+ // pNew->SetLevel( nTmp + 1 );
+ if( pOutlNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle())
+ {
+ const int nTmp = pOutlNd->GetTxtColl()->GetAttrOutlineLevel();
+ pNew->SetLevel( static_cast<sal_uInt16>(nTmp) );//<-end ,zhaojianwei
+ }
+ }
+ }
+ InsertSorted(pNew);
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: String generieren anhand der Form
+ SonderZeichen 0-31 und 255 entfernen
+ --------------------------------------------------------------------*/
+
+String lcl_GetNumString( const SwTOXSortTabBase& rBase, sal_Bool bUsePrefix, sal_uInt8 nLevel )
+{
+ String sRet;
+
+ if( !rBase.pTxtMark && rBase.aTOXSources.Count() > 0 )
+ { // nur wenn es keine Marke ist
+ const SwTxtNode* pNd = rBase.aTOXSources[0].pNd->GetTxtNode();
+ if( pNd )
+ {
+ const SwNumRule* pRule = pNd->GetNumRule();
+
+ if( pRule && pNd->GetActualListLevel() < MAXLEVEL )
+ sRet = pNd->GetNumString(bUsePrefix, nLevel);
+ }
+ }
+ return sRet;
+}
+
+// OD 18.03.2003 #106329# - add parameter <_TOXSectNdIdx> and <_pDefaultPageDesc>
+// in order to control, which page description is used, no appropriate one is found.
+void SwTOXBaseSection::GenerateText( sal_uInt16 nArrayIdx,
+ sal_uInt16 nCount,
+ SvStringsDtor& ,
+ const sal_uInt32 _nTOXSectNdIdx,
+ const SwPageDesc* _pDefaultPageDesc )
+{
+ LinkStructArr aLinkArr;
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ //pTOXNd is only set at the first mark
+ SwTxtNode* pTOXNd = (SwTxtNode*)aSortArr[nArrayIdx]->pTOXNd;
+ String& rTxt = (String&)pTOXNd->GetTxt();
+ rTxt.Erase();
+ for(sal_uInt16 nIndex = nArrayIdx; nIndex < nArrayIdx + nCount; nIndex++)
+ {
+ if(nIndex > nArrayIdx)
+ rTxt.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ", " )); // comma separation
+ // String mit dem Pattern aus der Form initialisieren
+ const SwTOXSortTabBase& rBase = *aSortArr[nIndex];
+ sal_uInt16 nLvl = rBase.GetLevel();
+ ASSERT( nLvl < GetTOXForm().GetFormMax(), "ungueltiges FORM_LEVEL");
+
+ SvxTabStopItem aTStops( 0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
+ xub_StrLen nLinkStartPosition = STRING_NOTFOUND;
+ String sLinkCharacterStyle; //default to "Default" character style - which is none
+ String sURL;
+ // create an enumerator
+ // #i21237#
+ SwFormTokens aPattern = GetTOXForm().GetPattern(nLvl);
+ SwFormTokens::iterator aIt = aPattern.begin();
+ // remove text from node
+ while(aIt != aPattern.end()) // #i21237#
+ {
+ SwFormToken aToken = *aIt; // #i21237#
+ xub_StrLen nStartCharStyle = rTxt.Len();
+ switch( aToken.eTokenType )
+ {
+ case TOKEN_ENTRY_NO:
+ // fuer Inhaltsverzeichnis Numerierung
+ rTxt.Insert( lcl_GetNumString( rBase, aToken.nChapterFormat == CF_NUMBER, static_cast<sal_uInt8>(aToken.nOutlineLevel - 1)) );
+ break;
+
+ case TOKEN_ENTRY_TEXT:
+ {
+ SwIndex aIdx( pTOXNd, rTxt.Len() );
+ rBase.FillText( *pTOXNd, aIdx );
+ }
+ break;
+
+ case TOKEN_ENTRY:
+ {
+ // fuer Inhaltsverzeichnis Numerierung
+ rTxt.Insert( lcl_GetNumString( rBase, sal_True, MAXLEVEL ));
+
+ SwIndex aIdx( pTOXNd, rTxt.Len() );
+ rBase.FillText( *pTOXNd, aIdx );
+ }
+ break;
+
+ case TOKEN_TAB_STOP:
+ if (aToken.bWithTab) // #i21237#
+ rTxt.Append('\t');
+ //
+
+ if(SVX_TAB_ADJUST_END > aToken.eTabAlign)
+ {
+ const SvxLRSpaceItem& rLR =
+ (SvxLRSpaceItem&)pTOXNd->
+ SwCntntNode::GetAttr( RES_LR_SPACE, sal_True );
+
+ long nTabPosition = aToken.nTabStopPosition;
+ if( !GetTOXForm().IsRelTabPos() && rLR.GetTxtLeft() )
+ nTabPosition -= rLR.GetTxtLeft();
+ aTStops.Insert( SvxTabStop( nTabPosition,
+ aToken.eTabAlign,
+ cDfltDecimalChar,
+ aToken.cTabFillChar ));
+ }
+ else
+ {
+ const SwPageDesc* pPageDesc = ((SwFmtPageDesc&)pTOXNd->
+ SwCntntNode::GetAttr( RES_PAGEDESC )).GetPageDesc();
+
+ sal_Bool bCallFindRect = sal_True;
+ long nRightMargin;
+ if( pPageDesc )
+ {
+ const SwFrm* pFrm = pTOXNd->GetFrm( 0, 0, sal_True );
+ if( !pFrm || 0 == ( pFrm = pFrm->FindPageFrm() ) ||
+ pPageDesc != ((SwPageFrm*)pFrm)->GetPageDesc() )
+ // dann muss man ueber den PageDesc gehen
+ bCallFindRect = sal_False;
+ }
+
+ SwRect aNdRect;
+ if( bCallFindRect )
+ aNdRect = pTOXNd->FindLayoutRect( sal_True );
+
+ if( aNdRect.IsEmpty() )
+ {
+ // dann hilft alles nichts, wir muessen ueber die Seiten-
+ // vorlage gehen.
+ // OD 18.03.2003 #106329# - call
+ sal_uInt32 nPgDescNdIdx = pTOXNd->GetIndex() + 1;
+ sal_uInt32* pPgDescNdIdx = &nPgDescNdIdx;
+ pPageDesc = pTOXNd->FindPageDesc( sal_False, pPgDescNdIdx );
+ if ( !pPageDesc ||
+ *pPgDescNdIdx < _nTOXSectNdIdx )
+ {
+ // use default page description, if none is found
+ // or the found one is given by a node before the
+ // table-of-content section.
+ pPageDesc = _pDefaultPageDesc;
+ }
+
+ const SwFrmFmt& rPgDscFmt = pPageDesc->GetMaster();
+ nRightMargin = rPgDscFmt.GetFrmSize().GetWidth() -
+ rPgDscFmt.GetLRSpace().GetLeft() -
+ rPgDscFmt.GetLRSpace().GetRight();
+ }
+ else
+ nRightMargin = aNdRect.Width();
+ //#i24363# tab stops relative to indent
+ if( pDoc->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
+ {
+ //left margin of paragraph style
+ const SvxLRSpaceItem& rLRSpace = pTOXNd->GetTxtColl()->GetLRSpace();
+ nRightMargin -= rLRSpace.GetLeft();
+ nRightMargin -= rLRSpace.GetTxtFirstLineOfst();
+ }
+
+ aTStops.Insert( SvxTabStop( nRightMargin, SVX_TAB_ADJUST_RIGHT,
+ cDfltDecimalChar,
+ aToken.cTabFillChar ));
+ }
+ break;
+
+ case TOKEN_TEXT:
+ rTxt.Append( aToken.sText );
+ break;
+
+ case TOKEN_PAGE_NUMS:
+ // Platzhalter fuer Seitennummer(n) es wird nur der erste beachtet
+ //
+ {
+ // Die Anzahl der gleichen Eintrage bestimmt die Seitennummern-Pattern
+ //
+ sal_uInt16 nSize = rBase.aTOXSources.Count();
+ if( nSize > 0 )
+ {
+ String aInsStr( cNumRepl );
+ for(sal_uInt16 i=1; i < nSize; ++i)
+ {
+ aInsStr.AppendAscii( sPageDeli );
+ aInsStr += cNumRepl;
+ }
+ aInsStr += cEndPageNum;
+ rTxt.Append( aInsStr );
+ }
+// // Tab entfernen, wenn keine Seitennummer
+// else if( rTxt.Len() && '\t' == rTxt.GetChar( rTxt.Len() - 1 ))
+// rTxt.Erase( rTxt.Len()-1, 1 );
+ }
+ break;
+
+ case TOKEN_CHAPTER_INFO:
+ {
+ // ein bischen trickreich: suche irgend einen Frame
+ const SwTOXSource* pTOXSource = 0;
+ if(rBase.aTOXSources.Count())
+ pTOXSource = &rBase.aTOXSources[0];
+
+ // --> OD 2008-02-14 #i53420#
+// if( pTOXSource && pTOXSource->pNd
+// pTOXSource->pNd->IsTxtNode() )
+ if ( pTOXSource && pTOXSource->pNd &&
+ pTOXSource->pNd->IsCntntNode() )
+ // <--
+ {
+ const SwCntntFrm* pFrm = pTOXSource->pNd->GetFrm();
+ if( pFrm )
+ {
+ SwChapterFieldType aFldTyp;
+ SwChapterField aFld( &aFldTyp, aToken.nChapterFormat );
+ aFld.SetLevel( static_cast<sal_uInt8>(aToken.nOutlineLevel - 1) );
+ // --> OD 2008-02-14 #i53420#
+// aFld.ChangeExpansion( pFrm, (SwTxtNode*)pTOXSource->pNd, sal_True );
+ aFld.ChangeExpansion( pFrm,
+ dynamic_cast<const SwCntntNode*>(pTOXSource->pNd),
+ sal_True );
+ // <--
+ //---> i89791
+ // OD 2008-06-26 - continue to support CF_NUMBER
+ // and CF_NUM_TITLE in order to handle ODF 1.0/1.1
+ // written by OOo 3.x in the same way as OOo 2.x
+ // would handle them.
+ if ( CF_NUM_NOPREPST_TITLE == aToken.nChapterFormat ||
+ CF_NUMBER == aToken.nChapterFormat )
+ rTxt.Insert(aFld.GetNumber()); //get the string number without pre/postfix
+ else if ( CF_NUMBER_NOPREPST == aToken.nChapterFormat ||
+ CF_NUM_TITLE == aToken.nChapterFormat )
+ //<---
+ {
+ rTxt += aFld.GetNumber();
+ rTxt += ' ';
+ rTxt += aFld.GetTitle();
+ }
+ else if(CF_TITLE == aToken.nChapterFormat)
+ rTxt += aFld.GetTitle();
+ }
+ }
+ }
+ break;
+
+ case TOKEN_LINK_START:
+ nLinkStartPosition = rTxt.Len();
+ sLinkCharacterStyle = aToken.sCharStyleName;
+ break;
+
+ case TOKEN_LINK_END:
+ //TODO: only paired start/end tokens are valid
+ if( STRING_NOTFOUND != nLinkStartPosition)
+ {
+ SwIndex aIdx( pTOXNd, nLinkStartPosition );
+ //pTOXNd->Erase( aIdx, SwForm::nFormLinkSttLen );
+ xub_StrLen nEnd = rTxt.Len();
+
+ if( !sURL.Len() )
+ {
+ sURL = rBase.GetURL();
+ if( !sURL.Len() )
+ break;
+ }
+ LinkStruct* pNewLink = new LinkStruct(sURL, nLinkStartPosition,
+ nEnd);
+ pNewLink->aINetFmt.SetVisitedFmt(sLinkCharacterStyle);
+ pNewLink->aINetFmt.SetINetFmt(sLinkCharacterStyle);
+ if(sLinkCharacterStyle.Len())
+ {
+ sal_uInt16 nPoolId =
+ SwStyleNameMapper::GetPoolIdFromUIName( sLinkCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
+ pNewLink->aINetFmt.SetVisitedFmtId(nPoolId);
+ pNewLink->aINetFmt.SetINetFmtId(nPoolId);
+ }
+ else
+ {
+ pNewLink->aINetFmt.SetVisitedFmtId(USHRT_MAX);
+ pNewLink->aINetFmt.SetINetFmtId(USHRT_MAX);
+ }
+ aLinkArr.Insert( pNewLink, aLinkArr.Count() );
+ nLinkStartPosition = STRING_NOTFOUND;
+ sLinkCharacterStyle.Erase();
+ }
+ break;
+
+ case TOKEN_AUTHORITY:
+ {
+ ToxAuthorityField eField = (ToxAuthorityField)aToken.nAuthorityField;
+ SwIndex aIdx( pTOXNd, rTxt.Len() );
+ rBase.FillText( *pTOXNd, aIdx, static_cast<sal_uInt16>(eField) );
+ }
+ break;
+ case TOKEN_END: break;
+ }
+
+ if( aToken.sCharStyleName.Len() )
+ {
+ SwCharFmt* pCharFmt;
+ if( USHRT_MAX != aToken.nPoolId )
+ pCharFmt = pDoc->GetCharFmtFromPool( aToken.nPoolId );
+ else
+ pCharFmt = pDoc->FindCharFmtByName( aToken.sCharStyleName);
+
+ if (pCharFmt)
+ {
+ SwFmtCharFmt aFmt( pCharFmt );
+ pTOXNd->InsertItem( aFmt, nStartCharStyle,
+ rTxt.Len(), nsSetAttrMode::SETATTR_DONTEXPAND );
+ }
+ }
+
+ aIt++; // #i21237#
+ }
+
+ pTOXNd->SetAttr( aTStops );
+ }
+
+ if(aLinkArr.Count())
+ for(sal_uInt16 i = 0; i < aLinkArr.Count(); ++i )
+ {
+ LinkStruct* pTmp = aLinkArr.GetObject(i);
+ pTOXNd->InsertItem( pTmp->aINetFmt, pTmp->nStartTextPos,
+ pTmp->nEndTextPos);
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Seitennummer errechnen und nach dem Formatieren
+ eintragen
+ --------------------------------------------------------------------*/
+
+void SwTOXBaseSection::UpdatePageNum()
+{
+ if( !aSortArr.Count() )
+ return ;
+
+ // die aktuellen Seitennummern ins Verzeichnis eintragen
+ SwPageFrm* pAktPage = 0;
+ sal_uInt16 nPage = 0;
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+
+ SwTOXInternational aIntl( GetLanguage(),
+ TOX_INDEX == GetTOXType()->GetType() ?
+ GetOptions() : 0,
+ GetSortAlgorithm() );
+
+ for( sal_uInt16 nCnt = 0; nCnt < aSortArr.Count(); ++nCnt )
+ {
+ // Schleife ueber alle SourceNodes
+ SvUShorts aNums; //Die Seitennummern
+ SvPtrarr aDescs; //Die PageDescriptoren passend zu den Seitennummern.
+ SvUShorts* pMainNums = 0; // contains page numbers of main entries
+
+ // process run in lines
+ sal_uInt16 nRange = 0;
+ if(GetTOXForm().IsCommaSeparated() &&
+ aSortArr[nCnt]->GetType() == TOX_SORT_INDEX)
+ {
+ const SwTOXMark& rMark = aSortArr[nCnt]->pTxtMark->GetTOXMark();
+ const String sPrimKey = rMark.GetPrimaryKey();
+ const String sSecKey = rMark.GetSecondaryKey();
+ const SwTOXMark* pNextMark = 0;
+ while(aSortArr.Count() > (nCnt + nRange)&&
+ aSortArr[nCnt + nRange]->GetType() == TOX_SORT_INDEX &&
+ 0 != (pNextMark = &(aSortArr[nCnt + nRange]->pTxtMark->GetTOXMark())) &&
+ pNextMark->GetPrimaryKey() == sPrimKey &&
+ pNextMark->GetSecondaryKey() == sSecKey)
+ nRange++;
+ }
+ else
+ nRange = 1;
+
+ for(sal_uInt16 nRunInEntry = nCnt; nRunInEntry < nCnt + nRange; nRunInEntry++)
+ {
+ SwTOXSortTabBase* pSortBase = aSortArr[nRunInEntry];
+ sal_uInt16 nSize = pSortBase->aTOXSources.Count();
+ sal_uInt16 i;
+ for( sal_uInt16 j = 0; j < nSize; ++j )
+ {
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ SwTOXSource& rTOXSource = pSortBase->aTOXSources[j];
+ if( rTOXSource.pNd )
+ {
+ SwCntntFrm* pFrm = rTOXSource.pNd->GetFrm();
+ ASSERT( pFrm || pDoc->IsUpdateTOX(), "TOX, no Frame found");
+ if( !pFrm )
+ continue;
+ if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->HasFollow() )
+ {
+ // dann suche den richtigen heraus
+ SwTxtFrm* pNext = (SwTxtFrm*)pFrm;
+ while( 0 != ( pNext = (SwTxtFrm*)pFrm->GetFollow() )
+ && rTOXSource.nPos >= pNext->GetOfst() )
+ pFrm = pNext;
+ }
+
+ SwPageFrm* pTmpPage = pFrm->FindPageFrm();
+ if( pTmpPage != pAktPage )
+ {
+ nPage = pTmpPage->GetVirtPageNum();
+ pAktPage = pTmpPage;
+ }
+
+ // sortiert einfuegen
+ for( i = 0; i < aNums.Count() && aNums[i] < nPage; ++i )
+ ;
+
+ if( i >= aNums.Count() || aNums[ i ] != nPage )
+ {
+ aNums.Insert( nPage, i );
+ aDescs.Insert( (void*)pAktPage->GetPageDesc(), i );
+ }
+ // is it a main entry?
+ if(TOX_SORT_INDEX == pSortBase->GetType() &&
+ rTOXSource.bMainEntry)
+ {
+ if(!pMainNums)
+ pMainNums = new SvUShorts;
+ pMainNums->Insert(nPage, pMainNums->Count());
+ }
+ }
+ }
+ // einfuegen der Seitennummer in den Verzeichnis-Text-Node
+ const SwTOXSortTabBase* pBase = aSortArr[ nCnt ];
+ if(pBase->pTOXNd)
+ {
+ const SwTxtNode* pTxtNd = pBase->pTOXNd->GetTxtNode();
+ ASSERT( pTxtNd, "kein TextNode, falsches Verzeichnis" );
+
+ _UpdatePageNum( (SwTxtNode*)pTxtNd, aNums, aDescs, pMainNums,
+ aIntl );
+ }
+ DELETEZ(pMainNums);
+ aNums.Remove(0, aNums.Count());
+ }
+ }
+ // nach dem Setzen der richtigen Seitennummer, das Mapping-Array
+ // wieder loeschen !!
+ aSortArr.DeleteAndDestroy( 0, aSortArr.Count() );
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Austausch der Seitennummer-Platzhalter
+ --------------------------------------------------------------------*/
+
+// search for the page no in the array of main entry page numbers
+sal_Bool lcl_HasMainEntry( const SvUShorts* pMainEntryNums, sal_uInt16 nToFind )
+{
+ for(sal_uInt16 i = 0; pMainEntryNums && i < pMainEntryNums->Count(); ++i)
+ if(nToFind == (*pMainEntryNums)[i])
+ return sal_True;
+ return sal_False;
+}
+
+void SwTOXBaseSection::_UpdatePageNum( SwTxtNode* pNd,
+ const SvUShorts& rNums,
+ const SvPtrarr & rDescs,
+ const SvUShorts* pMainEntryNums,
+ const SwTOXInternational& rIntl )
+{
+ //collect starts end ends of main entry character style
+ SvUShorts* pCharStyleIdx = pMainEntryNums ? new SvUShorts : 0;
+
+ String sSrchStr( cNumRepl );
+ sSrchStr.AppendAscii( sPageDeli ) += cNumRepl;
+ xub_StrLen nStartPos = pNd->GetTxt().Search( sSrchStr );
+ ( sSrchStr = cNumRepl ) += cEndPageNum;
+ xub_StrLen nEndPos = pNd->GetTxt().Search( sSrchStr );
+ sal_uInt16 i;
+
+ if( STRING_NOTFOUND == nEndPos || !rNums.Count() )
+ return;
+
+ if( STRING_NOTFOUND == nStartPos || nStartPos > nEndPos)
+ nStartPos = nEndPos;
+
+ sal_uInt16 nOld = rNums[0],
+ nBeg = nOld,
+ nCount = 0;
+ String aNumStr( SvxNumberType( ((SwPageDesc*)rDescs[0])->GetNumType() ).
+ GetNumStr( nBeg ) );
+ if( pCharStyleIdx && lcl_HasMainEntry( pMainEntryNums, nBeg ))
+ {
+ sal_uInt16 nTemp = 0;
+ pCharStyleIdx->Insert( nTemp, pCharStyleIdx->Count());
+ }
+
+ // Platzhalter loeschen
+ SwIndex aPos(pNd, nStartPos);
+ SwCharFmt* pPageNoCharFmt = 0;
+ SwpHints* pHints = pNd->GetpSwpHints();
+ if(pHints)
+ for(sal_uInt16 nHintIdx = 0; nHintIdx < pHints->GetStartCount(); nHintIdx++)
+ {
+ SwTxtAttr* pAttr = pHints->GetStart(nHintIdx);
+ xub_StrLen nTmpEnd = pAttr->GetEnd() ? *pAttr->GetEnd() : 0;
+ if( nStartPos >= *pAttr->GetStart() &&
+ (nStartPos + 2) <= nTmpEnd &&
+ pAttr->Which() == RES_TXTATR_CHARFMT)
+ {
+ pPageNoCharFmt = pAttr->GetCharFmt().GetCharFmt();
+ break;
+ }
+ }
+ pNd->EraseText(aPos, nEndPos - nStartPos + 2);
+
+ for( i = 1; i < rNums.Count(); ++i)
+ {
+ SvxNumberType aType( ((SwPageDesc*)rDescs[i])->GetNumType() );
+ if( TOX_INDEX == SwTOXBase::GetType() )
+ { // Zusammenfassen f. ff.
+ // Alle folgenden aufaddieren
+ // break up if main entry starts or ends and
+ // insert a char style index
+ sal_Bool bMainEntryChanges = lcl_HasMainEntry(pMainEntryNums, nOld)
+ != lcl_HasMainEntry(pMainEntryNums, rNums[i]);
+
+ if(nOld == rNums[i]-1 && !bMainEntryChanges &&
+ 0 != (GetOptions() & (nsSwTOIOptions::TOI_FF|nsSwTOIOptions::TOI_DASH)))
+ nCount++;
+ else
+ {
+ // ff. f. alten Wert flushen
+ if(GetOptions() & nsSwTOIOptions::TOI_FF)
+ {
+ if ( nCount >= 1 )
+ aNumStr += rIntl.GetFollowingText( nCount > 1 );
+ }
+ else
+ {
+ if(nCount >= 2 )
+ aNumStr += '-';
+ else if(nCount == 1 )
+ aNumStr.AppendAscii( sPageDeli );
+//#58127# Wenn nCount == 0, dann steht die einzige Seitenzahl schon im aNumStr!
+ if(nCount)
+ aNumStr += aType.GetNumStr( nBeg + nCount );
+ }
+
+ // neuen String anlegen
+ nBeg = rNums[i];
+ aNumStr.AppendAscii( sPageDeli );
+ //the change of the character style must apply after sPageDeli is appended
+ if(pCharStyleIdx && bMainEntryChanges)
+ pCharStyleIdx->Insert(aNumStr.Len(),
+ pCharStyleIdx->Count());
+ aNumStr += aType.GetNumStr( nBeg );
+ nCount = 0;
+ }
+ nOld = rNums[i];
+ }
+ else
+ { // Alle Nummern eintragen
+ aNumStr += aType.GetNumStr( sal_uInt16(rNums[i]) );
+ if(i != (rNums.Count()-1))
+ aNumStr.AppendAscii( sPageDeli );
+ }
+ }
+ // Bei Ende und ff. alten Wert flushen
+ if( TOX_INDEX == SwTOXBase::GetType() )
+ {
+ if(GetOptions() & nsSwTOIOptions::TOI_FF)
+ {
+ if( nCount >= 1 )
+ aNumStr += rIntl.GetFollowingText( nCount > 1 );
+ }
+ else
+ {
+ if(nCount >= 2)
+ aNumStr +='-';
+ else if(nCount == 1)
+ aNumStr.AppendAscii( sPageDeli );
+//#58127# Wenn nCount == 0, dann steht die einzige Seitenzahl schon im aNumStr!
+ if(nCount)
+ aNumStr += SvxNumberType( ((SwPageDesc*)rDescs[i-1])->
+ GetNumType() ).GetNumStr( nBeg+nCount );
+ }
+ }
+ pNd->InsertText( aNumStr, aPos,
+ static_cast<IDocumentContentOperations::InsertFlags>(
+ IDocumentContentOperations::INS_EMPTYEXPAND |
+ IDocumentContentOperations::INS_FORCEHINTEXPAND) );
+ if(pPageNoCharFmt)
+ {
+ SwFmtCharFmt aCharFmt( pPageNoCharFmt );
+ pNd->InsertItem(aCharFmt, nStartPos, nStartPos + aNumStr.Len(), nsSetAttrMode::SETATTR_DONTEXPAND);
+ }
+
+ //now the main entries should get there character style
+ if(pCharStyleIdx && pCharStyleIdx->Count() && GetMainEntryCharStyle().Len())
+ {
+ // eventually the last index must me appended
+ if(pCharStyleIdx->Count()&0x01)
+ pCharStyleIdx->Insert(aNumStr.Len(), pCharStyleIdx->Count());
+
+ //search by name
+ SwDoc* pDoc = pNd->GetDoc();
+ sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( GetMainEntryCharStyle(), nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
+ SwCharFmt* pCharFmt = 0;
+ if(USHRT_MAX != nPoolId)
+ pCharFmt = pDoc->GetCharFmtFromPool(nPoolId);
+ else
+ pCharFmt = pDoc->FindCharFmtByName( GetMainEntryCharStyle() );
+ if(!pCharFmt)
+ pCharFmt = pDoc->MakeCharFmt(GetMainEntryCharStyle(), 0);
+
+ //find the page numbers in aNumStr and set the character style
+ xub_StrLen nOffset = pNd->GetTxt().Len() - aNumStr.Len();
+ SwFmtCharFmt aCharFmt(pCharFmt);
+ for(sal_uInt16 j = 0; j < pCharStyleIdx->Count(); j += 2)
+ {
+ xub_StrLen nStartIdx = (*pCharStyleIdx)[j] + nOffset;
+ xub_StrLen nEndIdx = (*pCharStyleIdx)[j + 1] + nOffset;
+ pNd->InsertItem(aCharFmt, nStartIdx, nEndIdx, nsSetAttrMode::SETATTR_DONTEXPAND);
+ }
+
+ }
+ delete pCharStyleIdx;
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Sortiert einfuegen in das SortArr
+ --------------------------------------------------------------------*/
+
+void SwTOXBaseSection::InsertSorted(SwTOXSortTabBase* pNew)
+{
+ Range aRange(0, aSortArr.Count());
+ if( TOX_INDEX == SwTOXBase::GetType() && pNew->pTxtMark )
+ {
+ const SwTOXMark& rMark = pNew->pTxtMark->GetTOXMark();
+ // Schluessel auswerten
+ // Den Bereich ermitteln, in dem einzufuegen ist
+ if( 0 == (GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY) &&
+ rMark.GetPrimaryKey().Len() )
+ {
+ aRange = GetKeyRange( rMark.GetPrimaryKey(),
+ rMark.GetPrimaryKeyReading(),
+ *pNew, FORM_PRIMARY_KEY, aRange );
+
+ if( rMark.GetSecondaryKey().Len() )
+ aRange = GetKeyRange( rMark.GetSecondaryKey(),
+ rMark.GetSecondaryKeyReading(),
+ *pNew, FORM_SECONDARY_KEY, aRange );
+ }
+ }
+ //search for identical entries and remove the trailing one
+ if(TOX_AUTHORITIES == SwTOXBase::GetType())
+ {
+ for(short i = (short)aRange.Min(); i < (short)aRange.Max(); ++i)
+ {
+ SwTOXSortTabBase* pOld = aSortArr[i];
+ if(*pOld == *pNew)
+ {
+ if(*pOld < *pNew)
+ {
+ delete pNew;
+ return;
+ }
+ else
+ {
+ // remove the old content
+ aSortArr.DeleteAndDestroy( i, 1 );
+ aRange.Max()--;
+ break;
+ }
+ }
+ }
+ }
+
+ // find position and insert
+ //
+ short i;
+
+ for( i = (short)aRange.Min(); i < (short)aRange.Max(); ++i)
+ { // nur auf gleicher Ebene pruefen
+ //
+ SwTOXSortTabBase* pOld = aSortArr[i];
+ if(*pOld == *pNew)
+ {
+ if(TOX_AUTHORITIES != SwTOXBase::GetType())
+ {
+ // Eigener Eintrag fuer Doppelte oder Keywords
+ //
+ if( pOld->GetType() == TOX_SORT_CUSTOM &&
+ pNew->GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY)
+ continue;
+
+ if(!(pNew->GetOptions() & nsSwTOIOptions::TOI_SAME_ENTRY))
+ { // Eigener Eintrag
+ aSortArr.Insert(pNew, i );
+ return;
+ }
+ // Eintrag schon vorhanden in Referenzliste aufnehmen
+ pOld->aTOXSources.Insert( pNew->aTOXSources[0],
+ pOld->aTOXSources.Count() );
+
+ delete pNew;
+ return;
+ }
+#ifdef DBG_UTIL
+ else
+ DBG_ERROR("Bibliography entries cannot be found here");
+#endif
+ }
+ if(*pNew < *pOld)
+ break;
+ }
+ // SubLevel Skippen
+ while( TOX_INDEX == SwTOXBase::GetType() && i < aRange.Max() &&
+ aSortArr[i]->GetLevel() > pNew->GetLevel() )
+ i++;
+
+ // An Position i wird eingefuegt
+ aSortArr.Insert(pNew, i );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Schluessel-Bereich suchen und evtl einfuegen
+ --------------------------------------------------------------------*/
+
+Range SwTOXBaseSection::GetKeyRange(const String& rStr, const String& rStrReading,
+ const SwTOXSortTabBase& rNew,
+ sal_uInt16 nLevel, const Range& rRange )
+{
+ const SwTOXInternational& rIntl = *rNew.pTOXIntl;
+ String sToCompare(rStr);
+ String sToCompareReading(rStrReading);
+
+ if( 0 != (nsSwTOIOptions::TOI_INITIAL_CAPS & GetOptions()) )
+ {
+ String sUpper( rIntl.ToUpper( sToCompare, 0 ));
+ sToCompare.Erase( 0, 1 ).Insert( sUpper, 0 );
+ }
+
+ ASSERT(rRange.Min() >= 0 && rRange.Max() >= 0, "Min Max < 0");
+
+ const sal_uInt16 nMin = (sal_uInt16)rRange.Min();
+ const sal_uInt16 nMax = (sal_uInt16)rRange.Max();
+
+ sal_uInt16 i;
+
+ for( i = nMin; i < nMax; ++i)
+ {
+ SwTOXSortTabBase* pBase = aSortArr[i];
+
+ String sMyString, sMyStringReading;
+ pBase->GetTxt( sMyString, sMyStringReading );
+
+ if( rIntl.IsEqual( sMyString, sMyStringReading, pBase->GetLocale(),
+ sToCompare, sToCompareReading, rNew.GetLocale() ) &&
+ pBase->GetLevel() == nLevel )
+ break;
+ }
+ if(i == nMax)
+ { // Falls nicht vorhanden erzeugen und einfuegen
+ //
+ SwTOXCustom* pKey = new SwTOXCustom( sToCompare, sToCompareReading, nLevel, rIntl,
+ rNew.GetLocale() );
+ for(i = nMin; i < nMax; ++i)
+ {
+ if(nLevel == aSortArr[i]->GetLevel() && *pKey < *(aSortArr[i]))
+ break;
+ }
+ aSortArr.Insert(pKey, i );
+ }
+ sal_uInt16 nStart = i+1;
+ sal_uInt16 nEnd = aSortArr.Count();
+
+ // Ende des Bereiches suchen
+ for(i = nStart; i < aSortArr.Count(); ++i)
+ {
+ if(aSortArr[i]->GetLevel() <= nLevel)
+ { nEnd = i;
+ break;
+ }
+ }
+ return Range(nStart, nEnd);
+}
+
+
+sal_Bool SwTOXBase::IsTOXBaseInReadonly() const
+{
+ const SwTOXBaseSection *pSect = PTR_CAST(SwTOXBaseSection, this);
+ sal_Bool bRet = sal_False;
+ const SwSectionNode* pSectNode;
+ if(pSect && pSect->GetFmt() &&
+ 0 != (pSectNode = pSect->GetFmt()->GetSectionNode()))
+ {
+ const SwDocShell* pDocSh;
+ bRet = (0 != (pDocSh = pSectNode->GetDoc()->GetDocShell()) &&
+ pDocSh->IsReadOnly()) ||
+ (0 != (pSectNode = pSectNode->StartOfSectionNode()->FindSectionNode())&&
+ pSectNode->GetSection().IsProtectFlag());
+
+ }
+ return bRet;
+}
+/* -----------------17.08.99 13:29-------------------
+
+ --------------------------------------------------*/
+const SfxItemSet* SwTOXBase::GetAttrSet() const
+{
+ const SwTOXBaseSection *pSect = PTR_CAST(SwTOXBaseSection, this);
+ if(pSect && pSect->GetFmt())
+ return &pSect->GetFmt()->GetAttrSet();
+ return 0;
+}
+
+void SwTOXBase::SetAttrSet( const SfxItemSet& rSet )
+{
+ SwTOXBaseSection *pSect = PTR_CAST(SwTOXBaseSection, this);
+ if( pSect && pSect->GetFmt() )
+ pSect->GetFmt()->SetFmtAttr( rSet );
+}
+
+sal_Bool SwTOXBase::GetInfo( SfxPoolItem& rInfo ) const
+{
+ switch( rInfo.Which() )
+ {
+ case RES_CONTENT_VISIBLE:
+ {
+ SwTOXBaseSection *pSect = PTR_CAST(SwTOXBaseSection, this);
+ if( pSect && pSect->GetFmt() )
+ pSect->GetFmt()->GetInfo( rInfo );
+ }
+ return sal_False;
+ }
+ return sal_True;
+}
+
+/* */
+
+
diff --git a/sw/source/core/doc/docxforms.cxx b/sw/source/core/doc/docxforms.cxx
new file mode 100644
index 000000000000..febab662a8fa
--- /dev/null
+++ b/sw/source/core/doc/docxforms.cxx
@@ -0,0 +1,123 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+
+#include <doc.hxx>
+#include <docsh.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/frame/XModule.hpp>
+#include <com/sun/star/xforms/XModel.hpp>
+#include <com/sun/star/xforms/XFormsUIHelper1.hpp>
+#include <unotools/processfactory.hxx>
+#include <tools/diagnose_ex.h>
+
+
+using namespace ::com::sun::star;
+
+using uno::Reference;
+using uno::XInterface;
+using uno::UNO_QUERY;
+using uno::makeAny;
+using uno::Exception;
+using container::XNameContainer;
+using xforms::XModel;
+using frame::XModule;
+using xforms::XFormsUIHelper1;
+using rtl::OUString;
+
+
+Reference<XNameContainer> SwDoc::getXForms() const
+{
+ return xXForms;
+}
+
+bool SwDoc::isXForms() const
+{
+ return xXForms.is();
+}
+
+Reference<XInterface> lcl_createInstance( const sal_Char* pServiceName )
+{
+ DBG_ASSERT( pServiceName != NULL, "no service name" );
+ return utl::getProcessServiceFactory()->createInstance(
+ OUString::createFromAscii( pServiceName ) );
+}
+
+void SwDoc::initXForms( bool bCreateDefaultModel )
+{
+ DBG_ASSERT( ! isXForms(), "please initialize only once" );
+
+ try
+ {
+ // create XForms components
+ xXForms.set( lcl_createInstance( "com.sun.star.xforms.XForms" ),
+ UNO_QUERY );
+ DBG_ASSERT( xXForms.is(), "can't create XForms container" );
+
+ // change our module identifier, to be able to have a dedicated UI
+ Reference< XModule > xModule;
+ SwDocShell* pShell( GetDocShell() );
+ if ( pShell )
+ xModule = xModule.query( pShell->GetModel() );
+ DBG_ASSERT( xModule.is(), "SwDoc::initXForms: no XModule at the document!" );
+ if ( xModule.is() )
+ xModule->setIdentifier( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xforms.XMLFormDocument" ) ) );
+
+ // create default model
+ if( bCreateDefaultModel && xXForms.is() )
+ {
+ OUString sName(RTL_CONSTASCII_USTRINGPARAM("Model 1"));
+ Reference<XModel> xModel(
+ lcl_createInstance( "com.sun.star.xforms.Model" ),
+ UNO_QUERY );
+ DBG_ASSERT( xModel.is(), "no model?" );
+ if( xModel.is() )
+ {
+ xModel->setID( sName );
+ Reference<XFormsUIHelper1>( xModel, UNO_QUERY )->newInstance(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Instance 1")),
+ OUString(), sal_True );
+ xModel->initialize();
+ xXForms->insertByName( sName, makeAny( xModel ) );
+ }
+ DBG_ASSERT( xXForms->hasElements(), "can't create XForms model" );
+ }
+
+ DBG_ASSERT( isXForms(), "initialization failed" );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
diff --git a/sw/source/core/doc/extinput.cxx b/sw/source/core/doc/extinput.cxx
new file mode 100644
index 000000000000..93d177aed548
--- /dev/null
+++ b/sw/source/core/doc/extinput.cxx
@@ -0,0 +1,300 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/i18n/ScriptType.hpp>
+
+#include <editeng/langitem.hxx>
+#include <editeng/scripttypeitem.hxx>
+
+#include <vcl/keycodes.hxx>
+#include <vcl/cmdevt.hxx>
+
+#include <hintids.hxx>
+#include <extinput.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <index.hxx>
+#include <ndtxt.hxx>
+#include <txtfrm.hxx>
+#include <swundo.hxx>
+
+
+using namespace ::com::sun::star;
+
+SwExtTextInput::SwExtTextInput( const SwPaM& rPam, Ring* pRing )
+ : SwPaM( *rPam.GetPoint(), (SwPaM*)pRing ),
+ eInputLanguage(LANGUAGE_DONTKNOW)
+{
+ bIsOverwriteCursor = sal_False;
+ bInsText = sal_True;
+}
+
+SwExtTextInput::~SwExtTextInput()
+{
+ SwDoc *const pDoc = GetDoc();
+ if (pDoc->IsInDtor()) { return; /* #i58606# */ }
+
+ SwTxtNode* pTNd = GetPoint()->nNode.GetNode().GetTxtNode();
+ if( pTNd )
+ {
+ SwIndex& rIdx = GetPoint()->nContent;
+ xub_StrLen nSttCnt = rIdx.GetIndex(),
+ nEndCnt = GetMark()->nContent.GetIndex();
+ if( nEndCnt != nSttCnt )
+ {
+ if( nEndCnt < nSttCnt )
+ {
+ xub_StrLen n = nEndCnt; nEndCnt = nSttCnt; nSttCnt = n;
+ }
+
+ // damit Undo / Redlining usw. richtig funktioniert,
+ // muss ueber die Doc-Schnittstellen gegangen werden !!!
+ if(eInputLanguage != LANGUAGE_DONTKNOW)
+ {
+ // --> FME 2005-02-11 #i41974# Only set language attribute
+ // for CJK/CTL scripts.
+ bool bLang = true;
+ // <--
+ sal_uInt16 nWhich = RES_CHRATR_LANGUAGE;
+ switch(GetI18NScriptTypeOfLanguage(eInputLanguage))
+ {
+ case i18n::ScriptType::ASIAN: nWhich = RES_CHRATR_CJK_LANGUAGE; break;
+ case i18n::ScriptType::COMPLEX: nWhich = RES_CHRATR_CTL_LANGUAGE; break;
+ default: bLang = false;
+ }
+ if ( bLang )
+ {
+ SvxLanguageItem aLangItem( eInputLanguage, nWhich );
+ pDoc->InsertPoolItem(*this, aLangItem, 0 );
+ }
+ }
+ rIdx = nSttCnt;
+ String sTxt( pTNd->GetTxt().Copy( nSttCnt, nEndCnt - nSttCnt ));
+ if( bIsOverwriteCursor && sOverwriteText.Len() )
+ {
+ xub_StrLen nLen = sTxt.Len();
+ if( nLen > sOverwriteText.Len() )
+ {
+ rIdx += sOverwriteText.Len();
+ pTNd->EraseText( rIdx, nLen - sOverwriteText.Len() );
+ rIdx = nSttCnt;
+ pTNd->ReplaceText( rIdx, sOverwriteText.Len(),
+ sOverwriteText );
+ if( bInsText )
+ {
+ rIdx = nSttCnt;
+ pDoc->GetIDocumentUndoRedo().StartUndo(
+ UNDO_OVERWRITE, NULL );
+ pDoc->Overwrite( *this, sTxt.Copy( 0,
+ sOverwriteText.Len() ));
+ pDoc->InsertString( *this,
+ sTxt.Copy( sOverwriteText.Len() ) );
+ pDoc->GetIDocumentUndoRedo().EndUndo(
+ UNDO_OVERWRITE, NULL );
+ }
+ }
+ else
+ {
+ pTNd->ReplaceText( rIdx, nLen,
+ sOverwriteText.Copy( 0, nLen ));
+ if( bInsText )
+ {
+ rIdx = nSttCnt;
+ pDoc->Overwrite( *this, sTxt );
+ }
+ }
+ }
+ else
+ {
+ pTNd->EraseText( rIdx, nEndCnt - nSttCnt );
+
+ if( bInsText )
+ {
+ pDoc->InsertString( *this, sTxt );
+ }
+ }
+ }
+ }
+}
+
+void SwExtTextInput::SetInputData( const CommandExtTextInputData& rData )
+{
+ SwTxtNode* pTNd = GetPoint()->nNode.GetNode().GetTxtNode();
+ if( pTNd )
+ {
+ xub_StrLen nSttCnt = GetPoint()->nContent.GetIndex(),
+ nEndCnt = GetMark()->nContent.GetIndex();
+ if( nEndCnt < nSttCnt )
+ {
+ xub_StrLen n = nEndCnt; nEndCnt = nSttCnt; nSttCnt = n;
+ }
+
+ SwIndex aIdx( pTNd, nSttCnt );
+ const String& rNewStr = rData.GetText();
+
+ if( bIsOverwriteCursor && sOverwriteText.Len() )
+ {
+ xub_StrLen nReplace = nEndCnt - nSttCnt;
+ if( rNewStr.Len() < nReplace )
+ {
+ // then we must insert from the saved original text
+ // some characters
+ nReplace = nReplace - rNewStr.Len();
+ aIdx += rNewStr.Len();
+ pTNd->ReplaceText( aIdx, nReplace,
+ sOverwriteText.Copy( rNewStr.Len(), nReplace ));
+ aIdx = nSttCnt;
+ nReplace = rNewStr.Len();
+ }
+ else if( sOverwriteText.Len() < nReplace )
+ {
+ nReplace = nReplace - sOverwriteText.Len();
+ aIdx += sOverwriteText.Len();
+ pTNd->EraseText( aIdx, nReplace );
+ aIdx = nSttCnt;
+ nReplace = sOverwriteText.Len();
+ }
+ else if( (nReplace = sOverwriteText.Len()) > rNewStr.Len() )
+ nReplace = rNewStr.Len();
+
+ pTNd->ReplaceText( aIdx, nReplace, rNewStr );
+ if( !HasMark() )
+ SetMark();
+ GetMark()->nContent = aIdx;
+ }
+ else
+ {
+ if( nSttCnt < nEndCnt )
+ {
+ pTNd->EraseText( aIdx, nEndCnt - nSttCnt );
+ }
+
+ pTNd->InsertText( rNewStr, aIdx,
+ IDocumentContentOperations::INS_EMPTYEXPAND );
+ if( !HasMark() )
+ SetMark();
+ }
+
+ GetPoint()->nContent = nSttCnt;
+
+ if( aAttrs.Count() )
+ aAttrs.Remove( 0, aAttrs.Count() );
+ if( rData.GetTextAttr() )
+ aAttrs.Insert( rData.GetTextAttr(), rData.GetText().Len(), 0 );
+ }
+}
+
+void SwExtTextInput::SetOverwriteCursor( sal_Bool bFlag )
+{
+ bIsOverwriteCursor = bFlag;
+
+ SwTxtNode* pTNd;
+ if( bIsOverwriteCursor &&
+ 0 != (pTNd = GetPoint()->nNode.GetNode().GetTxtNode()) )
+ {
+ xub_StrLen nSttCnt = GetPoint()->nContent.GetIndex(),
+ nEndCnt = GetMark()->nContent.GetIndex();
+ sOverwriteText = pTNd->GetTxt().Copy( nEndCnt < nSttCnt ? nEndCnt
+ : nSttCnt );
+ if( sOverwriteText.Len() )
+ {
+ xub_StrLen nInWrdAttrPos = sOverwriteText.Search( CH_TXTATR_INWORD ),
+ nWrdAttrPos = sOverwriteText.Search( CH_TXTATR_BREAKWORD );
+ if( nWrdAttrPos < nInWrdAttrPos )
+ nInWrdAttrPos = nWrdAttrPos;
+ if( STRING_NOTFOUND != nInWrdAttrPos )
+ sOverwriteText.Erase( nInWrdAttrPos );
+ }
+ }
+}
+
+// die Doc Schnittstellen:
+
+SwExtTextInput* SwDoc::CreateExtTextInput( const SwPaM& rPam )
+{
+ SwExtTextInput* pNew = new SwExtTextInput( rPam, pExtInputRing );
+ if( !pExtInputRing )
+ pExtInputRing = pNew;
+ pNew->SetMark();
+ return pNew;
+}
+
+void SwDoc::DeleteExtTextInput( SwExtTextInput* pDel )
+{
+ if( pDel == pExtInputRing )
+ {
+ if( pDel->GetNext() != pExtInputRing )
+ pExtInputRing = (SwPaM*)pDel->GetNext();
+ else
+ pExtInputRing = 0;
+ }
+ delete pDel;
+}
+
+SwExtTextInput* SwDoc::GetExtTextInput( const SwNode& rNd,
+ xub_StrLen nCntntPos ) const
+{
+ SwExtTextInput* pRet = 0;
+ if( pExtInputRing )
+ {
+ sal_uLong nNdIdx = rNd.GetIndex();
+ SwExtTextInput* pTmp = (SwExtTextInput*)pExtInputRing;
+ do {
+ sal_uLong nPt = pTmp->GetPoint()->nNode.GetIndex(),
+ nMk = pTmp->GetMark()->nNode.GetIndex();
+ xub_StrLen nPtCnt = pTmp->GetPoint()->nContent.GetIndex(),
+ nMkCnt = pTmp->GetMark()->nContent.GetIndex();
+
+ if( nPt < nMk || ( nPt == nMk && nPtCnt < nMkCnt ))
+ {
+ sal_uLong nTmp = nMk; nMk = nPt; nPt = nTmp;
+ nTmp = nMkCnt; nMkCnt = nPtCnt; nPtCnt = (xub_StrLen)nTmp;
+ }
+
+ if( nMk <= nNdIdx && nNdIdx <= nPt &&
+ ( STRING_NOTFOUND == nCntntPos ||
+ ( nMkCnt <= nCntntPos && nCntntPos <= nPtCnt )))
+ {
+ pRet = pTmp;
+ break;
+ }
+ } while( pExtInputRing != (pTmp = (SwExtTextInput*)pExtInputRing ) );
+ }
+ return pRet;
+}
+
+SwExtTextInput* SwDoc::GetExtTextInput() const
+{
+ ASSERT( !pExtInputRing || pExtInputRing == pExtInputRing->GetNext(),
+ "more then one InputEngine available" );
+ return (SwExtTextInput*)pExtInputRing;
+}
+
+
diff --git a/sw/source/core/doc/fmtcol.cxx b/sw/source/core/doc/fmtcol.cxx
new file mode 100644
index 000000000000..c43e363e3a72
--- /dev/null
+++ b/sw/source/core/doc/fmtcol.cxx
@@ -0,0 +1,717 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <hintids.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <doc.hxx> // fuer GetAttrPool
+#include <errhdl.hxx>
+#include <fmtcol.hxx>
+// --> OD 2006-11-22 #i71574#
+#include <fmtcolfunc.hxx>
+// <--
+#include <hints.hxx>
+#include <calc.hxx>
+#include <node.hxx>
+#include <numrule.hxx>
+#include <paratr.hxx>
+
+//--> #outlinelevel added by zhaojianwei
+#ifndef _SFXINTITEM_HXX
+#include <svl/intitem.hxx>
+#endif
+//<--end
+
+TYPEINIT1( SwTxtFmtColl, SwFmtColl );
+TYPEINIT1( SwGrfFmtColl, SwFmtColl );
+TYPEINIT1( SwConditionTxtFmtColl, SwTxtFmtColl );
+TYPEINIT1( SwCollCondition, SwClient );
+
+SV_IMPL_PTRARR( SwFmtCollConditions, SwCollConditionPtr );
+
+// --> OD 2008-03-04 #refactorlists#
+namespace TxtFmtCollFunc
+{
+
+ // --> OD 2006-11-22 #i71574#
+ void CheckTxtFmtCollForDeletionOfAssignmentToOutlineStyle(
+ SwFmt* pFmt,
+ const SwNumRuleItem* pNewNumRuleItem )
+ {
+ SwTxtFmtColl* pTxtFmtColl = dynamic_cast<SwTxtFmtColl*>(pFmt);
+ if ( !pTxtFmtColl )
+ {
+ #if OSL_DEBUG_LEVEL > 1
+ ASSERT( false,
+ "<TxtFmtCollFunc::CheckTxtFmtCollFuncForDeletionOfAssignmentToOutlineStyle> - misuse of method - it's only for instances of <SwTxtFmtColl>" );
+ #endif
+ return;
+ }
+
+ // --> OD 2007-01-24 #i73790#
+ // if ( pTxtFmtColl->AssignedToListLevelOfOutlineStyle() )
+ if ( !pTxtFmtColl->StayAssignedToListLevelOfOutlineStyle() &&
+ pTxtFmtColl->IsAssignedToListLevelOfOutlineStyle() )
+ // <--
+ {
+ if ( !pNewNumRuleItem )
+ {
+ pTxtFmtColl->GetItemState( RES_PARATR_NUMRULE, sal_False, (const SfxPoolItem**)&pNewNumRuleItem );
+ }
+ if ( pNewNumRuleItem )
+ {
+ String sNumRuleName = pNewNumRuleItem->GetValue();
+ if ( sNumRuleName.Len() == 0 ||
+ sNumRuleName != pTxtFmtColl->GetDoc()->GetOutlineNumRule()->GetName() )
+ {
+ // delete assignment of paragraph style to list level of outline style.
+ pTxtFmtColl->DeleteAssignmentToListLevelOfOutlineStyle();
+ }
+ }
+ }
+ }
+ // <--
+
+ SwNumRule* GetNumRule( SwTxtFmtColl& rTxtFmtColl )
+ {
+ SwNumRule* pNumRule( 0 );
+
+ const SwNumRuleItem* pNumRuleItem( 0 );
+ rTxtFmtColl.GetItemState( RES_PARATR_NUMRULE, sal_False, (const SfxPoolItem**)&pNumRuleItem );
+ if ( pNumRuleItem )
+ {
+ const String sNumRuleName = pNumRuleItem->GetValue();
+ if ( sNumRuleName.Len() > 0 )
+ {
+ pNumRule = rTxtFmtColl.GetDoc()->FindNumRulePtr( sNumRuleName );
+ }
+ }
+
+ return pNumRule;
+ }
+
+ void AddToNumRule( SwTxtFmtColl& rTxtFmtColl )
+ {
+ SwNumRule* pNumRule = GetNumRule( rTxtFmtColl );
+ if ( pNumRule )
+ {
+ pNumRule->AddParagraphStyle( rTxtFmtColl );
+ }
+ }
+
+ void RemoveFromNumRule( SwTxtFmtColl& rTxtFmtColl )
+ {
+ SwNumRule* pNumRule = GetNumRule( rTxtFmtColl );
+ if ( pNumRule )
+ {
+ pNumRule->RemoveParagraphStyle( rTxtFmtColl );
+ }
+ }
+} // end of namespace TxtFmtCollFunc
+// <--
+
+/*
+ * SwTxtFmtColl TXT
+ */
+
+void SwTxtFmtColl::Modify( SfxPoolItem* pOld, SfxPoolItem* pNew )
+{
+ if( GetDoc()->IsInDtor() )
+ {
+ SwFmtColl::Modify( pOld, pNew );
+ return;
+ }
+
+ // --> OD 2006-06-16 #i66431# - adjust type of <bNewParent>
+ bool bNewParent( false );
+ // <--
+ SvxULSpaceItem *pNewULSpace = 0, *pOldULSpace = 0;
+ SvxLRSpaceItem *pNewLRSpace = 0, *pOldLRSpace = 0;
+ SvxFontHeightItem* aFontSizeArr[3] = {0,0,0};
+ // --> OD 2006-10-17 #i70223#
+ const bool bAssignedToListLevelOfOutlineStyle(IsAssignedToListLevelOfOutlineStyle());//#outline level ,zhaojianwei
+ const SwNumRuleItem* pNewNumRuleItem( 0L );
+ // <--
+
+ SwAttrSetChg *pNewChgSet = 0, *pOldChgSet = 0;
+
+ switch( pOld ? pOld->Which() : pNew ? pNew->Which() : 0 )
+ {
+ case RES_ATTRSET_CHG:
+ // nur neu berechnen, wenn nicht wir der "Versender" sind !!!
+ pNewChgSet = (SwAttrSetChg*)pNew;
+ pOldChgSet = (SwAttrSetChg*)pOld;
+ pNewChgSet->GetChgSet()->GetItemState(
+ RES_LR_SPACE, sal_False, (const SfxPoolItem**)&pNewLRSpace );
+ pNewChgSet->GetChgSet()->GetItemState(
+ RES_UL_SPACE, sal_False, (const SfxPoolItem**)&pNewULSpace );
+ pNewChgSet->GetChgSet()->GetItemState( RES_CHRATR_FONTSIZE,
+ sal_False, (const SfxPoolItem**)&(aFontSizeArr[0]) );
+ pNewChgSet->GetChgSet()->GetItemState( RES_CHRATR_CJK_FONTSIZE,
+ sal_False, (const SfxPoolItem**)&(aFontSizeArr[1]) );
+ pNewChgSet->GetChgSet()->GetItemState( RES_CHRATR_CTL_FONTSIZE,
+ sal_False, (const SfxPoolItem**)&(aFontSizeArr[2]) );
+ // --> OD 2006-10-17 #i70223#
+ // --> OD 2007-12-19 #i84745#
+ // check, if attribute set is applied to this paragraph style
+ if ( bAssignedToListLevelOfOutlineStyle &&
+ pNewChgSet->GetTheChgdSet() == &GetAttrSet() )
+ {
+ pNewChgSet->GetChgSet()->GetItemState( RES_PARATR_NUMRULE, sal_False,
+ (const SfxPoolItem**)&pNewNumRuleItem );
+ }
+ // <--
+
+ break;
+
+ case RES_FMT_CHG:
+ if( GetAttrSet().GetParent() )
+ {
+ const SfxItemSet* pParent = GetAttrSet().GetParent();
+ pNewLRSpace = (SvxLRSpaceItem*)&pParent->Get( RES_LR_SPACE );
+ pNewULSpace = (SvxULSpaceItem*)&pParent->Get( RES_UL_SPACE );
+ aFontSizeArr[0] = (SvxFontHeightItem*)&pParent->Get( RES_CHRATR_FONTSIZE );
+ aFontSizeArr[1] = (SvxFontHeightItem*)&pParent->Get( RES_CHRATR_CJK_FONTSIZE );
+ aFontSizeArr[2] = (SvxFontHeightItem*)&pParent->Get( RES_CHRATR_CTL_FONTSIZE );
+ // --> OD 2006-06-16 #i66431#
+ // modify has to be propagated, because of new parent format.
+ bNewParent = true;
+ // <--
+ }
+ break;
+
+ case RES_LR_SPACE:
+ pNewLRSpace = (SvxLRSpaceItem*)pNew;
+ break;
+ case RES_UL_SPACE:
+ pNewULSpace = (SvxULSpaceItem*)pNew;
+ break;
+ case RES_CHRATR_FONTSIZE:
+ aFontSizeArr[0] = (SvxFontHeightItem*)pNew;
+ break;
+ case RES_CHRATR_CJK_FONTSIZE:
+ aFontSizeArr[1] = (SvxFontHeightItem*)pNew;
+ break;
+ case RES_CHRATR_CTL_FONTSIZE:
+ aFontSizeArr[2] = (SvxFontHeightItem*)pNew;
+ break;
+ // --> OD 2006-10-17 #i70223#
+ case RES_PARATR_NUMRULE:
+ {
+ if ( bAssignedToListLevelOfOutlineStyle )
+ {
+ pNewNumRuleItem = (SwNumRuleItem*)pNew;
+ }
+ }
+ default:
+ break;
+ }
+
+ // --> OD 2006-10-17 #i70223#
+ if ( bAssignedToListLevelOfOutlineStyle && pNewNumRuleItem )
+ {
+ TxtFmtCollFunc::CheckTxtFmtCollForDeletionOfAssignmentToOutlineStyle(
+ this, pNewNumRuleItem );
+ }
+ // <--
+
+ int bWeiter = sal_True;
+
+ // dann pruefe doch mal gegen die eigenen Attribute
+ if( pNewLRSpace && SFX_ITEM_SET == GetItemState( RES_LR_SPACE, sal_False,
+ (const SfxPoolItem**)&pOldLRSpace ))
+ {
+ int bChg = sal_False;
+ if( pOldLRSpace != pNewLRSpace ) // verhinder Rekursion (SetAttr!!)
+ {
+ SvxLRSpaceItem aNew( *pOldLRSpace );
+ // wir hatten eine relative Angabe -> neu berechnen
+ if( 100 != aNew.GetPropLeft() )
+ {
+ long nTmp = aNew.GetLeft(); // alten zum Vergleichen
+ aNew.SetLeft( pNewLRSpace->GetLeft(), aNew.GetPropLeft() );
+ bChg |= nTmp != aNew.GetLeft();
+ }
+ // wir hatten eine relative Angabe -> neu berechnen
+ if( 100 != aNew.GetPropRight() )
+ {
+ long nTmp = aNew.GetRight(); // alten zum Vergleichen
+ aNew.SetRight( pNewLRSpace->GetRight(), aNew.GetPropRight() );
+ bChg |= nTmp != aNew.GetRight();
+ }
+ // wir hatten eine relative Angabe -> neu berechnen
+ if( 100 != aNew.GetPropTxtFirstLineOfst() )
+ {
+ short nTmp = aNew.GetTxtFirstLineOfst(); // alten zum Vergleichen
+ aNew.SetTxtFirstLineOfst( pNewLRSpace->GetTxtFirstLineOfst(),
+ aNew.GetPropTxtFirstLineOfst() );
+ bChg |= nTmp != aNew.GetTxtFirstLineOfst();
+ }
+ if( bChg )
+ {
+ SetFmtAttr( aNew );
+ bWeiter = 0 != pOldChgSet || bNewParent;
+ }
+ // bei uns absolut gesetzt -> nicht weiter propagieren, es sei
+ // denn es wird bei uns gesetzt!
+ else if( pNewChgSet )
+ bWeiter = pNewChgSet->GetTheChgdSet() == &GetAttrSet();
+ }
+ }
+
+ if( pNewULSpace && SFX_ITEM_SET == GetItemState(
+ RES_UL_SPACE, sal_False, (const SfxPoolItem**)&pOldULSpace ) &&
+ pOldULSpace != pNewULSpace ) // verhinder Rekursion (SetAttr!!)
+ {
+ SvxULSpaceItem aNew( *pOldULSpace );
+ int bChg = sal_False;
+ // wir hatten eine relative Angabe -> neu berechnen
+ if( 100 != aNew.GetPropUpper() )
+ {
+ sal_uInt16 nTmp = aNew.GetUpper(); // alten zum Vergleichen
+ aNew.SetUpper( pNewULSpace->GetUpper(), aNew.GetPropUpper() );
+ bChg |= nTmp != aNew.GetUpper();
+ }
+ // wir hatten eine relative Angabe -> neu berechnen
+ if( 100 != aNew.GetPropLower() )
+ {
+ sal_uInt16 nTmp = aNew.GetLower(); // alten zum Vergleichen
+ aNew.SetLower( pNewULSpace->GetLower(), aNew.GetPropLower() );
+ bChg |= nTmp != aNew.GetLower();
+ }
+ if( bChg )
+ {
+ SetFmtAttr( aNew );
+ bWeiter = 0 != pOldChgSet || bNewParent;
+ }
+ // bei uns absolut gesetzt -> nicht weiter propagieren, es sei
+ // denn es wird bei uns gesetzt!
+ else if( pNewChgSet )
+ bWeiter = pNewChgSet->GetTheChgdSet() == &GetAttrSet();
+ }
+
+
+ for( int nC = 0, nArrLen = sizeof(aFontSizeArr) / sizeof( aFontSizeArr[0]);
+ nC < nArrLen; ++nC )
+ {
+ SvxFontHeightItem *pFSize = aFontSizeArr[ nC ], *pOldFSize;
+ if( pFSize && SFX_ITEM_SET == GetItemState(
+ pFSize->Which(), sal_False, (const SfxPoolItem**)&pOldFSize ) &&
+ // verhinder Rekursion (SetAttr!!)
+ pFSize != pOldFSize )
+ {
+ if( 100 == pOldFSize->GetProp() &&
+ SFX_MAPUNIT_RELATIVE == pOldFSize->GetPropUnit() )
+ {
+ // bei uns absolut gesetzt -> nicht weiter propagieren, es sei
+ // denn es wird bei uns gesetzt!
+ if( pNewChgSet )
+ bWeiter = pNewChgSet->GetTheChgdSet() == &GetAttrSet();
+ }
+ else
+ {
+ // wir hatten eine relative Angabe -> neu berechnen
+ sal_uInt32 nTmp = pOldFSize->GetHeight(); // alten zum Vergleichen
+ SvxFontHeightItem aNew(240 , 100, pFSize->Which());
+ aNew.SetHeight( pFSize->GetHeight(), pOldFSize->GetProp(),
+ pOldFSize->GetPropUnit() );
+ if( nTmp != aNew.GetHeight() )
+ {
+ SetFmtAttr( aNew );
+ bWeiter = 0 != pOldChgSet || bNewParent;
+ }
+ // bei uns absolut gesetzt -> nicht weiter propagieren, es sei
+ // denn es wird bei uns gesetzt!
+ else if( pNewChgSet )
+ bWeiter = pNewChgSet->GetTheChgdSet() == &GetAttrSet();
+ }
+ }
+ }
+
+ if( bWeiter )
+ SwFmtColl::Modify( pOld, pNew );
+}
+
+sal_Bool SwTxtFmtColl::IsAtDocNodeSet() const
+{
+ SwClientIter aIter( *(SwModify*)this );
+ const SwNodes& rNds = GetDoc()->GetNodes();
+ for( SwClient* pC = aIter.First(TYPE(SwCntntNode)); pC; pC = aIter.Next() )
+ if( &((SwCntntNode*)pC)->GetNodes() == &rNds )
+ return sal_True;
+
+ return sal_False;
+}
+
+// --> OD 2008-03-04 #refactorlists#
+sal_Bool SwTxtFmtColl::SetFmtAttr( const SfxPoolItem& rAttr )
+{
+ const bool bIsNumRuleItem = rAttr.Which() == RES_PARATR_NUMRULE;
+ if ( bIsNumRuleItem )
+ {
+ TxtFmtCollFunc::RemoveFromNumRule( *this );
+ }
+
+ const sal_Bool bRet = SwFmtColl::SetFmtAttr( rAttr );
+
+ if ( bIsNumRuleItem )
+ {
+ TxtFmtCollFunc::AddToNumRule( *this );
+ }
+
+ return bRet;
+}
+
+sal_Bool SwTxtFmtColl::SetFmtAttr( const SfxItemSet& rSet )
+{
+ const bool bIsNumRuleItemAffected =
+ rSet.GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET;
+ if ( bIsNumRuleItemAffected )
+ {
+ TxtFmtCollFunc::RemoveFromNumRule( *this );
+ }
+
+ const sal_Bool bRet = SwFmtColl::SetFmtAttr( rSet );
+
+ if ( bIsNumRuleItemAffected )
+ {
+ TxtFmtCollFunc::AddToNumRule( *this );
+ }
+
+ return bRet;
+}
+
+sal_Bool SwTxtFmtColl::ResetFmtAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 )
+{
+ const bool bIsNumRuleItemAffected =
+ ( nWhich2 != 0 && nWhich2 > nWhich1 )
+ ? ( nWhich1 <= RES_PARATR_NUMRULE &&
+ RES_PARATR_NUMRULE <= nWhich2 )
+ : nWhich1 == RES_PARATR_NUMRULE;
+ if ( bIsNumRuleItemAffected )
+ {
+ TxtFmtCollFunc::RemoveFromNumRule( *this );
+ }
+
+ const sal_Bool bRet = SwFmtColl::ResetFmtAttr( nWhich1, nWhich2 );
+
+ return bRet;
+}
+// <--
+
+// --> OD 2007-01-24 #i73790#
+sal_uInt16 SwTxtFmtColl::ResetAllFmtAttr()
+{
+ const bool bOldState( mbStayAssignedToListLevelOfOutlineStyle );
+ mbStayAssignedToListLevelOfOutlineStyle = true;
+ // --> OD 2008-12-16 #i70748#
+ // Outline level is no longer a member, it is a attribute now.
+ // Thus, it needs to be restored, if the paragraph style is assigned
+ // to the outline style
+ const int nAssignedOutlineStyleLevel = IsAssignedToListLevelOfOutlineStyle()
+ ? GetAssignedOutlineStyleLevel()
+ : -1;
+ // <--
+
+ sal_uInt16 nRet = SwFmtColl::ResetAllFmtAttr();
+
+ // --> OD 2008-12-16 #i70748#
+ if ( nAssignedOutlineStyleLevel != -1 )
+ {
+ AssignToListLevelOfOutlineStyle( nAssignedOutlineStyleLevel );
+ }
+ // <--
+
+ mbStayAssignedToListLevelOfOutlineStyle = bOldState;
+
+ return nRet;
+}
+// <--
+
+// --> OD 2008-02-13 #newlistlevelattrs#
+bool SwTxtFmtColl::AreListLevelIndentsApplicable() const
+{
+ bool bAreListLevelIndentsApplicable( true );
+
+ if ( GetItemState( RES_PARATR_NUMRULE ) != SFX_ITEM_SET )
+ {
+ // no list style applied to paragraph style
+ bAreListLevelIndentsApplicable = false;
+ }
+ else if ( GetItemState( RES_LR_SPACE, sal_False ) == SFX_ITEM_SET )
+ {
+ // paragraph style has hard-set indent attributes
+ bAreListLevelIndentsApplicable = false;
+ }
+ else if ( GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET )
+ {
+ // list style is directly applied to paragraph style and paragraph
+ // style has no hard-set indent attributes
+ bAreListLevelIndentsApplicable = true;
+ }
+ else
+ {
+ // list style is applied through one of the parent paragraph styles and
+ // paragraph style has no hard-set indent attributes
+
+ // check parent paragraph styles
+ const SwTxtFmtColl* pColl = dynamic_cast<const SwTxtFmtColl*>(DerivedFrom());
+ while ( pColl )
+ {
+ if ( pColl->GetAttrSet().GetItemState( RES_LR_SPACE, sal_False ) == SFX_ITEM_SET )
+ {
+ // indent attributes found in the paragraph style hierarchy.
+ bAreListLevelIndentsApplicable = false;
+ break;
+ }
+
+ if ( pColl->GetAttrSet().GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET )
+ {
+ // paragraph style with the list style found and until now no
+ // indent attributes are found in the paragraph style hierarchy.
+ bAreListLevelIndentsApplicable = true;
+ break;
+ }
+
+ pColl = dynamic_cast<const SwTxtFmtColl*>(pColl->DerivedFrom());
+ ASSERT( pColl,
+ "<SwTxtFmtColl::AreListLevelIndentsApplicable()> - something wrong in paragraph style hierarchy. The applied list style is not found." );
+ }
+ }
+
+ return bAreListLevelIndentsApplicable;
+}
+// <--
+
+//FEATURE::CONDCOLL
+
+SwCollCondition::SwCollCondition( SwTxtFmtColl* pColl, sal_uLong nMasterCond,
+ sal_uLong nSubCond )
+ : SwClient( pColl ), nCondition( nMasterCond )
+{
+ aSubCondition.nSubCondition = nSubCond;
+}
+
+
+SwCollCondition::SwCollCondition( SwTxtFmtColl* pColl, sal_uLong nMasterCond,
+ const String& rSubExp )
+ : SwClient( pColl ), nCondition( nMasterCond )
+{
+ if( USRFLD_EXPRESSION & nCondition )
+ aSubCondition.pFldExpression = new String( rSubExp );
+ else
+ aSubCondition.nSubCondition = 0;
+}
+
+
+SwCollCondition::SwCollCondition( const SwCollCondition& rCopy )
+ : SwClient( (SwModify*)rCopy.GetRegisteredIn() ), nCondition( rCopy.nCondition )
+{
+ if( USRFLD_EXPRESSION & rCopy.nCondition )
+ aSubCondition.pFldExpression = new String( *rCopy.GetFldExpression() );
+ else
+ aSubCondition.nSubCondition = rCopy.aSubCondition.nSubCondition;
+}
+
+
+SwCollCondition::~SwCollCondition()
+{
+ if( USRFLD_EXPRESSION & nCondition )
+ delete aSubCondition.pFldExpression;
+}
+
+
+int SwCollCondition::operator==( const SwCollCondition& rCmp ) const
+{
+ int nRet = 0;
+ if( nCondition == rCmp.nCondition )
+ {
+ if( USRFLD_EXPRESSION & nCondition )
+ {
+ // in der SubCondition steht die Expression fuer das UserFeld
+ const String* pTmp = aSubCondition.pFldExpression;
+ if( !pTmp )
+ pTmp = rCmp.aSubCondition.pFldExpression;
+ if( pTmp )
+ {
+ SwTxtFmtColl* pColl = GetTxtFmtColl();
+ if( !pColl )
+ pColl = rCmp.GetTxtFmtColl();
+
+ if( pColl )
+ {
+ SwCalc aCalc( *pColl->GetDoc() );
+ nRet = 0 != aCalc.Calculate( *pTmp ).GetBool();
+ }
+ }
+ }
+ else if( aSubCondition.nSubCondition ==
+ rCmp.aSubCondition.nSubCondition )
+ nRet = 1;
+ }
+ return nRet;
+}
+
+
+void SwCollCondition::SetCondition( sal_uLong nCond, sal_uLong nSubCond )
+{
+ if( USRFLD_EXPRESSION & nCondition )
+ delete aSubCondition.pFldExpression;
+ nCondition = nCond;
+ aSubCondition.nSubCondition = nSubCond;
+}
+
+
+SwConditionTxtFmtColl::~SwConditionTxtFmtColl()
+{
+}
+
+const SwCollCondition* SwConditionTxtFmtColl::HasCondition(
+ const SwCollCondition& rCond ) const
+{
+ const SwCollCondition* pFnd = 0;
+ sal_uInt16 n;
+
+ for( n = 0; n < aCondColls.Count(); ++n )
+ if( *( pFnd = aCondColls[ n ]) == rCond )
+ break;
+
+ return n < aCondColls.Count() ? pFnd : 0;
+}
+
+
+void SwConditionTxtFmtColl::InsertCondition( const SwCollCondition& rCond )
+{
+ for( sal_uInt16 n = 0; n < aCondColls.Count(); ++n )
+ if( *aCondColls[ n ] == rCond )
+ {
+ aCondColls.DeleteAndDestroy( n );
+ break;
+ }
+
+ // nicht gefunden -> als einfuegen
+ SwCollCondition* pNew = new SwCollCondition( rCond );
+ aCondColls.Insert( pNew, aCondColls.Count() );
+}
+
+
+sal_Bool SwConditionTxtFmtColl::RemoveCondition( const SwCollCondition& rCond )
+{
+ sal_Bool bRet = sal_False;
+ for( sal_uInt16 n = 0; n < aCondColls.Count(); ++n )
+ if( *aCondColls[ n ] == rCond )
+ {
+ aCondColls.DeleteAndDestroy( n );
+ bRet = sal_True;
+ }
+
+ return bRet;
+}
+
+void SwConditionTxtFmtColl::SetConditions( const SwFmtCollConditions& rCndClls )
+{
+ // Kopiere noch die Bedingungen
+ // aber erst die alten loeschen!
+ if( aCondColls.Count() )
+ aCondColls.DeleteAndDestroy( 0, aCondColls.Count() );
+ SwDoc& rDoc = *GetDoc();
+ for( sal_uInt16 n = 0; n < rCndClls.Count(); ++n )
+ {
+ SwCollCondition* pFnd = rCndClls[ n ];
+ SwTxtFmtColl* pTmpColl = pFnd->GetTxtFmtColl()
+ ? rDoc.CopyTxtColl( *pFnd->GetTxtFmtColl() )
+ : 0;
+ SwCollCondition* pNew;
+ if( USRFLD_EXPRESSION & pFnd->GetCondition() )
+ pNew = new SwCollCondition( pTmpColl, pFnd->GetCondition(),
+ *pFnd->GetFldExpression() );
+ else
+ pNew = new SwCollCondition( pTmpColl, pFnd->GetCondition(),
+ pFnd->GetSubCondition() );
+ aCondColls.Insert( pNew, n );
+ }
+}
+//#outline level, zhaojianwei
+void SwTxtFmtColl::SetAttrOutlineLevel( int nLevel)
+{
+ ASSERT( 0 <= nLevel && nLevel <= MAXLEVEL ,"SwTxtFmtColl: Level Out Of Range" );
+ SetFmtAttr( SfxUInt16Item( RES_PARATR_OUTLINELEVEL,
+ static_cast<sal_uInt16>(nLevel) ) );
+}
+
+int SwTxtFmtColl::GetAttrOutlineLevel() const
+{
+ return ((const SfxUInt16Item &)GetFmtAttr(RES_PARATR_OUTLINELEVEL)).GetValue();
+}
+
+int SwTxtFmtColl::GetAssignedOutlineStyleLevel() const
+{
+ ASSERT( IsAssignedToListLevelOfOutlineStyle(),
+ "<SwTxtFmtColl::GetAssignedOutlineStyleLevel()> - misuse of method");
+ return GetAttrOutlineLevel() - 1;
+}
+
+void SwTxtFmtColl::AssignToListLevelOfOutlineStyle(const int nAssignedListLevel)
+{
+ mbAssignedToOutlineStyle = true;
+ SetAttrOutlineLevel(nAssignedListLevel+1);
+
+ // --> OD 2009-03-18 #i100277#
+ SwClientIter aIter( *this );
+ SwTxtFmtColl* pDerivedTxtFmtColl =
+ dynamic_cast<SwTxtFmtColl*>(aIter.First( TYPE( SwTxtFmtColl ) ));
+ while ( pDerivedTxtFmtColl != 0 )
+ {
+ if ( !pDerivedTxtFmtColl->IsAssignedToListLevelOfOutlineStyle() )
+ {
+ if ( pDerivedTxtFmtColl->GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_DEFAULT )
+ {
+ SwNumRuleItem aItem(aEmptyStr);
+ pDerivedTxtFmtColl->SetFmtAttr( aItem );
+ }
+ if ( pDerivedTxtFmtColl->GetItemState( RES_PARATR_OUTLINELEVEL, sal_False ) == SFX_ITEM_DEFAULT )
+ {
+ pDerivedTxtFmtColl->SetAttrOutlineLevel( 0 );
+ }
+ }
+
+ pDerivedTxtFmtColl = dynamic_cast<SwTxtFmtColl*>(aIter.Next());
+ }
+ // <--
+}
+
+void SwTxtFmtColl::DeleteAssignmentToListLevelOfOutlineStyle()
+{
+ mbAssignedToOutlineStyle = false;
+ ResetFmtAttr(RES_PARATR_OUTLINELEVEL);
+}
+//<-end,zhaojianwei
+
+//FEATURE::CONDCOLL
diff --git a/sw/source/core/doc/ftnidx.cxx b/sw/source/core/doc/ftnidx.cxx
new file mode 100644
index 000000000000..7395e7ae7449
--- /dev/null
+++ b/sw/source/core/doc/ftnidx.cxx
@@ -0,0 +1,398 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <ftninfo.hxx>
+#include <doc.hxx>
+#include <ftnidx.hxx>
+#include <ndtxt.hxx>
+#include <ndindex.hxx>
+#include <section.hxx>
+#include <fmtftntx.hxx>
+#include <rootfrm.hxx>
+
+
+_SV_IMPL_SORTAR_ALG( _SwFtnIdxs, SwTxtFtnPtr )
+sal_Bool _SwFtnIdxs::Seek_Entry( const SwTxtFtnPtr rSrch, sal_uInt16* pFndPos ) const
+{
+ sal_uLong nIdx = _SwTxtFtn_GetIndex( rSrch );
+ xub_StrLen nCntIdx = *rSrch->GetStart();
+
+ sal_uInt16 nO = Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ sal_uLong nFndIdx = _SwTxtFtn_GetIndex( (*this)[ nM ] );
+ if( nFndIdx == nIdx && *(*this)[ nM ]->GetStart() == nCntIdx )
+ {
+ if( pFndPos )
+ *pFndPos = nM;
+ return sal_True;
+ }
+ else if( nFndIdx < nIdx ||
+ (nFndIdx == nIdx && *(*this)[ nM ]->GetStart() < nCntIdx ))
+ nU = nM + 1;
+ else if( nM == 0 )
+ {
+ if( pFndPos )
+ *pFndPos = nU;
+ return sal_False;
+ }
+ else
+ nO = nM - 1;
+ }
+ }
+ if( pFndPos )
+ *pFndPos = nU;
+ return sal_False;
+}
+
+
+void SwFtnIdxs::UpdateFtn( const SwNodeIndex& rStt )
+{
+ if( !Count() )
+ return;
+
+ // besorge erstmal das Nodes-Array ueber den StartIndex der ersten Fussnote
+ SwDoc* pDoc = rStt.GetNode().GetDoc();
+ if( pDoc->IsInReading() )
+ return ;
+ SwTxtFtn* pTxtFtn;
+
+ const SwEndNoteInfo& rEndInfo = pDoc->GetEndNoteInfo();
+ const SwFtnInfo& rFtnInfo = pDoc->GetFtnInfo();
+
+ //Fuer normale Fussnoten werden Chapter- und Dokumentweise Nummerierung
+ //getrennt behandelt. Fuer Endnoten gibt es nur die Dokumentweise
+ //Nummerierung.
+ if( FTNNUM_CHAPTER == rFtnInfo.eNum )
+ {
+ const SwOutlineNodes& rOutlNds = pDoc->GetNodes().GetOutLineNds();
+ const SwNode* pCapStt = &pDoc->GetNodes().GetEndOfExtras();
+ sal_uLong nCapEnd = pDoc->GetNodes().GetEndOfContent().GetIndex();
+ if( rOutlNds.Count() )
+ {
+ // suche den Start des Kapitels, in den rStt steht.
+ sal_uInt16 n;
+
+ for( n = 0; n < rOutlNds.Count(); ++n )
+ if( rOutlNds[ n ]->GetIndex() > rStt.GetIndex() )
+ break; // gefunden
+ //else if( !rOutlNds[ n ]->GetTxtNode()->GetTxtColl()->GetOutlineLevel() ) //#outline level,zhaojianwei
+ else if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 ) //<-end,zhaojianwei
+ pCapStt = rOutlNds[ n ]; // Start eines neuen Kapitels
+ // dann suche jetzt noch das Ende vom Bereich
+ for( ; n < rOutlNds.Count(); ++n )
+ //if( !rOutlNds[ n ]->GetTxtNode()->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
+ if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 )//<-end,zhaojianwei
+ {
+ nCapEnd = rOutlNds[ n ]->GetIndex(); // Ende des gefundenen Kapitels
+ break;
+ }
+ }
+
+ sal_uInt16 nPos, nFtnNo = 1;
+ if( SeekEntry( *pCapStt, &nPos ) && nPos )
+ {
+ // gehe nach vorne bis der Index nicht mehr gleich ist
+ const SwNode* pCmpNd = &rStt.GetNode();
+ while( nPos && pCmpNd == &((*this)[ --nPos ]->GetTxtNode()) )
+ ;
+ ++nPos;
+ }
+
+ if( nPos == Count() ) // nichts gefunden
+ return;
+
+ if( !rOutlNds.Count() )
+ nFtnNo = nPos+1;
+
+ for( ; nPos < Count(); ++nPos )
+ {
+ pTxtFtn = (*this)[ nPos ];
+ if( pTxtFtn->GetTxtNode().GetIndex() >= nCapEnd )
+ break;
+
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if( !rFtn.GetNumStr().Len() && !rFtn.IsEndNote() &&
+ !SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
+ pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nFtnNo++,
+ &rFtn.GetNumStr() );
+ }
+ }
+
+ SwUpdFtnEndNtAtEnd aNumArr;
+
+ // sal_Bool, damit hier auch bei Chapter-Einstellung die Endnoten
+ // durchlaufen.
+ const sal_Bool bEndNoteOnly = FTNNUM_DOC != rFtnInfo.eNum;
+
+ sal_uInt16 nPos, nFtnNo = 1, nEndNo = 1;
+ sal_uLong nUpdNdIdx = rStt.GetIndex();
+ for( nPos = 0; nPos < Count(); ++nPos )
+ {
+ pTxtFtn = (*this)[ nPos ];
+ if( nUpdNdIdx <= pTxtFtn->GetTxtNode().GetIndex() )
+ break;
+
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if( !rFtn.GetNumStr().Len() )
+ {
+ if( !aNumArr.ChkNumber( *pTxtFtn ) )
+ {
+ if( pTxtFtn->GetFtn().IsEndNote() )
+ nEndNo++;
+ else
+ nFtnNo++;
+ }
+ }
+ }
+
+ // ab nPos bei allen FootNotes die Array-Nummer setzen
+ for( ; nPos < Count(); ++nPos )
+ {
+ pTxtFtn = (*this)[ nPos ];
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if( !rFtn.GetNumStr().Len() )
+ {
+ sal_uInt16 nSectNo = aNumArr.ChkNumber( *pTxtFtn );
+ if( !nSectNo && ( rFtn.IsEndNote() || !bEndNoteOnly ))
+ nSectNo = rFtn.IsEndNote()
+ ? rEndInfo.nFtnOffset + nEndNo++
+ : rFtnInfo.nFtnOffset + nFtnNo++;
+
+ if( nSectNo )
+ {
+ if( rFtn.IsEndNote() )
+ pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
+ else
+ pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
+ }
+ }
+ }
+ // Pageweise wird vom MA erfuellt !!
+}
+
+
+void SwFtnIdxs::UpdateAllFtn()
+{
+ if( !Count() )
+ return;
+
+ // besorge erstmal das Nodes-Array ueber den StartIndex der
+ // ersten Fussnote
+ SwDoc* pDoc = (SwDoc*) (*this)[ 0 ]->GetTxtNode().GetDoc();
+ SwTxtFtn* pTxtFtn;
+ const SwEndNoteInfo& rEndInfo = pDoc->GetEndNoteInfo();
+ const SwFtnInfo& rFtnInfo = pDoc->GetFtnInfo();
+
+ SwUpdFtnEndNtAtEnd aNumArr;
+
+ //Fuer normale Fussnoten werden Chapter- und Dokumentweise Nummerierung
+ //getrennt behandelt. Fuer Endnoten gibt es nur die Dokumentweise
+ //Nummerierung.
+ if( FTNNUM_CHAPTER == rFtnInfo.eNum )
+ {
+ const SwOutlineNodes& rOutlNds = pDoc->GetNodes().GetOutLineNds();
+ sal_uInt16 nNo = 1, // Nummer fuer die Fussnoten
+ nFtnIdx = 0; // Index in das FtnIdx-Array
+ for( sal_uInt16 n = 0; n < rOutlNds.Count(); ++n )
+ {
+ //if( !rOutlNds[ n ]->GetTxtNode()->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
+ if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 )//<-end,zhaojianwei
+ {
+ sal_uLong nCapStt = rOutlNds[ n ]->GetIndex(); // Start eines neuen Kapitels
+ for( ; nFtnIdx < Count(); ++nFtnIdx )
+ {
+ pTxtFtn = (*this)[ nFtnIdx ];
+ if( pTxtFtn->GetTxtNode().GetIndex() >= nCapStt )
+ break;
+
+ // Endnoten nur Dokumentweise
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if( !rFtn.IsEndNote() && !rFtn.GetNumStr().Len() &&
+ !SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
+ pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nNo++,
+ &rFtn.GetNumStr() );
+ }
+ if( nFtnIdx >= Count() )
+ break; // ok alles geupdatet
+ nNo = 1;
+ }
+ }
+
+ for( nNo = 1; nFtnIdx < Count(); ++nFtnIdx )
+ {
+ //Endnoten nur Dokumentweise
+ pTxtFtn = (*this)[ nFtnIdx ];
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if( !rFtn.IsEndNote() && !rFtn.GetNumStr().Len() &&
+ !SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
+ pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nNo++,
+ &rFtn.GetNumStr() );
+ }
+
+ }
+
+ // sal_Bool, damit hier auch bei Chapter-Einstellung die Endnoten
+ // durchlaufen.
+ const sal_Bool bEndNoteOnly = FTNNUM_DOC != rFtnInfo.eNum;
+ sal_uInt16 nFtnNo = 0, nEndNo = 0;
+ for( sal_uInt16 nPos = 0; nPos < Count(); ++nPos )
+ {
+ pTxtFtn = (*this)[ nPos ];
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if( !rFtn.GetNumStr().Len() )
+ {
+ sal_uInt16 nSectNo = aNumArr.ChkNumber( *pTxtFtn );
+ if( !nSectNo && ( rFtn.IsEndNote() || !bEndNoteOnly ))
+ nSectNo = rFtn.IsEndNote()
+ ? rEndInfo.nFtnOffset + (++nEndNo)
+ : rFtnInfo.nFtnOffset + (++nFtnNo);
+
+ if( nSectNo )
+ {
+ if( rFtn.IsEndNote() )
+ pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
+ else
+ pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
+ }
+ }
+ }
+
+ if( pDoc->GetRootFrm() && FTNNUM_PAGE == rFtnInfo.eNum )
+ pDoc->GetRootFrm()->UpdateFtnNums();
+}
+
+SwTxtFtn* SwFtnIdxs::SeekEntry( const SwNodeIndex& rPos, sal_uInt16* pFndPos ) const
+{
+ sal_uLong nIdx = rPos.GetIndex();
+
+ sal_uInt16 nO = Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ sal_uLong nNdIdx = _SwTxtFtn_GetIndex( (*this)[ nM ] );
+ if( nNdIdx == nIdx )
+ {
+ if( pFndPos )
+ *pFndPos = nM;
+ return (*this)[ nM ];
+ }
+ else if( nNdIdx < nIdx )
+ nU = nM + 1;
+ else if( nM == 0 )
+ {
+ if( pFndPos )
+ *pFndPos = nU;
+ return 0;
+ }
+ else
+ nO = nM - 1;
+ }
+ }
+ if( pFndPos )
+ *pFndPos = nU;
+ return 0;
+}
+
+/* */
+
+const SwSectionNode* SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr(
+ const SwTxtFtn& rTxtFtn )
+{
+ sal_uInt16 nWh = static_cast<sal_uInt16>( rTxtFtn.GetFtn().IsEndNote() ?
+ RES_END_AT_TXTEND : RES_FTN_AT_TXTEND );
+ sal_uInt16 nVal;
+ const SwSectionNode* pNd = rTxtFtn.GetTxtNode().FindSectionNode();
+ while( pNd && FTNEND_ATTXTEND_OWNNUMSEQ != ( nVal =
+ ((const SwFmtFtnAtTxtEnd&)pNd->GetSection().GetFmt()->
+ GetFmtAttr( nWh, sal_True )).GetValue() ) &&
+ FTNEND_ATTXTEND_OWNNUMANDFMT != nVal )
+ pNd = pNd->StartOfSectionNode()->FindSectionNode();
+
+ return pNd;
+}
+
+sal_uInt16 SwUpdFtnEndNtAtEnd::GetNumber( const SwTxtFtn& rTxtFtn,
+ const SwSectionNode& rNd )
+{
+ sal_uInt16 nRet = 0, nWh;
+ SvPtrarr* pArr;
+ SvUShorts* pNum;
+ if( rTxtFtn.GetFtn().IsEndNote() )
+ {
+ pArr = &aEndSects;
+ pNum = &aEndNums;
+ nWh = RES_END_AT_TXTEND;
+ }
+ else
+ {
+ pArr = &aFtnSects;
+ pNum = &aFtnNums;
+ nWh = RES_FTN_AT_TXTEND;
+ }
+ void* pNd = (void*)&rNd;
+
+ for( sal_uInt16 n = pArr->Count(); n; )
+ if( pArr->GetObject( --n ) == pNd )
+ {
+ nRet = ++pNum->GetObject( n );
+ break;
+ }
+
+ if( !nRet )
+ {
+ pArr->Insert( pNd, pArr->Count() );
+ nRet = ((SwFmtFtnEndAtTxtEnd&)rNd.GetSection().GetFmt()->
+ GetFmtAttr( nWh )).GetOffset();
+ ++nRet;
+ pNum->Insert( nRet, pNum->Count() );
+ }
+ return nRet;
+}
+
+sal_uInt16 SwUpdFtnEndNtAtEnd::ChkNumber( const SwTxtFtn& rTxtFtn )
+{
+ const SwSectionNode* pSectNd = FindSectNdWithEndAttr( rTxtFtn );
+ return pSectNd ? GetNumber( rTxtFtn, *pSectNd ) : 0;
+}
+
+
+
+
diff --git a/sw/source/core/doc/gctable.cxx b/sw/source/core/doc/gctable.cxx
new file mode 100644
index 000000000000..607bb4f79c2e
--- /dev/null
+++ b/sw/source/core/doc/gctable.cxx
@@ -0,0 +1,451 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <editeng/boxitem.hxx>
+#include <tblrwcl.hxx>
+#include <swtblfmt.hxx>
+
+
+inline const SvxBorderLine* GetLineTB( const SvxBoxItem* pBox, sal_Bool bTop )
+{
+ return bTop ? pBox->GetTop() : pBox->GetBottom();
+}
+
+
+sal_Bool _SwGCBorder_BoxBrd::CheckLeftBorderOfFormat( const SwFrmFmt& rFmt )
+{
+ const SvxBorderLine* pBrd;
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == rFmt.GetItemState( RES_BOX, sal_True, &pItem ) &&
+ 0 != ( pBrd = ((SvxBoxItem*)pItem)->GetLeft() ) )
+ {
+ if( *pBrdLn == *pBrd )
+ bAnyBorderFnd = sal_True;
+ return sal_True;
+ }
+ return sal_False;
+}
+
+
+
+sal_Bool lcl_GCBorder_ChkBoxBrd_L( const SwTableLine*& rpLine, void* pPara )
+{
+ const SwTableBox* pBox = rpLine->GetTabBoxes()[ 0 ];
+ return lcl_GCBorder_ChkBoxBrd_B( pBox, pPara );
+}
+
+sal_Bool lcl_GCBorder_ChkBoxBrd_B( const SwTableBox*& rpBox, void* pPara )
+{
+ sal_Bool bRet = sal_True;
+ if( rpBox->GetTabLines().Count() )
+ {
+ for( sal_uInt16 n = 0, nLines = rpBox->GetTabLines().Count();
+ n < nLines && bRet; ++n )
+ {
+ const SwTableLine* pLine = rpBox->GetTabLines()[ n ];
+ bRet = lcl_GCBorder_ChkBoxBrd_L( pLine, pPara );
+ }
+ }
+ else
+ {
+ _SwGCBorder_BoxBrd* pBPara = (_SwGCBorder_BoxBrd*)pPara;
+ bRet = pBPara->CheckLeftBorderOfFormat( *rpBox->GetFrmFmt() );
+ }
+ return bRet;
+}
+
+sal_Bool lcl_GCBorder_GetLastBox_L( const SwTableLine*& rpLine, void* pPara )
+{
+ const SwTableBoxes& rBoxes = rpLine->GetTabBoxes();
+ const SwTableBox* pBox = rBoxes[ rBoxes.Count()-1 ];
+ ::lcl_GCBorder_GetLastBox_B( pBox, pPara );
+ return sal_True;
+}
+
+sal_Bool lcl_GCBorder_GetLastBox_B( const SwTableBox*& rpBox, void* pPara )
+{
+ SwTableLines& rLines = (SwTableLines&)rpBox->GetTabLines();
+ if( rLines.Count() )
+ rLines.ForEach( &lcl_GCBorder_GetLastBox_L, pPara );
+ else
+ ((SwTableBoxes*)pPara)->Insert( rpBox, ((SwTableBoxes*)pPara)->Count() );
+ return sal_True;
+}
+
+// suche das "Ende" der vorgegebene BorderLine. Returnt wird die "Layout"Pos!
+sal_uInt16 lcl_FindEndPosOfBorder( const SwCollectTblLineBoxes& rCollTLB,
+ const SvxBorderLine& rBrdLn, sal_uInt16& rStt, sal_Bool bTop )
+{
+ sal_uInt16 nPos, nLastPos = 0;
+ for( sal_uInt16 nEnd = rCollTLB.Count(); rStt < nEnd; ++rStt )
+ {
+ const SfxPoolItem* pItem;
+ const SvxBorderLine* pBrd;
+ const SwTableBox& rBox = rCollTLB.GetBox( rStt, &nPos );
+
+ if( SFX_ITEM_SET != rBox.GetFrmFmt()->GetItemState(RES_BOX,sal_True, &pItem )
+ || 0 == ( pBrd = GetLineTB( (SvxBoxItem*)pItem, bTop ))
+ || !( *pBrd == rBrdLn ))
+ break;
+ nLastPos = nPos;
+ }
+ return nLastPos;
+}
+
+inline const SvxBorderLine* lcl_GCBorder_GetBorder( const SwTableBox& rBox,
+ sal_Bool bTop,
+ const SfxPoolItem** ppItem )
+{
+ return SFX_ITEM_SET == rBox.GetFrmFmt()->GetItemState( RES_BOX, sal_True, ppItem )
+ ? GetLineTB( (SvxBoxItem*)*ppItem, bTop )
+ : 0;
+}
+
+void lcl_GCBorder_DelBorder( const SwCollectTblLineBoxes& rCollTLB,
+ sal_uInt16& rStt, sal_Bool bTop,
+ const SvxBorderLine& rLine,
+ const SfxPoolItem* pItem,
+ sal_uInt16 nEndPos,
+ SwShareBoxFmts* pShareFmts )
+{
+ SwTableBox* pBox = (SwTableBox*)&rCollTLB.GetBox( rStt );
+ sal_uInt16 nNextPos;
+ const SvxBorderLine* pLn = &rLine;
+
+ do {
+ if( pLn && *pLn == rLine )
+ {
+ SvxBoxItem aBox( *(SvxBoxItem*)pItem );
+ if( bTop )
+ aBox.SetLine( 0, BOX_LINE_TOP );
+ else
+ aBox.SetLine( 0, BOX_LINE_BOTTOM );
+
+ if( pShareFmts )
+ pShareFmts->SetAttr( *pBox, aBox );
+ else
+ pBox->ClaimFrmFmt()->SetFmtAttr( aBox );
+ }
+
+ if( ++rStt >= rCollTLB.Count() )
+ break;
+
+ pBox = (SwTableBox*)&rCollTLB.GetBox( rStt, &nNextPos );
+ if( nNextPos > nEndPos )
+ break;
+
+ pLn = lcl_GCBorder_GetBorder( *pBox, bTop, &pItem );
+
+ } while( sal_True );
+}
+
+
+sal_Bool lcl_GC_Line_Border( const SwTableLine*& rpLine, void* pPara )
+{
+ _SwGCLineBorder* pGCPara = (_SwGCLineBorder*)pPara;
+
+ // zuerst die rechte Kante mit der linken Kante der naechsten Box
+ // innerhalb dieser Line
+ {
+ _SwGCBorder_BoxBrd aBPara;
+ const SvxBorderLine* pBrd;
+ const SfxPoolItem* pItem;
+ const SwTableBoxes& rBoxes = rpLine->GetTabBoxes();
+ for( sal_uInt16 n = 0, nBoxes = rBoxes.Count() - 1; n < nBoxes; ++n )
+ {
+ SwTableBoxes aBoxes;
+ {
+ const SwTableBox* pBox = rBoxes[ n ];
+ if( pBox->GetSttNd() )
+ aBoxes.Insert( pBox, 0 );
+ else
+ lcl_GCBorder_GetLastBox_B( pBox, &aBoxes );
+ }
+
+ SwTableBox* pBox;
+ for( sal_uInt16 i = aBoxes.Count(); i; )
+ if( SFX_ITEM_SET == (pBox = aBoxes[ --i ])->GetFrmFmt()->
+ GetItemState( RES_BOX, sal_True, &pItem ) &&
+ 0 != ( pBrd = ((SvxBoxItem*)pItem)->GetRight() ) )
+ {
+ aBPara.SetBorder( *pBrd );
+ const SwTableBox* pNextBox = rBoxes[n+1];
+ if( lcl_GCBorder_ChkBoxBrd_B( pNextBox, &aBPara ) &&
+ aBPara.IsAnyBorderFound() )
+ {
+ SvxBoxItem aBox( *(SvxBoxItem*)pItem );
+ aBox.SetLine( 0, BOX_LINE_RIGHT );
+ if( pGCPara->pShareFmts )
+ pGCPara->pShareFmts->SetAttr( *pBox, aBox );
+ else
+ pBox->ClaimFrmFmt()->SetFmtAttr( aBox );
+ }
+ }
+
+ aBoxes.Remove( 0, aBoxes.Count() );
+ }
+ }
+
+ // und jetzt die eigene untere Kante mit der nachfolgenden oberen Kante
+ if( !pGCPara->IsLastLine() )
+ {
+ SwCollectTblLineBoxes aBottom( sal_False );
+ SwCollectTblLineBoxes aTop( sal_True );
+
+ ::lcl_Line_CollectBox( rpLine, &aBottom );
+
+ const SwTableLine* pNextLine = (*pGCPara->pLines)[ pGCPara->nLinePos+1 ];
+ ::lcl_Line_CollectBox( pNextLine, &aTop );
+
+ // dann entferne mal alle "doppelten" gleichen Lines
+ sal_uInt16 nBtmPos, nTopPos,
+ nSttBtm = 0, nSttTop = 0,
+ nEndBtm = aBottom.Count(), nEndTop = aTop.Count();
+
+ const SwTableBox *pBtmBox = &aBottom.GetBox( nSttBtm++, &nBtmPos ),
+ *pTopBox = &aTop.GetBox( nSttTop++, &nTopPos );
+ const SfxPoolItem *pBtmItem = 0, *pTopItem = 0;
+ const SvxBorderLine *pBtmLine(0), *pTopLine(0);
+ sal_Bool bGetTopItem = sal_True, bGetBtmItem = sal_True;
+
+ do {
+ if( bGetBtmItem )
+ pBtmLine = lcl_GCBorder_GetBorder( *pBtmBox, sal_False, &pBtmItem );
+ if( bGetTopItem )
+ pTopLine = lcl_GCBorder_GetBorder( *pTopBox, sal_True, &pTopItem );
+
+ if( pTopLine && pBtmLine && *pTopLine == *pBtmLine )
+ {
+ // dann kann einer entfernt werden, aber welche?
+ sal_uInt16 nSavSttBtm = nSttBtm, nSavSttTop = nSttTop;
+ sal_uInt16 nBtmEndPos = ::lcl_FindEndPosOfBorder( aBottom,
+ *pTopLine, nSttBtm, sal_False );
+ if( !nBtmEndPos ) nBtmEndPos = nBtmPos;
+ sal_uInt16 nTopEndPos = ::lcl_FindEndPosOfBorder( aTop,
+ *pTopLine, nSttTop, sal_True );
+ if( !nTopEndPos ) nTopEndPos = nTopPos;
+
+
+ if( nTopEndPos <= nBtmEndPos )
+ {
+ // dann die TopBorder bis zur BottomEndPos loeschen
+ nSttTop = nSavSttTop;
+ if( nTopPos <= nBtmEndPos )
+ lcl_GCBorder_DelBorder( aTop, --nSttTop, sal_True,
+ *pBtmLine, pTopItem, nBtmEndPos,
+ pGCPara->pShareFmts );
+ else
+ nSttBtm = nSavSttBtm;
+ }
+ else
+ {
+ // sonst die BottomBorder bis zur TopEndPos loeschen
+ nSttBtm = nSavSttBtm;
+ if( nBtmPos <= nTopEndPos )
+ lcl_GCBorder_DelBorder( aBottom, --nSttBtm, sal_False,
+ *pTopLine, pBtmItem, nTopEndPos,
+ pGCPara->pShareFmts );
+ else
+ nSttTop = nSavSttTop;
+ }
+ nTopPos = nBtmPos;
+ }
+
+ if( nTopPos == nBtmPos )
+ {
+ if( nSttBtm >= nEndBtm || nSttTop >= nEndTop )
+ break;
+
+ pBtmBox = &aBottom.GetBox( nSttBtm++, &nBtmPos );
+ pTopBox = &aTop.GetBox( nSttTop++, &nTopPos );
+ bGetTopItem = bGetBtmItem = sal_True;
+ }
+ else if( nTopPos < nBtmPos )
+ {
+ if( nSttTop >= nEndTop )
+ break;
+ pTopBox = &aTop.GetBox( nSttTop++, &nTopPos );
+ bGetTopItem = sal_True;
+ bGetBtmItem = sal_False;
+ }
+ else
+ {
+ if( nSttBtm >= nEndBtm )
+ break;
+ pBtmBox = &aBottom.GetBox( nSttBtm++, &nBtmPos );
+ bGetTopItem = sal_False;
+ bGetBtmItem = sal_True;
+ }
+
+ } while( sal_True );
+ }
+
+ ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_GC_Box_Border, pPara );
+
+ ++pGCPara->nLinePos;
+
+ return sal_True;
+}
+
+sal_Bool lcl_GC_Box_Border( const SwTableBox*& rpBox, void* pPara )
+{
+ if( rpBox->GetTabLines().Count() )
+ {
+ _SwGCLineBorder aPara( *rpBox );
+ aPara.pShareFmts = ((_SwGCLineBorder*)pPara)->pShareFmts;
+ ((SwTableBox*)rpBox)->GetTabLines().ForEach( &lcl_GC_Line_Border, &aPara );
+ }
+ return sal_True;
+}
+
+struct _GCLinePara
+{
+ SwTableLines* pLns;
+ SwShareBoxFmts* pShareFmts;
+
+ _GCLinePara( SwTableLines& rLns, _GCLinePara* pPara = 0 )
+ : pLns( &rLns ), pShareFmts( pPara ? pPara->pShareFmts : 0 )
+ {}
+};
+
+sal_Bool lcl_MergeGCBox( const SwTableBox*& rpTblBox, void* pPara )
+{
+ SwTableBox*& rpBox = (SwTableBox*&)rpTblBox;
+ sal_uInt16 n, nLen = rpBox->GetTabLines().Count();
+ if( nLen )
+ {
+ // ACHTUNG: die Anzahl der Lines kann sich aendern!
+ _GCLinePara aPara( rpBox->GetTabLines(), (_GCLinePara*)pPara );
+ for( n = 0; n < rpBox->GetTabLines().Count() &&
+ lcl_MergeGCLine( *(rpBox->GetTabLines().GetData() + n), &aPara );
+ ++n )
+ ;
+
+ if( 1 == rpBox->GetTabLines().Count() )
+ {
+ // Box mit einer Line, dann verschiebe alle Boxen der Line
+ // hinter diese Box in der Parent-Line und loesche diese Box
+ SwTableLine* pInsLine = rpBox->GetUpper();
+ SwTableLine* pCpyLine = rpBox->GetTabLines()[0];
+ sal_uInt16 nInsPos = pInsLine->GetTabBoxes().C40_GETPOS( SwTableBox, rpBox );
+ for( n = 0; n < pCpyLine->GetTabBoxes().Count(); ++n )
+ pCpyLine->GetTabBoxes()[n]->SetUpper( pInsLine );
+
+ pInsLine->GetTabBoxes().Insert( &pCpyLine->GetTabBoxes(), nInsPos+1 );
+ pCpyLine->GetTabBoxes().Remove( 0, n );
+ // loesche alte die Box mit der Line
+ pInsLine->GetTabBoxes().DeleteAndDestroy( nInsPos );
+
+ return sal_False; // neu aufsetzen
+ }
+ }
+ return sal_True;
+}
+
+sal_Bool lcl_MergeGCLine( const SwTableLine*& rpLine, void* pPara )
+{
+ SwTableLine* pLn = (SwTableLine*)rpLine;
+ sal_uInt16 nLen = pLn->GetTabBoxes().Count();
+ if( nLen )
+ {
+ _GCLinePara* pGCPara = (_GCLinePara*)pPara;
+ while( 1 == nLen )
+ {
+ // es gibt eine Box mit Lines
+ SwTableBox* pBox = pLn->GetTabBoxes()[0];
+ if( !pBox->GetTabLines().Count() )
+ break;
+
+ SwTableLine* pLine = pBox->GetTabLines()[0];
+
+ // pLine wird zu der aktuellen, also der rpLine,
+ // die restlichen werden ins LinesArray hinter der akt.
+ // verschoben.
+ // Das LinesArray ist im pPara!
+ nLen = pBox->GetTabLines().Count();
+
+ SwTableLines& rLns = *pGCPara->pLns;
+ const SwTableLine* pTmp = pLn;
+ sal_uInt16 nInsPos = rLns.GetPos( pTmp );
+ ASSERT( USHRT_MAX != nInsPos, "Line nicht gefunden!" );
+
+ SwTableBox* pUpper = pLn->GetUpper();
+
+ rLns.Remove( nInsPos, 1 ); // die Line dem aus Array loeschen
+ rLns.Insert( &pBox->GetTabLines(), nInsPos );
+
+ // JP 31.03.99: Bug 60000 - die Attribute der zu loeschenden
+ // Line an die "eingefuegten" uebertragen
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pLn->GetFrmFmt()->GetItemState(
+ RES_BACKGROUND, sal_True, &pItem ))
+ {
+ SwTableLines& rBoxLns = pBox->GetTabLines();
+ for( sal_uInt16 nLns = 0; nLns < nLen; ++nLns )
+ if( SFX_ITEM_SET != rBoxLns[ nLns ]->GetFrmFmt()->
+ GetItemState( RES_BACKGROUND, sal_True ))
+ pGCPara->pShareFmts->SetAttr( *rBoxLns[ nLns ], *pItem );
+ }
+
+ pBox->GetTabLines().Remove( 0, nLen ); // Lines aus Array loeschen
+
+ delete pLn;
+
+ // Abhaengigkeit neu setzen
+ while( nLen-- )
+ rLns[ nInsPos++ ]->SetUpper( pUpper );
+
+ pLn = pLine; // und neu setzen
+ nLen = pLn->GetTabBoxes().Count();
+ }
+
+ // ACHTUNG: die Anzahl der Boxen kann sich aendern!
+ for( nLen = 0; nLen < pLn->GetTabBoxes().Count(); ++nLen )
+ if( !lcl_MergeGCBox( *(pLn->GetTabBoxes().GetData() + nLen ), pPara ))
+ --nLen;
+ }
+ return sal_True;
+}
+
+ // Struktur ein wenig aufraeumen
+void SwTable::GCLines()
+{
+ // ACHTUNG: die Anzahl der Lines kann sich aendern!
+ _GCLinePara aPara( GetTabLines() );
+ SwShareBoxFmts aShareFmts;
+ aPara.pShareFmts = &aShareFmts;
+ for( sal_uInt16 n = 0; n < GetTabLines().Count() &&
+ lcl_MergeGCLine( *(GetTabLines().GetData() + n ), &aPara ); ++n )
+ ;
+}
+
+
diff --git a/sw/source/core/doc/htmltbl.cxx b/sw/source/core/doc/htmltbl.cxx
new file mode 100644
index 000000000000..9cef646cffce
--- /dev/null
+++ b/sw/source/core/doc/htmltbl.cxx
@@ -0,0 +1,1903 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "hintids.hxx"
+
+//#define TEST_DELAYED_RESIZE
+
+#ifdef TEST_DELAYED_RESIZE
+#include <vcl/sound.hxx>
+#endif
+#ifndef _WRKWIN_HXX //autogen
+#include <vcl/wrkwin.hxx>
+#endif
+#ifndef _APP_HXX //autogen
+#include <vcl/svapp.hxx>
+#endif
+#include <sot/storage.hxx>
+#include <fmtornt.hxx>
+#include <fmtfsize.hxx>
+#include <frmfmt.hxx>
+#include <docary.hxx>
+#include "ndtxt.hxx"
+#include "doc.hxx"
+#include "swtable.hxx"
+#include "rootfrm.hxx"
+#include "docsh.hxx"
+#include "flyfrm.hxx"
+#include "poolfmt.hxx"
+#include "viewsh.hxx"
+#include "tabfrm.hxx"
+
+#include "htmltbl.hxx"
+#include "ndindex.hxx"
+
+using namespace ::com::sun::star;
+
+
+#define COLFUZZY 20
+#define MAX_TABWIDTH (USHRT_MAX - 2001)
+
+
+/* */
+
+class SwHTMLTableLayoutConstraints
+{
+ sal_uInt16 nRow; // Start-Zeile
+ sal_uInt16 nCol; // Start-Spalte
+ sal_uInt16 nColSpan; // COLSPAN der Zelle
+
+ SwHTMLTableLayoutConstraints *pNext; // die naechste Bedingung
+
+ sal_uLong nMinNoAlign, nMaxNoAlign; // Zwischenergebnisse AL-Pass 1
+
+public:
+
+ SwHTMLTableLayoutConstraints( sal_uLong nMin, sal_uLong nMax, sal_uInt16 nRow,
+ sal_uInt16 nCol, sal_uInt16 nColSp );
+ ~SwHTMLTableLayoutConstraints();
+
+ sal_uLong GetMinNoAlign() const { return nMinNoAlign; }
+ sal_uLong GetMaxNoAlign() const { return nMaxNoAlign; }
+
+ SwHTMLTableLayoutConstraints *InsertNext( SwHTMLTableLayoutConstraints *pNxt );
+ SwHTMLTableLayoutConstraints* GetNext() const { return pNext; }
+
+ sal_uInt16 GetRow() const { return nRow; }
+
+ sal_uInt16 GetColSpan() const { return nColSpan; }
+ sal_uInt16 GetColumn() const { return nCol; }
+};
+
+/* */
+
+SwHTMLTableLayoutCnts::SwHTMLTableLayoutCnts( const SwStartNode *pSttNd,
+ SwHTMLTableLayout* pTab,
+ sal_Bool bNoBrTag,
+ SwHTMLTableLayoutCnts* pNxt ) :
+ pNext( pNxt ), pBox( 0 ), pTable( pTab ), pStartNode( pSttNd ),
+ nPass1Done( 0 ), nWidthSet( 0 ), bNoBreakTag( bNoBrTag )
+{}
+
+SwHTMLTableLayoutCnts::~SwHTMLTableLayoutCnts()
+{
+ delete pNext;
+ delete pTable;
+}
+
+const SwStartNode *SwHTMLTableLayoutCnts::GetStartNode() const
+{
+ return pBox ? pBox->GetSttNd() : pStartNode;
+}
+
+
+/* */
+
+SwHTMLTableLayoutCell::SwHTMLTableLayoutCell( SwHTMLTableLayoutCnts *pCnts,
+ sal_uInt16 nRSpan, sal_uInt16 nCSpan,
+ sal_uInt16 nWidth, sal_Bool bPrcWidth,
+ sal_Bool bNWrapOpt ) :
+ pContents( pCnts ),
+ nRowSpan( nRSpan ), nColSpan( nCSpan ),
+ nWidthOption( nWidth ), bPrcWidthOption( bPrcWidth ),
+ bNoWrapOption( bNWrapOpt )
+{}
+
+SwHTMLTableLayoutCell::~SwHTMLTableLayoutCell()
+{
+ if( nRowSpan==1 && nColSpan==1 )
+ {
+ delete pContents;
+ }
+}
+
+/* */
+
+SwHTMLTableLayoutColumn::SwHTMLTableLayoutColumn( sal_uInt16 nWidth,
+ sal_Bool bRelWidth,
+ sal_Bool bLBorder ) :
+ nMinNoAlign(MINLAY), nMaxNoAlign(MINLAY), nAbsMinNoAlign(MINLAY),
+ nMin(0), nMax(0),
+ nAbsColWidth(0), nRelColWidth(0),
+ nWidthOption( nWidth ), bRelWidthOption( bRelWidth ),
+ bLeftBorder( bLBorder )
+{}
+
+
+/* */
+
+SwHTMLTableLayoutConstraints::SwHTMLTableLayoutConstraints(
+ sal_uLong nMin, sal_uLong nMax, sal_uInt16 nRw, sal_uInt16 nColumn, sal_uInt16 nColSp ):
+ nRow( nRw ), nCol( nColumn ), nColSpan( nColSp ),
+ pNext( 0 ),
+ nMinNoAlign( nMin ), nMaxNoAlign( nMax )
+{}
+
+SwHTMLTableLayoutConstraints::~SwHTMLTableLayoutConstraints()
+{
+ delete pNext;
+}
+
+SwHTMLTableLayoutConstraints *SwHTMLTableLayoutConstraints::InsertNext(
+ SwHTMLTableLayoutConstraints *pNxt )
+{
+ SwHTMLTableLayoutConstraints *pPrev = 0;
+ SwHTMLTableLayoutConstraints *pConstr = this;
+ while( pConstr )
+ {
+ if( pConstr->GetRow() > pNxt->GetRow() ||
+ pConstr->GetColumn() > pNxt->GetColumn() )
+ break;
+ pPrev = pConstr;
+ pConstr = pConstr->GetNext();
+ }
+
+ if( pPrev )
+ {
+ pNxt->pNext = pPrev->GetNext();
+ pPrev->pNext = pNxt;
+ pConstr = this;
+ }
+ else
+ {
+ pNxt->pNext = this;
+ pConstr = pNxt;
+ }
+
+ return pConstr;
+}
+
+/* */
+
+typedef SwHTMLTableLayoutColumn *SwHTMLTableLayoutColumnPtr;
+typedef SwHTMLTableLayoutCell *SwHTMLTableLayoutCellPtr;
+
+SwHTMLTableLayout::SwHTMLTableLayout(
+ const SwTable * pSwTbl,
+ sal_uInt16 nRws, sal_uInt16 nCls, sal_Bool bColsOpt, sal_Bool bColTgs,
+ sal_uInt16 nWdth, sal_Bool bPrcWdth, sal_uInt16 nBorderOpt,
+ sal_uInt16 nCellPad, sal_uInt16 nCellSp, SvxAdjust eAdjust,
+ sal_uInt16 nLMargin, sal_uInt16 nRMargin,
+ sal_uInt16 nBWidth, sal_uInt16 nLeftBWidth,
+ sal_uInt16 nRightBWidth,
+ sal_uInt16 nInhLeftBWidth, sal_uInt16 nInhRightBWidth ) :
+ aColumns( new SwHTMLTableLayoutColumnPtr[nCls] ),
+ aCells( new SwHTMLTableLayoutCellPtr[nRws*nCls] ),
+ pSwTable( pSwTbl ), pLeftFillerBox( 0 ), pRightFillerBox( 0 ),
+ nMin( 0 ), nMax( 0 ),
+ nRows( nRws ), nCols( nCls ),
+ nLeftMargin( nLMargin ), nRightMargin( nRMargin ),
+ nInhAbsLeftSpace( 0 ), nInhAbsRightSpace( 0 ),
+ nRelLeftFill( 0 ), nRelRightFill( 0 ),
+ nRelTabWidth( 0 ), nWidthOption( nWdth ),
+ nCellPadding( nCellPad ), nCellSpacing( nCellSp ), nBorder( nBorderOpt ),
+ nLeftBorderWidth( nLeftBWidth ), nRightBorderWidth( nRightBWidth ),
+ nInhLeftBorderWidth( nInhLeftBWidth ),
+ nInhRightBorderWidth( nInhRightBWidth ),
+ nBorderWidth( nBWidth ),
+ nDelayedResizeAbsAvail( 0 ), nLastResizeAbsAvail( 0 ),
+ nPass1Done( 0 ), nWidthSet( 0 ), eTableAdjust( eAdjust ),
+ bColsOption( bColsOpt ), bColTags( bColTgs ),
+ bPrcWidthOption( bPrcWdth ), bUseRelWidth( sal_False ),
+ bMustResize( sal_True ), bExportable( sal_True ), bBordersChanged( sal_False ),
+ bMustNotResize( sal_False ), bMustNotRecalc( sal_False )
+{
+ aResizeTimer.SetTimeoutHdl( STATIC_LINK( this, SwHTMLTableLayout,
+ DelayedResize_Impl ) );
+}
+
+SwHTMLTableLayout::~SwHTMLTableLayout()
+{
+ sal_uInt16 i;
+
+ for( i = 0; i < nCols; i++ )
+ delete aColumns[i];
+ delete[] aColumns;
+
+ sal_uInt16 nCount = nRows*nCols;
+ for( i=0; i<nCount; i++ )
+ delete aCells[i];
+ delete[] aCells;
+}
+
+// Die Breiten der Umrandung werden zunaechst wie in Netscape berechnet:
+// Aussere Umrandung: BORDER + CELLSPACING + CELLPADDING
+// Innere Umrandung: CELLSPACING + CELLPADDING
+// Allerdings wird die Breite der Umrandung im SW trotzdem beachtet, wenn
+// bSwBorders gesetzt ist, damit nicht faellschlich umgebrochen wird.
+// MIB 27.6.97: Dabei muss auch der Abstand zum Inhalt berueckichtigt werden,
+// und zwar auch dann, wenn wenn nur die gegenueberliegende Seite
+// eine Umrandung hat.
+sal_uInt16 SwHTMLTableLayout::GetLeftCellSpace( sal_uInt16 nCol, sal_uInt16 nColSpan,
+ sal_Bool bSwBorders ) const
+{
+ sal_uInt16 nSpace = nCellSpacing + nCellPadding;
+
+ if( nCol == 0 )
+ {
+ nSpace = nSpace + nBorder;
+
+ if( bSwBorders && nSpace < nLeftBorderWidth )
+ nSpace = nLeftBorderWidth;
+ }
+ else if( bSwBorders )
+ {
+ if( GetColumn(nCol)->HasLeftBorder() )
+ {
+ if( nSpace < nBorderWidth )
+ nSpace = nBorderWidth;
+ }
+ else if( nCol+nColSpan == nCols && nRightBorderWidth &&
+ nSpace < MIN_BORDER_DIST )
+ {
+ ASSERT( !nCellPadding, "GetLeftCellSpace: CELLPADDING!=0" );
+ // Wenn die Gegenueberliegende Seite umrandet ist muessen
+ // wir zumindest den minimalen Abstand zum Inhalt
+ // beruecksichtigen. (Koennte man zusaetzlich auch an
+ // nCellPadding festmachen.)
+ nSpace = MIN_BORDER_DIST;
+ }
+ }
+
+ return nSpace;
+}
+
+sal_uInt16 SwHTMLTableLayout::GetRightCellSpace( sal_uInt16 nCol, sal_uInt16 nColSpan,
+ sal_Bool bSwBorders ) const
+{
+ sal_uInt16 nSpace = nCellPadding;
+
+ if( nCol+nColSpan == nCols )
+ {
+ nSpace += nBorder + nCellSpacing;
+ if( bSwBorders && nSpace < nRightBorderWidth )
+ nSpace = nRightBorderWidth;
+ }
+ else if( bSwBorders && GetColumn(nCol)->HasLeftBorder() &&
+ nSpace < MIN_BORDER_DIST )
+ {
+ ASSERT( !nCellPadding, "GetRightCellSpace: CELLPADDING!=0" );
+ // Wenn die Gegenueberliegende Seite umrandet ist muessen
+ // wir zumindest den minimalen Abstand zum Inhalt
+ // beruecksichtigen. (Koennte man zusaetzlich auch an
+ // nCellPadding festmachen.)
+ nSpace = MIN_BORDER_DIST;
+ }
+
+ return nSpace;
+}
+
+void SwHTMLTableLayout::AddBorderWidth( sal_uLong &rMin, sal_uLong &rMax,
+ sal_uLong &rAbsMin,
+ sal_uInt16 nCol, sal_uInt16 nColSpan,
+ sal_Bool bSwBorders ) const
+{
+ sal_uLong nAdd = GetLeftCellSpace( nCol, nColSpan, bSwBorders ) +
+ GetRightCellSpace( nCol, nColSpan, bSwBorders );
+
+ rMin += nAdd;
+ rMax += nAdd;
+ rAbsMin += nAdd;
+}
+
+void SwHTMLTableLayout::SetBoxWidth( SwTableBox *pBox, sal_uInt16 nCol,
+ sal_uInt16 nColSpan ) const
+{
+ SwFrmFmt *pFrmFmt = pBox->GetFrmFmt();
+
+ // die Breite der Box berechnen
+ SwTwips nFrmWidth = 0;
+ while( nColSpan-- )
+ nFrmWidth += GetColumn( nCol++ )->GetRelColWidth();
+
+ // und neu setzen
+
+ pFrmFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nFrmWidth, 0 ));
+}
+
+void SwHTMLTableLayout::GetAvail( sal_uInt16 nCol, sal_uInt16 nColSpan,
+ sal_uInt16& rAbsAvail, sal_uInt16& rRelAvail ) const
+{
+ rAbsAvail = 0;
+ rRelAvail = 0;
+ for( sal_uInt16 i=nCol; i<nCol+nColSpan;i++ )
+ {
+ const SwHTMLTableLayoutColumn *pColumn = GetColumn(i);
+ rAbsAvail = rAbsAvail + pColumn->GetAbsColWidth();
+ rRelAvail = rRelAvail + pColumn->GetRelColWidth();
+ }
+}
+
+sal_uInt16 SwHTMLTableLayout::GetBrowseWidthByVisArea( const SwDoc& rDoc )
+{
+ ViewShell *pVSh = 0;
+ rDoc.GetEditShell( &pVSh );
+ if( pVSh )
+ {
+ return (sal_uInt16)pVSh->GetBrowseWidth();
+ }
+
+ return 0;
+}
+
+sal_uInt16 SwHTMLTableLayout::GetBrowseWidth( const SwDoc& rDoc )
+{
+ // Wenn ein Layout da ist, koennen wir die Breite dort herholen.
+ const SwRootFrm *pRootFrm = rDoc.GetRootFrm();
+ if( pRootFrm )
+ {
+ const SwFrm *pPageFrm = pRootFrm->GetLower();
+ if( pPageFrm )
+ return (sal_uInt16)pPageFrm->Prt().Width();
+ }
+
+ // --> OD 2010-05-12 #i91658#
+ // Assertion removed which state that no browse width is available.
+ // Investigation reveals that all calls can handle the case that no browse
+ // width is provided.
+ return GetBrowseWidthByVisArea( rDoc );
+ // <--
+}
+
+sal_uInt16 SwHTMLTableLayout::GetBrowseWidthByTabFrm(
+ const SwTabFrm& rTabFrm ) const
+{
+ SwTwips nWidth = 0;
+
+ const SwFrm *pUpper = rTabFrm.GetUpper();
+ if( MayBeInFlyFrame() && pUpper->IsFlyFrm() &&
+ ((const SwFlyFrm *)pUpper)->GetAnchorFrm() )
+ {
+ // Wenn die Tabelle in einem selbst angelegten Rahmen steht, dann ist
+ // die Breite Ankers und nicht die Breite Rahmens von Bedeutung.
+ // Bei Absatz-gebundenen Rahmen werden Absatz-Einzuege nicht beachtet.
+ const SwFrm *pAnchor = ((const SwFlyFrm *)pUpper)->GetAnchorFrm();
+ if( pAnchor->IsTxtFrm() )
+ nWidth = pAnchor->Frm().Width();
+ else
+ nWidth = pAnchor->Prt().Width();
+ }
+ else
+ {
+ nWidth = pUpper->Prt().Width();
+ }
+
+ SwTwips nUpperDummy = 0;
+ long nRightOffset = 0,
+ nLeftOffset = 0;
+ rTabFrm.CalcFlyOffsets( nUpperDummy, nLeftOffset, nRightOffset );
+ nWidth -= (nLeftOffset + nRightOffset);
+
+ return nWidth < USHRT_MAX ? static_cast<sal_uInt16>(nWidth) : USHRT_MAX;
+}
+
+sal_uInt16 SwHTMLTableLayout::GetBrowseWidthByTable( const SwDoc& rDoc ) const
+{
+ sal_uInt16 nBrowseWidth = 0;
+ SwClientIter aIter( *(SwModify*)pSwTable->GetFrmFmt() );
+ SwClient* pCli = aIter.First( TYPE( SwTabFrm ));
+ if( pCli )
+ {
+ nBrowseWidth = GetBrowseWidthByTabFrm( *(SwTabFrm*)pCli );
+ }
+ else
+ {
+ nBrowseWidth = SwHTMLTableLayout::GetBrowseWidth( rDoc );
+ }
+
+ return nBrowseWidth;
+}
+
+const SwStartNode *SwHTMLTableLayout::GetAnyBoxStartNode() const
+{
+ const SwStartNode *pBoxSttNd;
+
+ const SwTableBox* pBox = pSwTable->GetTabLines()[0]->GetTabBoxes()[0];
+ while( 0 == (pBoxSttNd = pBox->GetSttNd()) )
+ {
+ ASSERT( pBox->GetTabLines().Count() > 0,
+ "Box ohne Start-Node und Lines" );
+ ASSERT( pBox->GetTabLines()[0]->GetTabBoxes().Count() > 0,
+ "Line ohne Boxen" );
+ pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
+ }
+
+ return pBoxSttNd;
+}
+
+SwFrmFmt *SwHTMLTableLayout::FindFlyFrmFmt() const
+{
+ const SwTableNode *pTblNd = GetAnyBoxStartNode()->FindTableNode();
+ ASSERT( pTblNd, "Kein Table-Node?" );
+ return pTblNd->GetFlyFmt();
+}
+
+static void lcl_GetMinMaxSize( sal_uLong& rMinNoAlignCnts, sal_uLong& rMaxNoAlignCnts,
+ sal_uLong& rAbsMinNoAlignCnts,
+#ifdef FIX41370
+ sal_Bool& rHR,
+#endif
+ SwTxtNode *pTxtNd, sal_uLong nIdx, sal_Bool bNoBreak )
+{
+ pTxtNd->GetMinMaxSize( nIdx, rMinNoAlignCnts, rMaxNoAlignCnts,
+ rAbsMinNoAlignCnts );
+ ASSERT( rAbsMinNoAlignCnts <= rMinNoAlignCnts,
+ "GetMinMaxSize: absmin > min" );
+ ASSERT( rMinNoAlignCnts <= rMaxNoAlignCnts,
+ "GetMinMaxSize: max > min" );
+
+ //Bei einen <PRE>-Absatz entspricht die maximale Breite der
+ // minimalen breite
+ const SwFmtColl *pColl = &pTxtNd->GetAnyFmtColl();
+ while( pColl && !pColl->IsDefault() &&
+ (USER_FMT & pColl->GetPoolFmtId()) )
+ {
+ pColl = (const SwFmtColl *)pColl->DerivedFrom();
+ }
+
+ // <NOBR> in der gesamten Zelle bezieht sich auf Text, aber nicht
+ // auf Tabellen. Netscape beruecksichtigt dies nur fuer Grafiken.
+ if( (pColl && RES_POOLCOLL_HTML_PRE==pColl->GetPoolFmtId()) || bNoBreak )
+ {
+ rMinNoAlignCnts = rMaxNoAlignCnts;
+ rAbsMinNoAlignCnts = rMaxNoAlignCnts;
+ }
+#ifdef FIX41370
+ else if( pColl && RES_POOLCOLL_HTML_HR==pColl->GetPoolFmtId() )
+ {
+ rHR |= !pTxtNd->HasSwAttrSet() ||
+ SFX_ITEM_SET != pTxtNd->GetpSwAttrSet()
+ ->GetItemState( RES_LR_SPACE, sal_False );
+ }
+#endif
+}
+
+void SwHTMLTableLayout::AutoLayoutPass1()
+{
+ nPass1Done++;
+
+ ClearPass1Info();
+
+ sal_Bool bFixRelWidths = sal_False;
+ sal_uInt16 i;
+
+ SwHTMLTableLayoutConstraints *pConstraints = 0;
+
+ for( i=0; i<nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ pColumn->ClearPass1Info( !HasColTags() );
+ sal_uInt16 nMinColSpan = USHRT_MAX; // Spaltenzahl, auf die sich dir
+ // berechnete Breite bezieht
+ sal_uInt16 nColSkip = USHRT_MAX; // Wie viele Spalten muessen
+ // uebersprungen werden
+
+ for( sal_uInt16 j=0; j<nRows; j++ )
+ {
+ SwHTMLTableLayoutCell *pCell = GetCell(j,i);
+ SwHTMLTableLayoutCnts *pCnts = pCell->GetContents();
+
+ // fix #31488#: Zum Ermitteln der naechsten zu berechnenden
+ // Spalte muessen alle Zeilen herangezogen werden
+ sal_uInt16 nColSpan = pCell->GetColSpan();
+ if( nColSpan < nColSkip )
+ nColSkip = nColSpan;
+
+ if( !pCnts || (pCnts && !pCnts->IsPass1Done(nPass1Done)) )
+ {
+ // die Zelle ist leer oder ihr Inhalt wurde nich nicht
+ // bearbeitet
+ if( nColSpan < nMinColSpan )
+ nMinColSpan = nColSpan;
+
+ sal_uLong nMinNoAlignCell = 0;
+ sal_uLong nMaxNoAlignCell = 0;
+ sal_uLong nAbsMinNoAlignCell = 0;
+ sal_uLong nMaxTableCell = 0;
+ sal_uLong nAbsMinTableCell = 0;
+#ifdef FIX41370
+ sal_Bool bHR = sal_False;
+#endif
+
+ while( pCnts )
+ {
+ const SwStartNode *pSttNd = pCnts->GetStartNode();
+ if( pSttNd )
+ {
+ const SwDoc *pDoc = pSttNd->GetDoc();
+ sal_uLong nIdx = pSttNd->GetIndex();
+ while( !(pDoc->GetNodes()[nIdx])->IsEndNode() )
+ {
+ SwTxtNode *pTxtNd = (pDoc->GetNodes()[nIdx])->GetTxtNode();
+ if( pTxtNd )
+ {
+ sal_uLong nMinNoAlignCnts = 0;
+ sal_uLong nMaxNoAlignCnts = 0;
+ sal_uLong nAbsMinNoAlignCnts = 0;
+
+ lcl_GetMinMaxSize( nMinNoAlignCnts,
+ nMaxNoAlignCnts,
+ nAbsMinNoAlignCnts,
+#ifdef FIX41370
+ bHR,
+#endif
+ pTxtNd, nIdx,
+ pCnts->HasNoBreakTag() );
+
+ if( nMinNoAlignCnts > nMinNoAlignCell )
+ nMinNoAlignCell = nMinNoAlignCnts;
+ if( nMaxNoAlignCnts > nMaxNoAlignCell )
+ nMaxNoAlignCell = nMaxNoAlignCnts;
+ if( nAbsMinNoAlignCnts > nAbsMinNoAlignCell )
+ nAbsMinNoAlignCell = nAbsMinNoAlignCnts;
+ }
+ else
+ {
+ SwTableNode *pTabNd = (pDoc->GetNodes()[nIdx])->GetTableNode();
+ if( pTabNd )
+ {
+ SwHTMLTableLayout *pChild = pTabNd->GetTable().GetHTMLTableLayout();
+ if( pChild )
+ {
+ pChild->AutoLayoutPass1();
+ sal_uLong nMaxTableCnts = pChild->nMax;
+ sal_uLong nAbsMinTableCnts = pChild->nMin;
+
+ // Eine feste Tabellen-Breite wird als Minimum
+ // und Maximum gleichzeitig uebernommen
+ if( !pChild->bPrcWidthOption && pChild->nWidthOption )
+ {
+ sal_uLong nTabWidth = pChild->nWidthOption;
+ if( nTabWidth >= nAbsMinTableCnts )
+ {
+ nMaxTableCnts = nTabWidth;
+ nAbsMinTableCnts = nTabWidth;
+ }
+ else
+ {
+ nMaxTableCnts = nAbsMinTableCnts;
+ }
+ }
+
+ if( nMaxTableCnts > nMaxTableCell )
+ nMaxTableCell = nMaxTableCnts;
+ if( nAbsMinTableCnts > nAbsMinTableCell )
+ nAbsMinTableCell = nAbsMinTableCnts;
+ }
+ nIdx = pTabNd->EndOfSectionNode()->GetIndex();
+ }
+ }
+ nIdx++;
+ }
+ }
+ else
+ {
+ ASSERT( !this, "Sub tables in HTML import?" )
+ SwHTMLTableLayout *pChild = pCnts->GetTable();
+ pChild->AutoLayoutPass1();
+ sal_uLong nMaxTableCnts = pChild->nMax;
+ sal_uLong nAbsMinTableCnts = pChild->nMin;
+
+ // Eine feste Tabellen-Breite wird als Minimum
+ // und Maximum gleichzeitig uebernommen
+ if( !pChild->bPrcWidthOption && pChild->nWidthOption )
+ {
+ sal_uLong nTabWidth = pChild->nWidthOption;
+ if( nTabWidth >= nAbsMinTableCnts )
+ {
+ nMaxTableCnts = nTabWidth;
+ nAbsMinTableCnts = nTabWidth;
+ }
+ else
+ {
+ nMaxTableCnts = nAbsMinTableCnts;
+ }
+ }
+
+ if( nMaxTableCnts > nMaxTableCell )
+ nMaxTableCell = nMaxTableCnts;
+ if( nAbsMinTableCnts > nAbsMinTableCell )
+ nAbsMinTableCell = nAbsMinTableCnts;
+ }
+ pCnts->SetPass1Done( nPass1Done );
+ pCnts = pCnts->GetNext();
+ }
+
+// War frueher hinter AddBorderWidth
+ // Wenn die Breite einer Tabelle in der Zelle breiter ist als
+ // das, was wir fuer sonstigen Inhalt berechnet haben, mussen
+ // wir die Breite der Tabelle nutzen
+ if( nMaxTableCell > nMaxNoAlignCell )
+ nMaxNoAlignCell = nMaxTableCell;
+ if( nAbsMinTableCell > nAbsMinNoAlignCell )
+ {
+ nAbsMinNoAlignCell = nAbsMinTableCell;
+ if( nMinNoAlignCell < nAbsMinNoAlignCell )
+ nMinNoAlignCell = nAbsMinNoAlignCell;
+ if( nMaxNoAlignCell < nMinNoAlignCell )
+ nMaxNoAlignCell = nMinNoAlignCell;
+ }
+// War frueher hinter AddBorderWidth
+
+ sal_Bool bRelWidth = pCell->IsPrcWidthOption();
+ sal_uInt16 nWidth = pCell->GetWidthOption();
+
+ // Eine NOWRAP-Option bezieht sich auf Text und auf
+ // Tabellen, wird aber bei fester Zellenbreite
+ // nicht uebernommen. Stattdessen wirkt die angegebene
+ // Zellenbreite wie eine Mindestbreite.
+ if( pCell->HasNoWrapOption() )
+ {
+ if( nWidth==0 || bRelWidth )
+ {
+ nMinNoAlignCell = nMaxNoAlignCell;
+ nAbsMinNoAlignCell = nMaxNoAlignCell;
+ }
+ else
+ {
+ if( nWidth>nMinNoAlignCell )
+ nMinNoAlignCell = nWidth;
+ if( nWidth>nAbsMinNoAlignCell )
+ nAbsMinNoAlignCell = nWidth;
+ }
+ }
+#ifdef FIX41370
+ else if( bHR && nWidth>0 && !bRelWidth )
+ {
+ // Ein kleiner Hack, um einen Bug in Netscape 4.0
+ // nachzubilden (siehe #41370#). Wenn eine Zelle eine
+ // fixe Breite besitzt und gleichzeitig ein HR, wird
+ // sie nie schmaler als die angegebene Breite.
+ // (Genaugenomen scheint die Zelle nie schmaler zu werden
+ // als die HR-Linie, denn wenn man fuer die Linie eine
+ // Breite angibt, die breiter ist als die der Zelle, dann
+ // wird die Zelle so breit wie die Linie. Das bekommen wir
+ // natuerlich nicht hin.)
+ if( nWidth>nMinNoAlignCell )
+ nMinNoAlignCell = nWidth;
+ if( nWidth>nAbsMinNoAlignCell )
+ nAbsMinNoAlignCell = nWidth;
+ }
+#endif
+
+ // Mindestbreite fuer Inhalt einhalten
+ if( nMinNoAlignCell < MINLAY )
+ nMinNoAlignCell = MINLAY;
+ if( nMaxNoAlignCell < MINLAY )
+ nMaxNoAlignCell = MINLAY;
+ if( nAbsMinNoAlignCell < MINLAY )
+ nAbsMinNoAlignCell = MINLAY;
+
+ // Umrandung und Abstand zum Inhalt beachten.
+ AddBorderWidth( nMinNoAlignCell, nMaxNoAlignCell,
+ nAbsMinNoAlignCell, i, nColSpan );
+
+ if( 1==nColSpan )
+ {
+ // die Werte direkt uebernehmen
+ pColumn->MergeMinMaxNoAlign( nMinNoAlignCell,
+ nMaxNoAlignCell,
+ nAbsMinNoAlignCell );
+
+ // bei den WIDTH angaben gewinnt die breiteste
+ if( !HasColTags() )
+ pColumn->MergeCellWidthOption( nWidth, bRelWidth );
+ }
+ else
+ {
+ // die Angaben erst am Ende, und zwar zeilenweise von
+ // links nach rechts bearbeiten
+
+ // Wann welche Werte wie uebernommen werden ist weiter
+ // unten erklaert.
+ if( !HasColTags() && nWidth && !bRelWidth )
+ {
+ sal_uLong nAbsWidth = nWidth, nDummy = 0, nDummy2 = 0;
+ AddBorderWidth( nAbsWidth, nDummy, nDummy2,
+ i, nColSpan, sal_False );
+
+ if( nAbsWidth >= nMinNoAlignCell )
+ {
+ nMaxNoAlignCell = nAbsWidth;
+ if( HasColsOption() )
+ nMinNoAlignCell = nAbsWidth;
+ }
+ else if( nAbsWidth >= nAbsMinNoAlignCell )
+ {
+ nMaxNoAlignCell = nAbsWidth;
+ nMinNoAlignCell = nAbsWidth;
+ }
+ else
+ {
+ nMaxNoAlignCell = nAbsMinNoAlignCell;
+ nMinNoAlignCell = nAbsMinNoAlignCell;
+ }
+ }
+ else if( HasColsOption() || HasColTags() )
+ nMinNoAlignCell = nAbsMinNoAlignCell;
+
+ SwHTMLTableLayoutConstraints *pConstr =
+ new SwHTMLTableLayoutConstraints( nMinNoAlignCell,
+ nMaxNoAlignCell, j, i, nColSpan );
+ if( pConstraints )
+ pConstraints = pConstraints->InsertNext( pConstr );
+ else
+ pConstraints = pConstr;
+ }
+ }
+ }
+
+ ASSERT( nMinColSpan>0 && nColSkip>0 && nColSkip <= nMinColSpan,
+ "Layout Pass 1: Da werden Spalten vergessen!" );
+ ASSERT( nMinColSpan!=USHRT_MAX,
+ "Layout Pass 1: unnoetiger Schleifendurchlauf oder Bug" );
+
+ if( 1==nMinColSpan )
+ {
+ // es gibt Zellen mit COLSPAN 1 und demnach auch sinnvolle
+ // Werte in pColumn
+
+ // Werte anhand folgender Tabelle (Netscape 4.0 pv 3) uebernehmen:
+ //
+ // WIDTH: kein COLS COLS
+ //
+ // keine min = min min = absmin
+ // max = max max = max
+ //
+ // >= min min = min min = width
+ // max = width max = width
+ //
+ // >= absmin min = wdith(*) min = width
+ // max = width max = width
+ //
+ // < absmin min = absmin min = absmin
+ // max = absmin max = absmin
+ //
+ // (*) Netscape benutzt hier die Mindestbreite ohne einen
+ // Umbruch vor der letzten Grafik. Haben wir (noch?) nicht,
+ // also belassen wir es bei width.^
+
+ if( pColumn->GetWidthOption() && !pColumn->IsRelWidthOption() )
+ {
+ // absolute Breiten als Minimal- und Maximalbreite
+ // uebernehmen.
+ sal_uLong nAbsWidth = pColumn->GetWidthOption();
+ sal_uLong nDummy = 0, nDummy2 = 0;
+ AddBorderWidth( nAbsWidth, nDummy, nDummy2, i, 1, sal_False );
+
+ if( nAbsWidth >= pColumn->GetMinNoAlign() )
+ {
+ pColumn->SetMinMax( HasColsOption() ? nAbsWidth
+ : pColumn->GetMinNoAlign(),
+ nAbsWidth );
+ }
+ else if( nAbsWidth >= pColumn->GetAbsMinNoAlign() )
+ {
+ pColumn->SetMinMax( nAbsWidth, nAbsWidth );
+ }
+ else
+ {
+ pColumn->SetMinMax( pColumn->GetAbsMinNoAlign(),
+ pColumn->GetAbsMinNoAlign() );
+ }
+ }
+ else
+ {
+ pColumn->SetMinMax( HasColsOption() ? pColumn->GetAbsMinNoAlign()
+ : pColumn->GetMinNoAlign(),
+ pColumn->GetMaxNoAlign() );
+ }
+ }
+ else if( USHRT_MAX!=nMinColSpan )
+ {
+ // kann irgendwas !=0 sein, weil es durch die Constraints
+ // angepasst wird.
+ pColumn->SetMinMax( MINLAY, MINLAY );
+
+ // die naechsten Spalten muessen nicht bearbeitet werden
+ i += (nColSkip-1);
+ }
+
+ nMin += pColumn->GetMin();
+ nMax += pColumn->GetMax();
+ bFixRelWidths |= pColumn->IsRelWidthOption();
+ }
+
+ // jetzt noch die Constrains verarbeiten
+ SwHTMLTableLayoutConstraints *pConstr = pConstraints;
+ while( pConstr )
+ {
+ // Erstmal muss die Breite analog zu den den Spaltenbreiten
+ // aufbereitet werden
+ sal_uInt16 nCol = pConstr->GetColumn();
+ sal_uInt16 nColSpan = pConstr->GetColSpan();
+ sal_uLong nConstrMin = pConstr->GetMinNoAlign();
+ sal_uLong nConstrMax = pConstr->GetMaxNoAlign();
+
+ // jetzt holen wir uns die bisherige Breite der ueberspannten
+ // Spalten
+ sal_uLong nColsMin = 0;
+ sal_uLong nColsMax = 0;
+ for( sal_uInt16 j=nCol; j<nCol+nColSpan; j++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( j );
+ nColsMin += pColumn->GetMin();
+ nColsMax += pColumn->GetMax();
+ }
+
+ if( nColsMin<nConstrMin )
+ {
+ // den Minimalwert anteilig auf die Spalten verteilen
+ sal_uLong nMinD = nConstrMin-nColsMin;
+
+ if( nConstrMin > nColsMax )
+ {
+ // Anteilig anhand der Mindestbreiten
+ sal_uInt16 nEndCol = nCol+nColSpan;
+ sal_uLong nDiff = nMinD;
+ for( sal_uInt16 ic=nCol; ic<nEndCol; ic++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( ic );
+
+ sal_uLong nColMin = pColumn->GetMin();
+ sal_uLong nColMax = pColumn->GetMax();
+
+ nMin -= nColMin;
+ sal_uLong nAdd = ic<nEndCol-1 ? (nColMin * nMinD) / nColsMin
+ : nDiff;
+ nColMin += nAdd;
+ nMin += nColMin;
+ ASSERT( nDiff >= nAdd, "Ooops: nDiff stimmt nicht mehr" );
+ nDiff -= nAdd;
+
+ if( nColMax < nColMin )
+ {
+ nMax -= nColMax;
+ nColsMax -= nColMax;
+ nColMax = nColMin;
+ nMax += nColMax;
+ nColsMax += nColMax;
+ }
+
+ pColumn->SetMinMax( nColMin, nColMax );
+ }
+ }
+ else
+ {
+ // Anteilig anhand der Differenz zwischen Max und Min
+ for( sal_uInt16 ic=nCol; ic<nCol+nColSpan; ic++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( ic );
+
+ sal_uLong nDiff = pColumn->GetMax()-pColumn->GetMin();
+ if( nMinD < nDiff )
+ nDiff = nMinD;
+
+ pColumn->AddToMin( nDiff );
+
+ ASSERT( pColumn->GetMax() >= pColumn->GetMin(),
+ "Wieso ist die SPalte auf einmal zu schmal?" )
+
+ nMin += nDiff;
+ nMinD -= nDiff;
+ }
+ }
+ }
+
+ if( !HasColTags() && nColsMax<nConstrMax )
+ {
+ sal_uLong nMaxD = nConstrMax-nColsMax;
+
+ for( sal_uInt16 ic=nCol; ic<nCol+nColSpan; ic++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( ic );
+
+ nMax -= pColumn->GetMax();
+
+ pColumn->AddToMax( (pColumn->GetMax() * nMaxD) / nColsMax );
+
+ nMax += pColumn->GetMax();
+ }
+ }
+
+ pConstr = pConstr->GetNext();
+ }
+
+
+ if( bFixRelWidths )
+ {
+ if( HasColTags() )
+ {
+ // Zum Anpassen der relativen Breiten werden im 1. Schritt die
+ // Minmalbreiten aller anzupassenden Zellen jeweils mit der
+ // relativen Breite einer Spalte multipliziert. Dadurch stimmen
+ // dann die Breitenverhaeltnisse der Spalten untereinander.
+ // Ausserdem wird der Faktor berechnet, um den die Zelle dadurch
+ // breiter gworden ist als die Minmalbreite.
+ // Im 2. Schritt werden dann die berechneten Breiten durch diesen
+ // Faktor geteilt. Dadurch bleibt die Breite (nimd.) einer Zelle
+ // erhalten und dient als Ausgangsbasis fuer die andern Breiten.
+ // Es werden auch hier nur die Maximalbreiten beeinflusst!
+
+ sal_uLong nAbsMin = 0; // absolte Min-Breite alter Spalten mit
+ // relativer Breite
+ sal_uLong nRel = 0; // Summe der relativen Breiten aller Spalten
+ for( i=0; i<nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
+ {
+ nAbsMin += pColumn->GetMin();
+ nRel += pColumn->GetWidthOption();
+ }
+ }
+
+ sal_uLong nQuot = ULONG_MAX;
+ for( i=0; i<nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() )
+ {
+ nMax -= pColumn->GetMax();
+ if( pColumn->GetWidthOption() && pColumn->GetMin() )
+ {
+ pColumn->SetMax( nAbsMin * pColumn->GetWidthOption() );
+ sal_uLong nColQuot = pColumn->GetMax() / pColumn->GetMin();
+ if( nColQuot<nQuot )
+ nQuot = nColQuot;
+ }
+ }
+ }
+ ASSERT( 0==nRel || nQuot!=ULONG_MAX,
+ "Wo sind die relativen Spalten geblieben?" );
+ for( i=0; i<nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() )
+ {
+ if( pColumn->GetWidthOption() )
+ pColumn->SetMax( pColumn->GetMax() / nQuot );
+ else
+ pColumn->SetMax( pColumn->GetMin() );
+ ASSERT( pColumn->GetMax() >= pColumn->GetMin(),
+ "Maximale Spaltenbreite kleiner als Minimale" );
+ nMax += pColumn->GetMax();
+ }
+ }
+ }
+ else
+ {
+ sal_uInt16 nRel = 0; // Summe der relativen Breiten aller Spalten
+ sal_uInt16 nRelCols = 0; // Anzahl Spalten mit relativer Angabe
+ sal_uLong nRelMax = 0; // Anteil am Maximum dieser Spalten
+ for( i=0; i<nCols; i++ )
+ {
+ ASSERT( nRel<=100, "relative Breite aller Spalten>100%" );
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
+ {
+ // Sicherstellen, dass die relativen breiten nicht
+ // ueber 100% landen
+ sal_uInt16 nColWidth = pColumn->GetWidthOption();
+ if( nRel+nColWidth > 100 )
+ {
+ nColWidth = 100 - nRel;
+ pColumn->SetWidthOption( nColWidth, sal_True, sal_False );
+ }
+ nRelMax += pColumn->GetMax();
+ nRel = nRel + nColWidth;
+ nRelCols++;
+ }
+ else if( !pColumn->GetMin() )
+ {
+ // Die Spalte ist leer (wurde also auschliesslich
+ // durch COLSPAN erzeugt) und darf deshalb auch
+ // keine %-Breite zugewiesen bekommen.
+ nRelCols++;
+ }
+ }
+
+ // Eventuell noch vorhandene Prozente werden auf die Spalten ohne
+ // eine Breiten-Angabe verteilt. Wie in Netscape werden die
+ // verbleibenden Prozente enstprechend der Verhaeltnisse
+ // der Maximalbreiten der in Frage kommenden Spalten
+ // untereinander verteilt.
+ // ??? Wie beruecksichtigen bei den Maximalbreiten auch Spalten
+ // mit fester Breite. Ist das richtig???
+ if( nRel < 100 && nRelCols < nCols )
+ {
+ sal_uInt16 nRelLeft = 100 - nRel;
+ sal_uLong nFixMax = nMax - nRelMax;
+ for( i=0; i<nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( !pColumn->IsRelWidthOption() &&
+ !pColumn->GetWidthOption() &&
+ pColumn->GetMin() )
+ {
+ // den Rest bekommt die naechste Spalte
+ sal_uInt16 nColWidth =
+ (sal_uInt16)((pColumn->GetMax() * nRelLeft) / nFixMax);
+ pColumn->SetWidthOption( nColWidth, sal_True, sal_False );
+ }
+ }
+ }
+
+ // nun die Maximalbreiten entsprechend anpassen
+ sal_uLong nQuotMax = ULONG_MAX;
+ sal_uLong nOldMax = nMax;
+ nMax = 0;
+ for( i=0; i<nCols; i++ )
+ {
+ // Spalten mit %-Angaben werden enstprechend angepasst.
+ // Spalten, die
+ // - keine %-Angabe besitzen und in einer Tabelle mit COLS
+ // oder WIDTH vorkommen, oder
+ // - als Breite 0% angegeben haben erhalten die Minimalbreite
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
+ {
+ sal_uLong nNewMax;
+ sal_uLong nColQuotMax;
+ if( !nWidthOption )
+ {
+ nNewMax = nOldMax * pColumn->GetWidthOption();
+ nColQuotMax = nNewMax / pColumn->GetMax();
+ }
+ else
+ {
+ nNewMax = nMin * pColumn->GetWidthOption();
+ nColQuotMax = nNewMax / pColumn->GetMin();
+ }
+ pColumn->SetMax( nNewMax );
+ if( nColQuotMax < nQuotMax )
+ nQuotMax = nColQuotMax;
+ }
+ else if( HasColsOption() || nWidthOption ||
+ (pColumn->IsRelWidthOption() &&
+ !pColumn->GetWidthOption()) )
+ pColumn->SetMax( pColumn->GetMin() );
+ }
+ // und durch den Quotienten teilen
+ ASSERT( nQuotMax!=ULONG_MAX, "Wo sind die relativen Spalten geblieben?" );
+ for( i=0; i<nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
+ {
+ if( pColumn->GetWidthOption() )
+ {
+ pColumn->SetMax( pColumn->GetMax() / nQuotMax );
+ ASSERT( pColumn->GetMax() >= pColumn->GetMin(),
+ "Minimalbreite ein Spalte Groesser Maximum" );
+ if( pColumn->GetMax() < pColumn->GetMin() )
+ pColumn->SetMax( pColumn->GetMin() );
+ }
+ }
+ nMax += pColumn->GetMax();
+ }
+ }
+ }
+
+ delete pConstraints;
+}
+
+// nAbsAvail ist der verfuegbare Platz in TWIPS.
+// nRelAvail ist der auf USHRT_MAX bezogene verfuegbare Platz oder 0
+// nAbsSpace ist der Anteil von nAbsAvail, der durch der umgebende Zelle
+// fur die Umrandung und den Abstand zum Inhalt reserviert ist.
+void SwHTMLTableLayout::AutoLayoutPass2( sal_uInt16 nAbsAvail, sal_uInt16 nRelAvail,
+ sal_uInt16 nAbsLeftSpace,
+ sal_uInt16 nAbsRightSpace,
+ sal_uInt16 nParentInhAbsSpace )
+{
+ // Erstmal fuehren wie jede Menge Plausibilaets-Test durch
+
+ // Eine abolute zur Verfuegung stehende Breite muss immer uebergeben
+ // werden.
+ ASSERT( nAbsAvail, "AutoLayout Pass 2: Keine absolute Breite gegeben" );
+
+ // Eine realtive zur Verfuegung stehende Breite darf nur und muss fuer
+ // Tabellen in Tabellen uebergeben
+ ASSERT( IsTopTable() == (nRelAvail==0),
+ "AutoLayout Pass 2: Rel. Breite bei Tab in Tab oder umgekehrt" );
+
+ // Die Minimalbreite der Tabelle darf natuerlich nie groesser sein
+ // als das die Maximalbreite.
+ ASSERT( nMin<=nMax, "AutoLayout Pass2: nMin > nMax" );
+
+ // Die verfuegbare Breite, fuer die die Tabelle berechnet wurde, merken.
+ // (Dies ist ein guter Ort, denn hier kommer wir bei der Erstberechnung
+ // der Tabelle aus dem Parser und bei jedem _Resize-Aufruf vorbei.)
+ nLastResizeAbsAvail = nAbsAvail;
+
+ // Schritt 1: Der verfuegbar Platz wird an linke/rechte Raender,
+ // vorhandene Filler-Zellen und Abstande angepasst
+
+ // Abstand zum Inhalt und Unrandung
+ sal_uInt16 nAbsLeftFill = 0, nAbsRightFill = 0;
+ if( !IsTopTable() &&
+ GetMin() + nAbsLeftSpace + nAbsRightSpace <= nAbsAvail )
+ {
+ nAbsLeftFill = nAbsLeftSpace;
+ nAbsRightFill = nAbsRightSpace;
+ }
+
+ // Linker und rechter Abstand
+ if( nLeftMargin || nRightMargin )
+ {
+ if( IsTopTable() )
+ {
+ // fuer die Top-Table beruecksichtigen wir die Raender immer,
+ // den die Minimalbreite der Tabelle wird hier nie unterschritten
+ nAbsAvail -= (nLeftMargin + nRightMargin);
+ }
+ else if( GetMin() + nLeftMargin + nRightMargin <= nAbsAvail )
+ {
+ // sonst beruecksichtigen wir die Raender nur, wenn auch Platz
+ // fuer sie da ist (nMin ist hier bereits berechnet!)
+ nAbsLeftFill = nAbsLeftFill + nLeftMargin;
+ nAbsRightFill = nAbsRightFill + nRightMargin;
+ }
+ }
+
+ // Filler-Zellen
+ if( !IsTopTable() )
+ {
+ if( pLeftFillerBox && nAbsLeftFill<MINLAY+nInhLeftBorderWidth )
+ nAbsLeftFill = MINLAY+nInhLeftBorderWidth;
+ if( pRightFillerBox && nAbsRightFill<MINLAY+nInhRightBorderWidth )
+ nAbsRightFill = MINLAY+nInhRightBorderWidth;
+ }
+
+ // Anpassen des verfuegbaren Platzes.
+ nRelLeftFill = 0;
+ nRelRightFill = 0;
+ if( !IsTopTable() && (nAbsLeftFill>0 || nAbsRightFill) )
+ {
+ sal_uLong nAbsLeftFillL = nAbsLeftFill, nAbsRightFillL = nAbsRightFill;
+
+ nRelLeftFill = (sal_uInt16)((nAbsLeftFillL * nRelAvail) / nAbsAvail);
+ nRelRightFill = (sal_uInt16)((nAbsRightFillL * nRelAvail) / nAbsAvail);
+
+ nAbsAvail -= (nAbsLeftFill + nAbsRightFill);
+ if( nRelAvail )
+ nRelAvail -= (nRelLeftFill + nRelRightFill);
+ }
+
+
+ // Schritt 2: Die absolute Tabellenbreite wird berechnet.
+ sal_uInt16 nAbsTabWidth = 0;
+ bUseRelWidth = sal_False;
+ if( nWidthOption )
+ {
+ if( bPrcWidthOption )
+ {
+ ASSERT( nWidthOption<=100, "Prozentangabe zu gross" );
+ if( nWidthOption > 100 )
+ nWidthOption = 100;
+
+ // Die absolute Breite entspricht den angegeben Prozent der
+ // zur Verfuegung stehenden Breite.
+ // Top-Tabellen bekommen nur eine relative Breite, wenn der
+ // verfuegbare Platz *echt groesser* ist als die Minimalbreite.
+ // ACHTUNG: Das "echte groesser" ist noetig, weil der Wechsel
+ // von einer relativen Breite zu einer absoluten Breite durch
+ // Resize sonst zu einer Endlosschleife fuehrt.
+ // Weil bei Tabellen in Rahmen kein Resize aufgerufen wird,
+ // wenn der Rahmen eine nicht-relative Breite besitzt, koennen
+ // wir da solche Spielchen nicht spielen
+ // MIB 19.2.98: Wegen fix #47394# spielen wir solche Spielchen
+ // jetzt doch. Dort war eine Grafik in einer 1%-breiten
+ // Tabelle und hat da natuerlich nicht hineingepasst.
+ nAbsTabWidth = (sal_uInt16)( ((sal_uLong)nAbsAvail * nWidthOption) / 100 );
+ if( IsTopTable() &&
+ ( /*MayBeInFlyFrame() ||*/ (sal_uLong)nAbsTabWidth > nMin ) )
+ {
+ nRelAvail = USHRT_MAX;
+ bUseRelWidth = sal_True;
+ }
+ }
+ else
+ {
+ nAbsTabWidth = nWidthOption;
+ if( nAbsTabWidth > MAX_TABWIDTH )
+ nAbsTabWidth = MAX_TABWIDTH;
+
+ // Tabellen in Tabellen duerfen niemals breiter werden als der
+ // verfuegbare Platz.
+ if( !IsTopTable() && nAbsTabWidth > nAbsAvail )
+ nAbsTabWidth = nAbsAvail;
+ }
+ }
+
+ ASSERT( IsTopTable() || nAbsTabWidth<=nAbsAvail,
+ "AutoLayout Pass2: nAbsTabWidth > nAbsAvail fuer Tab in Tab" );
+ ASSERT( !nRelAvail || nAbsTabWidth<=nAbsAvail,
+ "AutoLayout Pass2: nAbsTabWidth > nAbsAvail fuer relative Breite" );
+
+ // Catch fuer die beiden Asserts von oben (man weiss ja nie!)
+ if( (!IsTopTable() || nRelAvail>0) && nAbsTabWidth>nAbsAvail )
+ nAbsTabWidth = nAbsAvail;
+
+
+ // Schritt 3: Bestimmen der Spaltenbreiten und ggf. auch der
+ // absoluten und relativen Tabellenbreiten.
+ if( (!IsTopTable() && nMin > (sal_uLong)nAbsAvail) ||
+ nMin > MAX_TABWIDTH )
+ {
+ // Wenn
+ // - das Minumum einer inneren Tabelle groesser ist als der
+ // verfuegbare Platz, oder
+ // - das Minumum einer Top-Table groesser ist als USHRT_MAX
+ // muss die Tabelle an den verfuegbaren Platz bzw. USHRT_MAX
+ // abgepasst werden. Dabei bleiben die Verhaeltnisse der Breiten
+ // untereinander erhalten.
+
+ nAbsTabWidth = IsTopTable() ? MAX_TABWIDTH : nAbsAvail;
+ nRelTabWidth = (nRelAvail ? nRelAvail : nAbsTabWidth );
+
+ // First of all, we check wether we can fit the layout constrains,
+ // that are: Every cell's width excluding the borders must be at least
+ // MINLAY:
+
+ sal_uLong nRealMin = 0;
+ for( sal_uInt16 i=0; i<nCols; i++ )
+ {
+ sal_uLong nRealColMin = MINLAY, nDummy1, nDummy2;
+ AddBorderWidth( nRealColMin, nDummy1, nDummy2, i, 1 );
+ nRealMin += nRealColMin;
+ }
+ if( (nRealMin >= nAbsTabWidth) || (nRealMin >= nMin) )
+ {
+ // "Nichts geht mehr". We cannot get the minimum column widths
+ // the layout wants to have.
+
+ sal_uInt16 nAbs = 0, nRel = 0;
+ SwHTMLTableLayoutColumn *pColumn;
+ for( sal_uInt16 i=0; i<nCols-1; i++ )
+ {
+ pColumn = GetColumn( i );
+ sal_uLong nColMin = pColumn->GetMin();
+ if( nColMin <= USHRT_MAX )
+ {
+ pColumn->SetAbsColWidth(
+ (sal_uInt16)((nColMin * nAbsTabWidth) / nMin) );
+ pColumn->SetRelColWidth(
+ (sal_uInt16)((nColMin * nRelTabWidth) / nMin) );
+ }
+ else
+ {
+ double nColMinD = nColMin;
+ pColumn->SetAbsColWidth(
+ (sal_uInt16)((nColMinD * nAbsTabWidth) / nMin) );
+ pColumn->SetRelColWidth(
+ (sal_uInt16)((nColMinD * nRelTabWidth) / nMin) );
+ }
+
+ nAbs = nAbs + (sal_uInt16)pColumn->GetAbsColWidth();
+ nRel = nRel + (sal_uInt16)pColumn->GetRelColWidth();
+ }
+ pColumn = GetColumn( nCols-1 );
+ pColumn->SetAbsColWidth( nAbsTabWidth - nAbs );
+ pColumn->SetRelColWidth( nRelTabWidth - nRel );
+ }
+ else
+ {
+ sal_uLong nDistAbs = nAbsTabWidth - nRealMin;
+ sal_uLong nDistRel = nRelTabWidth - nRealMin;
+ sal_uLong nDistMin = nMin - nRealMin;
+ sal_uInt16 nAbs = 0, nRel = 0;
+ SwHTMLTableLayoutColumn *pColumn;
+ for( sal_uInt16 i=0; i<nCols-1; i++ )
+ {
+ pColumn = GetColumn( i );
+ sal_uLong nColMin = pColumn->GetMin();
+ sal_uLong nRealColMin = MINLAY, nDummy1, nDummy2;
+ AddBorderWidth( nRealColMin, nDummy1, nDummy2, i, 1 );
+
+ if( nColMin <= USHRT_MAX )
+ {
+ pColumn->SetAbsColWidth(
+ (sal_uInt16)((((nColMin-nRealColMin) * nDistAbs) / nDistMin) + nRealColMin) );
+ pColumn->SetRelColWidth(
+ (sal_uInt16)((((nColMin-nRealColMin) * nDistRel) / nDistMin) + nRealColMin) );
+ }
+ else
+ {
+ double nColMinD = nColMin;
+ pColumn->SetAbsColWidth(
+ (sal_uInt16)((((nColMinD-nRealColMin) * nDistAbs) / nDistMin) + nRealColMin) );
+ pColumn->SetRelColWidth(
+ (sal_uInt16)((((nColMinD-nRealColMin) * nDistRel) / nDistMin) + nRealColMin) );
+ }
+
+ nAbs = nAbs + (sal_uInt16)pColumn->GetAbsColWidth();
+ nRel = nRel + (sal_uInt16)pColumn->GetRelColWidth();
+ }
+ pColumn = GetColumn( nCols-1 );
+ pColumn->SetAbsColWidth( nAbsTabWidth - nAbs );
+ pColumn->SetRelColWidth( nRelTabWidth - nRel );
+ }
+ }
+ else if( nMax <= (sal_uLong)(nAbsTabWidth ? nAbsTabWidth : nAbsAvail) )
+ {
+ // Wenn
+ // - die Tabelle eine fixe Breite besitzt und das Maximum der
+ // Tabelle kleiner ist, oder
+ // - das Maximum kleiner ist als der verfuegbare Platz
+ // kann das Maximum direkt uebernommen werden bzw. die Tabelle nur
+ // unter Beruecksichtigung des Maxumums an die fixe Breite
+ // angepasst werden.
+
+ // Keine fixe Breite, dann das Maximum nehmen.
+ if( !nAbsTabWidth )
+ nAbsTabWidth = (sal_uInt16)nMax;
+
+ // Eine Top-Table darf auch beriter werden als der verfuegbare Platz.
+ if( nAbsTabWidth > nAbsAvail )
+ {
+ ASSERT( IsTopTable(),
+ "Tabelle in Tabelle soll breiter werden als umgebende Zelle" );
+ nAbsAvail = nAbsTabWidth;
+ }
+
+ // Nur den Anteil der relativen Breite verwenden, der auch fuer
+ // die absolute Breite verwendet wuerde.
+ sal_uLong nAbsTabWidthL = nAbsTabWidth;
+ nRelTabWidth =
+ ( nRelAvail ? (sal_uInt16)((nAbsTabWidthL * nRelAvail) / nAbsAvail)
+ : nAbsTabWidth );
+
+ // Gibt es Spalten mit und Spalten ohne %-Angabe?
+ sal_uLong nFixMax = nMax;
+ for( sal_uInt16 i=0; i<nCols; i++ )
+ {
+ const SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption()>0 )
+ nFixMax -= pColumn->GetMax();
+ }
+
+ if( nFixMax > 0 && nFixMax < nMax )
+ {
+ // ja, dann den zu verteilenden Platz nur auf die Spalten
+ // mit %-Angabe verteilen.
+
+ // In diesem (und nur in diesem) Fall gibt es Spalten,
+ // die ihre Maximalbreite genau einhalten, also weder
+ // schmaler noch breiter werden. Beim zurueckrechnen der
+ // absoluten Breite aus der relativen Breite kann es
+ // zu Rundungsfehlern kommen (bug #45598#). Um die auszugeleichen
+ // werden zuerst die fixen Breiten entsprechend korrigiert
+ // eingestellt und erst danach die relativen.
+
+ sal_uInt16 nAbs = 0, nRel = 0;
+ sal_uInt16 nFixedCols = 0;
+ sal_uInt16 i;
+
+ for( i = 0; i < nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( !pColumn->IsRelWidthOption() || !pColumn->GetWidthOption() )
+ {
+ // Die Spalte behaelt ihre Breite bei.
+ nFixedCols++;
+ sal_uLong nColMax = pColumn->GetMax();
+ pColumn->SetAbsColWidth( (sal_uInt16)nColMax );
+
+ sal_uLong nRelColWidth =
+ (nColMax * nRelTabWidth) / nAbsTabWidth;
+ sal_uLong nChkWidth =
+ (nRelColWidth * nAbsTabWidth) / nRelTabWidth;
+ if( nChkWidth < nColMax )
+ nRelColWidth++;
+ else if( nChkWidth > nColMax )
+ nRelColWidth--;
+ pColumn->SetRelColWidth( (sal_uInt16)nRelColWidth );
+
+ nAbs = nAbs + (sal_uInt16)nColMax;
+ nRel = nRel + (sal_uInt16)nRelColWidth;
+ }
+ }
+
+ // Zu verteilende Anteile des Maximums und der relativen und
+ // absoluten Breiten. nFixMax entspricht an dieser Stelle
+ // nAbs, so dass man gleich nFixMax haette nehmen koennen.
+ // Der Code ist so aber verstaendlicher.
+ ASSERT( nFixMax == nAbs, "Zwei Schleifen, zwei Summen?" )
+ sal_uLong nDistMax = nMax - nFixMax;
+ sal_uInt16 nDistAbsTabWidth = nAbsTabWidth - nAbs;
+ sal_uInt16 nDistRelTabWidth = nRelTabWidth - nRel;
+
+ for( i=0; i<nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() > 0 )
+ {
+ // Die Spalte wird anteilig breiter.
+ nFixedCols++;
+ if( nFixedCols == nCols )
+ {
+ pColumn->SetAbsColWidth( nAbsTabWidth-nAbs );
+ pColumn->SetRelColWidth( nRelTabWidth-nRel );
+ }
+ else
+ {
+ sal_uLong nColMax = pColumn->GetMax();
+ pColumn->SetAbsColWidth(
+ (sal_uInt16)((nColMax * nDistAbsTabWidth) / nDistMax) );
+ pColumn->SetRelColWidth(
+ (sal_uInt16)((nColMax * nDistRelTabWidth) / nDistMax) );
+ }
+ nAbs = nAbs + pColumn->GetAbsColWidth();
+ nRel = nRel + pColumn->GetRelColWidth();
+ }
+ }
+ ASSERT( nCols==nFixedCols, "Spalte vergessen!" );
+ }
+ else
+ {
+ // nein, dann den zu verteilenden Platz auf alle Spalten
+ // gleichmaessig vertilen.
+ for( sal_uInt16 i=0; i<nCols; i++ )
+ {
+ sal_uLong nColMax = GetColumn( i )->GetMax();
+ GetColumn( i )->SetAbsColWidth(
+ (sal_uInt16)((nColMax * nAbsTabWidth) / nMax) );
+ GetColumn( i )->SetRelColWidth(
+ (sal_uInt16)((nColMax * nRelTabWidth) / nMax) );
+ }
+ }
+ }
+ else
+ {
+ // den ueber die Minimalbreite herausgehenden Platz entsprechend
+ // den einzelnen Spalten anteilig zuschlagen
+ if( !nAbsTabWidth )
+ nAbsTabWidth = nAbsAvail;
+ if( nAbsTabWidth < nMin )
+ nAbsTabWidth = (sal_uInt16)nMin;
+
+ if( nAbsTabWidth > nAbsAvail )
+ {
+ ASSERT( IsTopTable(),
+ "Tabelle in Tabelle soll breiter werden als Platz da ist" );
+ nAbsAvail = nAbsTabWidth;
+ }
+
+ sal_uLong nAbsTabWidthL = nAbsTabWidth;
+ nRelTabWidth =
+ ( nRelAvail ? (sal_uInt16)((nAbsTabWidthL * nRelAvail) / nAbsAvail)
+ : nAbsTabWidth );
+ double nW = nAbsTabWidth - nMin;
+ double nD = (nMax==nMin ? 1 : nMax-nMin);
+ sal_uInt16 nAbs = 0, nRel = 0;
+ for( sal_uInt16 i=0; i<nCols-1; i++ )
+ {
+ double nd = GetColumn( i )->GetMax() - GetColumn( i )->GetMin();
+ sal_uLong nAbsColWidth = GetColumn( i )->GetMin() + (sal_uLong)((nd*nW)/nD);
+ sal_uLong nRelColWidth = nRelAvail
+ ? (nAbsColWidth * nRelTabWidth) / nAbsTabWidth
+ : nAbsColWidth;
+
+ GetColumn( i )->SetAbsColWidth( (sal_uInt16)nAbsColWidth );
+ GetColumn( i )->SetRelColWidth( (sal_uInt16)nRelColWidth );
+ nAbs = nAbs + (sal_uInt16)nAbsColWidth;
+ nRel = nRel + (sal_uInt16)nRelColWidth;
+ }
+ GetColumn( nCols-1 )->SetAbsColWidth( nAbsTabWidth - nAbs );
+ GetColumn( nCols-1 )->SetRelColWidth( nRelTabWidth - nRel );
+
+ }
+
+ // Schritt 4: Fuer Tabellen in Tabellen kann es links und/oder rechts
+ // noch Ausgleichzellen geben. Deren Breite wird jetzt berechnet.
+ nInhAbsLeftSpace = 0;
+ nInhAbsRightSpace = 0;
+ if( !IsTopTable() && (nRelLeftFill>0 || nRelRightFill>0 ||
+ nAbsTabWidth<nAbsAvail) )
+ {
+ // Die Breite von zusaetzlichen Zellen zur Ausrichtung der
+ // inneren Tabelle bestimmen
+ sal_uInt16 nAbsDist = (sal_uInt16)(nAbsAvail-nAbsTabWidth);
+ sal_uInt16 nRelDist = (sal_uInt16)(nRelAvail-nRelTabWidth);
+ sal_uInt16 nParentInhAbsLeftSpace = 0, nParentInhAbsRightSpace = 0;
+
+ // Groesse und Position der zusaetzlichen Zellen bestimmen
+ switch( eTableAdjust )
+ {
+ case SVX_ADJUST_RIGHT:
+ nAbsLeftFill = nAbsLeftFill + nAbsDist;
+ nRelLeftFill = nRelLeftFill + nRelDist;
+ nParentInhAbsLeftSpace = nParentInhAbsSpace;
+ break;
+ case SVX_ADJUST_CENTER:
+ {
+ sal_uInt16 nAbsLeftDist = nAbsDist / 2;
+ nAbsLeftFill = nAbsLeftFill + nAbsLeftDist;
+ nAbsRightFill += nAbsDist - nAbsLeftDist;
+ sal_uInt16 nRelLeftDist = nRelDist / 2;
+ nRelLeftFill = nRelLeftFill + nRelLeftDist;
+ nRelRightFill += nRelDist - nRelLeftDist;
+ nParentInhAbsLeftSpace = nParentInhAbsSpace / 2;
+ nParentInhAbsRightSpace = nParentInhAbsSpace -
+ nParentInhAbsLeftSpace;
+ }
+ break;
+ case SVX_ADJUST_LEFT:
+ default:
+ nAbsRightFill = nAbsRightFill + nAbsDist;
+ nRelRightFill = nRelRightFill + nRelDist;
+ nParentInhAbsRightSpace = nParentInhAbsSpace;
+ break;
+ }
+
+ ASSERT( !pLeftFillerBox || nRelLeftFill>0,
+ "Fuer linke Filler-Box ist keine Breite da!" );
+ ASSERT( !pRightFillerBox || nRelRightFill>0,
+ "Fuer rechte Filler-Box ist keine Breite da!" );
+
+ // Filler-Breiten werden auf die ausseren Spalten geschlagen, wenn
+ // es nach dem ersten Durchlauf keine Boxen fuer sie gibt (nWidth>0)
+ // oder ihre Breite zu klein wuerde oder wenn es COL-Tags gibt und
+ // die Filler-Breite der Umrandung-Breite entspricht (dann haben wir
+ // die Tabelle wahrscheinlich selbst exportiert)
+ if( nRelLeftFill && !pLeftFillerBox &&
+ ( nWidthSet>0 || nAbsLeftFill<MINLAY+nInhLeftBorderWidth ||
+ (HasColTags() && nAbsLeftFill < nAbsLeftSpace+nParentInhAbsLeftSpace+20) ) )
+// (nAbsLeftFill<MINLAY || nAbsLeftFill<=nAbsLeftSpace) )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( 0 );
+ pColumn->SetAbsColWidth( pColumn->GetAbsColWidth()+nAbsLeftFill );
+ pColumn->SetRelColWidth( pColumn->GetRelColWidth()+nRelLeftFill );
+ nRelLeftFill = 0;
+ nInhAbsLeftSpace = nAbsLeftSpace + nParentInhAbsLeftSpace;
+ }
+ if( nRelRightFill && !pRightFillerBox &&
+ ( nWidthSet>0 || nAbsRightFill<MINLAY+nInhRightBorderWidth ||
+ (HasColTags() && nAbsRightFill < nAbsRightSpace+nParentInhAbsRightSpace+20) ) )
+// (nAbsRightFill<MINLAY || nAbsRightFill<=nAbsRightSpace) )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( nCols-1 );
+ pColumn->SetAbsColWidth( pColumn->GetAbsColWidth()+nAbsRightFill );
+ pColumn->SetRelColWidth( pColumn->GetRelColWidth()+nRelRightFill );
+ nRelRightFill = 0;
+ nInhAbsRightSpace = nAbsRightSpace + nParentInhAbsRightSpace;
+ }
+ }
+}
+
+static sal_Bool lcl_ResizeLine( const SwTableLine*& rpLine, void* pPara );
+
+static sal_Bool lcl_ResizeBox( const SwTableBox*& rpBox, void* pPara )
+{
+ sal_uInt16 *pWidth = (sal_uInt16 *)pPara;
+
+ if( !rpBox->GetSttNd() )
+ {
+ sal_uInt16 nWidth = 0;
+ ((SwTableBox *)rpBox)->GetTabLines().ForEach( &lcl_ResizeLine, &nWidth );
+ rpBox->GetFrmFmt()->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth, 0 ));
+ *pWidth = *pWidth + nWidth;
+ }
+ else
+ {
+ *pWidth = *pWidth + (sal_uInt16)rpBox->GetFrmFmt()->GetFrmSize().GetSize().Width();
+ }
+
+ return sal_True;
+}
+
+static sal_Bool lcl_ResizeLine( const SwTableLine*& rpLine, void* pPara )
+{
+ sal_uInt16 *pWidth = (sal_uInt16 *)pPara;
+#ifdef DBG_UTIL
+ sal_uInt16 nOldWidth = *pWidth;
+#endif
+ *pWidth = 0;
+ ((SwTableLine *)rpLine)->GetTabBoxes().ForEach( &lcl_ResizeBox, pWidth );
+
+#ifdef DBG_UTIL
+ ASSERT( !nOldWidth || Abs(*pWidth-nOldWidth) < COLFUZZY,
+ "Zeilen einer Box sind unterschiedlich lang" );
+#endif
+
+ return sal_True;
+}
+
+void SwHTMLTableLayout::SetWidths( sal_Bool bCallPass2, sal_uInt16 nAbsAvail,
+ sal_uInt16 nRelAvail, sal_uInt16 nAbsLeftSpace,
+ sal_uInt16 nAbsRightSpace,
+ sal_uInt16 nParentInhAbsSpace )
+{
+ // SetWidth muss am Ende einmal mehr fuer jede Zelle durchlaufen
+ // worden sein.
+ nWidthSet++;
+
+ // Schritt 0: Wenn noetig, wird hier noch der Pass2 des Layout-Alogithmus
+ // aufgerufen.
+ if( bCallPass2 )
+ AutoLayoutPass2( nAbsAvail, nRelAvail, nAbsLeftSpace, nAbsRightSpace,
+ nParentInhAbsSpace );
+
+ // Schritt 1: Setzten der neuen Breite an allen Content-Boxen.
+ // Da die Boxen nichts von der HTML-Tabellen-Struktur wissen, wird
+ // ueber die HTML-Tabellen-Struktur iteriert. Fuer Tabellen in Tabellen
+ // in Tabellen wird rekursiv SetWidth aufgerufen.
+ for( sal_uInt16 i=0; i<nRows; i++ )
+ {
+ for( sal_uInt16 j=0; j<nCols; j++ )
+ {
+ SwHTMLTableLayoutCell *pCell = GetCell( i, j );
+
+ SwHTMLTableLayoutCnts* pCntnts = pCell->GetContents();
+ while( pCntnts && !pCntnts->IsWidthSet(nWidthSet) )
+ {
+ SwTableBox *pBox = pCntnts->GetTableBox();
+ if( pBox )
+ {
+ SetBoxWidth( pBox, j, pCell->GetColSpan() );
+ }
+ else
+ {
+ sal_uInt16 nAbs = 0, nRel = 0, nLSpace = 0, nRSpace = 0,
+ nInhSpace = 0;
+ if( bCallPass2 )
+ {
+ sal_uInt16 nColSpan = pCell->GetColSpan();
+ GetAvail( j, nColSpan, nAbs, nRel );
+ nLSpace = GetLeftCellSpace( j, nColSpan );
+ nRSpace = GetRightCellSpace( j, nColSpan );
+ nInhSpace = GetInhCellSpace( j, nColSpan );
+ }
+ pCntnts->GetTable()->SetWidths( bCallPass2, nAbs, nRel,
+ nLSpace, nRSpace,
+ nInhSpace );
+ }
+
+ pCntnts->SetWidthSet( nWidthSet );
+ pCntnts = pCntnts->GetNext();
+ }
+ }
+ }
+
+ // Schritt 2: Wenn eine Top-Tabelle vorliegt, werden jetzt die Formate
+ // der Nicht-Content-Boxen angepasst. Da diese aufgrund der
+ // Garbage-Collection in der HTML-Tabelle nicht bekannt sind, muessen
+ // wir hier ueber die Tabelle iterieren. Bei der Gelegenheit wird auch
+ // das Tabellen-Frameformat angepasst. Fuer Tabellen in Tabellen werden
+ // stattdessen die Breiten der Filler-Zellen gesetzt.
+ if( IsTopTable() )
+ {
+ sal_uInt16 nCalcTabWidth = 0;
+ ((SwTable *)pSwTable)->GetTabLines().ForEach( &lcl_ResizeLine,
+ &nCalcTabWidth );
+ ASSERT( Abs( nRelTabWidth-nCalcTabWidth ) < COLFUZZY,
+ "Tabellebreite stimmt nicht mit Zeilenbreite ueberein." );
+
+ // Beim Anpassen des Tabellen-Formats dieses locken, weil sonst
+ // die Boxformate erneut angepasst werden. Ausserdem muss eine
+ // evtl. vorhandene %-Angabe in jedem Fall erhalten bleiben.
+ SwFrmFmt *pFrmFmt = pSwTable->GetFrmFmt();
+ ((SwTable *)pSwTable)->LockModify();
+ SwFmtFrmSize aFrmSize( pFrmFmt->GetFrmSize() );
+ aFrmSize.SetWidth( nRelTabWidth );
+ sal_Bool bRel = bUseRelWidth &&
+ text::HoriOrientation::FULL!=pFrmFmt->GetHoriOrient().GetHoriOrient();
+ aFrmSize.SetWidthPercent( (sal_uInt8)(bRel ? nWidthOption : 0) );
+ pFrmFmt->SetFmtAttr( aFrmSize );
+ ((SwTable *)pSwTable)->UnlockModify();
+
+ // Wenn die Tabelle in einem Rahmen steht, muss auch noch dessen
+ // breite angepasst werden.
+ if( MayBeInFlyFrame() )
+ {
+ SwFrmFmt *pFlyFrmFmt = FindFlyFrmFmt();
+ if( pFlyFrmFmt )
+ {
+ SwFmtFrmSize aFlyFrmSize( ATT_VAR_SIZE, nRelTabWidth, MINLAY );
+
+ if( bUseRelWidth )
+ {
+ // Bei %-Angaben wird die Breite auf das Minimum gesetzt.
+ aFlyFrmSize.SetWidth( nMin > USHRT_MAX ? USHRT_MAX
+ : nMin );
+ aFlyFrmSize.SetWidthPercent( (sal_uInt8)nWidthOption );
+ }
+ pFlyFrmFmt->SetFmtAttr( aFlyFrmSize );
+ }
+ }
+
+#ifdef DBG_UTIL
+ {
+ // steht im tblrwcl.cxx
+ extern void _CheckBoxWidth( const SwTableLine&, SwTwips );
+
+ // checke doch mal ob die Tabellen korrekte Breiten haben
+ SwTwips nSize = pSwTable->GetFrmFmt()->GetFrmSize().GetWidth();
+ const SwTableLines& rLines = pSwTable->GetTabLines();
+ for( sal_uInt16 n = 0; n < rLines.Count(); ++n )
+ _CheckBoxWidth( *rLines[ n ], nSize );
+ }
+#endif
+
+ }
+ else
+ {
+ if( pLeftFillerBox )
+ {
+ pLeftFillerBox->GetFrmFmt()->SetFmtAttr(
+ SwFmtFrmSize( ATT_VAR_SIZE, nRelLeftFill, 0 ));
+ }
+ if( pRightFillerBox )
+ {
+ pRightFillerBox->GetFrmFmt()->SetFmtAttr(
+ SwFmtFrmSize( ATT_VAR_SIZE, nRelRightFill, 0 ));
+ }
+ }
+}
+
+void SwHTMLTableLayout::_Resize( sal_uInt16 nAbsAvail, sal_Bool bRecalc )
+{
+ // Wenn bRecalc gestzt ist, hat sich am Inhalt der Tabelle etwas
+ // geaendert. Es muss dann der erste Pass noch einmal durchgefuehrt
+ // werden.
+ if( bRecalc )
+ AutoLayoutPass1();
+
+ SwRootFrm *pRoot = (SwRootFrm*)GetDoc()->GetRootFrm();
+ if ( pRoot && pRoot->IsCallbackActionEnabled() )
+ pRoot->StartAllAction();
+
+ // Sonst koennen die Breiten gesetzt werden, wobei zuvor aber jewils
+ // noch der Pass 2 laufen muss.
+ SetWidths( sal_True, nAbsAvail );
+
+ if ( pRoot && pRoot->IsCallbackActionEnabled() )
+ pRoot->EndAllAction( sal_True ); //True per VirDev (Browsen ruhiger)
+}
+
+IMPL_STATIC_LINK( SwHTMLTableLayout, DelayedResize_Impl, void*, EMPTYARG )
+{
+#ifdef TEST_DELAYED_RESIZE
+ Sound::Beep( SOUND_WARNING );
+#endif
+ pThis->aResizeTimer.Stop();
+ pThis->_Resize( pThis->nDelayedResizeAbsAvail,
+ pThis->bDelayedResizeRecalc );
+
+ return 0;
+}
+
+
+sal_Bool SwHTMLTableLayout::Resize( sal_uInt16 nAbsAvail, sal_Bool bRecalc,
+ sal_Bool bForce, sal_uLong nDelay )
+{
+ if( 0 == nAbsAvail )
+ return sal_False;
+ ASSERT( IsTopTable(), "Resize darf nur an Top-Tabellen aufgerufen werden" );
+
+ // Darf die Tabelle uberhaupt Resized werden oder soll sie es trotzdem?
+ if( bMustNotResize && !bForce )
+ return sal_False;
+
+ // Darf ein Recalc der Tabelle durchgefuehrt werden?
+ if( bMustNotRecalc && !bForce )
+ bRecalc = sal_False;
+
+ const SwDoc *pDoc = GetDoc();
+
+ // Wenn es ein Layout gibt, wurde evtl. die Groesse der Root-Frames
+ // und nicht die der VisArea uebergeben. Wenn wir nicht in einem Rahmen
+ // stehen, muss die Tabelle allerdings fuer die VisArea berechnet werden,
+ // weil sond die Umschaltung von relativ nach absolut nicht funktioniert.
+ if( pDoc->GetRootFrm() && pDoc->get(IDocumentSettingAccess::BROWSE_MODE) )
+ {
+ const sal_uInt16 nVisAreaWidth = GetBrowseWidthByVisArea( *pDoc );
+ if( nVisAreaWidth < nAbsAvail && !FindFlyFrmFmt() )
+ nAbsAvail = nVisAreaWidth;
+ }
+
+ if( nDelay==0 && aResizeTimer.IsActive() )
+ {
+ // Wenn beim Aufruf eines synchronen Resize noch ein asynchrones
+ // Resize aussteht, dann werden nur die neuen Werte uebernommen.
+
+ bRecalc |= bDelayedResizeRecalc;
+ nDelayedResizeAbsAvail = nAbsAvail;
+ return sal_False;
+ }
+
+ // Optimierung:
+ // Wenn die Minima/Maxima nicht neu berechnet werden sollen und
+ // - die Breite der Tabelle nie neu berechnet werden muss, oder
+ // - die Tabelle schon fuer die uebergebene Breite berechnet wurde, oder
+ // - der verfuegbare Platz kleiner oder gleich der Minimalbreite ist
+ // und die Tabelle bereits die Minimalbreite besitzt, oder
+ // - der verfuegbare Platz groesser ist als die Maximalbreite und
+ // die Tabelle bereits die Maximalbreite besitzt
+ // wird sich an der Tabelle nichts aendern.
+ if( !bRecalc && ( !bMustResize ||
+ (nLastResizeAbsAvail==nAbsAvail) ||
+ (nAbsAvail<=nMin && nRelTabWidth==nMin) ||
+ (!bPrcWidthOption && nAbsAvail>=nMax && nRelTabWidth==nMax) ) )
+ return sal_False;
+
+ if( nDelay==HTMLTABLE_RESIZE_NOW )
+ {
+ if( aResizeTimer.IsActive() )
+ aResizeTimer.Stop();
+ _Resize( nAbsAvail, bRecalc );
+ }
+ else if( nDelay > 0 )
+ {
+ nDelayedResizeAbsAvail = nAbsAvail;
+ bDelayedResizeRecalc = bRecalc;
+ aResizeTimer.SetTimeout( nDelay );
+ aResizeTimer.Start();
+#ifdef TEST_DELAYED_RESIZE
+ Sound::Beep( SOUND_DEFAULT );
+#endif
+ }
+ else
+ {
+ _Resize( nAbsAvail, bRecalc );
+ }
+
+ return sal_True;
+}
+
+void SwHTMLTableLayout::BordersChanged( sal_uInt16 nAbsAvail, sal_Bool bRecalc )
+{
+ bBordersChanged = sal_True;
+
+ Resize( nAbsAvail, bRecalc );
+}
+
+
diff --git a/sw/source/core/doc/lineinfo.cxx b/sw/source/core/doc/lineinfo.cxx
new file mode 100644
index 000000000000..7490cf9f0719
--- /dev/null
+++ b/sw/source/core/doc/lineinfo.cxx
@@ -0,0 +1,154 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#include "doc.hxx"
+#include "lineinfo.hxx"
+#include "charfmt.hxx"
+#include "poolfmt.hxx"
+#include "rootfrm.hxx"
+#include "viewsh.hxx"
+
+void SwDoc::SetLineNumberInfo( const SwLineNumberInfo &rNew )
+{
+ if ( GetRootFrm() &&
+ (rNew.IsCountBlankLines() != pLineNumberInfo->IsCountBlankLines() ||
+ rNew.IsRestartEachPage() != pLineNumberInfo->IsRestartEachPage()) )
+ {
+ GetRootFrm()->StartAllAction();
+ // FME 2007-08-14 #i80120# Invalidate size, because ChgThisLines()
+ // is only (onny may only be) called by the formatting routines
+ GetRootFrm()->InvalidateAllCntnt( INV_LINENUM | INV_SIZE );
+ GetRootFrm()->EndAllAction();
+ }
+ *pLineNumberInfo = rNew;
+ SetModified();
+}
+
+const SwLineNumberInfo& SwDoc::GetLineNumberInfo() const
+{
+ return *pLineNumberInfo;
+}
+
+SwLineNumberInfo::SwLineNumberInfo() :
+ nPosFromLeft( MM50 ),
+ nCountBy( 5 ),
+ nDividerCountBy( 3 ),
+ ePos( LINENUMBER_POS_LEFT ),
+ bPaintLineNumbers( sal_False ),
+ bCountBlankLines( sal_True ),
+ bCountInFlys( sal_False ),
+ bRestartEachPage( sal_False )
+{
+}
+
+SwLineNumberInfo::SwLineNumberInfo(const SwLineNumberInfo &rCpy ) : SwClient(),
+ aType( rCpy.GetNumType() ),
+ aDivider( rCpy.GetDivider() ),
+ nPosFromLeft( rCpy.GetPosFromLeft() ),
+ nCountBy( rCpy.GetCountBy() ),
+ nDividerCountBy( rCpy.GetDividerCountBy() ),
+ ePos( rCpy.GetPos() ),
+ bPaintLineNumbers( rCpy.IsPaintLineNumbers() ),
+ bCountBlankLines( rCpy.IsCountBlankLines() ),
+ bCountInFlys( rCpy.IsCountInFlys() ),
+ bRestartEachPage( rCpy.IsRestartEachPage() )
+{
+ if ( rCpy.GetRegisteredIn() )
+ ((SwModify*)rCpy.GetRegisteredIn())->Add( this );
+}
+
+SwLineNumberInfo& SwLineNumberInfo::operator=(const SwLineNumberInfo &rCpy)
+{
+ if ( rCpy.GetRegisteredIn() )
+ ((SwModify*)rCpy.GetRegisteredIn())->Add( this );
+ else if ( GetRegisteredIn() )
+ pRegisteredIn->Remove( this );
+
+ aType = rCpy.GetNumType();
+ aDivider = rCpy.GetDivider();
+ nPosFromLeft = rCpy.GetPosFromLeft();
+ nCountBy = rCpy.GetCountBy();
+ nDividerCountBy = rCpy.GetDividerCountBy();
+ ePos = rCpy.GetPos();
+ bPaintLineNumbers = rCpy.IsPaintLineNumbers();
+ bCountBlankLines = rCpy.IsCountBlankLines();
+ bCountInFlys = rCpy.IsCountInFlys();
+ bRestartEachPage = rCpy.IsRestartEachPage();
+
+ return *this;
+}
+
+sal_Bool SwLineNumberInfo::operator==( const SwLineNumberInfo& rInf ) const
+{
+ return GetRegisteredIn() == rInf.GetRegisteredIn() &&
+ aType.GetNumberingType() == rInf.GetNumType().GetNumberingType() &&
+ aDivider == rInf.GetDivider() &&
+ nPosFromLeft == rInf.GetPosFromLeft() &&
+ nCountBy == rInf.GetCountBy() &&
+ nDividerCountBy == rInf.GetDividerCountBy() &&
+ ePos == rInf.GetPos() &&
+ bPaintLineNumbers == rInf.IsPaintLineNumbers() &&
+ bCountBlankLines == rInf.IsCountBlankLines() &&
+ bCountInFlys == rInf.IsCountInFlys() &&
+ bRestartEachPage == rInf.IsRestartEachPage();
+}
+
+
+SwCharFmt* SwLineNumberInfo::GetCharFmt( IDocumentStylePoolAccess& rIDSPA ) const
+{
+ if ( !GetRegisteredIn() )
+ {
+ SwCharFmt* pFmt = rIDSPA.GetCharFmtFromPool( RES_POOLCHR_LINENUM );
+ pFmt->Add( (SwClient*)this );
+ }
+ return (SwCharFmt*)GetRegisteredIn();
+}
+
+void SwLineNumberInfo::SetCharFmt( SwCharFmt *pChFmt )
+{
+ ASSERT( pChFmt, "SetCharFmt, 0 is not a valid pointer" );
+ pChFmt->Add( this );
+}
+
+void SwLineNumberInfo::Modify( SfxPoolItem* pOld, SfxPoolItem* pNew )
+{
+ SwClient::Modify( pOld, pNew );
+ SwDoc *pDoc = ((SwCharFmt*)GetRegisteredIn())->GetDoc();
+ SwRootFrm* pRoot = pDoc->GetRootFrm();
+ if( pRoot && pRoot->GetCurrShell() )
+ {
+ pRoot->StartAllAction();
+ pRoot->GetCurrShell()->AddPaintRect( pRoot->Frm() );
+ pRoot->EndAllAction();
+ }
+}
+
diff --git a/sw/source/core/doc/list.cxx b/sw/source/core/doc/list.cxx
new file mode 100644
index 000000000000..81f139bba99e
--- /dev/null
+++ b/sw/source/core/doc/list.cxx
@@ -0,0 +1,303 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#include "precompiled_sw.hxx"
+
+#include <list.hxx>
+
+#include <vector>
+#include <numrule.hxx>
+#include <ndarr.hxx>
+#include <node.hxx>
+#include <pam.hxx>
+#include <SwNodeNum.hxx>
+
+// ----------------------------------------------------------------------------
+// SwListImpl
+// implementation class for SwList
+// ----------------------------------------------------------------------------
+class SwListImpl
+{
+ public:
+ SwListImpl( const String sListId,
+ SwNumRule& rDefaultListStyle,
+ const SwNodes& rNodes );
+ ~SwListImpl();
+
+ const String GetListId() const;
+
+ const String GetDefaultListStyleName() const;
+
+ void InsertListItem( SwNodeNum& rNodeNum,
+ const int nLevel );
+ void RemoveListItem( SwNodeNum& rNodeNum );
+
+ void InvalidateListTree();
+ void ValidateListTree();
+
+ void MarkListLevel( const int nListLevel,
+ const sal_Bool bValue );
+
+ bool IsListLevelMarked( const int nListLevel ) const;
+
+ private:
+ // unique identifier of the list
+ const String msListId;
+ // default list style for the list items, identified by the list style name
+ String msDefaultListStyleName;
+
+ // list trees for certain document ranges
+ typedef std::pair<SwNodeNum*, SwPaM*> tListTreeForRange;
+ typedef std::vector<tListTreeForRange> tListTrees;
+ tListTrees maListTrees;
+
+ int mnMarkedListLevel;
+
+ void NotifyItemsOnListLevel( const int nLevel );
+};
+
+SwListImpl::SwListImpl( const String sListId,
+ SwNumRule& rDefaultListStyle,
+ const SwNodes& rNodes )
+ : msListId( sListId ),
+ msDefaultListStyleName( rDefaultListStyle.GetName() ),
+ maListTrees(),
+ mnMarkedListLevel( MAXLEVEL )
+{
+ // create empty list trees for the document ranges
+ const SwNode* pNode = rNodes[0];
+ do
+ {
+ SwPaM aPam( *pNode, *pNode->EndOfSectionNode() );
+
+ SwNodeNum* pNumberTreeRootNode = new SwNodeNum( &rDefaultListStyle );
+ SwPaM* pPam = new SwPaM( *(aPam.Start()), *(aPam.End()) );
+ tListTreeForRange aListTreeForRange( pNumberTreeRootNode, pPam );
+ maListTrees.push_back( aListTreeForRange );
+
+ pNode = pNode->EndOfSectionNode();
+ if (pNode != &rNodes.GetEndOfContent())
+ {
+ sal_uLong nIndex = pNode->GetIndex();
+ nIndex++;
+ pNode = rNodes[nIndex];
+ }
+ }
+ while ( pNode != &rNodes.GetEndOfContent() );
+}
+
+SwListImpl::~SwListImpl()
+{
+ tListTrees::iterator aNumberTreeIter;
+ for ( aNumberTreeIter = maListTrees.begin();
+ aNumberTreeIter != maListTrees.end();
+ ++aNumberTreeIter )
+ {
+ SwNodeNum::HandleNumberTreeRootNodeDelete( *((*aNumberTreeIter).first) );
+ delete (*aNumberTreeIter).first;
+ delete (*aNumberTreeIter).second;
+ }
+}
+
+const String SwListImpl::GetListId() const
+{
+ return msListId;
+}
+
+const String SwListImpl::GetDefaultListStyleName() const
+{
+ return msDefaultListStyleName;
+}
+
+void SwListImpl::InsertListItem( SwNodeNum& rNodeNum,
+ const int nLevel )
+{
+ const SwPosition aPosOfNodeNum( rNodeNum.GetPosition() );
+ const SwNodes* pNodesOfNodeNum = &(aPosOfNodeNum.nNode.GetNode().GetNodes());
+
+ tListTrees::const_iterator aNumberTreeIter;
+ for ( aNumberTreeIter = maListTrees.begin();
+ aNumberTreeIter != maListTrees.end();
+ ++aNumberTreeIter )
+ {
+ const SwPosition* pStart = (*aNumberTreeIter).second->Start();
+ const SwPosition* pEnd = (*aNumberTreeIter).second->End();
+ const SwNodes* pRangeNodes = &(pStart->nNode.GetNode().GetNodes());
+
+ if ( pRangeNodes == pNodesOfNodeNum &&
+ *pStart <= aPosOfNodeNum && aPosOfNodeNum <= *pEnd)
+ {
+ (*aNumberTreeIter).first->AddChild( &rNodeNum, nLevel );
+
+ break;
+ }
+ }
+}
+
+void SwListImpl::RemoveListItem( SwNodeNum& rNodeNum )
+{
+ rNodeNum.RemoveMe();
+}
+
+void SwListImpl::InvalidateListTree()
+{
+ tListTrees::iterator aNumberTreeIter;
+ for ( aNumberTreeIter = maListTrees.begin();
+ aNumberTreeIter != maListTrees.end();
+ ++aNumberTreeIter )
+ {
+ (*aNumberTreeIter).first->InvalidateTree();
+ }
+}
+
+void SwListImpl::ValidateListTree()
+{
+ tListTrees::iterator aNumberTreeIter;
+ for ( aNumberTreeIter = maListTrees.begin();
+ aNumberTreeIter != maListTrees.end();
+ ++aNumberTreeIter )
+ {
+ (*aNumberTreeIter).first->NotifyInvalidChildren();
+ }
+}
+
+void SwListImpl::MarkListLevel( const int nListLevel,
+ const sal_Bool bValue )
+{
+ if ( bValue )
+ {
+ if ( nListLevel != mnMarkedListLevel )
+ {
+ if ( mnMarkedListLevel != MAXLEVEL )
+ {
+ // notify former marked list nodes
+ NotifyItemsOnListLevel( mnMarkedListLevel );
+ }
+
+ mnMarkedListLevel = nListLevel;
+
+ // notify new marked list nodes
+ NotifyItemsOnListLevel( mnMarkedListLevel );
+ }
+ }
+ else
+ {
+ if ( mnMarkedListLevel != MAXLEVEL )
+ {
+ // notify former marked list nodes
+ NotifyItemsOnListLevel( mnMarkedListLevel );
+ }
+
+ mnMarkedListLevel = MAXLEVEL;
+ }
+}
+
+bool SwListImpl::IsListLevelMarked( const int nListLevel ) const
+{
+ return nListLevel == mnMarkedListLevel;
+}
+
+void SwListImpl::NotifyItemsOnListLevel( const int nLevel )
+{
+ tListTrees::iterator aNumberTreeIter;
+ for ( aNumberTreeIter = maListTrees.begin();
+ aNumberTreeIter != maListTrees.end();
+ ++aNumberTreeIter )
+ {
+ (*aNumberTreeIter).first->NotifyNodesOnListLevel( nLevel );
+ }
+}
+
+// ----------------------------------------------------------------------------
+// SwList
+// ----------------------------------------------------------------------------
+SwList::SwList( const String sListId,
+ SwNumRule& rDefaultListStyle,
+ const SwNodes& rNodes )
+ : mpListImpl( new SwListImpl( sListId, rDefaultListStyle, rNodes ) )
+{
+}
+
+SwList::~SwList()
+{
+ delete mpListImpl;
+}
+
+const String SwList::GetListId() const
+{
+ return mpListImpl->GetListId();
+}
+
+const String SwList::GetDefaultListStyleName() const
+{
+ return mpListImpl->GetDefaultListStyleName();
+}
+
+void SwList::InsertListItem( SwNodeNum& rNodeNum,
+ const int nLevel )
+{
+ mpListImpl->InsertListItem( rNodeNum, nLevel );
+}
+
+void SwList::RemoveListItem( SwNodeNum& rNodeNum )
+{
+ mpListImpl->RemoveListItem( rNodeNum );
+}
+
+void SwList::InvalidateListTree()
+{
+ mpListImpl->InvalidateListTree();
+}
+
+void SwList::ValidateListTree()
+{
+ mpListImpl->ValidateListTree();
+}
+
+void SwList::MarkListLevel( const int nListLevel,
+ const sal_Bool bValue )
+{
+ mpListImpl->MarkListLevel( nListLevel, bValue );
+}
+
+bool SwList::IsListLevelMarked( const int nListLevel ) const
+{
+ return mpListImpl->IsListLevelMarked( nListLevel );
+}
+
+//void SwList::ContinueList( SwList& rList )
+//{
+// mpListImpl->ContinueList( rList );
+//}
+//const SwList* SwList::GetContinuedList() const
+//{
+// return mpListImpl->GetContinuedList();
+//}
+//void SwList::ClearContinuation()
+//{
+// mpListImpl->ClearContinuation();
+//}
diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx
new file mode 100644
index 000000000000..8721d5d21164
--- /dev/null
+++ b/sw/source/core/doc/notxtfrm.cxx
@@ -0,0 +1,1098 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <tools/urlobj.hxx>
+#include <vcl/print.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/svapp.hxx>
+#include <svtools/imapobj.hxx>
+#include <svtools/imap.hxx>
+#include <svl/urihelper.hxx>
+#include <svtools/soerr.hxx>
+#include <sfx2/progress.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/printer.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/colritem.hxx>
+#include <svx/xoutbmp.hxx>
+#include <vcl/window.hxx>
+#include <fmturl.hxx>
+#include <fmtsrnd.hxx>
+#include <frmfmt.hxx>
+#include <swrect.hxx>
+#include <fesh.hxx>
+#include <doc.hxx>
+#include <flyfrm.hxx>
+#include <frmtool.hxx>
+#include <viewopt.hxx>
+#include <viewimp.hxx>
+#include <pam.hxx>
+#include <hints.hxx>
+#include <rootfrm.hxx>
+#include <dflyobj.hxx>
+#include <pagefrm.hxx>
+#include <notxtfrm.hxx>
+#include <grfatr.hxx>
+#include <charatr.hxx>
+#include <fmtornt.hxx>
+#include <ndnotxt.hxx>
+#include <ndgrf.hxx>
+#include <ndole.hxx>
+#include <swregion.hxx>
+#include <poolfmt.hxx>
+#include <mdiexp.hxx>
+#include <swwait.hxx>
+#include <comcore.hrc>
+#include <accessibilityoptions.hxx>
+#include <com/sun/star/embed/EmbedMisc.hpp>
+#include <com/sun/star/embed/EmbedStates.hpp>
+
+#include <svtools/embedhlp.hxx>
+#include <svtools/chartprettypainter.hxx>
+// --> OD 2009-03-05 #i99665#
+#include <dview.hxx>
+// <--
+
+using namespace com::sun::star;
+
+#define DEFTEXTSIZE 12
+
+extern void ClrContourCache( const SdrObject *pObj ); // TxtFly.Cxx
+
+
+inline sal_Bool GetRealURL( const SwGrfNode& rNd, String& rTxt )
+{
+ sal_Bool bRet = rNd.GetFileFilterNms( &rTxt, 0 );
+ if( bRet )
+ rTxt = URIHelper::removePassword( rTxt, INetURLObject::WAS_ENCODED,
+ INetURLObject::DECODE_UNAMBIGUOUS);
+ return bRet;
+}
+
+void lcl_PaintReplacement( const SwRect &rRect, const String &rText,
+ const ViewShell &rSh, const SwNoTxtFrm *pFrm,
+ sal_Bool bDefect )
+{
+ static Font *pFont = 0;
+ if ( !pFont )
+ {
+ pFont = new Font();
+ pFont->SetWeight( WEIGHT_BOLD );
+ pFont->SetStyleName( aEmptyStr );
+ pFont->SetName( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "Arial Unicode" )));
+ pFont->SetFamily( FAMILY_SWISS );
+ pFont->SetTransparent( sal_True );
+ }
+
+ Color aCol( COL_RED );
+ FontUnderline eUnderline = UNDERLINE_NONE;
+ const SwFmtURL &rURL = pFrm->FindFlyFrm()->GetFmt()->GetURL();
+ if( rURL.GetURL().Len() || rURL.GetMap() )
+ {
+ sal_Bool bVisited = sal_False;
+ if ( rURL.GetMap() )
+ {
+ ImageMap *pMap = (ImageMap*)rURL.GetMap();
+ for( sal_uInt16 i = 0; i < pMap->GetIMapObjectCount(); i++ )
+ {
+ IMapObject *pObj = pMap->GetIMapObject( i );
+ if( rSh.GetDoc()->IsVisitedURL( pObj->GetURL() ) )
+ {
+ bVisited = sal_True;
+ break;
+ }
+ }
+ }
+ else if ( rURL.GetURL().Len() )
+ bVisited = rSh.GetDoc()->IsVisitedURL( rURL.GetURL() );
+
+ SwFmt *pFmt = rSh.GetDoc()->GetFmtFromPool( static_cast<sal_uInt16>
+ (bVisited ? RES_POOLCHR_INET_VISIT : RES_POOLCHR_INET_NORMAL ) );
+ aCol = pFmt->GetColor().GetValue();
+ eUnderline = pFmt->GetUnderline().GetLineStyle();
+ }
+
+ pFont->SetUnderline( eUnderline );
+ pFont->SetColor( aCol );
+
+ const BitmapEx& rBmp = ViewShell::GetReplacementBitmap( bDefect != sal_False );
+ Graphic::DrawEx( rSh.GetOut(), rText, *pFont, rBmp, rRect.Pos(), rRect.SSize() );
+}
+
+/*************************************************************************
+|*
+|* SwGrfFrm::SwGrfFrm(ViewShell * const,SwGrfNode *)
+|*
+|* Beschreibung
+|* Ersterstellung JP 05.03.91
+|* Letzte Aenderung MA 03. Mar. 93
+|*
+*************************************************************************/
+
+
+SwNoTxtFrm::SwNoTxtFrm(SwNoTxtNode * const pNode)
+ : SwCntntFrm(pNode)
+{
+ InitCtor();
+}
+
+// Initialisierung: z.Zt. Eintragen des Frames im Cache
+
+
+void SwNoTxtFrm::InitCtor()
+{
+ nType = FRMC_NOTXT;
+ // Das Gewicht der Grafik ist 0, wenn sie noch nicht
+ // gelesen ist, < 0, wenn ein Lesefehler auftrat und
+ // Ersatzdarstellung angewendet werden musste und >0,
+ // wenn sie zur Verfuegung steht.
+ nWeight = 0;
+}
+
+/*************************************************************************
+|*
+|* SwNoTxtNode::MakeFrm()
+|*
+|* Beschreibung
+|* Ersterstellung JP 05.03.91
+|* Letzte Aenderung MA 03. Mar. 93
+|*
+*************************************************************************/
+
+
+SwCntntFrm *SwNoTxtNode::MakeFrm()
+{
+ return new SwNoTxtFrm(this);
+}
+
+/*************************************************************************
+|*
+|* SwNoTxtFrm::~SwNoTxtFrm()
+|*
+|* Beschreibung
+|* Ersterstellung JP 05.03.91
+|* Letzte Aenderung MA 30. Apr. 96
+|*
+*************************************************************************/
+
+SwNoTxtFrm::~SwNoTxtFrm()
+{
+ StopAnimation();
+}
+
+/*************************************************************************
+|*
+|* void SwNoTxtFrm::Modify( SwHint * pOld, SwHint * pNew )
+|*
+|* Beschreibung
+|* Ersterstellung JP 05.03.91
+|* Letzte Aenderung JP 05.03.91
+|*
+*************************************************************************/
+
+void SetOutDev( ViewShell *pSh, OutputDevice *pOut )
+{
+ pSh->pOut = pOut;
+}
+
+
+
+
+void lcl_ClearArea( const SwFrm &rFrm,
+ OutputDevice &rOut, const SwRect& rPtArea,
+ const SwRect &rGrfArea )
+{
+ SwRegionRects aRegion( rPtArea, 4, 4 );
+ aRegion -= rGrfArea;
+
+ if ( aRegion.Count() )
+ {
+ const SvxBrushItem *pItem; const Color *pCol; SwRect aOrigRect;
+ if ( rFrm.GetBackgroundBrush( pItem, pCol, aOrigRect, sal_False ) )
+ for( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ ::DrawGraphic( pItem, &rOut, aOrigRect, aRegion[i] );
+ else
+ {
+ // OD 2004-04-23 #116347#
+ rOut.Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ rOut.SetFillColor( rFrm.GetShell()->Imp()->GetRetoucheColor());
+ rOut.SetLineColor();
+ for( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ rOut.DrawRect( aRegion[i].SVRect() );
+ rOut.Pop();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* void SwNoTxtFrm::Paint()
+|*
+|* Beschreibung
+|* Ersterstellung JP 05.03.91
+|* Letzte Aenderung MA 10. Jan. 97
+|*
+*************************************************************************/
+
+void SwNoTxtFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
+{
+ if ( Frm().IsEmpty() )
+ return;
+
+ const ViewShell* pSh = GetShell();
+ if( !pSh->GetViewOptions()->IsGraphic() )
+ {
+ StopAnimation();
+ // OD 10.01.2003 #i6467# - no paint of placeholder for page preview
+ if ( pSh->GetWin() && !pSh->IsPreView() )
+ {
+ const SwNoTxtNode* pNd = GetNode()->GetNoTxtNode();
+ String aTxt( pNd->GetTitle() );
+ if ( !aTxt.Len() && pNd->IsGrfNode() )
+ GetRealURL( *(SwGrfNode*)pNd, aTxt );
+ if( !aTxt.Len() )
+ aTxt = FindFlyFrm()->GetFmt()->GetName();
+ lcl_PaintReplacement( Frm(), aTxt, *pSh, this, sal_False );
+ }
+ return;
+ }
+
+ if( pSh->GetAccessibilityOptions()->IsStopAnimatedGraphics() ||
+ // --> FME 2004-06-21 #i9684# Stop animation during printing/pdf export
+ !pSh->GetWin() )
+ // <--
+ StopAnimation();
+
+ SfxProgress::EnterLock(); //Keine Progress-Reschedules im Paint (SwapIn)
+
+ OutputDevice *pOut = pSh->GetOut();
+ pOut->Push();
+ sal_Bool bClip = sal_True;
+ PolyPolygon aPoly;
+
+ SwNoTxtNode& rNoTNd = *(SwNoTxtNode*)GetNode();
+ SwGrfNode* pGrfNd = rNoTNd.GetGrfNode();
+ if( pGrfNd )
+ pGrfNd->SetFrameInPaint( sal_True );
+
+ // OD 16.04.2003 #i13147# - add 2nd parameter with value <sal_True> to
+ // method call <FindFlyFrm().GetContour(..)> to indicate that it is called
+ // for paint in order to avoid load of the intrinsic graphic.
+ if ( ( !pOut->GetConnectMetaFile() ||
+ !pSh->GetWin() ) &&
+ FindFlyFrm()->GetContour( aPoly, sal_True )
+ )
+ {
+ pOut->SetClipRegion( aPoly );
+ bClip = sal_False;
+ }
+
+ SwRect aOrigPaint( rRect );
+ if ( HasAnimation() && pSh->GetWin() )
+ {
+ aOrigPaint = Frm(); aOrigPaint += Prt().Pos();
+ }
+
+ SwRect aGrfArea( Frm() );
+ SwRect aPaintArea( aGrfArea );
+ aPaintArea._Intersection( aOrigPaint );
+
+ SwRect aNormal( Frm().Pos() + Prt().Pos(), Prt().SSize() );
+ aNormal.Justify(); //Normalisiertes Rechteck fuer die Vergleiche
+
+ if( aPaintArea.IsOver( aNormal ) )
+ {
+ // berechne die 4 zu loeschenden Rechtecke
+ if( pSh->GetWin() )
+ ::lcl_ClearArea( *this, *pSh->GetOut(), aPaintArea, aNormal );
+
+ // in der Schnittmenge vom PaintBereich und der Bitmap liegt
+ // der absolut sichtbare Bereich vom Frame
+ aPaintArea._Intersection( aNormal );
+
+ if ( bClip )
+ pOut->IntersectClipRegion( aPaintArea.SVRect() );
+ /// OD 25.09.2002 #99739# - delete unused 3rd parameter
+ PaintPicture( pOut, aGrfArea );
+ }
+ else
+ // wenn nicht sichtbar, loesche einfach den angegebenen Bereich
+ lcl_ClearArea( *this, *pSh->GetOut(), aPaintArea, SwRect() );
+ if( pGrfNd )
+ pGrfNd->SetFrameInPaint( sal_False );
+
+ pOut->Pop();
+ SfxProgress::LeaveLock();
+}
+
+/*************************************************************************
+|*
+|* void lcl_CalcRect( Point & aPt, Size & aDim,
+|* sal_uInt16 nMirror )
+|*
+|* Beschreibung Errechne die Position und die Groesse der Grafik im
+|* Frame, entsprechen der aktuellen Grafik-Attribute
+|*
+|* Parameter Point& die Position im Frame ( auch Return-Wert )
+|* Size& die Groesse der Grafik ( auch Return-Wert )
+|* MirrorGrf akt. Spiegelungs-Attribut
+|* Ersterstellung JP 04.03.91
+|* Letzte Aenderung JP 31.08.94
+|*
+*************************************************************************/
+
+
+void lcl_CalcRect( Point& rPt, Size& rDim, sal_uInt16 nMirror )
+{
+ if( nMirror == RES_MIRROR_GRAPH_VERT || nMirror == RES_MIRROR_GRAPH_BOTH )
+ {
+ rPt.X() += rDim.Width() -1;
+ rDim.Width() = -rDim.Width();
+ }
+
+ if( nMirror == RES_MIRROR_GRAPH_HOR || nMirror == RES_MIRROR_GRAPH_BOTH )
+ {
+ rPt.Y() += rDim.Height() -1;
+ rDim.Height() = -rDim.Height();
+ }
+}
+
+/*************************************************************************
+|*
+|* void SwNoTxtFrm::GetGrfArea()
+|*
+|* Beschreibung Errechne die Position und die Groesse der Bitmap
+|* innerhalb des uebergebenem Rechtecks.
+|*
+|* Ersterstellung JP 03.09.91
+|* Letzte Aenderung MA 11. Oct. 94
+|*
+*************************************************************************/
+
+void SwNoTxtFrm::GetGrfArea( SwRect &rRect, SwRect* pOrigRect,
+ sal_Bool ) const
+{
+ // JP 23.01.2001: currently only used for scaling, cropping and mirroring
+ // the contour of graphics!
+ // all other is handled by the GraphicObject
+
+ //In rRect wird das sichbare Rechteck der Grafik gesteckt.
+ //In pOrigRect werden Pos+Size der Gesamtgrafik gesteck.
+
+ const SwAttrSet& rAttrSet = GetNode()->GetSwAttrSet();
+ const SwCropGrf& rCrop = rAttrSet.GetCropGrf();
+ sal_uInt16 nMirror = rAttrSet.GetMirrorGrf().GetValue();
+
+ if( rAttrSet.GetMirrorGrf().IsGrfToggle() )
+ {
+ if( !(FindPageFrm()->GetVirtPageNum() % 2) )
+ {
+ switch ( nMirror )
+ {
+ case RES_MIRROR_GRAPH_DONT: nMirror = RES_MIRROR_GRAPH_VERT; break;
+ case RES_MIRROR_GRAPH_VERT: nMirror = RES_MIRROR_GRAPH_DONT; break;
+ case RES_MIRROR_GRAPH_HOR: nMirror = RES_MIRROR_GRAPH_BOTH; break;
+ default: nMirror = RES_MIRROR_GRAPH_HOR; break;
+ }
+ }
+ }
+
+ //Grafik wird vom Node eingelesen falls notwendig. Kann aber schiefgehen.
+ long nLeftCrop, nRightCrop, nTopCrop, nBottomCrop;
+ Size aOrigSz( ((SwNoTxtNode*)GetNode())->GetTwipSize() );
+ if ( !aOrigSz.Width() )
+ {
+ aOrigSz.Width() = Prt().Width();
+ nLeftCrop = -rCrop.GetLeft();
+ nRightCrop = -rCrop.GetRight();
+ }
+ else
+ {
+ nLeftCrop = Max( aOrigSz.Width() -
+ (rCrop.GetRight() + rCrop.GetLeft()), long(1) );
+ const double nScale = double(Prt().Width()) / double(nLeftCrop);
+ nLeftCrop = long(nScale * -rCrop.GetLeft() );
+ nRightCrop = long(nScale * -rCrop.GetRight() );
+ }
+
+ // crop values have to be mirrored too
+ if( nMirror == RES_MIRROR_GRAPH_VERT || nMirror == RES_MIRROR_GRAPH_BOTH )
+ {
+ long nTmpCrop = nLeftCrop;
+ nLeftCrop = nRightCrop;
+ nRightCrop= nTmpCrop;
+ }
+
+ if( !aOrigSz.Height() )
+ {
+ aOrigSz.Height() = Prt().Height();
+ nTopCrop = -rCrop.GetTop();
+ nBottomCrop= -rCrop.GetBottom();
+ }
+ else
+ {
+ nTopCrop = Max( aOrigSz.Height() - (rCrop.GetTop() + rCrop.GetBottom()), long(1) );
+ const double nScale = double(Prt().Height()) / double(nTopCrop);
+ nTopCrop = long(nScale * -rCrop.GetTop() );
+ nBottomCrop= long(nScale * -rCrop.GetBottom() );
+ }
+
+ // crop values have to be mirrored too
+ if( nMirror == RES_MIRROR_GRAPH_HOR || nMirror == RES_MIRROR_GRAPH_BOTH )
+ {
+ long nTmpCrop = nTopCrop;
+ nTopCrop = nBottomCrop;
+ nBottomCrop= nTmpCrop;
+ }
+
+ Size aVisSz( Prt().SSize() );
+ Size aGrfSz( aVisSz );
+ Point aVisPt( Frm().Pos() + Prt().Pos() );
+ Point aGrfPt( aVisPt );
+
+ //Erst das 'sichtbare' Rect einstellen.
+ if ( nLeftCrop > 0 )
+ {
+ aVisPt.X() += nLeftCrop;
+ aVisSz.Width() -= nLeftCrop;
+ }
+ if ( nTopCrop > 0 )
+ {
+ aVisPt.Y() += nTopCrop;
+ aVisSz.Height() -= nTopCrop;
+ }
+ if ( nRightCrop > 0 )
+ aVisSz.Width() -= nRightCrop;
+ if ( nBottomCrop > 0 )
+ aVisSz.Height() -= nBottomCrop;
+
+ rRect.Pos ( aVisPt );
+ rRect.SSize( aVisSz );
+
+ //Ggf. Die Gesamtgrafik berechnen
+ if ( pOrigRect )
+ {
+ Size aTmpSz( aGrfSz );
+ aGrfPt.X() += nLeftCrop;
+ aTmpSz.Width() -= nLeftCrop + nRightCrop;
+ aGrfPt.Y() += nTopCrop;
+ aTmpSz.Height()-= nTopCrop + nBottomCrop;
+
+ if( RES_MIRROR_GRAPH_DONT != nMirror )
+ lcl_CalcRect( aGrfPt, aTmpSz, nMirror );
+
+ pOrigRect->Pos ( aGrfPt );
+ pOrigRect->SSize( aTmpSz );
+ }
+}
+
+/*************************************************************************
+|*
+|* Size SwNoTxtFrm::GetSize()
+|*
+|* Beschreibung Gebe die Groesse des umgebenen FLys und
+|* damit die der Grafik zurueck.
+|* Ersterstellung JP 04.03.91
+|* Letzte Aenderung JP 31.08.94
+|*
+*************************************************************************/
+
+
+const Size& SwNoTxtFrm::GetSize() const
+{
+ // gebe die Groesse des Frames zurueck
+ const SwFrm *pFly = FindFlyFrm();
+ if( !pFly )
+ pFly = this;
+ return pFly->Prt().SSize();
+}
+
+/*************************************************************************
+|*
+|* SwNoTxtFrm::MakeAll()
+|*
+|* Ersterstellung MA 29. Nov. 96
+|* Letzte Aenderung MA 29. Nov. 96
+|*
+*************************************************************************/
+
+
+void SwNoTxtFrm::MakeAll()
+{
+ SwCntntNotify aNotify( this );
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+
+ while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ {
+ MakePos();
+
+ if ( !bValidSize )
+ Frm().Width( GetUpper()->Prt().Width() );
+
+ MakePrtArea( rAttrs );
+
+ if ( !bValidSize )
+ { bValidSize = sal_True;
+ Format();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwNoTxtFrm::Format()
+|*
+|* Beschreibung Errechne die Groesse der Bitmap, wenn noetig
+|* Ersterstellung JP 11.03.91
+|* Letzte Aenderung MA 13. Mar. 96
+|*
+*************************************************************************/
+
+
+void SwNoTxtFrm::Format( const SwBorderAttrs * )
+{
+ const Size aNewSize( GetSize() );
+
+ // hat sich die Hoehe geaendert?
+ SwTwips nChgHght = IsVertical() ?
+ (SwTwips)(aNewSize.Width() - Prt().Width()) :
+ (SwTwips)(aNewSize.Height() - Prt().Height());
+ if( nChgHght > 0)
+ Grow( nChgHght );
+ else if( nChgHght < 0)
+ Shrink( Min(Prt().Height(), -nChgHght) );
+}
+
+/*************************************************************************
+|*
+|* SwNoTxtFrm::GetCharRect()
+|*
+|* Beschreibung
+|* Ersterstellung SS 29-Apr-1991
+|* Letzte Aenderung MA 10. Oct. 94
+|*
+|*************************************************************************/
+
+
+sal_Bool SwNoTxtFrm::GetCharRect( SwRect &rRect, const SwPosition& rPos,
+ SwCrsrMoveState *pCMS ) const
+{
+ if ( &rPos.nNode.GetNode() != (SwNode*)GetNode() )
+ return sal_False;
+
+ Calc();
+ SwRect aFrameRect( Frm() );
+ rRect = aFrameRect;
+ rRect.Pos( Frm().Pos() + Prt().Pos() );
+ rRect.SSize( Prt().SSize() );
+
+ rRect.Justify();
+
+ // liegt die Bitmap ueberhaupt im sichtbaren Berich ?
+ if( !aFrameRect.IsOver( rRect ) )
+ {
+ // wenn nicht dann steht der Cursor auf dem Frame
+ rRect = aFrameRect;
+ rRect.Width( 1 );
+ }
+ else
+ rRect._Intersection( aFrameRect );
+
+ if ( pCMS )
+ {
+ if ( pCMS->bRealHeight )
+ {
+ pCMS->aRealHeight.Y() = rRect.Height();
+ pCMS->aRealHeight.X() = 0;
+ }
+ }
+
+ return sal_True;
+}
+
+
+sal_Bool SwNoTxtFrm::GetCrsrOfst(SwPosition* pPos, Point& ,
+ SwCrsrMoveState* ) const
+{
+ SwCntntNode* pCNd = (SwCntntNode*)GetNode();
+ pPos->nNode = *pCNd;
+ pPos->nContent.Assign( pCNd, 0 );
+ return sal_True;
+}
+
+#define CLEARCACHE( pNd ) {\
+ (pNd)->GetGrfObj().ReleaseFromCache();\
+ SwFlyFrm* pFly = FindFlyFrm();\
+ if( pFly && pFly->GetFmt()->GetSurround().IsContour() )\
+ {\
+ ClrContourCache( pFly->GetVirtDrawObj() );\
+ pFly->NotifyBackground( FindPageFrm(), Prt(), PREP_FLY_ATTR_CHG );\
+ }\
+}
+
+void SwNoTxtFrm::Modify( SfxPoolItem* pOld, SfxPoolItem* pNew )
+{
+ sal_uInt16 nWhich = pNew ? pNew->Which() : pOld ? pOld->Which() : 0;
+
+ // --> OD 2007-03-06 #i73788#
+ // no <SwCntntFrm::Modify(..)> for RES_LINKED_GRAPHIC_STREAM_ARRIVED
+ if ( RES_GRAPHIC_PIECE_ARRIVED != nWhich &&
+ RES_GRAPHIC_ARRIVED != nWhich &&
+ RES_GRF_REREAD_AND_INCACHE != nWhich &&
+ RES_LINKED_GRAPHIC_STREAM_ARRIVED != nWhich )
+ // <--
+ {
+ SwCntntFrm::Modify( pOld, pNew );
+ }
+
+ sal_Bool bComplete = sal_True;
+
+ switch( nWhich )
+ {
+ case RES_OBJECTDYING:
+ break;
+
+ case RES_GRF_REREAD_AND_INCACHE:
+ if( ND_GRFNODE == GetNode()->GetNodeType() )
+ {
+ bComplete = sal_False;
+ SwGrfNode* pNd = (SwGrfNode*) GetNode();
+
+ ViewShell *pVSh = 0;
+ pNd->GetDoc()->GetEditShell( &pVSh );
+ if( pVSh )
+ {
+ GraphicAttr aAttr;
+ if( pNd->GetGrfObj().IsCached( pVSh->GetOut(), Point(),
+ Prt().SSize(), &pNd->GetGraphicAttr( aAttr, this ) ))
+ {
+ ViewShell *pSh = pVSh;
+ do {
+ SET_CURR_SHELL( pSh );
+ if( pSh->GetWin() )
+ {
+ if( pSh->IsPreView() )
+ ::RepaintPagePreview( pSh, Frm().SVRect() );
+ else
+ pSh->GetWin()->Invalidate( Frm().SVRect() );
+ }
+ } while( pVSh != (pSh = (ViewShell*)pSh->GetNext() ));
+ }
+ else
+ pNd->SwapIn();
+ }
+ }
+ break;
+
+ case RES_UPDATE_ATTR:
+ case RES_FMT_CHG:
+ CLEARCACHE( (SwGrfNode*) GetNode() )
+ break;
+
+ case RES_ATTRSET_CHG:
+ {
+ sal_uInt16 n;
+ for( n = RES_GRFATR_BEGIN; n < RES_GRFATR_END; ++n )
+ if( SFX_ITEM_SET == ((SwAttrSetChg*)pOld)->GetChgSet()->
+ GetItemState( n, sal_False ))
+ {
+ CLEARCACHE( (SwGrfNode*) GetNode() )
+ break;
+ }
+ if( RES_GRFATR_END == n ) // not found
+ return ;
+ }
+ break;
+
+ case RES_GRAPHIC_PIECE_ARRIVED:
+ case RES_GRAPHIC_ARRIVED:
+ // --> OD 2007-03-06 #i73788#
+ // handle RES_LINKED_GRAPHIC_STREAM_ARRIVED as RES_GRAPHIC_ARRIVED
+ case RES_LINKED_GRAPHIC_STREAM_ARRIVED:
+ // <--
+ if ( GetNode()->GetNodeType() == ND_GRFNODE )
+ {
+ bComplete = sal_False;
+ SwGrfNode* pNd = (SwGrfNode*) GetNode();
+
+ CLEARCACHE( pNd )
+
+ SwRect aRect( Frm() );
+
+ ViewShell *pVSh = 0;
+ pNd->GetDoc()->GetEditShell( &pVSh );
+ if( !pVSh )
+ break;
+
+ ViewShell *pSh = pVSh;
+ do {
+ SET_CURR_SHELL( pSh );
+ if( pSh->IsPreView() )
+ {
+ if( pSh->GetWin() )
+ ::RepaintPagePreview( pSh, aRect );
+ }
+ else if ( pSh->VisArea().IsOver( aRect ) &&
+ OUTDEV_WINDOW == pSh->GetOut()->GetOutDevType() )
+ {
+ // OD 27.11.2002 #105519# - invalidate instead of painting
+ pSh->GetWin()->Invalidate( aRect.SVRect() );
+ }
+
+ pSh = (ViewShell *)pSh->GetNext();
+ } while( pSh != pVSh );
+ }
+ break;
+
+ default:
+ if ( !pNew || !isGRFATR(nWhich) )
+ return;
+ }
+
+ if( bComplete )
+ {
+ InvalidatePrt();
+ SetCompletePaint();
+ }
+}
+
+void lcl_correctlyAlignRect( SwRect& rAlignedGrfArea, const SwRect& rInArea, OutputDevice* pOut )
+{
+
+ if(!pOut)
+ return;
+ Rectangle aPxRect = pOut->LogicToPixel( rInArea.SVRect() );
+ Rectangle aNewPxRect( aPxRect );
+ while( aNewPxRect.Left() < aPxRect.Left() )
+ {
+ rAlignedGrfArea.Left( rAlignedGrfArea.Left()+1 );
+ aNewPxRect = pOut->LogicToPixel( rAlignedGrfArea.SVRect() );
+ }
+ while( aNewPxRect.Top() < aPxRect.Top() )
+ {
+ rAlignedGrfArea.Top( rAlignedGrfArea.Top()+1 );
+ aNewPxRect = pOut->LogicToPixel( rAlignedGrfArea.SVRect() );
+ }
+ while( aNewPxRect.Bottom() > aPxRect.Bottom() )
+ {
+ rAlignedGrfArea.Bottom( rAlignedGrfArea.Bottom()-1 );
+ aNewPxRect = pOut->LogicToPixel( rAlignedGrfArea.SVRect() );
+ }
+ while( aNewPxRect.Right() > aPxRect.Right() )
+ {
+ rAlignedGrfArea.Right( rAlignedGrfArea.Right()-1 );
+ aNewPxRect = pOut->LogicToPixel( rAlignedGrfArea.SVRect() );
+ }
+}
+
+// Ausgabe der Grafik. Hier wird entweder eine QuickDraw-Bmp oder
+// eine Grafik vorausgesetzt. Ist nichts davon vorhanden, wird
+// eine Ersatzdarstellung ausgegeben.
+/// OD 25.09.2002 #99739# - delete unused 3rd parameter.
+/// OD 25.09.2002 #99739# - use aligned rectangle for drawing graphic.
+/// OD 25.09.2002 #99739# - pixel-align coordinations for drawing graphic.
+void SwNoTxtFrm::PaintPicture( OutputDevice* pOut, const SwRect &rGrfArea ) const
+{
+ ViewShell* pShell = GetShell();
+
+ SwNoTxtNode& rNoTNd = *(SwNoTxtNode*)GetNode();
+ SwGrfNode* pGrfNd = rNoTNd.GetGrfNode();
+ SwOLENode* pOLENd = rNoTNd.GetOLENode();
+
+ const sal_Bool bPrn = pOut == rNoTNd.getIDocumentDeviceAccess()->getPrinter( false ) ||
+ pOut->GetConnectMetaFile();
+
+ const bool bIsChart = pOLENd && ChartPrettyPainter::IsChart( pOLENd->GetOLEObj().GetObject() );
+
+ /// OD 25.09.2002 #99739# - calculate aligned rectangle from parameter <rGrfArea>.
+ /// Use aligned rectangle <aAlignedGrfArea> instead of <rGrfArea> in
+ /// the following code.
+ SwRect aAlignedGrfArea = rGrfArea;
+ ::SwAlignRect( aAlignedGrfArea, pShell );
+
+ if( !bIsChart )
+ {
+ /// OD 25.09.2002 #99739#
+ /// Because for drawing a graphic left-top-corner and size coordinations are
+ /// used, these coordinations have to be determined on pixel level.
+ ::SwAlignGrfRect( &aAlignedGrfArea, *pOut );
+ }
+ else //if( bIsChart )
+ {
+ //#i78025# charts own borders are not completely visible
+ //the above pixel correction is not correct - at least not for charts
+ //so a different pixel correction is choosen here
+ //this might be a good idea for all other OLE objects also,
+ //but as I cannot oversee the consequences I fix it only for charts for now
+ lcl_correctlyAlignRect( aAlignedGrfArea, rGrfArea, pOut );
+ }
+
+ if( pGrfNd )
+ {
+ sal_Bool bForceSwap = sal_False, bContinue = sal_True;
+ GraphicObject& rGrfObj = pGrfNd->GetGrfObj();
+
+ GraphicAttr aGrfAttr;
+ pGrfNd->GetGraphicAttr( aGrfAttr, this );
+
+ if( !bPrn )
+ {
+ // --> OD 2007-01-02 #i73788#
+ if ( pGrfNd->IsLinkedInputStreamReady() )
+ {
+ pGrfNd->UpdateLinkWithInputStream();
+ }
+ // <--
+ // --> OD 2008-01-30 #i85717#
+ // --> OD 2008-07-21 #i90395# - check, if asynchronous retrieval
+ // if input stream for the graphic is possible
+// else if( GRAPHIC_DEFAULT == rGrfObj.GetType() &&
+ else if ( ( rGrfObj.GetType() == GRAPHIC_DEFAULT ||
+ rGrfObj.GetType() == GRAPHIC_NONE ) &&
+ pGrfNd->IsLinkedFile() &&
+ pGrfNd->IsAsyncRetrieveInputStreamPossible() )
+ // <--
+ {
+ Size aTmpSz;
+ ::sfx2::SvLinkSource* pGrfObj = pGrfNd->GetLink()->GetObj();
+ if( !pGrfObj ||
+ !pGrfObj->IsDataComplete() ||
+ !(aTmpSz = pGrfNd->GetTwipSize()).Width() ||
+ !aTmpSz.Height() || !pGrfNd->GetAutoFmtLvl() )
+ {
+ // --> OD 2006-12-22 #i73788#
+ pGrfNd->TriggerAsyncRetrieveInputStream();
+ // <--
+ }
+ String aTxt( pGrfNd->GetTitle() );
+ if ( !aTxt.Len() )
+ GetRealURL( *pGrfNd, aTxt );
+ ::lcl_PaintReplacement( aAlignedGrfArea, aTxt, *pShell, this, sal_False );
+ bContinue = sal_False;
+ }
+ else if( rGrfObj.IsCached( pOut, aAlignedGrfArea.Pos(),
+ aAlignedGrfArea.SSize(), &aGrfAttr ))
+ {
+ rGrfObj.DrawWithPDFHandling( *pOut,
+ aAlignedGrfArea.Pos(), aAlignedGrfArea.SSize(),
+ &aGrfAttr );
+ bContinue = sal_False;
+ }
+ }
+
+ if( bContinue )
+ {
+ const sal_Bool bSwapped = rGrfObj.IsSwappedOut();
+ const sal_Bool bSwappedIn = 0 != pGrfNd->SwapIn( bPrn );
+ if( bSwappedIn && rGrfObj.GetGraphic().IsSupportedGraphic())
+ {
+ const sal_Bool bAnimate = rGrfObj.IsAnimated() &&
+ !pShell->IsPreView() &&
+ !pShell->GetAccessibilityOptions()->IsStopAnimatedGraphics() &&
+ // --> FME 2004-06-21 #i9684# Stop animation during printing/pdf export
+ pShell->GetWin();
+ // <--
+
+ if( bAnimate &&
+ FindFlyFrm() != ::GetFlyFromMarked( 0, pShell ))
+ {
+ OutputDevice* pVout;
+ if( pOut == pShell->GetOut() && SwRootFrm::FlushVout() )
+ pVout = pOut, pOut = pShell->GetOut();
+ else if( pShell->GetWin() &&
+ OUTDEV_VIRDEV == pOut->GetOutDevType() )
+ pVout = pOut, pOut = pShell->GetWin();
+ else
+ pVout = 0;
+
+ ASSERT( OUTDEV_VIRDEV != pOut->GetOutDevType() ||
+ pShell->GetViewOptions()->IsPDFExport(),
+ "pOut sollte kein virtuelles Device sein" );
+
+ rGrfObj.StartAnimation( pOut, aAlignedGrfArea.Pos(),
+ aAlignedGrfArea.SSize(), long(this),
+ 0, GRFMGR_DRAW_STANDARD, pVout );
+ }
+ else
+ rGrfObj.DrawWithPDFHandling( *pOut,
+ aAlignedGrfArea.Pos(), aAlignedGrfArea.SSize(),
+ &aGrfAttr );
+ }
+ else
+ {
+ sal_uInt16 nResId = 0;
+ if( bSwappedIn )
+ {
+ if( GRAPHIC_NONE == rGrfObj.GetType() )
+ nResId = STR_COMCORE_READERROR;
+ else if ( !rGrfObj.GetGraphic().IsSupportedGraphic() )
+ nResId = STR_COMCORE_CANT_SHOW;
+ }
+ ((SwNoTxtFrm*)this)->nWeight = -1;
+ String aText;
+ if ( !nResId &&
+ !(aText = pGrfNd->GetTitle()).Len() &&
+ (!GetRealURL( *pGrfNd, aText ) || !aText.Len()))
+ {
+ nResId = STR_COMCORE_READERROR;
+ }
+ if ( nResId )
+ aText = SW_RESSTR( nResId );
+
+ ::lcl_PaintReplacement( aAlignedGrfArea, aText, *pShell, this, sal_True );
+ }
+
+ //Beim Drucken duerfen wir nicht die Grafiken sammeln...
+ if( bSwapped && bPrn )
+ bForceSwap = sal_True;
+ }
+ if( bForceSwap )
+ pGrfNd->SwapOut();
+ }
+ else if( bIsChart
+ //charts must be painted resolution dependent!! #i82893#, #i75867#
+ && ChartPrettyPainter::ShouldPrettyPaintChartOnThisDevice( pOut )
+ && svt::EmbeddedObjectRef::TryRunningState( pOLENd->GetOLEObj().GetOleRef() )
+ && ChartPrettyPainter::DoPrettyPaintChart( uno::Reference< frame::XModel >(
+ pOLENd->GetOLEObj().GetOleRef()->getComponent(), uno::UNO_QUERY), pOut, aAlignedGrfArea.SVRect() ) )
+ {
+ (void)(0);//all was done in if statement
+ }
+ else if( pOLENd )
+ {
+ // --> OD 2009-03-05 #i99665#
+ // Adjust AntiAliasing mode at output device for chart OLE
+ const sal_uInt16 nFormerAntialiasingAtOutput( pOut->GetAntialiasing() );
+ if ( pOLENd->IsChart() &&
+ pShell->Imp()->GetDrawView()->IsAntiAliasing() )
+ {
+ const sal_uInt16 nAntialiasingForChartOLE =
+ nFormerAntialiasingAtOutput | ANTIALIASING_PIXELSNAPHAIRLINE;
+ pOut->SetAntialiasing( nAntialiasingForChartOLE );
+ }
+ // <--
+
+ Point aPosition(aAlignedGrfArea.Pos());
+ Size aSize(aAlignedGrfArea.SSize());
+
+ // Im BrowseModus gibt es nicht unbedingt einen Drucker und
+ // damit kein JobSetup, also legen wir eines an ...
+ const JobSetup* pJobSetup = pOLENd->getIDocumentDeviceAccess()->getJobsetup();
+ sal_Bool bDummyJobSetup = 0 == pJobSetup;
+ if( bDummyJobSetup )
+ pJobSetup = new JobSetup();
+
+ // #i42323#
+ // The reason for #114233# is gone, so i remove it again
+ //TODO/LATER: is it a problem that the JopSetup isn't used?
+ //xRef->DoDraw( pOut, aAlignedGrfArea.Pos(), aAlignedGrfArea.SSize(), *pJobSetup );
+
+ // get hi-contrast image, but never for printing
+ Graphic* pGraphic = NULL;
+ if (pOut && !bPrn && Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ pGraphic = pOLENd->GetHCGraphic();
+
+ // when it is not possible to get HC-representation, the original image should be used
+ if ( !pGraphic )
+ pGraphic = pOLENd->GetGraphic();
+
+ if ( pGraphic && pGraphic->GetType() != GRAPHIC_NONE )
+ {
+ pGraphic->Draw( pOut, aPosition, aSize );
+
+ // shade the representation if the object is activated outplace
+ uno::Reference < embed::XEmbeddedObject > xObj = pOLENd->GetOLEObj().GetOleRef();
+ if ( xObj.is() && xObj->getCurrentState() == embed::EmbedStates::ACTIVE )
+ {
+ ::svt::EmbeddedObjectRef::DrawShading( Rectangle( aPosition, aSize ), pOut );
+ }
+ }
+ else
+ ::svt::EmbeddedObjectRef::DrawPaintReplacement( Rectangle( aPosition, aSize ), pOLENd->GetOLEObj().GetCurrentPersistName(), pOut );
+
+ if( bDummyJobSetup )
+ delete pJobSetup; // ... und raeumen wieder auf.
+
+ sal_Int64 nMiscStatus = pOLENd->GetOLEObj().GetOleRef()->getStatus( pOLENd->GetAspect() );
+ if ( !bPrn && pShell->ISA( SwCrsrShell ) &&
+ nMiscStatus & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE )
+ {
+ const SwFlyFrm *pFly = FindFlyFrm();
+ ASSERT( pFly, "OLE not in FlyFrm" );
+ ((SwFEShell*)pShell)->ConnectObj( pOLENd->GetOLEObj().GetObject(), pFly->Prt(), pFly->Frm());
+ }
+
+ // --> OD 2009-03-05 #i99665#
+ if ( pOLENd->IsChart() &&
+ pShell->Imp()->GetDrawView()->IsAntiAliasing() )
+ {
+ pOut->SetAntialiasing( nFormerAntialiasingAtOutput );
+ }
+ // <--
+ }
+}
+
+
+sal_Bool SwNoTxtFrm::IsTransparent() const
+{
+ const ViewShell* pSh = GetShell();
+ if ( !pSh || !pSh->GetViewOptions()->IsGraphic() )
+ return sal_True;
+
+ const SwGrfNode *pNd;
+ if( 0 != (pNd = GetNode()->GetGrfNode()) )
+ return pNd->IsTransparent();
+
+ //#29381# OLE sind immer Transparent.
+ return sal_True;
+}
+
+
+void SwNoTxtFrm::StopAnimation( OutputDevice* pOut ) const
+{
+ //animierte Grafiken anhalten
+ SwGrfNode* pGrfNd = (SwGrfNode*)GetNode()->GetGrfNode();
+ if( pGrfNd && pGrfNd->IsAnimated() )
+ pGrfNd->GetGrfObj().StopAnimation( pOut, long(this) );
+}
+
+
+sal_Bool SwNoTxtFrm::HasAnimation() const
+{
+ const SwGrfNode* pGrfNd = GetNode()->GetGrfNode();
+ return pGrfNd && pGrfNd->IsAnimated();
+}
+
+
+
diff --git a/sw/source/core/doc/number.cxx b/sw/source/core/doc/number.cxx
new file mode 100644
index 000000000000..2333169f2222
--- /dev/null
+++ b/sw/source/core/doc/number.cxx
@@ -0,0 +1,1686 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#include <string.h>
+#include <vcl/font.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/numitem.hxx>
+#include <fmtornt.hxx>
+#include <doc.hxx>
+#include <pam.hxx>
+#include <charfmt.hxx>
+#include <paratr.hxx>
+#include <frmfmt.hxx>
+#include <ndtxt.hxx>
+#include <docary.hxx>
+#ifndef _DOCSH_HXX
+#include <docsh.hxx>
+#endif
+#include <SwStyleNameMapper.hxx>
+// --> OD 2006-06-28 #b6440955#
+// Needed to load default bullet list configuration
+#include <unotools/configitem.hxx>
+// <--
+#include <numrule.hxx>
+#include <SwNodeNum.hxx>
+
+#include <hash_map>
+// --> OD 2008-02-19 #refactorlists#
+#include <list.hxx>
+#include <algorithm>
+// <--
+// --> OD 2008-06-06 #i89178#
+#include <unotools/saveopt.hxx>
+// <--
+// --> OD 2008-07-08 #i91400#
+#include <IDocumentListsAccess.hxx>
+// <--
+
+using namespace ::com::sun::star;
+
+
+sal_uInt16 SwNumRule::nRefCount = 0;
+SwNumFmt* SwNumRule::aBaseFmts[ RULE_END ][ MAXLEVEL ] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
+// --> OD 2008-02-11 #newlistlevelattrs#
+SwNumFmt* SwNumRule::aLabelAlignmentBaseFmts[ RULE_END ][ MAXLEVEL ] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
+
+char sOutline[] = "Outline";
+char* SwNumRule::pDefOutlineName = sOutline;
+
+// #i30312#
+sal_uInt16 SwNumRule::aDefNumIndents[ MAXLEVEL ] = {
+//inch: 0,5 1,0 1,5 2,0 2,5 3,0 3,5 4,0 4,5 5,0
+ 1440/4, 1440/2, 1440*3/4, 1440, 1440*5/4, 1440*3/2, 1440*7/4, 1440*2,
+ 1440*9/4, 1440*5/2
+};
+
+const SwNumFmt& SwNumRule::Get( sal_uInt16 i ) const
+{
+ ASSERT_ID( i < MAXLEVEL && eRuleType < RULE_END, ERR_NUMLEVEL);
+ return aFmts[ i ]
+ ? *aFmts[ i ]
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ : ( meDefaultNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
+ ? *aBaseFmts[ eRuleType ][ i ]
+ : *aLabelAlignmentBaseFmts[ eRuleType ][ i ] );
+ // <--
+}
+
+const SwNumFmt* SwNumRule::GetNumFmt( sal_uInt16 i ) const
+{
+ const SwNumFmt * pResult = NULL;
+
+ ASSERT_ID( i < MAXLEVEL && eRuleType < RULE_END, ERR_NUMLEVEL);
+ if ( i < MAXLEVEL && eRuleType < RULE_END)
+ {
+ pResult = aFmts[ i ];
+ }
+
+ return pResult;
+}
+
+// --> OD 2008-07-08 #i91400#
+void SwNumRule::SetName( const String & rName,
+ IDocumentListsAccess& rDocListAccess)
+// <--
+{
+ if ( sName != rName )
+ {
+ if (pNumRuleMap)
+ {
+ pNumRuleMap->erase(sName);
+ (*pNumRuleMap)[rName] = this;
+
+ // --> OD 2008-07-08 #i91400#
+ if ( GetDefaultListId().Len() > 0 )
+ {
+ rDocListAccess.trackChangeOfListStyleName( sName, rName );
+ }
+ // <--
+ }
+
+ sName = rName;
+ }
+}
+
+// --> OD 2008-02-19 #refactorlists#
+void SwNumRule::GetTxtNodeList( SwNumRule::tTxtNodeList& rTxtNodeList ) const
+{
+ rTxtNodeList = maTxtNodeList;
+}
+
+SwNumRule::tTxtNodeList::size_type SwNumRule::GetTxtNodeListSize() const
+{
+ return maTxtNodeList.size();
+}
+
+void SwNumRule::AddTxtNode( SwTxtNode& rTxtNode )
+{
+ tTxtNodeList::iterator aIter =
+ std::find( maTxtNodeList.begin(), maTxtNodeList.end(), &rTxtNode );
+
+ if ( aIter == maTxtNodeList.end() )
+ {
+ maTxtNodeList.push_back( &rTxtNode );
+ }
+}
+
+void SwNumRule::RemoveTxtNode( SwTxtNode& rTxtNode )
+{
+ tTxtNodeList::iterator aIter =
+ std::find( maTxtNodeList.begin(), maTxtNodeList.end(), &rTxtNode );
+
+ if ( aIter != maTxtNodeList.end() )
+ {
+ maTxtNodeList.erase( aIter );
+ }
+}
+// <--
+
+void SwNumRule::SetNumRuleMap(std::hash_map<String, SwNumRule *, StringHash> *
+ _pNumRuleMap)
+{
+ pNumRuleMap = _pNumRuleMap;
+}
+
+sal_uInt16 SwNumRule::GetNumIndent( sal_uInt8 nLvl )
+{
+ ASSERT( MAXLEVEL > nLvl, "NumLevel is out of range" );
+ return aDefNumIndents[ nLvl ];
+}
+
+sal_uInt16 SwNumRule::GetBullIndent( sal_uInt8 nLvl )
+{
+ ASSERT( MAXLEVEL > nLvl, "NumLevel is out of range" );
+ return aDefNumIndents[ nLvl ];
+}
+
+
+
+static void lcl_SetRuleChgd( SwTxtNode& rNd, sal_uInt8 nLevel )
+{
+ if( rNd.GetActualListLevel() == nLevel )
+ rNd.NumRuleChgd();
+}
+/* -----------------------------22.02.01 13:41--------------------------------
+
+ ---------------------------------------------------------------------------*/
+SwNumFmt::SwNumFmt() :
+ SvxNumberFormat(SVX_NUM_ARABIC),
+ SwClient( 0 ),
+ pVertOrient(new SwFmtVertOrient( 0, text::VertOrientation::NONE))
+{
+}
+/* -----------------------------22.02.01 13:42--------------------------------
+
+ ---------------------------------------------------------------------------*/
+SwNumFmt::SwNumFmt( const SwNumFmt& rFmt) :
+ SvxNumberFormat(rFmt),
+ SwClient( rFmt.pRegisteredIn ),
+ pVertOrient(new SwFmtVertOrient( 0, rFmt.GetVertOrient()))
+{
+ sal_Int16 eMyVertOrient = rFmt.GetVertOrient();
+ SetGraphicBrush( rFmt.GetBrush(), &rFmt.GetGraphicSize(),
+ &eMyVertOrient);
+}
+/* -----------------------------22.02.01 13:58--------------------------------
+
+ ---------------------------------------------------------------------------*/
+SwNumFmt::SwNumFmt(const SvxNumberFormat& rNumFmt, SwDoc* pDoc) :
+ SvxNumberFormat(rNumFmt),
+ pVertOrient(new SwFmtVertOrient( 0, rNumFmt.GetVertOrient()))
+{
+ sal_Int16 eMyVertOrient = rNumFmt.GetVertOrient();
+ SetGraphicBrush( rNumFmt.GetBrush(), &rNumFmt.GetGraphicSize(),
+ &eMyVertOrient);
+ const String& rCharStyleName = rNumFmt.SvxNumberFormat::GetCharFmtName();
+ if( rCharStyleName.Len() )
+ {
+ SwCharFmt* pCFmt = pDoc->FindCharFmtByName( rCharStyleName );
+ if( !pCFmt )
+ {
+ sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( rCharStyleName,
+ nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
+ pCFmt = nId != USHRT_MAX
+ ? pDoc->GetCharFmtFromPool( nId )
+ : pDoc->MakeCharFmt( rCharStyleName, 0 );
+ }
+ pCFmt->Add( this );
+ }
+ else if( GetRegisteredIn() )
+ pRegisteredIn->Remove( this );
+
+}
+/* -----------------------------22.02.01 13:42--------------------------------
+
+ ---------------------------------------------------------------------------*/
+SwNumFmt::~SwNumFmt()
+{
+ delete pVertOrient;
+}
+/* -----------------------------02.07.01 15:37--------------------------------
+
+ ---------------------------------------------------------------------------*/
+void SwNumFmt::NotifyGraphicArrived()
+{
+ if( GetCharFmt() )
+ UpdateNumNodes( (SwDoc*)GetCharFmt()->GetDoc() );
+}
+
+// #i22362#
+sal_Bool SwNumFmt::IsEnumeration() const
+{
+ // --> FME 2004-08-12 #i30655# native numbering did not work any longer
+ // using this code. Therefore HBRINKM and I agreed upon defining
+ // IsEnumeration() as !IsItemize()
+ return !IsItemize();
+ // <--
+
+ /*
+ sal_Bool bResult;
+
+ switch(GetNumberingType())
+ {
+ case SVX_NUM_CHARS_UPPER_LETTER:
+ case SVX_NUM_CHARS_LOWER_LETTER:
+ case SVX_NUM_ROMAN_UPPER:
+ case SVX_NUM_ROMAN_LOWER:
+ case SVX_NUM_ARABIC:
+ case SVX_NUM_PAGEDESC:
+ case SVX_NUM_CHARS_UPPER_LETTER_N:
+ case SVX_NUM_CHARS_LOWER_LETTER_N:
+ bResult = sal_True;
+
+ break;
+
+ default:
+ bResult = sal_False;
+ }
+
+ return bResult;
+ */
+}
+
+// #i29560#
+sal_Bool SwNumFmt::IsItemize() const
+{
+ sal_Bool bResult;
+
+ switch(GetNumberingType())
+ {
+ case SVX_NUM_CHAR_SPECIAL:
+ case SVX_NUM_BITMAP:
+ bResult = sal_True;
+
+ break;
+
+ default:
+ bResult = sal_False;
+ }
+
+ return bResult;
+
+}
+
+
+/* -----------------------------23.02.01 09:28--------------------------------
+
+ ---------------------------------------------------------------------------*/
+SwNumFmt& SwNumFmt::operator=( const SwNumFmt& rNumFmt)
+{
+ SvxNumberFormat::operator=(rNumFmt);
+ if( rNumFmt.GetRegisteredIn() )
+ rNumFmt.pRegisteredIn->Add( this );
+ else if( GetRegisteredIn() )
+ pRegisteredIn->Remove( this );
+ return *this;
+}
+/* -----------------------------23.02.01 09:28--------------------------------
+
+ ---------------------------------------------------------------------------*/
+sal_Bool SwNumFmt::operator==( const SwNumFmt& rNumFmt) const
+{
+ sal_Bool bRet = SvxNumberFormat::operator==(rNumFmt) &&
+ pRegisteredIn == rNumFmt.pRegisteredIn;
+ return bRet;
+}
+
+/* -----------------------------22.02.01 13:44--------------------------------
+
+ ---------------------------------------------------------------------------*/
+void SwNumFmt::SetCharFmt( SwCharFmt* pChFmt)
+{
+ if( pChFmt )
+ pChFmt->Add( this );
+ else if( GetRegisteredIn() )
+ pRegisteredIn->Remove( this );
+}
+/* -----------------------------22.02.01 13:45--------------------------------
+
+ ---------------------------------------------------------------------------*/
+void SwNumFmt::Modify( SfxPoolItem* pOld, SfxPoolItem* pNew )
+{
+ // dann suche mal in dem Doc nach dem NumRules-Object, in dem dieses
+ // NumFormat gesetzt ist. Das Format muss es nicht geben!
+ const SwCharFmt* pFmt = 0;
+ switch( pOld ? pOld->Which() : pNew ? pNew->Which() : 0 )
+ {
+ case RES_ATTRSET_CHG:
+ case RES_FMT_CHG:
+ pFmt = GetCharFmt();
+ break;
+ }
+
+ if( pFmt && !pFmt->GetDoc()->IsInDtor() )
+ UpdateNumNodes( (SwDoc*)pFmt->GetDoc() );
+ else
+ SwClient::Modify( pOld, pNew );
+}
+/* -----------------------------23.02.01 11:08--------------------------------
+
+ ---------------------------------------------------------------------------*/
+void SwNumFmt::SetCharFmtName(const String& rSet)
+{
+ SvxNumberFormat::SetCharFmtName(rSet);
+}
+/* -----------------------------22.02.01 13:47--------------------------------
+
+ ---------------------------------------------------------------------------*/
+const String& SwNumFmt::GetCharFmtName() const
+{
+ if((SwCharFmt*)pRegisteredIn)
+ return ((SwCharFmt*)pRegisteredIn)->GetName();
+ else
+ return aEmptyStr;
+}
+/* -----------------------------22.02.01 16:05--------------------------------
+
+ ---------------------------------------------------------------------------*/
+void SwNumFmt::SetGraphicBrush( const SvxBrushItem* pBrushItem, const Size* pSize,
+ const sal_Int16* pOrient)
+{
+ if(pOrient)
+ pVertOrient->SetVertOrient( *pOrient );
+ SvxNumberFormat::SetGraphicBrush( pBrushItem, pSize, pOrient);
+}
+/* -----------------------------22.02.01 16:05--------------------------------
+
+ ---------------------------------------------------------------------------*/
+void SwNumFmt::SetVertOrient(sal_Int16 eSet)
+{
+ SvxNumberFormat::SetVertOrient(eSet);
+}
+/* -----------------------------22.02.01 16:05--------------------------------
+
+ ---------------------------------------------------------------------------*/
+sal_Int16 SwNumFmt::GetVertOrient() const
+{
+ return SvxNumberFormat::GetVertOrient();
+}
+/* -----------------------------22.02.01 13:54--------------------------------
+
+ ---------------------------------------------------------------------------*/
+void SwNumFmt::UpdateNumNodes( SwDoc* pDoc )
+{
+ sal_Bool bDocIsModified = pDoc->IsModified();
+ sal_Bool bFnd = sal_False;
+ const SwNumRule* pRule;
+ for( sal_uInt16 n = pDoc->GetNumRuleTbl().Count(); !bFnd && n; )
+ {
+ pRule = pDoc->GetNumRuleTbl()[ --n ];
+ for( sal_uInt8 i = 0; i < MAXLEVEL; ++i )
+ if( pRule->GetNumFmt( i ) == this )
+ {
+ // --> OD 2008-02-19 #refactorlists#
+// const String& rRuleNm = pRule->GetName();
+
+// SwModify* pMod;
+// const SfxPoolItem* pItem;
+// sal_uInt16 k, nMaxItems = pDoc->GetAttrPool().GetItemCount(
+// RES_PARATR_NUMRULE );
+// for( k = 0; k < nMaxItems; ++k )
+// if( 0 != (pItem = pDoc->GetAttrPool().GetItem(
+// RES_PARATR_NUMRULE, k ) ) &&
+// 0 != ( pMod = (SwModify*)((SwNumRuleItem*)pItem)->
+// GetDefinedIn()) &&
+// ((SwNumRuleItem*)pItem)->GetValue() == rRuleNm )
+// {
+// if( pMod->IsA( TYPE( SwFmt )) )
+// {
+// SwNumRuleInfo aInfo( rRuleNm );
+// pMod->GetInfo( aInfo );
+
+// for( sal_uLong nFirst = 0, nLast = aInfo.GetList().Count();
+// nFirst < nLast; ++nFirst )
+// lcl_SetRuleChgd(
+// *aInfo.GetList().GetObject( nFirst ), i );
+// }
+// else if( ((SwTxtNode*)pMod)->GetNodes().IsDocNodes() )
+// lcl_SetRuleChgd( *(SwTxtNode*)pMod, i );
+// }
+ SwNumRule::tTxtNodeList aTxtNodeList;
+ pRule->GetTxtNodeList( aTxtNodeList );
+ for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
+ aIter != aTxtNodeList.end(); ++aIter )
+ {
+ lcl_SetRuleChgd( *(*aIter), i );
+ }
+ // <--
+ bFnd = sal_True;
+ break;
+ }
+ }
+
+ if( bFnd && !bDocIsModified )
+ pDoc->ResetModified();
+}
+/* -----------------------------31.05.01 16:08--------------------------------
+
+ ---------------------------------------------------------------------------*/
+const SwFmtVertOrient* SwNumFmt::GetGraphicOrientation() const
+{
+ sal_Int16 eOrient = SvxNumberFormat::GetVertOrient();
+ if(text::VertOrientation::NONE == eOrient)
+ return 0;
+ else
+ {
+ pVertOrient->SetVertOrient(eOrient);
+ return pVertOrient;
+ }
+}
+
+#ifdef DBG_UTIL
+long int SwNumRule::nInstances = 0;
+#endif
+
+// --> OD 2008-02-11 #newlistlevelattrs#
+// handle new parameter <eDefaultNumberFormatPositionAndSpaceMode>
+SwNumRule::SwNumRule( const String& rNm,
+ const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode,
+ SwNumRuleType eType,
+ sal_Bool bAutoFlg )
+ : maTxtNodeList(),
+ // --> OD 2008-03-03 #refactorlists#
+ maParagraphStyleList(),
+ // <--
+ pNumRuleMap(0),
+ sName( rNm ),
+ eRuleType( eType ),
+ nPoolFmtId( USHRT_MAX ),
+ nPoolHelpId( USHRT_MAX ),
+ nPoolHlpFileId( UCHAR_MAX ),
+ bAutoRuleFlag( bAutoFlg ),
+ bInvalidRuleFlag( sal_True ),
+ bContinusNum( sal_False ),
+ bAbsSpaces( sal_False ),
+ // --> OD 2005-10-21 - initialize member <mbCountPhantoms>
+ mbCountPhantoms( true ),
+ // <--
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ meDefaultNumberFormatPositionAndSpaceMode( eDefaultNumberFormatPositionAndSpaceMode ),
+ // <--
+ // --> OD 2008-04-03 #refactorlists#
+ msDefaultListId()
+ // <--
+{
+#ifdef DBG_UTIL
+ nSerial = nInstances++;
+#endif
+
+ if( !nRefCount++ ) // zum erstmal, also initialisiern
+ {
+ SwNumFmt* pFmt;
+ sal_uInt8 n;
+
+ // numbering:
+ // position-and-space mode LABEL_WIDTH_AND_POSITION:
+ for( n = 0; n < MAXLEVEL; ++n )
+ {
+ pFmt = new SwNumFmt;
+ pFmt->SetIncludeUpperLevels( 1 );
+ pFmt->SetStart( 1 );
+ pFmt->SetLSpace( lNumIndent );
+ pFmt->SetAbsLSpace( lNumIndent + SwNumRule::GetNumIndent( n ) );
+ pFmt->SetFirstLineOffset( lNumFirstLineOffset );
+ pFmt->SetSuffix( aDotStr );
+ // --> OD 2006-06-29 #b6440955#
+ pFmt->SetBulletChar( numfunc::GetBulletChar(n));
+ // <--
+ SwNumRule::aBaseFmts[ NUM_RULE ][ n ] = pFmt;
+ }
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ // position-and-space mode LABEL_ALIGNMENT
+ // first line indent of general numbering in inch: -0,25 inch
+ const long cFirstLineIndent = -1440/4;
+ // indent values of general numbering in inch:
+ // 0,5 0,75 1,0 1,25 1,5
+ // 1,75 2,0 2,25 2,5 2,75
+ const long cIndentAt[ MAXLEVEL ] = {
+ 1440/2, 1440*3/4, 1440, 1440*5/4, 1440*3/2,
+ 1440*7/4, 1440*2, 1440*9/4, 1440*5/2, 1440*11/4 };
+ for( n = 0; n < MAXLEVEL; ++n )
+ {
+ pFmt = new SwNumFmt;
+ pFmt->SetIncludeUpperLevels( 1 );
+ pFmt->SetStart( 1 );
+ // --> OD 2008-01-15 #newlistlevelattrs#
+ pFmt->SetPositionAndSpaceMode( SvxNumberFormat::LABEL_ALIGNMENT );
+ pFmt->SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ pFmt->SetListtabPos( cIndentAt[ n ] );
+ pFmt->SetFirstLineIndent( cFirstLineIndent );
+ pFmt->SetIndentAt( cIndentAt[ n ] );
+ // <--
+ pFmt->SetSuffix( aDotStr );
+ pFmt->SetBulletChar( numfunc::GetBulletChar(n));
+ SwNumRule::aLabelAlignmentBaseFmts[ NUM_RULE ][ n ] = pFmt;
+ }
+ // <--
+
+ // outline:
+ // position-and-space mode LABEL_WIDTH_AND_POSITION:
+ for( n = 0; n < MAXLEVEL; ++n )
+ {
+ pFmt = new SwNumFmt;
+ pFmt->SetNumberingType(SVX_NUM_NUMBER_NONE);
+ pFmt->SetIncludeUpperLevels( MAXLEVEL );
+ pFmt->SetStart( 1 );
+ pFmt->SetCharTextDistance( lOutlineMinTextDistance );
+ // --> OD 2006-06-29 #b6440955#
+ pFmt->SetBulletChar( numfunc::GetBulletChar(n));
+ // <--
+ SwNumRule::aBaseFmts[ OUTLINE_RULE ][ n ] = pFmt;
+ }
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ // position-and-space mode LABEL_ALIGNMENT:
+ // indent values of default outline numbering in inch:
+ // 0,3 0,4 0,5 0,6 0,7
+ // 0,8 0,9 1,0 1,1 1,2
+ const long cOutlineIndentAt[ MAXLEVEL ] = {
+ 1440*3/10, 1440*2/5, 1440/2, 1440*3/5, 1440*7/10,
+ 1440*4/5, 1440*9/10, 1440, 1440*11/10, 1440*6/5 };
+ for( n = 0; n < MAXLEVEL; ++n )
+ {
+ pFmt = new SwNumFmt;
+ pFmt->SetNumberingType(SVX_NUM_NUMBER_NONE);
+ pFmt->SetIncludeUpperLevels( MAXLEVEL );
+ pFmt->SetStart( 1 );
+ pFmt->SetPositionAndSpaceMode( SvxNumberFormat::LABEL_ALIGNMENT );
+ pFmt->SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ pFmt->SetListtabPos( cOutlineIndentAt[ n ] );
+ pFmt->SetFirstLineIndent( -cOutlineIndentAt[ n ] );
+ pFmt->SetIndentAt( cOutlineIndentAt[ n ] );
+ pFmt->SetBulletChar( numfunc::GetBulletChar(n));
+ SwNumRule::aLabelAlignmentBaseFmts[ OUTLINE_RULE ][ n ] = pFmt;
+ }
+ // <--
+ }
+ memset( aFmts, 0, sizeof( aFmts ));
+ ASSERT( sName.Len(), "NumRule ohne Namen!" );
+}
+
+SwNumRule::SwNumRule( const SwNumRule& rNumRule )
+ : maTxtNodeList(),
+ // --> OD 2008-03-03 #refactorlists#
+ maParagraphStyleList(),
+ // <--
+ pNumRuleMap(0),
+ sName( rNumRule.sName ),
+ eRuleType( rNumRule.eRuleType ),
+ nPoolFmtId( rNumRule.GetPoolFmtId() ),
+ nPoolHelpId( rNumRule.GetPoolHelpId() ),
+ nPoolHlpFileId( rNumRule.GetPoolHlpFileId() ),
+ bAutoRuleFlag( rNumRule.bAutoRuleFlag ),
+ bInvalidRuleFlag( sal_True ),
+ bContinusNum( rNumRule.bContinusNum ),
+ bAbsSpaces( rNumRule.bAbsSpaces ),
+ // --> OD 2005-10-21 - initialize member <mbCountPhantoms>
+ mbCountPhantoms( true ),
+ // <--
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ meDefaultNumberFormatPositionAndSpaceMode( rNumRule.meDefaultNumberFormatPositionAndSpaceMode ),
+ // <--
+ // --> OD 2008-04-03 #refactorlists#
+ msDefaultListId( rNumRule.msDefaultListId )
+ // <--
+{
+#ifdef DBG_UTIL
+ nSerial = nInstances++;
+#endif
+
+ ++nRefCount;
+ memset( aFmts, 0, sizeof( aFmts ));
+ for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
+ if( rNumRule.aFmts[ n ] )
+ Set( n, *rNumRule.aFmts[ n ] );
+}
+
+SwNumRule::~SwNumRule()
+{
+ for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
+ delete aFmts[ n ];
+
+ if (pNumRuleMap)
+ {
+ pNumRuleMap->erase(GetName());
+ }
+
+ if( !--nRefCount ) // der letzte macht die Tuer zu
+ {
+ // Nummerierung:
+ SwNumFmt** ppFmts = (SwNumFmt**)SwNumRule::aBaseFmts;
+ int n;
+
+ for( n = 0; n < MAXLEVEL; ++n, ++ppFmts )
+ delete *ppFmts, *ppFmts = 0;
+
+ // Gliederung:
+ for( n = 0; n < MAXLEVEL; ++n, ++ppFmts )
+ delete *ppFmts, *ppFmts = 0;
+
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ ppFmts = (SwNumFmt**)SwNumRule::aLabelAlignmentBaseFmts;
+ for( n = 0; n < MAXLEVEL; ++n, ++ppFmts )
+ delete *ppFmts, *ppFmts = 0;
+ for( n = 0; n < MAXLEVEL; ++n, ++ppFmts )
+ delete *ppFmts, *ppFmts = 0;
+ // <--
+ }
+
+ // --> OD 2008-02-19 #refactorlists#
+ maTxtNodeList.clear();
+ maParagraphStyleList.clear();
+ // <--
+}
+
+void SwNumRule::CheckCharFmts( SwDoc* pDoc )
+{
+ SwCharFmt* pFmt;
+ for( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
+ if( aFmts[ n ] && 0 != ( pFmt = aFmts[ n ]->GetCharFmt() ) &&
+ pFmt->GetDoc() != pDoc )
+ {
+ // dann kopieren!
+ SwNumFmt* pNew = new SwNumFmt( *aFmts[ n ] );
+ pNew->SetCharFmt( pDoc->CopyCharFmt( *pFmt ) );
+ delete aFmts[ n ];
+ aFmts[ n ] = pNew;
+ }
+}
+
+SwNumRule& SwNumRule::operator=( const SwNumRule& rNumRule )
+{
+ if( this != &rNumRule )
+ {
+ for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
+ Set( n, rNumRule.aFmts[ n ] );
+
+ eRuleType = rNumRule.eRuleType;
+ sName = rNumRule.sName;
+ bAutoRuleFlag = rNumRule.bAutoRuleFlag;
+ bInvalidRuleFlag = sal_True;
+ bContinusNum = rNumRule.bContinusNum;
+ bAbsSpaces = rNumRule.bAbsSpaces;
+ nPoolFmtId = rNumRule.GetPoolFmtId();
+ nPoolHelpId = rNumRule.GetPoolHelpId();
+ nPoolHlpFileId = rNumRule.GetPoolHlpFileId();
+ }
+ return *this;
+}
+
+
+sal_Bool SwNumRule::operator==( const SwNumRule& rRule ) const
+{
+ sal_Bool bRet = eRuleType == rRule.eRuleType &&
+ sName == rRule.sName &&
+ bAutoRuleFlag == rRule.bAutoRuleFlag &&
+ bContinusNum == rRule.bContinusNum &&
+ bAbsSpaces == rRule.bAbsSpaces &&
+ nPoolFmtId == rRule.GetPoolFmtId() &&
+ nPoolHelpId == rRule.GetPoolHelpId() &&
+ nPoolHlpFileId == rRule.GetPoolHlpFileId();
+ if( bRet )
+ {
+ for( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
+ if( !( rRule.Get( n ) == Get( n ) ))
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ return bRet;
+}
+
+
+void SwNumRule::Set( sal_uInt16 i, const SwNumFmt& rNumFmt )
+{
+ ASSERT( i < MAXLEVEL, "Serious defect, please inform OD" )
+ if( i < MAXLEVEL )
+ {
+ if( !aFmts[ i ] || !(rNumFmt == Get( i )) )
+ {
+ delete aFmts[ i ];
+ aFmts[ i ] = new SwNumFmt( rNumFmt );
+ bInvalidRuleFlag = sal_True;
+ }
+ }
+}
+
+void SwNumRule::Set( sal_uInt16 i, const SwNumFmt* pNumFmt )
+{
+ ASSERT( i < MAXLEVEL, "Serious defect, please inform OD" )
+ if( i >= MAXLEVEL )
+ return;
+ SwNumFmt* pOld = aFmts[ i ];
+ if( !pOld )
+ {
+ if( pNumFmt )
+ {
+ aFmts[ i ] = new SwNumFmt( *pNumFmt );
+ bInvalidRuleFlag = sal_True;
+ }
+ }
+ else if( !pNumFmt )
+ delete pOld, aFmts[ i ] = 0, bInvalidRuleFlag = sal_True;
+ else if( *pOld != *pNumFmt )
+ *pOld = *pNumFmt, bInvalidRuleFlag = sal_True;
+}
+
+
+String SwNumRule::MakeNumString( const SwNodeNum& rNum, sal_Bool bInclStrings,
+ sal_Bool bOnlyArabic ) const
+{
+ String aStr;
+
+ if (rNum.IsCounted())
+ aStr = MakeNumString(rNum.GetNumberVector(),
+ bInclStrings, bOnlyArabic, MAXLEVEL);
+
+ return aStr;
+}
+
+String SwNumRule::MakeNumString( const SwNumberTree::tNumberVector & rNumVector,
+ const sal_Bool bInclStrings,
+ const sal_Bool bOnlyArabic,
+ const unsigned int _nRestrictToThisLevel ) const
+{
+ String aStr;
+
+ unsigned int nLevel = rNumVector.size() - 1;
+ // --> OD 2005-10-17 #126238#
+ if ( nLevel > _nRestrictToThisLevel )
+ {
+ nLevel = _nRestrictToThisLevel;
+ }
+ // <--
+
+ if (nLevel < MAXLEVEL)
+ {
+ const SwNumFmt& rMyNFmt = Get( static_cast<sal_uInt16>(nLevel) );
+ // --> OD 2006-06-02 #b6432095#
+ // - levels with numbering none has to provide prefix and suffix string
+// if( SVX_NUM_NUMBER_NONE != rMyNFmt.GetNumberingType() )
+ // <--
+ {
+ sal_uInt8 i = static_cast<sal_uInt8>(nLevel);
+
+ if( !IsContinusNum() &&
+ // --> OD 2006-09-19 #i69672#
+ // - do not include upper levels, if level isn't numbered.
+ rMyNFmt.GetNumberingType() != SVX_NUM_NUMBER_NONE &&
+ // <--
+ rMyNFmt.GetIncludeUpperLevels() ) // nur der eigene Level ?
+ {
+ sal_uInt8 n = rMyNFmt.GetIncludeUpperLevels();
+ if( 1 < n )
+ {
+ if( i+1 >= n )
+ i -= n - 1;
+ else
+ i = 0;
+ }
+ }
+
+ for( ; i <= nLevel; ++i )
+ {
+ const SwNumFmt& rNFmt = Get( i );
+ if( SVX_NUM_NUMBER_NONE == rNFmt.GetNumberingType() )
+ {
+ // Soll aus 1.1.1 --> 2. NoNum --> 1..1 oder 1.1 ??
+ // if( i != rNum.nMyLevel )
+ // aStr += aDotStr;
+ continue;
+ }
+
+ if( rNumVector[ i ] )
+ {
+ if( bOnlyArabic )
+ aStr += String::CreateFromInt32( rNumVector[ i ] );
+ else
+ aStr += rNFmt.GetNumStr( rNumVector[ i ] );
+ }
+ else
+ aStr += '0'; // alle 0-Level sind eine 0
+ if( i != nLevel && aStr.Len() )
+ aStr += aDotStr;
+ }
+
+ //JP 14.12.99: the type dont have any number, so dont append
+ // the Post-/Prefix String
+ if( bInclStrings && !bOnlyArabic &&
+ SVX_NUM_CHAR_SPECIAL != rMyNFmt.GetNumberingType() &&
+ SVX_NUM_BITMAP != rMyNFmt.GetNumberingType() )
+ {
+ aStr.Insert( rMyNFmt.GetPrefix(), 0 );
+ aStr += rMyNFmt.GetSuffix();
+ }
+ }
+ }
+
+ return aStr;
+}
+
+// --> OD 2007-09-07 #i81002#
+String SwNumRule::MakeRefNumString( const SwNodeNum& rNodeNum,
+ const bool bInclSuperiorNumLabels,
+ const sal_uInt8 nRestrictInclToThisLevel ) const
+{
+ String aRefNumStr;
+
+ if ( rNodeNum.GetLevelInListTree() >= 0 )
+ {
+ const SwNodeNum* pWorkingNodeNum( &rNodeNum );
+ do
+ {
+ bool bMakeNumStringForPhantom( false );
+ if ( pWorkingNodeNum->IsPhantom() )
+ {
+ SwNumFmt aFmt( Get( static_cast<sal_uInt16>(pWorkingNodeNum->GetLevelInListTree()) ) );
+ bMakeNumStringForPhantom = aFmt.IsEnumeration() &&
+ SVX_NUM_NUMBER_NONE != aFmt.GetNumberingType();
+
+ }
+ if ( bMakeNumStringForPhantom ||
+ ( !pWorkingNodeNum->IsPhantom() &&
+ pWorkingNodeNum->GetTxtNode() &&
+ pWorkingNodeNum->GetTxtNode()->HasNumber() ) )
+ {
+ aRefNumStr.Insert( MakeNumString( pWorkingNodeNum->GetNumberVector() ), 0 );
+ }
+ else if ( aRefNumStr.Len() > 0 )
+ {
+ aRefNumStr.Insert( String::CreateFromAscii(" "), 0 );
+ }
+
+ if ( bInclSuperiorNumLabels && pWorkingNodeNum->GetLevelInListTree() > 0 )
+ {
+ sal_uInt8 n = Get( static_cast<sal_uInt16>(pWorkingNodeNum->GetLevelInListTree()) ).GetIncludeUpperLevels();
+ pWorkingNodeNum = dynamic_cast<SwNodeNum*>(pWorkingNodeNum->GetParent());
+ // skip parents, whose list label is already contained in the actual list label.
+ while ( pWorkingNodeNum && n > 1 )
+ {
+ pWorkingNodeNum = dynamic_cast<SwNodeNum*>(pWorkingNodeNum->GetParent());
+ --n;
+ }
+ }
+ else
+ {
+ break;
+ }
+ } while ( pWorkingNodeNum &&
+ pWorkingNodeNum->GetLevelInListTree() >= 0 &&
+ static_cast<sal_uInt8>(pWorkingNodeNum->GetLevelInListTree()) >= nRestrictInclToThisLevel );
+ }
+
+ return aRefNumStr;
+}
+
+// ----- Copy-Methode vom SwNumRule ------
+
+ // eine Art Copy-Constructor, damit die Num-Formate auch an den
+ // richtigen CharFormaten eines Dokumentes haengen !!
+ // (Kopiert die NumFormate und returnt sich selbst)
+
+SwNumRule& SwNumRule::CopyNumRule( SwDoc* pDoc, const SwNumRule& rNumRule )
+{
+ for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
+ {
+ Set( n, rNumRule.aFmts[ n ] );
+ if( aFmts[ n ] && aFmts[ n ]->GetCharFmt() &&
+ USHRT_MAX == pDoc->GetCharFmts()->GetPos( aFmts[n]->GetCharFmt() ))
+ // ueber unterschiedliche Dokumente kopieren, dann
+ // kopiere das entsprechende Char-Format ins neue
+ // Dokument.
+ aFmts[n]->SetCharFmt( pDoc->CopyCharFmt( *aFmts[n]->
+ GetCharFmt() ) );
+ }
+ eRuleType = rNumRule.eRuleType;
+ sName = rNumRule.sName;
+ bAutoRuleFlag = rNumRule.bAutoRuleFlag;
+ nPoolFmtId = rNumRule.GetPoolFmtId();
+ nPoolHelpId = rNumRule.GetPoolHelpId();
+ nPoolHlpFileId = rNumRule.GetPoolHlpFileId();
+ bInvalidRuleFlag = sal_True;
+ return *this;
+}
+/* -----------------30.10.98 08:33-------------------
+ *
+ * --------------------------------------------------*/
+void SwNumRule::SetSvxRule(const SvxNumRule& rNumRule, SwDoc* pDoc)
+{
+ for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
+ {
+ const SvxNumberFormat* pSvxFmt = rNumRule.Get(n);
+ delete aFmts[n];
+ aFmts[n] = pSvxFmt ? new SwNumFmt(*pSvxFmt, pDoc) : 0;
+ }
+
+ bInvalidRuleFlag = sal_True;
+ bContinusNum = rNumRule.IsContinuousNumbering();
+}
+/* -----------------30.10.98 08:33-------------------
+ *
+ * --------------------------------------------------*/
+SvxNumRule SwNumRule::MakeSvxNumRule() const
+{
+ SvxNumRule aRule(NUM_CONTINUOUS|NUM_CHAR_TEXT_DISTANCE|NUM_CHAR_STYLE|
+ NUM_ENABLE_LINKED_BMP|NUM_ENABLE_EMBEDDED_BMP,
+ MAXLEVEL, bContinusNum,
+ eRuleType ==
+ NUM_RULE ?
+ SVX_RULETYPE_NUMBERING :
+ SVX_RULETYPE_OUTLINE_NUMBERING );
+ for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
+ {
+ SwNumFmt aNumFmt = Get(n);
+ if(aNumFmt.GetCharFmt())
+ aNumFmt.SetCharFmtName(aNumFmt.GetCharFmt()->GetName());
+ aRule.SetLevel(n, aNumFmt, aFmts[n] != 0);
+ }
+ return aRule;
+}
+
+void SwNumRule::SetInvalidRule(sal_Bool bFlag)
+{
+ if (bFlag)
+ {
+ // --> OD 2008-03-13 #refactorlists#
+// tPamAndNums::iterator aIt;
+// for (aIt = aNumberRanges.begin(); aIt != aNumberRanges.end(); aIt++)
+// (*aIt).second->InvalidateTree();
+ std::set< SwList* > aLists;
+ tTxtNodeList::iterator aIter;
+ for ( aIter = maTxtNodeList.begin(); aIter != maTxtNodeList.end(); ++aIter )
+ {
+ const SwTxtNode* pTxtNode = *aIter;
+ // --> OD 2010-06-04 #i111681# - applying patch from cmc
+// aLists.insert( pTxtNode->GetDoc()->getListByName( pTxtNode->GetListId() ) );
+ SwList* pList = pTxtNode->GetDoc()->getListByName( pTxtNode->GetListId() );
+ ASSERT( pList, "<SwNumRule::SetInvalidRule(..)> - list at which the text node is registered at does not exist. This is a serious issue --> please inform OD.");
+ if ( pList )
+ {
+ aLists.insert( pList );
+ }
+ // <--
+ }
+ std::for_each( aLists.begin(), aLists.end(),
+ std::mem_fun( &SwList::InvalidateListTree ) );
+ // <--
+ }
+
+ bInvalidRuleFlag = bFlag;
+}
+
+// --> OD 2008-06-16 #i90078#
+// #i23725#, #i23726#
+//void SwNumRule::Indent(short nAmount, int nLevel, int nReferenceLevel,
+// sal_Bool bRelative, sal_Bool bFirstLine, sal_Bool bCheckGtZero)
+//{
+// int nStartLevel = 0;
+// int nEndLevel = MAXLEVEL - 1;
+// sal_Bool bGotInvalid = sal_False;
+
+// if (nLevel >= 0)
+// nStartLevel = nEndLevel = nLevel;
+
+// int i;
+// short nRealAmount = nAmount;
+
+// if (! bRelative)
+// {
+// if (bFirstLine)
+// {
+// if (nReferenceLevel >= 0)
+// nAmount = nAmount - Get(static_cast<sal_uInt16>(nReferenceLevel)).GetFirstLineOffset();
+// else
+// nAmount = nAmount - Get(static_cast<sal_uInt16>(nStartLevel)).GetFirstLineOffset();
+// }
+
+// sal_Bool bFirst = sal_True;
+
+// if (nReferenceLevel >= 0)
+// nRealAmount = nAmount - Get(static_cast<sal_uInt16>(nReferenceLevel)).GetAbsLSpace();
+// else
+// for (i = nStartLevel; i < nEndLevel + 1; i++)
+// {
+// short nTmp = nAmount - Get(static_cast<sal_uInt16>(i)).GetAbsLSpace();
+
+// if (bFirst || nTmp > nRealAmount)
+// {
+// nRealAmount = nTmp;
+// bFirst = sal_False;
+// }
+// }
+// }
+
+// if (nRealAmount < 0)
+// for (i = nStartLevel; i < nEndLevel + 1; i++)
+// if (Get(static_cast<sal_uInt16>(i)).GetAbsLSpace() + nRealAmount < 0)
+// nRealAmount = -Get(static_cast<sal_uInt16>(i)).GetAbsLSpace();
+
+// for (i = nStartLevel; i < nEndLevel + 1; i++)
+// {
+// short nNew = Get(static_cast<sal_uInt16>(i)).GetAbsLSpace() + nRealAmount;
+
+// if (bCheckGtZero && nNew < 0)
+// nNew = 0;
+
+// SwNumFmt aTmpNumFmt(Get(static_cast<sal_uInt16>(i)));
+// aTmpNumFmt.SetAbsLSpace(nNew);
+
+// Set(static_cast<sal_uInt16>(i), aTmpNumFmt);
+
+// bGotInvalid = sal_True;
+// }
+
+// if (bGotInvalid)
+// SetInvalidRule(bGotInvalid);
+//}
+
+// change indent of all list levels by given difference
+void SwNumRule::ChangeIndent( const short nDiff )
+{
+ for ( sal_uInt16 i = 0; i < MAXLEVEL; ++i )
+ {
+ SwNumFmt aTmpNumFmt( Get(i) );
+
+ const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
+ aTmpNumFmt.GetPositionAndSpaceMode() );
+ if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ short nNewIndent = nDiff +
+ aTmpNumFmt.GetAbsLSpace();
+ if ( nNewIndent < 0 )
+ {
+ nNewIndent = 0;
+ }
+ aTmpNumFmt.SetAbsLSpace( nNewIndent );
+ }
+ else if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ // --> OD 2009-01-20 #i93399#
+ // adjust also the list tab position, if a list tab stop is applied
+ if ( aTmpNumFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB )
+ {
+ const long nNewListTab = aTmpNumFmt.GetListtabPos() + nDiff;
+ aTmpNumFmt.SetListtabPos( nNewListTab );
+ }
+ // <--
+ const long nNewIndent = nDiff +
+ aTmpNumFmt.GetIndentAt();
+ aTmpNumFmt.SetIndentAt( nNewIndent );
+ }
+
+ Set( i, aTmpNumFmt );
+ }
+
+ SetInvalidRule( sal_True );
+}
+
+// set indent of certain list level to given value
+void SwNumRule::SetIndent( const short nNewIndent,
+ const sal_uInt16 nListLevel )
+{
+ SwNumFmt aTmpNumFmt( Get(nListLevel) );
+
+ const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
+ aTmpNumFmt.GetPositionAndSpaceMode() );
+ if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aTmpNumFmt.SetAbsLSpace( nNewIndent );
+ }
+ else if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ // --> OD 2009-01-20 #i93399#
+ // adjust also the list tab position, if a list tab stop is applied
+ if ( aTmpNumFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB )
+ {
+ const long nNewListTab = aTmpNumFmt.GetListtabPos() +
+ ( nNewIndent - aTmpNumFmt.GetIndentAt() );
+ aTmpNumFmt.SetListtabPos( nNewListTab );
+ }
+ // <--
+ aTmpNumFmt.SetIndentAt( nNewIndent );
+ }
+
+ SetInvalidRule( sal_True );
+}
+
+// set indent of first list level to given value and change other list level's
+// indents accordingly
+void SwNumRule::SetIndentOfFirstListLevelAndChangeOthers( const short nNewIndent )
+{
+ SwNumFmt aTmpNumFmt( Get(0) );
+
+ short nDiff( 0 );
+ const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
+ aTmpNumFmt.GetPositionAndSpaceMode() );
+ if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ nDiff = nNewIndent
+ - aTmpNumFmt.GetFirstLineOffset()
+ - aTmpNumFmt.GetAbsLSpace();
+ }
+ else if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ nDiff = static_cast<short>(nNewIndent
+ - aTmpNumFmt.GetIndentAt());
+ }
+ if ( nDiff != 0 )
+ {
+ ChangeIndent( nDiff );
+ }
+}
+// <--
+
+void SwNumRule::Validate()
+{
+ // --> OD 2008-03-13 #refactorlists#
+// tPamAndNums::iterator aIt;
+// for (aIt = aNumberRanges.begin(); aIt != aNumberRanges.end(); aIt++)
+// (*aIt).second->NotifyInvalidChildren();
+ std::set< SwList* > aLists;
+ tTxtNodeList::iterator aIter;
+ for ( aIter = maTxtNodeList.begin(); aIter != maTxtNodeList.end(); ++aIter )
+ {
+ const SwTxtNode* pTxtNode = *aIter;
+ aLists.insert( pTxtNode->GetDoc()->getListByName( pTxtNode->GetListId() ) );
+ }
+ std::for_each( aLists.begin(), aLists.end(),
+ std::mem_fun( &SwList::ValidateListTree ) );
+ // <--
+
+ SetInvalidRule(sal_False);
+}
+
+bool SwNumRule::IsCountPhantoms() const
+{
+ return mbCountPhantoms;
+}
+
+void SwNumRule::SetCountPhantoms(bool bCountPhantoms)
+{
+ mbCountPhantoms = bCountPhantoms;
+}
+
+// --> OD 2008-03-03 #refactorlists#
+SwNumRule::tParagraphStyleList::size_type SwNumRule::GetParagraphStyleListSize() const
+{
+ return maParagraphStyleList.size();
+}
+
+void SwNumRule::AddParagraphStyle( SwTxtFmtColl& rTxtFmtColl )
+{
+ tParagraphStyleList::iterator aIter =
+ std::find( maParagraphStyleList.begin(), maParagraphStyleList.end(), &rTxtFmtColl );
+
+ if ( aIter == maParagraphStyleList.end() )
+ {
+ maParagraphStyleList.push_back( &rTxtFmtColl );
+ }
+}
+
+void SwNumRule::RemoveParagraphStyle( SwTxtFmtColl& rTxtFmtColl )
+{
+ tParagraphStyleList::iterator aIter =
+ std::find( maParagraphStyleList.begin(), maParagraphStyleList.end(), &rTxtFmtColl );
+
+ if ( aIter != maParagraphStyleList.end() )
+ {
+ maParagraphStyleList.erase( aIter );
+ }
+}
+// <--
+
+// --> OD 2006-06-27 #b6440955#
+namespace numfunc
+{
+ /** class containing default bullet list configuration data
+
+ @author OD
+ */
+ class SwDefBulletConfig : private utl::ConfigItem
+ {
+ public:
+ static SwDefBulletConfig* getInstance()
+ {
+ if ( mpInstance == 0 )
+ {
+ mpInstance = new SwDefBulletConfig;
+ }
+
+ return mpInstance;
+ }
+
+ inline const String& GetFontname() const
+ {
+ return msFontname;
+ }
+ // --> OD 2008-06-02 #i63395#
+ inline bool IsFontnameUserDefined() const
+ {
+ return mbUserDefinedFontname;
+ }
+ // <--
+ inline const Font& GetFont() const
+ {
+ return *mpFont;
+ }
+ inline short GetFontWeight() const
+ {
+ return static_cast<short>(meFontWeight);
+ }
+ inline short GetFontItalic() const
+ {
+ return static_cast<short>(meFontItalic);
+ }
+ inline sal_Unicode GetChar( sal_uInt8 p_nListLevel ) const
+ {
+ if ( p_nListLevel > MAXLEVEL )
+ {
+ p_nListLevel = MAXLEVEL;
+ }
+
+ return mnLevelChars[p_nListLevel];
+ }
+
+ private:
+ SwDefBulletConfig();
+
+ /** sets internal default bullet configuration data to default values
+
+ @author OD
+ */
+ void SetToDefault();
+
+ /** returns sequence of default bullet configuration property names
+
+ @author OD
+ */
+ uno::Sequence<rtl::OUString> GetPropNames() const;
+
+ /** loads default bullet configuration properties and applies
+ values to internal data
+
+ @author OD
+ */
+ void LoadConfig();
+
+ /** initialize font instance for default bullet list
+
+ @author OD
+ */
+ void InitFont();
+
+ /** catches notification about changed default bullet configuration data
+
+ @author OD
+ */
+ virtual void Notify( const uno::Sequence<rtl::OUString>& aPropertyNames );
+ virtual void Commit();
+
+ static SwDefBulletConfig* mpInstance;
+
+ // default bullet list configuration data
+ String msFontname;
+ // --> OD 2008-06-02 #i63395#
+ bool mbUserDefinedFontname;
+ // <--
+ FontWeight meFontWeight;
+ FontItalic meFontItalic;
+ sal_Unicode mnLevelChars[MAXLEVEL];
+
+ // default bullet list font instance
+ Font* mpFont;
+ };
+
+ SwDefBulletConfig* SwDefBulletConfig::mpInstance = 0;
+
+ SwDefBulletConfig::SwDefBulletConfig()
+ : ConfigItem( rtl::OUString::createFromAscii("Office.Writer/Numbering/DefaultBulletList") ),
+ // --> OD 2008-06-02 #i63395#
+ // default bullet font is now OpenSymbol
+ msFontname( String::CreateFromAscii("OpenSymbol") ),
+ mbUserDefinedFontname( false ),
+ // <--
+ meFontWeight( WEIGHT_DONTKNOW ),
+ meFontItalic( ITALIC_NONE ),
+ mpFont( 0 )
+ {
+ SetToDefault();
+ LoadConfig();
+ InitFont();
+
+ // enable notification for changes on default bullet configuration change
+ EnableNotification( GetPropNames() );
+ }
+
+ void SwDefBulletConfig::SetToDefault()
+ {
+ // --> OD 2008-06-02 #i63395#
+ // default bullet font name is now OpenSymbol
+// msFontname = String::CreateFromAscii("StarSymbol");
+ msFontname = String::CreateFromAscii("OpenSymbol");
+ mbUserDefinedFontname = false;
+ // <--
+ meFontWeight = WEIGHT_DONTKNOW;
+ meFontItalic = ITALIC_NONE;
+
+ // --> OD 2008-06-03 #i63395#
+ // new bullet characters
+// mnLevelChars[0] = 0x25cf;
+// mnLevelChars[1] = 0x25cb;
+// mnLevelChars[2] = 0x25a0;
+// mnLevelChars[3] = 0x25cf;
+// mnLevelChars[4] = 0x25cb;
+// mnLevelChars[5] = 0x25a0;
+// mnLevelChars[6] = 0x25cf;
+// mnLevelChars[7] = 0x25cb;
+// mnLevelChars[8] = 0x25a0;
+// mnLevelChars[9] = 0x25cf;
+ mnLevelChars[0] = 0x2022;
+ mnLevelChars[1] = 0x25e6;
+ mnLevelChars[2] = 0x25aa;
+ mnLevelChars[3] = 0x2022;
+ mnLevelChars[4] = 0x25e6;
+ mnLevelChars[5] = 0x25aa;
+ mnLevelChars[6] = 0x2022;
+ mnLevelChars[7] = 0x25e6;
+ mnLevelChars[8] = 0x25aa;
+ mnLevelChars[9] = 0x2022;
+ // <--
+ }
+
+ uno::Sequence<rtl::OUString> SwDefBulletConfig::GetPropNames() const
+ {
+ uno::Sequence<rtl::OUString> aPropNames(13);
+ rtl::OUString* pNames = aPropNames.getArray();
+ pNames[0] = rtl::OUString::createFromAscii("BulletFont/FontFamilyname");
+ pNames[1] = rtl::OUString::createFromAscii("BulletFont/FontWeight");
+ pNames[2] = rtl::OUString::createFromAscii("BulletFont/FontItalic");
+ pNames[3] = rtl::OUString::createFromAscii("BulletCharLvl1");
+ pNames[4] = rtl::OUString::createFromAscii("BulletCharLvl2");
+ pNames[5] = rtl::OUString::createFromAscii("BulletCharLvl3");
+ pNames[6] = rtl::OUString::createFromAscii("BulletCharLvl4");
+ pNames[7] = rtl::OUString::createFromAscii("BulletCharLvl5");
+ pNames[8] = rtl::OUString::createFromAscii("BulletCharLvl6");
+ pNames[9] = rtl::OUString::createFromAscii("BulletCharLvl7");
+ pNames[10] = rtl::OUString::createFromAscii("BulletCharLvl8");
+ pNames[11] = rtl::OUString::createFromAscii("BulletCharLvl9");
+ pNames[12] = rtl::OUString::createFromAscii("BulletCharLvl10");
+
+ return aPropNames;
+ }
+
+ void SwDefBulletConfig::LoadConfig()
+ {
+ uno::Sequence<rtl::OUString> aPropNames = GetPropNames();
+ uno::Sequence<uno::Any> aValues =
+ GetProperties( aPropNames );
+ const uno::Any* pValues = aValues.getConstArray();
+ ASSERT( aValues.getLength() == aPropNames.getLength(),
+ "<SwDefBulletConfig::SwDefBulletConfig()> - GetProperties failed")
+ if ( aValues.getLength() == aPropNames.getLength() )
+ {
+ for ( int nProp = 0; nProp < aPropNames.getLength(); ++nProp )
+ {
+ if ( pValues[nProp].hasValue() )
+ {
+ switch ( nProp )
+ {
+ case 0:
+ {
+ rtl::OUString aStr;
+ pValues[nProp] >>= aStr;
+ msFontname = aStr;
+ // --> OD 2008-06-02 #i63395#
+ mbUserDefinedFontname = true;
+ // <--
+ }
+ break;
+ case 1:
+ case 2:
+ {
+ sal_uInt8 nTmp = 0;
+ pValues[nProp] >>= nTmp;
+ if ( nProp == 1 )
+ meFontWeight = static_cast<FontWeight>(nTmp);
+ else if ( nProp == 2 )
+ meFontItalic = static_cast<FontItalic>(nTmp);
+ }
+ break;
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ {
+ sal_Unicode cChar = sal_Unicode();
+ pValues[nProp] >>= cChar;
+ mnLevelChars[nProp-3] = cChar;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ void SwDefBulletConfig::InitFont()
+ {
+ delete mpFont;
+
+ mpFont = new Font( msFontname, aEmptyStr, Size( 0, 14 ) );
+ mpFont->SetWeight( meFontWeight );
+ mpFont->SetItalic( meFontItalic );
+ }
+
+ void SwDefBulletConfig::Notify( const uno::Sequence<rtl::OUString>& )
+ {
+ SetToDefault();
+ LoadConfig();
+ InitFont();
+ }
+
+ void SwDefBulletConfig::Commit()
+ {
+ }
+
+ const String& GetDefBulletFontname()
+ {
+ return SwDefBulletConfig::getInstance()->GetFontname();
+ }
+
+ // --> OD 2008-06-02 #i63395#
+ bool IsDefBulletFontUserDefined()
+ {
+ return SwDefBulletConfig::getInstance()->IsFontnameUserDefined();
+ }
+ // <--
+
+ const Font& GetDefBulletFont()
+ {
+ return SwDefBulletConfig::getInstance()->GetFont();
+ }
+
+ sal_Unicode GetBulletChar( sal_uInt8 nLevel )
+ {
+ return SwDefBulletConfig::getInstance()->GetChar( nLevel );
+ }
+
+ /** class containing configuration data about user interface behavior
+ regarding lists and list items.
+
+ OD 2007-10-01 #b660435#
+ configuration item about behavior of <TAB>/<SHIFT-TAB>-key at first
+ position of first list item
+
+ @author OD
+ */
+ class SwNumberingUIBehaviorConfig : private utl::ConfigItem
+ {
+ public:
+ static SwNumberingUIBehaviorConfig* getInstance()
+ {
+ if ( mpInstance == 0 )
+ {
+ mpInstance = new SwNumberingUIBehaviorConfig();
+ }
+
+ return mpInstance;
+ }
+
+ inline sal_Bool ChangeIndentOnTabAtFirstPosOfFirstListItem() const
+ {
+ return mbChangeIndentOnTabAtFirstPosOfFirstListItem;
+ }
+
+ private:
+ SwNumberingUIBehaviorConfig();
+
+ /** sets internal configuration data to default values
+
+ @author OD
+ */
+ void SetToDefault();
+
+ /** returns sequence of configuration property names
+
+ @author OD
+ */
+ com::sun::star::uno::Sequence<rtl::OUString> GetPropNames() const;
+
+ /** loads configuration properties and applies values to internal data
+
+ @author OD
+ */
+ void LoadConfig();
+
+ /** catches notification about changed configuration data
+
+ @author OD
+ */
+ virtual void Notify( const com::sun::star::uno::Sequence<rtl::OUString>& aPropertyNames );
+ virtual void Commit();
+
+ static SwNumberingUIBehaviorConfig* mpInstance;
+
+ // configuration data
+ sal_Bool mbChangeIndentOnTabAtFirstPosOfFirstListItem;
+ };
+
+ SwNumberingUIBehaviorConfig* SwNumberingUIBehaviorConfig::mpInstance = 0;
+
+ SwNumberingUIBehaviorConfig::SwNumberingUIBehaviorConfig()
+ : ConfigItem( rtl::OUString::createFromAscii("Office.Writer/Numbering/UserInterfaceBehavior") ),
+ mbChangeIndentOnTabAtFirstPosOfFirstListItem( sal_True )
+ {
+ SetToDefault();
+ LoadConfig();
+
+ // enable notification for changes on configuration change
+ EnableNotification( GetPropNames() );
+ }
+
+ void SwNumberingUIBehaviorConfig::SetToDefault()
+ {
+ mbChangeIndentOnTabAtFirstPosOfFirstListItem = sal_True;
+ }
+
+ com::sun::star::uno::Sequence<rtl::OUString> SwNumberingUIBehaviorConfig::GetPropNames() const
+ {
+ com::sun::star::uno::Sequence<rtl::OUString> aPropNames(1);
+ rtl::OUString* pNames = aPropNames.getArray();
+ pNames[0] = rtl::OUString::createFromAscii("ChangeIndentOnTabAtFirstPosOfFirstListItem");
+
+ return aPropNames;
+ }
+
+ void SwNumberingUIBehaviorConfig::Commit() {}
+
+ void SwNumberingUIBehaviorConfig::LoadConfig()
+ {
+ com::sun::star::uno::Sequence<rtl::OUString> aPropNames = GetPropNames();
+ com::sun::star::uno::Sequence<com::sun::star::uno::Any> aValues =
+ GetProperties( aPropNames );
+ const com::sun::star::uno::Any* pValues = aValues.getConstArray();
+ ASSERT( aValues.getLength() == aPropNames.getLength(),
+ "<SwNumberingUIBehaviorConfig::LoadConfig()> - GetProperties failed")
+ if ( aValues.getLength() == aPropNames.getLength() )
+ {
+ for ( int nProp = 0; nProp < aPropNames.getLength(); ++nProp )
+ {
+ if ( pValues[nProp].hasValue() )
+ {
+ switch ( nProp )
+ {
+ case 0:
+ {
+ pValues[nProp] >>= mbChangeIndentOnTabAtFirstPosOfFirstListItem;
+ }
+ break;
+ default:
+ {
+ ASSERT( false,
+ "<SwNumberingUIBehaviorConfig::LoadConfig()> - unknown configuration property")
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void SwNumberingUIBehaviorConfig::Notify( const com::sun::star::uno::Sequence<rtl::OUString>& aPropertyNames )
+ {
+ (void) aPropertyNames;
+ SetToDefault();
+ LoadConfig();
+ }
+
+ sal_Bool ChangeIndentOnTabAtFirstPosOfFirstListItem()
+ {
+ return SwNumberingUIBehaviorConfig::getInstance()->ChangeIndentOnTabAtFirstPosOfFirstListItem();
+ }
+
+ // --> OD 2008-06-06 #i89178#
+ SvxNumberFormat::SvxNumPositionAndSpaceMode GetDefaultPositionAndSpaceMode()
+ {
+ SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode;
+ SvtSaveOptions aSaveOptions;
+ switch ( aSaveOptions.GetODFDefaultVersion() )
+ {
+ case SvtSaveOptions::ODFVER_010:
+ case SvtSaveOptions::ODFVER_011:
+ {
+ ePosAndSpaceMode = SvxNumberFormat::LABEL_WIDTH_AND_POSITION;
+ }
+ break;
+ default: // ODFVER_UNKNOWN or ODFVER_012
+ {
+ ePosAndSpaceMode = SvxNumberFormat::LABEL_ALIGNMENT;
+ }
+ }
+
+ return ePosAndSpaceMode;
+ }
+ // <--
+}
+// <--
diff --git a/sw/source/core/doc/poolfmt.cxx b/sw/source/core/doc/poolfmt.cxx
new file mode 100644
index 000000000000..5c3bb6659b4a
--- /dev/null
+++ b/sw/source/core/doc/poolfmt.cxx
@@ -0,0 +1,2591 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <i18npool/mslangid.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <editeng/paperinf.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/protitem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/emphitem.hxx>
+#include <editeng/scriptspaceitem.hxx>
+#include <viewopt.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <fmtanchr.hxx>
+#include <fmtornt.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtfsize.hxx>
+#include <poolfmt.hxx>
+#include <paratr.hxx>
+#include <pagedesc.hxx>
+#include <frmtool.hxx>
+#include <charfmt.hxx>
+#include <docary.hxx>
+#include <fmtcol.hxx>
+#include <ndtxt.hxx>
+#include <fmtline.hxx>
+#include <poolfmt.hrc>
+#include <GetMetricVal.hxx>
+#include <numrule.hxx>
+
+
+using namespace ::com::sun::star;
+
+const sal_uInt16 PT_3 = 3 * 20; // 3 pt
+const sal_uInt16 PT_6 = 6 * 20; // 6 pt
+const sal_uInt16 PT_7 = 7 * 20; // 6 pt
+const sal_uInt16 PT_8 = 8 * 20; // 8 pt
+const sal_uInt16 PT_9 = 9 * 20; // 9 pt
+const sal_uInt16 PT_10 = 10 * 20; // 10 pt
+const sal_uInt16 PT_11 = 11 * 20; // 11 pt
+const sal_uInt16 PT_12 = 12 * 20; // 12 pt
+const sal_uInt16 PT_14 = 14 * 20; // 14 pt
+const sal_uInt16 PT_16 = 16 * 20; // 16 pt
+const sal_uInt16 PT_18 = 18 * 20; // 18 pt
+const sal_uInt16 PT_22 = 22 * 20; // 22 pt
+const sal_uInt16 PT_24 = 24 * 20; // 22 pt
+
+
+//const sal_uInt16 HTML_PARSPACE = ((CM_05 * 7) / 10);
+#define HTML_PARSPACE GetMetricVal( CM_05 )
+
+static const sal_Char __FAR_DATA sKomma[] = ", ";
+
+static const sal_uInt16 aHeadlineSizes[ 2 * MAXLEVEL ] = {
+// PT_16, PT_14, PT_14, PT_12, PT_12, // normal
+//JP 10.12.96: jetzt soll alles prozentual sein:
+ 115, 100, 100, 85, 85,
+ 75, 75, 75, 75, 75, // normal
+// PT_22, PT_16, PT_12, PT_11, PT_9 // HTML-Mode
+ PT_24, PT_18, PT_14, PT_12, PT_10,
+ PT_7, PT_7, PT_7, PT_7, PT_7 // HTML-Mode
+};
+
+long lcl_GetRightMargin( SwDoc& rDoc )
+{
+ // sorge dafuer, dass die Druckereinstellungen in die Standard-
+ // Seitenvorlage uebernommen wurden.
+ const SwFrmFmt& rPgDscFmt =
+ const_cast<const SwDoc *>(&rDoc)->GetPageDesc( 0 ).GetMaster();
+ const SvxLRSpaceItem& rLR = rPgDscFmt.GetLRSpace();
+ const long nLeft = rLR.GetLeft();
+ const long nRight = rLR.GetRight();
+ const long nWidth = rPgDscFmt.GetFrmSize().GetWidth();
+ return nWidth - nLeft - nRight;
+}
+
+void SetAllScriptItem( SfxItemSet& rSet, const SfxPoolItem& rItem )
+{
+ rSet.Put( rItem );
+ sal_uInt16 nWhCJK = 0, nWhCTL = 0;
+ switch( rItem.Which() )
+ {
+ case RES_CHRATR_FONTSIZE:
+ nWhCJK = RES_CHRATR_CJK_FONTSIZE, nWhCTL = RES_CHRATR_CTL_FONTSIZE;
+ break;
+ case RES_CHRATR_FONT:
+ nWhCJK = RES_CHRATR_CJK_FONT, nWhCTL = RES_CHRATR_CTL_FONT;
+ break;
+ case RES_CHRATR_LANGUAGE:
+ nWhCJK = RES_CHRATR_CJK_LANGUAGE, nWhCTL = RES_CHRATR_CTL_LANGUAGE;
+ break;
+ case RES_CHRATR_POSTURE:
+ nWhCJK = RES_CHRATR_CJK_POSTURE, nWhCTL = RES_CHRATR_CTL_POSTURE;
+ break;
+ case RES_CHRATR_WEIGHT:
+ nWhCJK = RES_CHRATR_CJK_WEIGHT, nWhCTL = RES_CHRATR_CTL_WEIGHT;
+ break;
+ }
+
+ if( nWhCJK )
+ rSet.Put( rItem, nWhCJK );
+ if( nWhCTL )
+ rSet.Put( rItem, nWhCTL );
+}
+
+void lcl_SetDfltFont( sal_uInt16 nFntType, SfxItemSet& rSet )
+{
+ static struct {
+ sal_uInt16 nResLngId;
+ sal_uInt16 nResFntId;
+ } aArr[ 3 ] = {
+ { RES_CHRATR_LANGUAGE, RES_CHRATR_FONT },
+ { RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_FONT },
+ { RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_FONT }
+ };
+ for( sal_uInt16 n = 0; n < 3; ++n )
+ {
+ sal_uInt16 nLng = ((SvxLanguageItem&)rSet.GetPool()->GetDefaultItem(
+ aArr[n].nResLngId )).GetLanguage();
+ Font aFnt( OutputDevice::GetDefaultFont( nFntType,
+ nLng, DEFAULTFONT_FLAGS_ONLYONE ) );
+
+ rSet.Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(),
+ aEmptyStr, aFnt.GetPitch(),
+ aFnt.GetCharSet(), aArr[n].nResFntId ));
+ }
+}
+
+void lcl_SetDfltFont( sal_uInt16 nLatinFntType, sal_uInt16 nCJKFntType,
+ sal_uInt16 nCTLFntType, SfxItemSet& rSet )
+{
+ static struct {
+ sal_uInt16 nResLngId;
+ sal_uInt16 nResFntId;
+ sal_uInt16 nFntType;
+ } aArr[ 3 ] = {
+ { RES_CHRATR_LANGUAGE, RES_CHRATR_FONT, 0 },
+ { RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_FONT, 0 },
+ { RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_FONT, 0 }
+ };
+ aArr[0].nFntType = nLatinFntType;
+ aArr[1].nFntType = nCJKFntType;
+ aArr[2].nFntType = nCTLFntType;
+
+ for( sal_uInt16 n = 0; n < 3; ++n )
+ {
+ sal_uInt16 nLng = ((SvxLanguageItem&)rSet.GetPool()->GetDefaultItem(
+ aArr[n].nResLngId )).GetLanguage();
+ Font aFnt( OutputDevice::GetDefaultFont( aArr[n].nFntType,
+ nLng, DEFAULTFONT_FLAGS_ONLYONE ) );
+
+ rSet.Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(),
+ aEmptyStr, aFnt.GetPitch(),
+ aFnt.GetCharSet(), aArr[n].nResFntId ));
+ }
+}
+
+void lcl_SetHeadline( SwDoc* pDoc, SwTxtFmtColl* pColl,
+ SfxItemSet& rSet,
+ sal_uInt16 nOutLvlBits, sal_uInt8 nLevel, sal_Bool bItalic )
+{
+ SetAllScriptItem( rSet, SvxWeightItem( WEIGHT_BOLD, RES_CHRATR_WEIGHT ) );
+ SvxFontHeightItem aHItem(240, 100, RES_CHRATR_FONTSIZE);
+ const bool bHTMLMode = pDoc->get(IDocumentSettingAccess::HTML_MODE);
+ if( bHTMLMode )
+ aHItem.SetHeight( aHeadlineSizes[ MAXLEVEL + nLevel ] );
+ else
+ aHItem.SetHeight( PT_14, aHeadlineSizes[ nLevel ] );
+ SetAllScriptItem( rSet, aHItem );
+
+ if( bItalic && !bHTMLMode )
+ SetAllScriptItem( rSet, SvxPostureItem( ITALIC_NORMAL, RES_CHRATR_POSTURE ) );
+
+ if( bHTMLMode )
+ {
+ ::lcl_SetDfltFont( DEFAULTFONT_LATIN_TEXT, DEFAULTFONT_CJK_TEXT,
+ DEFAULTFONT_CTL_TEXT, rSet );
+ }
+
+ if( pColl )
+ {
+ if( !( nOutLvlBits & ( 1 << nLevel )) )
+ {
+ //pColl->SetOutlineLevel( nLevel ); //#outline level zhaojianwei
+ pColl->AssignToListLevelOfOutlineStyle(nLevel);//<-end,zhaojianwei
+ if( !bHTMLMode )
+ {
+ SwNumRule * pOutlineRule = pDoc->GetOutlineNumRule();
+ const SwNumFmt& rNFmt = pOutlineRule->Get( nLevel );
+ // --> OD 2008-02-01 #newlistlevelattrs#
+ if ( rNFmt.GetPositionAndSpaceMode() ==
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION &&
+ ( rNFmt.GetAbsLSpace() || rNFmt.GetFirstLineOffset() ) )
+ // <--
+ {
+ SvxLRSpaceItem aLR( (SvxLRSpaceItem&)pColl->GetFmtAttr( RES_LR_SPACE ) );
+ aLR.SetTxtFirstLineOfstValue( rNFmt.GetFirstLineOffset() );
+ aLR.SetTxtLeft( rNFmt.GetAbsLSpace() );
+ pColl->SetFmtAttr( aLR );
+ }
+
+ // --> OD 2006-11-20 #i71764#
+ // Check on document setting OUTLINE_LEVEL_YIELDS_OUTLINE_RULE no longer needed.
+ // All paragraph styles, which are assigned to a level of the
+ // outline style has to have the outline style set as its list style.
+ {
+ SwNumRuleItem aItem(pOutlineRule->GetName());
+
+ pColl->SetFmtAttr(aItem);
+ }
+ // <--
+ }
+ }
+ pColl->SetNextTxtFmtColl( *pDoc->GetTxtCollFromPool(
+ RES_POOLCOLL_TEXT ));
+ }
+}
+
+
+
+void lcl_SetRegister( SwDoc* pDoc, SfxItemSet& rSet, sal_uInt16 nFact,
+ sal_Bool bHeader, sal_Bool bTab )
+{
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ sal_uInt16 nLeft = nFact ? GetMetricVal( CM_05 ) * nFact : 0;
+ aLR.SetTxtLeft( nLeft );
+
+ rSet.Put( aLR );
+ if( bHeader )
+ {
+ SetAllScriptItem( rSet, SvxWeightItem( WEIGHT_BOLD, RES_CHRATR_WEIGHT ) );
+ SetAllScriptItem( rSet, SvxFontHeightItem( PT_16, 100, RES_CHRATR_FONTSIZE ) );
+ }
+ if( bTab )
+ {
+ long nRightMargin = lcl_GetRightMargin( *pDoc );
+ SvxTabStopItem aTStops( 0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
+ aTStops.Insert( SvxTabStop( nRightMargin - nLeft,
+ SVX_TAB_ADJUST_RIGHT,
+ cDfltDecimalChar, '.' ));
+ rSet.Put( aTStops );
+ }
+}
+
+
+
+void lcl_SetNumBul( SwDoc* pDoc, SwTxtFmtColl* pColl,
+ SfxItemSet& rSet,
+ sal_uInt16 nNxt, SwTwips nEZ, SwTwips nLeft,
+ SwTwips nUpper, SwTwips nLower )
+{
+
+ SvxLRSpaceItem aLR( RES_LR_SPACE ); SvxULSpaceItem aUL( RES_UL_SPACE );
+ aLR.SetTxtFirstLineOfst( sal_uInt16(nEZ) ); aLR.SetTxtLeft( sal_uInt16(nLeft) );
+ aUL.SetUpper( sal_uInt16(nUpper) ); aUL.SetLower( sal_uInt16(nLower) );
+ rSet.Put( aLR );
+ rSet.Put( aUL );
+
+ if( !pColl )
+ pColl->SetNextTxtFmtColl( *pDoc->GetTxtCollFromPool( nNxt ));
+}
+
+
+
+// Gebe die "Auto-Collection" mit der Id zurueck. Existiert
+// sie noch nicht, dann erzeuge sie
+// Ist der String-Pointer definiert, dann erfrage nur die
+// Beschreibung der Attribute, !! es legt keine Vorlage an !!
+
+SvxFrameDirection GetDefaultFrameDirection(sal_uLong nLanguage)
+{
+ SvxFrameDirection eResult = (MsLangId::isRightToLeft( static_cast<LanguageType>(nLanguage)) ?
+ FRMDIR_HORI_RIGHT_TOP : FRMDIR_HORI_LEFT_TOP);
+ return eResult;
+}
+
+SwTxtFmtColl* SwDoc::GetTxtCollFromPool( sal_uInt16 nId, bool bRegardLanguage )
+{
+ ASSERT(
+ (RES_POOLCOLL_TEXT_BEGIN <= nId && nId < RES_POOLCOLL_TEXT_END) ||
+ (RES_POOLCOLL_LISTS_BEGIN <= nId && nId < RES_POOLCOLL_LISTS_END) ||
+ (RES_POOLCOLL_EXTRA_BEGIN <= nId && nId < RES_POOLCOLL_EXTRA_END) ||
+ (RES_POOLCOLL_REGISTER_BEGIN <= nId && nId < RES_POOLCOLL_REGISTER_END) ||
+ (RES_POOLCOLL_DOC_BEGIN <= nId && nId < RES_POOLCOLL_DOC_END) ||
+ (RES_POOLCOLL_HTML_BEGIN <= nId && nId < RES_POOLCOLL_HTML_END),
+ "Falsche AutoFormat-Id" );
+
+ SwTxtFmtColl* pNewColl;
+ sal_uInt16 nOutLvlBits = 0;
+ for( sal_uInt16 n = 0; n < pTxtFmtCollTbl->Count(); ++n )
+ {
+ if( nId == ( pNewColl = (*pTxtFmtCollTbl)[ n ] )->GetPoolFmtId() )
+ {
+ return pNewColl;
+ }
+ //if( pNewColl->GetOutlineLevel() < MAXLEVEL ) //#outline level,zhaojianwei
+ //nOutLvlBits |= ( 1 << pNewColl->GetOutlineLevel() );
+ if( pNewColl->IsAssignedToListLevelOfOutlineStyle())
+ nOutLvlBits |= ( 1 << pNewColl->GetAssignedOutlineStyleLevel() );//<-end,zhaojianwei
+ }
+
+ // bis hierher nicht gefunden -> neu anlegen
+ sal_uInt16 nResId = 0;
+ if( RES_POOLCOLL_TEXT_BEGIN <= nId && nId < RES_POOLCOLL_TEXT_END )
+ nResId = RC_POOLCOLL_TEXT_BEGIN - RES_POOLCOLL_TEXT_BEGIN;
+ else if (RES_POOLCOLL_LISTS_BEGIN <= nId && nId < RES_POOLCOLL_LISTS_END)
+ nResId = RC_POOLCOLL_LISTS_BEGIN - RES_POOLCOLL_LISTS_BEGIN;
+ else if (RES_POOLCOLL_EXTRA_BEGIN <= nId && nId < RES_POOLCOLL_EXTRA_END)
+ nResId = RC_POOLCOLL_EXTRA_BEGIN - RES_POOLCOLL_EXTRA_BEGIN;
+ else if (RES_POOLCOLL_REGISTER_BEGIN <= nId && nId < RES_POOLCOLL_REGISTER_END)
+ nResId = RC_POOLCOLL_REGISTER_BEGIN - RES_POOLCOLL_REGISTER_BEGIN;
+ else if (RES_POOLCOLL_DOC_BEGIN <= nId && nId < RES_POOLCOLL_DOC_END)
+ nResId = RC_POOLCOLL_DOC_BEGIN - RES_POOLCOLL_DOC_BEGIN;
+ else if (RES_POOLCOLL_HTML_BEGIN <= nId && nId < RES_POOLCOLL_HTML_END)
+ nResId = RC_POOLCOLL_HTML_BEGIN - RES_POOLCOLL_HTML_BEGIN;
+
+ ASSERT( nResId, "Ungueltige Pool-ID" );
+ if( !nResId )
+ return GetTxtCollFromPool( RES_POOLCOLL_STANDARD );
+
+ ResId aResId( nResId + nId, *pSwResMgr );
+ String aNm( aResId );
+
+ // ein Set fuer alle zusetzenden Attribute
+ SwAttrSet aSet( GetAttrPool(), aTxtFmtCollSetRange );
+ sal_uInt16 nParent = GetPoolParent( nId );
+
+ {
+
+//FEATURE::CONDCOLL
+ if(::IsConditionalByPoolId( nId ))
+ pNewColl = new SwConditionTxtFmtColl( GetAttrPool(), aNm, !nParent
+ ? pDfltTxtFmtColl
+ : GetTxtCollFromPool( nParent ));
+ else
+//FEATURE::CONDCOLL
+ pNewColl = new SwTxtFmtColl( GetAttrPool(), aNm, !nParent
+ ? pDfltTxtFmtColl
+ : GetTxtCollFromPool( nParent ));
+ pNewColl->SetPoolFmtId( nId );
+ pTxtFmtCollTbl->Insert( pNewColl, pTxtFmtCollTbl->Count() );
+ }
+
+ switch( nId )
+ {
+ // allgemeine Inhaltsformen
+ case RES_POOLCOLL_STANDARD:
+ /* #111214# koreans do not like SvxScriptItem(sal_True) */
+ if (bRegardLanguage)
+ {
+ sal_uLong nAppLanguage = GetAppLanguage();
+ if (GetDefaultFrameDirection(nAppLanguage) ==
+ FRMDIR_HORI_RIGHT_TOP)
+ {
+ SvxAdjustItem aAdjust(SVX_ADJUST_RIGHT, RES_PARATR_ADJUST );
+ aSet.Put(aAdjust);
+ }
+ if (nAppLanguage == LANGUAGE_KOREAN)
+ {
+ SvxScriptSpaceItem aScriptSpace(sal_False, RES_PARATR_SCRIPTSPACE);
+ aSet.Put(aScriptSpace);
+ }
+ }
+ break;
+
+ case RES_POOLCOLL_TEXT: // Textkoerper
+ {
+ SvxULSpaceItem aUL( 0, PT_6, RES_UL_SPACE );
+ if( get(IDocumentSettingAccess::HTML_MODE) ) aUL.SetLower( HTML_PARSPACE );
+ aSet.Put( aUL );
+ }
+ break;
+ case RES_POOLCOLL_TEXT_IDENT: // Textkoerper Einzug
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetTxtFirstLineOfst( GetMetricVal( CM_05 ));
+ aSet.Put( aLR );
+ }
+ break;
+ case RES_POOLCOLL_TEXT_NEGIDENT: // Textkoerper neg. Einzug
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetTxtFirstLineOfst( -(short)GetMetricVal( CM_05 ));
+ aLR.SetTxtLeft( GetMetricVal( CM_1 ));
+ SvxTabStopItem aTStops(RES_PARATR_TABSTOP); aTStops.Insert( SvxTabStop( 0 ));
+
+ aSet.Put( aLR );
+ aSet.Put( aTStops );
+ }
+ break;
+ case RES_POOLCOLL_TEXT_MOVE: // Textkoerper Einrueckung
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetTxtLeft( GetMetricVal( CM_05 ));
+ aSet.Put( aLR );
+ }
+ break;
+
+ case RES_POOLCOLL_CONFRONTATION: // Textkoerper Gegenueberstellung
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetTxtFirstLineOfst( - short( GetMetricVal( CM_1 ) * 4 +
+ GetMetricVal( CM_05)) );
+ aLR.SetTxtLeft( GetMetricVal( CM_1 ) * 5 );
+ SvxTabStopItem aTStops( RES_PARATR_TABSTOP ); aTStops.Insert( SvxTabStop( 0 ));
+
+ aSet.Put( aLR );
+ aSet.Put( aTStops );
+ }
+ break;
+ case RES_POOLCOLL_MARGINAL: // Textkoerper maginalie
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetTxtLeft( GetMetricVal( CM_1 ) * 4 );
+ aSet.Put( aLR );
+ }
+ break;
+
+ case RES_POOLCOLL_HEADLINE_BASE: // Basis Ueberschrift
+ {
+ static const sal_uInt16 aFntInit[] = {
+ DEFAULTFONT_LATIN_HEADING, RES_CHRATR_FONT,
+ RES_CHRATR_LANGUAGE, LANGUAGE_ENGLISH_US,
+ DEFAULTFONT_CJK_HEADING, RES_CHRATR_CJK_FONT,
+ RES_CHRATR_CJK_LANGUAGE, LANGUAGE_ENGLISH_US,
+ DEFAULTFONT_CTL_HEADING, RES_CHRATR_CTL_FONT,
+ RES_CHRATR_CTL_LANGUAGE, LANGUAGE_ARABIC_SAUDI_ARABIA,
+ 0
+ };
+
+ for( const sal_uInt16* pArr = aFntInit; *pArr; pArr += 4 )
+ {
+ sal_uInt16 nLng = ((SvxLanguageItem&)GetDefault( *(pArr+2) )).GetLanguage();
+ if( LANGUAGE_DONTKNOW == nLng )
+ nLng = *(pArr+3);
+
+ Font aFnt( OutputDevice::GetDefaultFont( *pArr,
+ nLng, DEFAULTFONT_FLAGS_ONLYONE ) );
+
+ aSet.Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(),
+ aEmptyStr, aFnt.GetPitch(),
+ aFnt.GetCharSet(), *(pArr+1) ));
+ }
+
+ SvxFontHeightItem aFntSize( PT_14, 100, RES_CHRATR_FONTSIZE );
+ SvxULSpaceItem aUL( PT_12, PT_6, RES_UL_SPACE );
+ if( get(IDocumentSettingAccess::HTML_MODE) )
+ aUL.SetLower( HTML_PARSPACE );
+ aSet.Put( SvxFmtKeepItem( sal_True, RES_KEEP ));
+
+ pNewColl->SetNextTxtFmtColl( *GetTxtCollFromPool( RES_POOLCOLL_TEXT ));
+
+ aSet.Put( aUL );
+ SetAllScriptItem( aSet, aFntSize );
+ }
+ break;
+
+ case RES_POOLCOLL_NUMBUL_BASE: // Basis Numerierung/Aufzaehlung
+ break;
+
+ case RES_POOLCOLL_GREETING: // Grussformel
+ case RES_POOLCOLL_REGISTER_BASE: // Basis Verzeichnisse
+ case RES_POOLCOLL_SIGNATURE: // Unterschrift
+ case RES_POOLCOLL_TABLE: // Tabelle-Inhalt
+ {
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+
+ case RES_POOLCOLL_HEADLINE1: // Ueberschrift 1
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 0, sal_False );
+ break;
+ case RES_POOLCOLL_HEADLINE2: // Ueberschrift 2
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 1, sal_True );
+ break;
+ case RES_POOLCOLL_HEADLINE3: // Ueberschrift 3
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 2, sal_False );
+ break;
+ case RES_POOLCOLL_HEADLINE4: // Ueberschrift 4
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 3, sal_True );
+ break;
+ case RES_POOLCOLL_HEADLINE5: // Ueberschrift 5
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 4, sal_False );
+ break;
+ case RES_POOLCOLL_HEADLINE6: // Ueberschrift 6
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 5, sal_False );
+ break;
+ case RES_POOLCOLL_HEADLINE7: // Ueberschrift 7
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 6, sal_False );
+ break;
+ case RES_POOLCOLL_HEADLINE8: // Ueberschrift 8
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 7, sal_False );
+ break;
+ case RES_POOLCOLL_HEADLINE9: // Ueberschrift 9
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 8, sal_False );
+ break;
+ case RES_POOLCOLL_HEADLINE10: // Ueberschrift 10
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 9, sal_False );
+ break;
+
+
+ // Sonderbereiche:
+ // Kopfzeilen
+ case RES_POOLCOLL_HEADER:
+ case RES_POOLCOLL_HEADERL:
+ case RES_POOLCOLL_HEADERR:
+ // Fusszeilen
+ case RES_POOLCOLL_FOOTER:
+ case RES_POOLCOLL_FOOTERL:
+ case RES_POOLCOLL_FOOTERR:
+ {
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+
+ long nRightMargin = lcl_GetRightMargin( *this );
+
+ SvxTabStopItem aTStops( 0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
+ aTStops.Insert( SvxTabStop( nRightMargin / 2, SVX_TAB_ADJUST_CENTER ) );
+ aTStops.Insert( SvxTabStop( nRightMargin, SVX_TAB_ADJUST_RIGHT ) );
+
+ aSet.Put( aTStops );
+ }
+ break;
+
+ case RES_POOLCOLL_TABLE_HDLN:
+ {
+ SetAllScriptItem( aSet, SvxWeightItem( WEIGHT_BOLD, RES_CHRATR_WEIGHT ) );
+ aSet.Put( SvxAdjustItem( SVX_ADJUST_CENTER, RES_PARATR_ADJUST ) );
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+
+ case RES_POOLCOLL_FOOTNOTE: // Fussnote
+ case RES_POOLCOLL_ENDNOTE:
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetTxtFirstLineOfst( -(short)GetMetricVal( CM_05 ));
+ aLR.SetTxtLeft( GetMetricVal( CM_05 ));
+ SetAllScriptItem( aSet, SvxFontHeightItem( PT_10, 100, RES_CHRATR_FONTSIZE ) );
+ aSet.Put( aLR );
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+
+ case RES_POOLCOLL_LABEL: // Beschriftung-Basis
+ {
+ SvxULSpaceItem aUL( RES_UL_SPACE ); aUL.SetUpper( PT_6 ); aUL.SetLower( PT_6 );
+ aSet.Put( aUL );
+ SetAllScriptItem( aSet, SvxPostureItem( ITALIC_NORMAL, RES_CHRATR_POSTURE ) );
+ SetAllScriptItem( aSet, SvxFontHeightItem( PT_10, 100, RES_CHRATR_FONTSIZE ) );
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+
+ case RES_POOLCOLL_FRAME: // Rahmen Inhalt
+ case RES_POOLCOLL_LABEL_ABB: // Beschriftung-Abbildung
+ case RES_POOLCOLL_LABEL_TABLE: // Beschriftung-Tabelle
+ case RES_POOLCOLL_LABEL_FRAME: // Beschriftung-Rahmen
+ case RES_POOLCOLL_LABEL_DRAWING: // Beschriftung-Zeichnung
+ break;
+
+ case RES_POOLCOLL_JAKETADRESS: // UmschlagAdresse
+ {
+ SvxULSpaceItem aUL( RES_UL_SPACE ); aUL.SetLower( PT_3 );
+ aSet.Put( aUL );
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+
+ case RES_POOLCOLL_SENDADRESS: // AbsenderAdresse
+ {
+ if( get(IDocumentSettingAccess::HTML_MODE) )
+ SetAllScriptItem( aSet, SvxPostureItem(ITALIC_NORMAL, RES_CHRATR_POSTURE) );
+ else
+ {
+ SvxULSpaceItem aUL( RES_UL_SPACE ); aUL.SetLower( PT_3 );
+ aSet.Put( aUL );
+ }
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+
+ // Benutzer-Verzeichnisse:
+ case RES_POOLCOLL_TOX_USERH: // Header
+ lcl_SetRegister( this, aSet, 0, sal_True, sal_False );
+ {
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+ case RES_POOLCOLL_TOX_USER1: // 1. Ebene
+ lcl_SetRegister( this, aSet, 0, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER2: // 2. Ebene
+ lcl_SetRegister( this, aSet, 1, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER3: // 3. Ebene
+ lcl_SetRegister( this, aSet, 2, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER4: // 4. Ebene
+ lcl_SetRegister( this, aSet, 3, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER5: // 5. Ebene
+ lcl_SetRegister( this, aSet, 4, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER6: // 6. Ebene
+ lcl_SetRegister( this, aSet, 5, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER7: // 7. Ebene
+ lcl_SetRegister( this, aSet, 6, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER8: // 8. Ebene
+ lcl_SetRegister( this, aSet, 7, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER9: // 9. Ebene
+ lcl_SetRegister( this, aSet, 8, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER10: // 10. Ebene
+ lcl_SetRegister( this, aSet, 9, sal_False, sal_True );
+ break;
+
+ // Index-Verzeichnisse
+ case RES_POOLCOLL_TOX_IDXH: // Header
+ lcl_SetRegister( this, aSet, 0, sal_True, sal_False );
+ {
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+ case RES_POOLCOLL_TOX_IDX1: // 1. Ebene
+ lcl_SetRegister( this, aSet, 0, sal_False, sal_False );
+ break;
+ case RES_POOLCOLL_TOX_IDX2: // 2. Ebene
+ lcl_SetRegister( this, aSet, 1, sal_False, sal_False );
+ break;
+ case RES_POOLCOLL_TOX_IDX3: // 3. Ebene
+ lcl_SetRegister( this, aSet, 2, sal_False, sal_False );
+ break;
+ case RES_POOLCOLL_TOX_IDXBREAK: // Trenner
+ lcl_SetRegister( this, aSet, 0, sal_False, sal_False );
+ break;
+
+ // Inhalts-Verzeichnisse
+ case RES_POOLCOLL_TOX_CNTNTH: // Header
+ lcl_SetRegister( this, aSet, 0, sal_True, sal_False );
+ {
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+ case RES_POOLCOLL_TOX_CNTNT1: // 1. Ebene
+ lcl_SetRegister( this, aSet, 0, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT2: // 2. Ebene
+ lcl_SetRegister( this, aSet, 1, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT3: // 3. Ebene
+ lcl_SetRegister( this, aSet, 2, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT4: // 4. Ebene
+ lcl_SetRegister( this, aSet, 3, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT5: // 5. Ebene
+ lcl_SetRegister( this, aSet, 4, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT6: // 6. Ebene
+ lcl_SetRegister( this, aSet, 5, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT7: // 7. Ebene
+ lcl_SetRegister( this, aSet, 6, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT8: // 8. Ebene
+ lcl_SetRegister( this, aSet, 7, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT9: // 9. Ebene
+ lcl_SetRegister( this, aSet, 8, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT10: // 10. Ebene
+ lcl_SetRegister( this, aSet, 9, sal_False, sal_True );
+ break;
+
+ case RES_POOLCOLL_TOX_ILLUSH:
+ case RES_POOLCOLL_TOX_OBJECTH:
+ case RES_POOLCOLL_TOX_TABLESH:
+ case RES_POOLCOLL_TOX_AUTHORITIESH:
+ lcl_SetRegister( this, aSet, 0, sal_True, sal_False );
+ {
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+ case RES_POOLCOLL_TOX_ILLUS1:
+ case RES_POOLCOLL_TOX_OBJECT1:
+ case RES_POOLCOLL_TOX_TABLES1:
+ case RES_POOLCOLL_TOX_AUTHORITIES1:
+ lcl_SetRegister( this, aSet, 0, sal_False, sal_True );
+ break;
+
+
+
+ case RES_POOLCOLL_NUM_LEVEL1S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL1,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 0 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL1:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL1,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 0 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL1E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL1,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 0 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_NUM_NONUM1:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_NONUM1,
+ 0, SwNumRule::GetNumIndent( 0 ), 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL2S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL2,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 1 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL2:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL2,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 1 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL2E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL2,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 1 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_NUM_NONUM2:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_NONUM2,
+ 0, SwNumRule::GetNumIndent( 1 ), 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL3S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL3,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 2 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL3:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL3,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 2 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL3E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL3,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 2 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_NUM_NONUM3:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_NONUM3,
+ 0, SwNumRule::GetNumIndent( 2 ), 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL4S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL4,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 3 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL4:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL4,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 3 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL4E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL4,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 3 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_NUM_NONUM4:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_NONUM4,
+ 0, SwNumRule::GetNumIndent( 3 ), 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL5S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL5,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 4 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL5:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL5,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 4 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL5E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL5,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 4 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_NUM_NONUM5:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_NONUM5,
+ 0, SwNumRule::GetNumIndent( 4 ), 0, PT_6 );
+ break;
+
+ case RES_POOLCOLL_BUL_LEVEL1S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL1,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 0 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL1:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL1,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 0 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL1E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL1,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 0 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_BUL_NONUM1:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_NONUM1,
+ 0, SwNumRule::GetBullIndent( 0 ), 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL2S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL2,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 1 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL2:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL2,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 1 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL2E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL2,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 1 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_BUL_NONUM2:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_NONUM2,
+ 0, SwNumRule::GetBullIndent( 1 ), 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL3S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL3,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 2 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL3:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL3,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 2 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL3E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL3,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 2 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_BUL_NONUM3:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_NONUM3,
+ 0, SwNumRule::GetBullIndent( 2 ), 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL4S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL4,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 3 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL4:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL4,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 3 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL4E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL4,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 3 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_BUL_NONUM4:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_NONUM4,
+ 0, SwNumRule::GetBullIndent( 3 ), 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL5S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL5,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 4 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL5:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL5,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 4 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL5E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL5,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 4 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_BUL_NONUM5:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_NONUM5,
+ 0, SwNumRule::GetBullIndent( 4 ), 0, PT_6 );
+ break;
+
+ case RES_POOLCOLL_DOC_TITEL: // Doc. Titel
+ {
+ SetAllScriptItem( aSet, SvxWeightItem( WEIGHT_BOLD, RES_CHRATR_WEIGHT ) );
+ SetAllScriptItem( aSet, SvxFontHeightItem( PT_18, 100, RES_CHRATR_FONTSIZE ) );
+
+ aSet.Put( SvxAdjustItem( SVX_ADJUST_CENTER, RES_PARATR_ADJUST ) );
+
+ pNewColl->SetNextTxtFmtColl( *GetTxtCollFromPool(
+ RES_POOLCOLL_DOC_SUBTITEL ));
+ }
+ break;
+
+ case RES_POOLCOLL_DOC_SUBTITEL: // Doc. UnterTitel
+ {
+ SetAllScriptItem( aSet, SvxPostureItem( ITALIC_NORMAL, RES_CHRATR_POSTURE ));
+ SetAllScriptItem( aSet, SvxFontHeightItem( PT_14, 100, RES_CHRATR_FONTSIZE ));
+
+ aSet.Put( SvxAdjustItem( SVX_ADJUST_CENTER, RES_PARATR_ADJUST ));
+
+ pNewColl->SetNextTxtFmtColl( *GetTxtCollFromPool(
+ RES_POOLCOLL_TEXT ));
+ }
+ break;
+
+ case RES_POOLCOLL_HTML_BLOCKQUOTE:
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetLeft( GetMetricVal( CM_1 ));
+ aLR.SetRight( GetMetricVal( CM_1 ));
+ aSet.Put( aLR );
+// aSet.Put( SvxAdjustItem( SVX_ADJUST_BLOCK, RES_PARATR_ADJUST ) );
+ SvxULSpaceItem aUL( RES_UL_SPACE );
+ aUL = pNewColl->GetULSpace();
+ aUL.SetLower( HTML_PARSPACE );
+ aSet.Put( aUL);
+ }
+ break;
+
+ case RES_POOLCOLL_HTML_PRE:
+ {
+ ::lcl_SetDfltFont( DEFAULTFONT_FIXED, aSet );
+
+// WORKAROUND: PRE auf 10pt setzten
+ SetAllScriptItem( aSet, SvxFontHeightItem(PT_10, 100, RES_CHRATR_FONTSIZE) );
+// WORKAROUND: PRE auf 10pt setzten
+
+ // der untere Absatz-Abstand wird explizit gesetzt (macht
+ // die harte Attributierung einfacher)
+ SvxULSpaceItem aULSpaceItem( RES_UL_SPACE );
+ aULSpaceItem = pNewColl->GetULSpace();
+ aULSpaceItem.SetLower( 0 );
+ aSet.Put( aULSpaceItem );
+ }
+ break;
+
+ case RES_POOLCOLL_HTML_HR:
+ {
+ SvxBoxItem aBox( RES_BOX );
+ Color aColor( COL_GRAY );
+ SvxBorderLine aNew( &aColor, DEF_DOUBLE_LINE0_OUT,
+ DEF_DOUBLE_LINE0_IN,
+ DEF_DOUBLE_LINE0_DIST );
+ aBox.SetLine( &aNew, BOX_LINE_BOTTOM );
+
+ aSet.Put( aBox );
+ aSet.Put( SwParaConnectBorderItem( sal_False ) );
+ SetAllScriptItem( aSet, SvxFontHeightItem(120, 100, RES_CHRATR_FONTSIZE) );
+
+ SvxULSpaceItem aUL( RES_UL_SPACE );
+ {
+ pNewColl->SetNextTxtFmtColl( *GetTxtCollFromPool(
+ RES_POOLCOLL_TEXT ));
+ aUL = pNewColl->GetULSpace();
+ }
+ aUL.SetLower( HTML_PARSPACE );
+ aSet.Put( aUL);
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+
+ case RES_POOLCOLL_HTML_DD:
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR = pNewColl->GetLRSpace();
+ // es wird um 1cm eingerueckt. Die IDs liegen immer 2 auseinander!
+ aLR.SetLeft( GetMetricVal( CM_1 ));
+ aSet.Put( aLR );
+ }
+ break;
+ case RES_POOLCOLL_HTML_DT:
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ {
+ pNewColl->SetNextTxtFmtColl( *GetTxtCollFromPool(
+ RES_POOLCOLL_HTML_DD ));
+ aLR = pNewColl->GetLRSpace();
+ }
+ // es wird um 0cm eingerueckt. Die IDs liegen immer 2 auseinander!
+ aLR.SetLeft( 0 );
+ aSet.Put( aLR );
+ }
+ break;
+ }
+
+ if( aSet.Count() )
+ {
+ {
+ pNewColl->SetFmtAttr( aSet );
+ // JP 31.08.95: erzeugen einer PoolVorlage ist keine Modifikation
+ // (Bug: 18545)
+ // SetModified();
+ }
+ }
+ return pNewColl;
+}
+
+
+
+ // pruefe, ob diese "Auto-Collection" in Dokument schon/noch
+ // benutzt wird
+bool SwDoc::IsPoolTxtCollUsed( sal_uInt16 nId ) const
+{
+ ASSERT(
+ (RES_POOLCOLL_TEXT_BEGIN <= nId && nId < RES_POOLCOLL_TEXT_END) ||
+ (RES_POOLCOLL_LISTS_BEGIN <= nId && nId < RES_POOLCOLL_LISTS_END) ||
+ (RES_POOLCOLL_EXTRA_BEGIN <= nId && nId < RES_POOLCOLL_EXTRA_END) ||
+ (RES_POOLCOLL_REGISTER_BEGIN <= nId && nId < RES_POOLCOLL_REGISTER_END) ||
+ (RES_POOLCOLL_DOC_BEGIN <= nId && nId < RES_POOLCOLL_DOC_END) ||
+ (RES_POOLCOLL_HTML_BEGIN <= nId && nId < RES_POOLCOLL_HTML_END),
+ "Falsche AutoFormat-Id" );
+
+ SwTxtFmtColl* pNewColl = 0;
+ sal_Bool bFnd = sal_False;
+ for( sal_uInt16 n = 0; !bFnd && n < pTxtFmtCollTbl->Count(); ++n )
+ {
+ pNewColl = (*pTxtFmtCollTbl)[ n ];
+ if( nId == pNewColl->GetPoolFmtId() )
+ bFnd = sal_True;
+ }
+
+ if( !bFnd || !pNewColl->GetDepends() )
+ return sal_False;
+
+ SwAutoFmtGetDocNode aGetHt( &GetNodes() );
+ return !pNewColl->GetInfo( aGetHt );
+}
+
+ // Gebe das "Auto[matische]-Format" mit der Id zurueck. Existiert
+ // es noch nicht, dann erzeuge es
+
+SwFmt* SwDoc::GetFmtFromPool( sal_uInt16 nId )
+{
+ SwFmt *pNewFmt = 0;
+ SwFmt *pDeriveFmt = 0;
+
+ SvPtrarr* pArray[ 2 ];
+ sal_uInt16 nArrCnt = 1, nRCId = 0;
+ sal_uInt16* pWhichRange = 0;
+
+ switch( nId & (COLL_GET_RANGE_BITS + POOLGRP_NOCOLLID) )
+ {
+ case POOLGRP_CHARFMT:
+ {
+ pArray[0] = pCharFmtTbl;
+ pDeriveFmt = pDfltCharFmt;
+
+ if( nId > RES_POOLCHR_NORMAL_END )
+ nRCId = RC_POOLCHRFMT_HTML_BEGIN - RES_POOLCHR_HTML_BEGIN;
+ else
+ nRCId = RC_POOLCHRFMT_BEGIN - RES_POOLCHR_BEGIN;
+ pWhichRange = aCharFmtSetRange;
+
+ // Fehlerfall: unbekanntes Format, aber CharFormat
+ // -> returne das erste
+ if( RES_POOLCHR_BEGIN > nId || nId >= RES_POOLCHR_END )
+ {
+ ASSERT( !this, "ungueltige Id" );
+ nId = RES_POOLCHR_BEGIN;
+ }
+ }
+ break;
+ case POOLGRP_FRAMEFMT:
+ {
+ pArray[0] = pFrmFmtTbl;
+ pArray[1] = pSpzFrmFmtTbl;
+ pDeriveFmt = pDfltFrmFmt;
+ nArrCnt = 2;
+ nRCId = RC_POOLFRMFMT_BEGIN - RES_POOLFRM_BEGIN;
+ pWhichRange = aFrmFmtSetRange;
+
+ // Fehlerfall: unbekanntes Format, aber FrameFormat
+ // -> returne das erste
+ if( RES_POOLFRM_BEGIN > nId || nId >= RES_POOLFRM_END )
+ {
+ ASSERT( !this, "ungueltige Id" );
+ nId = RES_POOLFRM_BEGIN;
+ }
+ }
+ break;
+
+ default:
+ // Fehlerfall, unbekanntes Format
+ ASSERT( nId, "ungueltige Id" );
+ return 0;
+ }
+ ASSERT( nRCId, "ungueltige Id" );
+
+ while( nArrCnt-- )
+ for( sal_uInt16 n = 0; n < (*pArray[nArrCnt]).Count(); ++n )
+ if( nId == ( pNewFmt = (SwFmt*)(*pArray[ nArrCnt ] )[ n ] )->
+ GetPoolFmtId() )
+ {
+ return pNewFmt;
+ }
+
+ ResId aResId( nRCId + nId, *pSwResMgr );
+ String aNm( aResId );
+ SwAttrSet aSet( GetAttrPool(), pWhichRange );
+
+ {
+ sal_Bool bIsModified = IsModified();
+
+ {
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+ switch (nId & (COLL_GET_RANGE_BITS + POOLGRP_NOCOLLID) )
+ {
+ case POOLGRP_CHARFMT:
+ pNewFmt = _MakeCharFmt(aNm, pDeriveFmt, sal_False, sal_True);
+ break;
+ case POOLGRP_FRAMEFMT:
+ pNewFmt = _MakeFrmFmt(aNm, pDeriveFmt, sal_False, sal_True);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if( !bIsModified )
+ ResetModified();
+ pNewFmt->SetPoolFmtId( nId );
+ pNewFmt->SetAuto( sal_False ); // kein Auto-Format
+ }
+
+ switch( nId )
+ {
+ case RES_POOLCHR_FOOTNOTE: // Fussnote
+ case RES_POOLCHR_PAGENO: // Seiten/Feld
+ case RES_POOLCHR_LABEL: // Beschriftung
+ case RES_POOLCHR_DROPCAPS: // Initialien
+ case RES_POOLCHR_NUM_LEVEL: // Aufzaehlungszeichen
+ case RES_POOLCHR_TOXJUMP: // Verzeichnissprung
+ case RES_POOLCHR_ENDNOTE: // Endnote
+ case RES_POOLCHR_LINENUM: // Zeilennummerierung
+ break;
+
+ case RES_POOLCHR_ENDNOTE_ANCHOR: // Endnotenanker
+ case RES_POOLCHR_FOOTNOTE_ANCHOR: // Fussnotenanker
+ {
+ aSet.Put( SvxEscapementItem( DFLT_ESC_AUTO_SUPER, 58, RES_CHRATR_ESCAPEMENT ) );
+ }
+ break;
+
+
+ case RES_POOLCHR_BUL_LEVEL: // Aufzaehlungszeichen
+ {
+ const Font& rBulletFont = numfunc::GetDefBulletFont();
+ SetAllScriptItem( aSet, SvxFontItem( rBulletFont.GetFamily(),
+ rBulletFont.GetName(), rBulletFont.GetStyleName(),
+ rBulletFont.GetPitch(), rBulletFont.GetCharSet(), RES_CHRATR_FONT ));
+ // --> OD 2008-06-02 #i63395#
+ // no font and no font size any more
+// SetAllScriptItem( aSet, SvxFontHeightItem( PT_9, 100, RES_CHRATR_FONTSIZE ));
+ // <--
+ }
+ break;
+
+ case RES_POOLCHR_INET_NORMAL:
+ {
+ Color aCol( COL_BLUE );
+ aSet.Put( SvxColorItem( aCol, RES_CHRATR_COLOR ) );
+ aSet.Put( SvxUnderlineItem( UNDERLINE_SINGLE, RES_CHRATR_UNDERLINE ) );
+ // i40133: patch submitted by rail: set language to 'none' to prevent spell checking:
+ aSet.Put( SvxLanguageItem( LANGUAGE_NONE, RES_CHRATR_LANGUAGE ) );
+ aSet.Put( SvxLanguageItem( LANGUAGE_NONE, RES_CHRATR_CJK_LANGUAGE ) );
+ aSet.Put( SvxLanguageItem( LANGUAGE_NONE, RES_CHRATR_CTL_LANGUAGE ) );
+ }
+ break;
+ case RES_POOLCHR_INET_VISIT:
+ {
+ Color aCol( COL_RED );
+ aSet.Put( SvxColorItem( aCol, RES_CHRATR_COLOR ) );
+ aSet.Put( SvxUnderlineItem( UNDERLINE_SINGLE, RES_CHRATR_UNDERLINE ) );
+ aSet.Put( SvxLanguageItem( LANGUAGE_NONE, RES_CHRATR_LANGUAGE ) );
+ aSet.Put( SvxLanguageItem( LANGUAGE_NONE, RES_CHRATR_CJK_LANGUAGE ) );
+ aSet.Put( SvxLanguageItem( LANGUAGE_NONE, RES_CHRATR_CTL_LANGUAGE ) );
+ }
+ break;
+ case RES_POOLCHR_JUMPEDIT:
+ {
+ Color aCol( COL_CYAN );
+ aSet.Put( SvxColorItem( aCol, RES_CHRATR_COLOR ) );
+ aSet.Put( SvxUnderlineItem( UNDERLINE_DOTTED, RES_CHRATR_UNDERLINE ) );
+ aSet.Put( SvxCaseMapItem( SVX_CASEMAP_KAPITAELCHEN, RES_CHRATR_CASEMAP ) );
+ }
+ break;
+
+ case RES_POOLCHR_RUBYTEXT:
+ {
+ long nH = ((SvxFontHeightItem*)GetDfltAttr(
+ RES_CHRATR_CJK_FONTSIZE ))->GetHeight() / 2;
+ SetAllScriptItem( aSet, SvxFontHeightItem( nH, 100, RES_CHRATR_FONTSIZE));
+ aSet.Put(SvxUnderlineItem( UNDERLINE_NONE, RES_CHRATR_UNDERLINE ));
+ aSet.Put(SvxEmphasisMarkItem( EMPHASISMARK_NONE, RES_CHRATR_EMPHASIS_MARK) );
+ }
+ break;
+
+ case RES_POOLCHR_HTML_EMPHASIS:
+ case RES_POOLCHR_HTML_CITIATION:
+ case RES_POOLCHR_HTML_VARIABLE:
+ {
+ SetAllScriptItem( aSet, SvxPostureItem( ITALIC_NORMAL, RES_CHRATR_POSTURE) );
+ }
+ break;
+
+ case RES_POOLCHR_IDX_MAIN_ENTRY:
+ case RES_POOLCHR_HTML_STRONG:
+ {
+ SetAllScriptItem( aSet, SvxWeightItem( WEIGHT_BOLD, RES_CHRATR_WEIGHT ));
+ }
+ break;
+
+ case RES_POOLCHR_HTML_CODE:
+ case RES_POOLCHR_HTML_SAMPLE:
+ case RES_POOLCHR_HTML_KEYBOARD:
+ case RES_POOLCHR_HTML_TELETYPE:
+ {
+ ::lcl_SetDfltFont( DEFAULTFONT_FIXED, aSet );
+ }
+ break;
+ case RES_POOLCHR_VERT_NUM:
+ aSet.Put( SvxCharRotateItem( 900, sal_False, RES_CHRATR_ROTATE ) );
+ break;
+//nichts besonderes
+// case RES_POOLCHR_HTML_DEFINSTANCE:
+// break;
+
+
+ case RES_POOLFRM_FRAME:
+ {
+ if ( get(IDocumentSettingAccess::BROWSE_MODE) )
+ {
+ aSet.Put( SwFmtAnchor( FLY_AS_CHAR ));
+ aSet.Put( SwFmtVertOrient( 0, text::VertOrientation::LINE_CENTER, text::RelOrientation::PRINT_AREA ) );
+ aSet.Put( SwFmtSurround( SURROUND_NONE ) );
+ }
+ else
+ {
+ aSet.Put( SwFmtAnchor( FLY_AT_PARA ));
+ aSet.Put( SwFmtSurround( SURROUND_PARALLEL ) );
+ aSet.Put( SwFmtHoriOrient( 0, text::HoriOrientation::CENTER, text::RelOrientation::PRINT_AREA ) );
+ aSet.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::PRINT_AREA ) );
+ Color aCol( COL_BLACK );
+ SvxBorderLine aLine( &aCol, DEF_LINE_WIDTH_0 );
+ SvxBoxItem aBox( RES_BOX );
+ aBox.SetLine( &aLine, BOX_LINE_TOP );
+ aBox.SetLine( &aLine, BOX_LINE_BOTTOM );
+ aBox.SetLine( &aLine, BOX_LINE_LEFT );
+ aBox.SetLine( &aLine, BOX_LINE_RIGHT );
+ aBox.SetDistance( 85 );
+ aSet.Put( aBox );
+ aSet.Put( SvxLRSpaceItem( 114, 114, 0, 0, RES_LR_SPACE ) );
+ aSet.Put( SvxULSpaceItem( 114, 114, RES_UL_SPACE ) );
+ }
+ }
+ break;
+ case RES_POOLFRM_GRAPHIC:
+ case RES_POOLFRM_OLE:
+ {
+ aSet.Put( SwFmtAnchor( FLY_AT_PARA ));
+ aSet.Put( SwFmtHoriOrient( 0, text::HoriOrientation::CENTER, text::RelOrientation::FRAME ));
+ aSet.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ));
+ aSet.Put( SwFmtSurround( SURROUND_NONE ));
+ }
+ break;
+ case RES_POOLFRM_FORMEL:
+ {
+ aSet.Put( SwFmtAnchor( FLY_AS_CHAR ) );
+ aSet.Put( SwFmtVertOrient( 0, text::VertOrientation::CHAR_CENTER, text::RelOrientation::FRAME ) );
+ aSet.Put( SvxLRSpaceItem( 114, 114, 0, 0, RES_LR_SPACE ) );
+ }
+ break;
+ case RES_POOLFRM_MARGINAL:
+ {
+ aSet.Put( SwFmtAnchor( FLY_AT_PARA ));
+ aSet.Put( SwFmtHoriOrient( 0, text::HoriOrientation::LEFT, text::RelOrientation::FRAME ));
+ aSet.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ));
+ aSet.Put( SwFmtSurround( SURROUND_PARALLEL ));
+ // Breite 3.5 centimeter vorgegeben, als Hoehe nur den
+ // min. Wert benutzen
+ aSet.Put( SwFmtFrmSize( ATT_MIN_SIZE,
+ GetMetricVal( CM_1 ) * 3 + GetMetricVal( CM_05 ),
+ MM50 ));
+ }
+ break;
+ case RES_POOLFRM_WATERSIGN:
+ {
+ aSet.Put( SwFmtAnchor( FLY_AT_PAGE ));
+ aSet.Put( SwFmtHoriOrient( 0, text::HoriOrientation::CENTER, text::RelOrientation::FRAME ));
+ aSet.Put( SwFmtVertOrient( 0, text::VertOrientation::CENTER, text::RelOrientation::FRAME ));
+ aSet.Put( SvxOpaqueItem( sal_False ));
+ aSet.Put( SwFmtSurround( SURROUND_THROUGHT ));
+ }
+ break;
+
+ case RES_POOLFRM_LABEL:
+ {
+ aSet.Put( SwFmtAnchor( FLY_AS_CHAR ) );
+ aSet.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ) );
+ aSet.Put( SvxLRSpaceItem( 114, 114, 0, 0, RES_LR_SPACE ) );
+
+ SvxProtectItem aProtect( RES_PROTECT );
+ aProtect.SetSizeProtect( sal_True );
+ aProtect.SetPosProtect( sal_True );
+ aSet.Put( aProtect );
+
+ pNewFmt->SetAutoUpdateFmt( sal_True );
+ }
+ break;
+ }
+ if( aSet.Count() )
+ {
+ {
+ pNewFmt->SetFmtAttr( aSet );
+ // JP 31.08.95: erzeugen einer PoolVorlage ist keine Modifikation
+ // (Bug: 18545)
+ // SetModified();
+ }
+ }
+ return pNewFmt;
+}
+
+SwFrmFmt* SwDoc::GetFrmFmtFromPool( sal_uInt16 nId )
+{
+ return (SwFrmFmt*)GetFmtFromPool( nId );
+}
+
+SwCharFmt* SwDoc::GetCharFmtFromPool( sal_uInt16 nId )
+{
+ return (SwCharFmt*)GetFmtFromPool( nId );
+}
+
+ // pruefe, ob diese "Auto-Collection" in Dokument schon/noch
+ // benutzt wird
+bool SwDoc::IsPoolFmtUsed( sal_uInt16 nId ) const
+{
+ SwFmt *pNewFmt = 0;
+ const SvPtrarr* pArray[ 2 ];
+ sal_uInt16 nArrCnt = 1;
+ sal_Bool bFnd = sal_True;
+
+ if( RES_POOLCHR_BEGIN <= nId && nId < RES_POOLCHR_END )
+ {
+ pArray[0] = pCharFmtTbl;
+ }
+ if( RES_POOLFRM_BEGIN <= nId && nId < RES_POOLFRM_END )
+ {
+ pArray[0] = pFrmFmtTbl;
+ pArray[1] = pSpzFrmFmtTbl;
+ nArrCnt = 2;
+ }
+ else
+ {
+ ASSERT( sal_False, "ungueltige Id" );
+ bFnd = sal_False;
+ }
+
+ if( bFnd )
+ {
+ bFnd = sal_False;
+ while( nArrCnt-- && !bFnd )
+ for( sal_uInt16 n = 0; !bFnd && n < (*pArray[nArrCnt]).Count(); ++n )
+ if( nId == ( pNewFmt = (SwFmt*)(*pArray[ nArrCnt ] )[ n ] )->
+ GetPoolFmtId() )
+ bFnd = sal_True;
+ }
+
+ // nicht gefunden oder keine Abhaengigen ?
+ if( bFnd && pNewFmt->GetDepends() )
+ {
+ // dann teste mal, ob es abhaengige ContentNodes im Nodes Array gibt
+ // (auch indirekte fuer Format-Ableitung! )
+ SwAutoFmtGetDocNode aGetHt( &GetNodes() );
+ bFnd = !pNewFmt->GetInfo( aGetHt );
+ }
+ else
+ bFnd = sal_False;
+
+ return bFnd;
+}
+
+
+
+void lcl_GetStdPgSize( SwDoc* pDoc, SfxItemSet& rSet )
+{
+ SwPageDesc* pStdPgDsc = pDoc->GetPageDescFromPool( RES_POOLPAGE_STANDARD );
+ SwFmtFrmSize aFrmSz( pStdPgDsc->GetMaster().GetFrmSize() );
+ if( pStdPgDsc->GetLandscape() )
+ {
+ SwTwips nTmp = aFrmSz.GetHeight();
+ aFrmSz.SetHeight( aFrmSz.GetWidth() );
+ aFrmSz.SetWidth( nTmp );
+ }
+ rSet.Put( aFrmSz );
+}
+
+SwPageDesc* SwDoc::GetPageDescFromPool( sal_uInt16 nId, bool bRegardLanguage )
+{
+ ASSERT( RES_POOLPAGE_BEGIN <= nId && nId < RES_POOLPAGE_END,
+ "Falsche AutoFormat-Id" );
+
+ SwPageDesc *pNewPgDsc;
+ sal_uInt16 n;
+
+ for( n = 0; n < aPageDescs.Count(); ++n )
+ if( nId == ( pNewPgDsc = aPageDescs[ n ] )->GetPoolFmtId() )
+ {
+ return pNewPgDsc;
+ }
+
+ // Fehlerfall: unbekannte Poolvorlage
+ if( RES_POOLPAGE_BEGIN > nId || nId >= RES_POOLPAGE_END )
+ {
+ ASSERT( !this, "ungueltige Id" );
+ nId = RES_POOLPAGE_BEGIN;
+ }
+
+ ResId aResId( sal_uInt32(RC_POOLPAGEDESC_BEGIN + nId - RES_POOLPAGE_BEGIN), *pSwResMgr );
+ String aNm( aResId );
+ {
+ sal_Bool bIsModified = IsModified();
+
+ {
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+ n = MakePageDesc( aNm, 0, bRegardLanguage );
+ }
+
+ pNewPgDsc = aPageDescs[ n ];
+ pNewPgDsc->SetPoolFmtId( nId );
+ if( !bIsModified )
+ ResetModified();
+ }
+
+
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetLeft( GetMetricVal( CM_1 ) * 2 );
+ aLR.SetRight( aLR.GetLeft() );
+ SvxULSpaceItem aUL( RES_UL_SPACE );
+ aUL.SetUpper( (sal_uInt16)aLR.GetLeft() );
+ aUL.SetLower( (sal_uInt16)aLR.GetLeft() );
+
+ SwAttrSet aSet( GetAttrPool(), aPgFrmFmtSetRange );
+ sal_Bool bSetLeft = sal_True;
+
+ switch( nId )
+ {
+ case RES_POOLPAGE_STANDARD: // Standard-Seite
+ {
+ aSet.Put( aLR );
+ aSet.Put( aUL );
+ if( pNewPgDsc )
+ pNewPgDsc->SetUseOn( nsUseOnPage::PD_ALL );
+ }
+ break;
+
+ case RES_POOLPAGE_FIRST: // Erste Seite
+ case RES_POOLPAGE_REGISTER: // Verzeichnis
+ {
+ lcl_GetStdPgSize( this, aSet );
+ aSet.Put( aLR );
+ aSet.Put( aUL );
+ if( pNewPgDsc )
+ {
+ pNewPgDsc->SetUseOn( nsUseOnPage::PD_ALL );
+ if( RES_POOLPAGE_FIRST == nId )
+ pNewPgDsc->SetFollow( GetPageDescFromPool( RES_POOLPAGE_STANDARD ));
+ }
+ }
+ break;
+
+ case RES_POOLPAGE_LEFT: // Linke Seite
+ {
+ lcl_GetStdPgSize( this, aSet );
+ aSet.Put( aLR );
+ aSet.Put( aUL );
+ bSetLeft = sal_False;
+ if( pNewPgDsc )
+ pNewPgDsc->SetUseOn( nsUseOnPage::PD_LEFT );
+ }
+ break;
+ case RES_POOLPAGE_RIGHT: // Rechte Seite
+ {
+ lcl_GetStdPgSize( this, aSet );
+ aSet.Put( aLR );
+ aSet.Put( aUL );
+ bSetLeft = sal_False;
+ if( pNewPgDsc )
+ pNewPgDsc->SetUseOn( nsUseOnPage::PD_RIGHT );
+ }
+ break;
+
+ case RES_POOLPAGE_JAKET: // Umschlag
+ {
+ aLR.SetLeft( 0 ); aLR.SetRight( 0 );
+ aUL.SetUpper( 0 ); aUL.SetLower( 0 );
+ Size aPSize( SvxPaperInfo::GetPaperSize( PAPER_ENV_C65 ) );
+ LandscapeSwap( aPSize );
+ aSet.Put( SwFmtFrmSize( ATT_FIX_SIZE, aPSize.Width(), aPSize.Height() ));
+ aSet.Put( aLR );
+ aSet.Put( aUL );
+
+ if( pNewPgDsc )
+ {
+ pNewPgDsc->SetUseOn( nsUseOnPage::PD_ALL );
+ pNewPgDsc->SetLandscape( sal_True );
+ }
+ }
+ break;
+
+ case RES_POOLPAGE_HTML: // HTML
+ {
+ lcl_GetStdPgSize( this, aSet );
+ aLR.SetRight( GetMetricVal( CM_1 ));
+ aUL.SetUpper( (sal_uInt16)aLR.GetRight() );
+ aUL.SetLower( (sal_uInt16)aLR.GetRight() );
+ aSet.Put( aLR );
+ aSet.Put( aUL );
+
+ if( pNewPgDsc )
+ pNewPgDsc->SetUseOn( nsUseOnPage::PD_ALL );
+ }
+ break;
+ case RES_POOLPAGE_FOOTNOTE:
+ case RES_POOLPAGE_ENDNOTE:
+ {
+ lcl_GetStdPgSize( this, aSet );
+ aSet.Put( aLR );
+ aSet.Put( aUL );
+ if( pNewPgDsc )
+ pNewPgDsc->SetUseOn( nsUseOnPage::PD_ALL );
+ SwPageFtnInfo aInf( pNewPgDsc->GetFtnInfo() );
+ aInf.SetLineWidth( 0 );
+ aInf.SetTopDist( 0 );
+ aInf.SetBottomDist( 0 );
+ pNewPgDsc->SetFtnInfo( aInf );
+ }
+ break;
+ case RES_POOLPAGE_LANDSCAPE:
+ {
+ SwPageDesc* pStdPgDsc = this->GetPageDescFromPool( RES_POOLPAGE_STANDARD );
+ SwFmtFrmSize aFrmSz( pStdPgDsc->GetMaster().GetFrmSize() );
+ SwTwips nTmp = aFrmSz.GetHeight();
+ aFrmSz.SetHeight( aFrmSz.GetWidth() );
+ aFrmSz.SetWidth( nTmp );
+ aSet.Put( aFrmSz );
+ aSet.Put( aLR );
+ aSet.Put( aUL );
+ if( pNewPgDsc )
+ {
+ pNewPgDsc->SetUseOn( nsUseOnPage::PD_ALL );
+ pNewPgDsc->SetLandscape( sal_True );
+ }
+ }
+ break;
+
+ }
+
+ if( aSet.Count() )
+ {
+ {
+ if( bSetLeft )
+ pNewPgDsc->GetLeft().SetFmtAttr( aSet );
+ pNewPgDsc->GetMaster().SetFmtAttr( aSet );
+ // JP 31.08.95: erzeugen einer PoolVorlage ist keine Modifikation
+ // (Bug: 18545)
+ // SetModified();
+ }
+ }
+ return pNewPgDsc;
+}
+
+SwNumRule* SwDoc::GetNumRuleFromPool( sal_uInt16 nId )
+{
+ ASSERT( RES_POOLNUMRULE_BEGIN <= nId && nId < RES_POOLNUMRULE_END,
+ "Falsche AutoFormat-Id" );
+
+ SwNumRule* pNewRule;
+ sal_uInt16 n;
+
+ for( n = 0; n < GetNumRuleTbl().Count(); ++n )
+ if( nId == ( pNewRule = GetNumRuleTbl()[ n ] )->GetPoolFmtId() )
+ {
+ return pNewRule;
+ }
+
+ // Fehlerfall: unbekannte Poolvorlage
+ if( RES_POOLNUMRULE_BEGIN > nId || nId >= RES_POOLNUMRULE_END )
+ {
+ ASSERT( !this, "ungueltige Id" );
+ nId = RES_POOLNUMRULE_BEGIN;
+ }
+
+ ResId aResId( sal_uInt32(RC_POOLNUMRULE_BEGIN + nId - RES_POOLNUMRULE_BEGIN), *pSwResMgr );
+ String aNm( aResId );
+
+ SwCharFmt *pNumCFmt = 0, *pBullCFmt = 0;
+
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ const SvxNumberFormat::SvxNumPositionAndSpaceMode eNumberFormatPositionAndSpaceMode
+ // --> OD 2008-06-06 #i89178#
+ = numfunc::GetDefaultPositionAndSpaceMode();
+ // <--
+ // <--
+ {
+ sal_Bool bIsModified = IsModified();
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ n = MakeNumRule( aNm, 0, sal_False, eNumberFormatPositionAndSpaceMode );
+ // <--
+ pNewRule = GetNumRuleTbl()[ n ];
+ pNewRule->SetPoolFmtId( nId );
+ pNewRule->SetAutoRule( sal_False );
+
+ if( RES_POOLNUMRULE_NUM1 <= nId && nId <= RES_POOLNUMRULE_NUM5 )
+ pNumCFmt = GetCharFmtFromPool( RES_POOLCHR_NUM_LEVEL );
+
+ if( ( RES_POOLNUMRULE_BUL1 <= nId && nId <= RES_POOLNUMRULE_BUL5 ) ||
+ RES_POOLNUMRULE_NUM5 == nId )
+ pBullCFmt = GetCharFmtFromPool( RES_POOLCHR_NUM_LEVEL );
+
+ if( !bIsModified )
+ ResetModified();
+ }
+
+ switch( nId )
+ {
+ case RES_POOLNUMRULE_NUM1:
+ {
+ SwNumFmt aFmt;
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ // <--
+ aFmt.SetNumberingType(SVX_NUM_ARABIC);
+ aFmt.SetCharFmt( pNumCFmt );
+ aFmt.SetStart( 1 );
+ aFmt.SetIncludeUpperLevels( 1 );
+ aFmt.SetSuffix( aDotStr );
+
+ static const sal_uInt16 aAbsSpace[ MAXLEVEL ] =
+ {
+// cm: 0,5 1,0 1,5 2,0 2,5 3,0 3,5 4,0 4,5 5,0
+ 283, 567, 850, 1134, 1417, 1701, 1984, 2268, 2551, 2835
+ };
+#ifdef USE_MEASUREMENT
+ static const sal_uInt16 aAbsSpaceInch[ MAXLEVEL ] =
+ {
+ 283, 567, 850, 1134, 1417, 1701, 1984, 2268, 2551, 2835
+ };
+ const sal_uInt16* pArr = MEASURE_METRIC ==
+ SvtSysLocale().GetLocaleData().getMeasurementSystemEnum()
+ ? aAbsSpace
+ : aAbsSpaceInch;
+#else
+ const sal_uInt16* pArr = aAbsSpace;
+#endif
+
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - (*pArr) );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ aFmt.SetFirstLineIndent( - (*pArr) );
+ }
+ // <--
+ for( n = 0; n < MAXLEVEL; ++n, ++pArr )
+ {
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( *pArr );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( *pArr );
+ aFmt.SetIndentAt( *pArr );
+ }
+ // <--
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+
+ case RES_POOLNUMRULE_NUM2:
+ {
+ static const sal_uInt16 aAbsSpace[ MAXLEVEL ] =
+ {
+ 283, 283, 567, 709, // 0.50, 0.50, 1.00, 1.25
+ 850, 1021, 1304, 1474, // 1.50, 1.80, 2.30, 2.60
+ 1588, 1758 // 2.80, 3.10
+ };
+
+#ifdef USE_MEASUREMENT
+ static const sal_uInt16 aAbsSpaceInch[ MAXLEVEL ] =
+ {
+ 385, 385, 770, 963,
+ 1155, 1386, 1771, 2002,
+ 2156, 2387
+ };
+
+ const sal_uInt16* pArr = MEASURE_METRIC ==
+ SvtSysLocale().GetLocaleData().getMeasurementSystemEnum()
+ ? aAbsSpace
+ : aAbsSpaceInch;
+#else
+ const sal_uInt16* pArr = aAbsSpace;
+#endif
+ SwNumFmt aFmt;
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ // <--
+ aFmt.SetNumberingType(SVX_NUM_ARABIC);
+ aFmt.SetCharFmt( pNumCFmt );
+ aFmt.SetIncludeUpperLevels( 1 );
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ }
+ // <--
+ sal_uInt16 nSpace = 0;
+ for( n = 0; n < MAXLEVEL; ++n )
+ {
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( nSpace = nSpace + pArr[ n ] );
+ aFmt.SetFirstLineOffset( - pArr[ n ] );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( nSpace = nSpace + pArr[ n ] );
+ aFmt.SetIndentAt( nSpace );
+ aFmt.SetFirstLineIndent( - pArr[ n ] );
+ }
+ // <--
+ aFmt.SetStart( n+1 );
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+ case RES_POOLNUMRULE_NUM3:
+ {
+ SwNumFmt aFmt;
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ // <--
+ aFmt.SetNumberingType(SVX_NUM_ARABIC);
+ aFmt.SetCharFmt( pNumCFmt );
+ aFmt.SetIncludeUpperLevels( 1 );
+
+ sal_uInt16 nOffs = GetMetricVal( CM_1 ) * 3;
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - nOffs );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ aFmt.SetFirstLineIndent( - nOffs );
+ }
+ // <--
+
+ for( n = 0; n < MAXLEVEL; ++n )
+ {
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( (n+1) * nOffs );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( (n+1) * nOffs );
+ aFmt.SetIndentAt( (n+1) * nOffs );
+ }
+ // <--
+ aFmt.SetStart( n+1 );
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+ case RES_POOLNUMRULE_NUM4:
+ {
+ SwNumFmt aFmt;
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ // <--
+ aFmt.SetNumberingType(SVX_NUM_ROMAN_UPPER);
+ aFmt.SetCharFmt( pNumCFmt );
+ aFmt.SetIncludeUpperLevels( 1 );
+ aFmt.SetSuffix( aDotStr );
+
+ static const sal_uInt16 aAbsSpace[ MAXLEVEL ] =
+ {
+// cm: 0,5 1,0 1,5 2,0 2,5 3,0 3,5 4,0 4,5 5,0
+ 283, 567, 850, 1134, 1417, 1701, 1984, 2268, 2551, 2835
+ };
+#ifdef USE_MEASUREMENT
+ static const sal_uInt16 aAbsSpaceInch[ MAXLEVEL ] =
+ {
+ 283, 567, 850, 1134, 1417, 1701, 1984, 2268, 2551, 2835
+ };
+ const sal_uInt16* pArr = MEASURE_METRIC ==
+ SvtSysLocale().GetLocaleData().getMeasurementSystemEnum()
+ ? aAbsSpace
+ : aAbsSpaceInch;
+#else
+ const sal_uInt16* pArr = aAbsSpace;
+#endif
+
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - (*pArr) );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::SPACE );
+ aFmt.SetFirstLineIndent( - (*pArr) );
+ }
+ // <--
+ for( n = 0; n < MAXLEVEL; ++n, ++pArr )
+ {
+ aFmt.SetStart( n + 1 );
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( *pArr );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( *pArr );
+ aFmt.SetIndentAt( *pArr );
+ }
+ // <--
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+ case RES_POOLNUMRULE_NUM5:
+ {
+ // [ First, LSpace ]
+ static const sal_uInt16 aAbsSpace0to2[] =
+ {
+ 227, 227, // 0.40, 0.40,
+ 369, 624, // 0.65, 1.10,
+ 255, 879 // 0.45, 1.55
+ };
+
+#ifdef USE_MEASUREMENT
+ static const sal_uInt16 aAbsSpaceInch0to2[] =
+ {
+ 308, 308,
+ 501, 847,
+ 347, 1194
+ };
+ const sal_uInt16* pArr0to2 = MEASURE_METRIC ==
+ SvtSysLocale().GetLocaleData().getMeasurementSystemEnum()
+ ? aAbsSpace0to2
+ : aAbsSpaceInch0to2;
+#else
+ const sal_uInt16* pArr0to2 = aAbsSpace0to2;
+#endif
+ SwNumFmt aFmt;
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ // <--
+ aFmt.SetNumberingType(SVX_NUM_ARABIC);
+ aFmt.SetStart( 1 );
+ aFmt.SetIncludeUpperLevels( 1 );
+ aFmt.SetSuffix( aDotStr );
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ }
+ // <--
+
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( -pArr0to2[0] ); // == 0.40 cm
+ aFmt.SetAbsLSpace( pArr0to2[1] ); // == 0.40 cm
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetFirstLineIndent( -pArr0to2[0] );
+ aFmt.SetListtabPos( pArr0to2[1] );
+ aFmt.SetIndentAt( pArr0to2[1] );
+ }
+ // <--
+
+ aFmt.SetCharFmt( pNumCFmt );
+ pNewRule->Set( 0, aFmt );
+
+ aFmt.SetIncludeUpperLevels( 2 );
+ aFmt.SetStart( 2 );
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( -pArr0to2[2] ); // == 0.65 cm
+ aFmt.SetAbsLSpace( pArr0to2[3] ); // == 1.10 cm
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetFirstLineIndent( -pArr0to2[2] );
+ aFmt.SetListtabPos( pArr0to2[3] );
+ aFmt.SetIndentAt( pArr0to2[3] );
+ }
+ // <--
+ pNewRule->Set( 1, aFmt );
+
+ aFmt.SetNumberingType(SVX_NUM_CHARS_LOWER_LETTER);
+ aFmt.SetSuffix( ')');
+ aFmt.SetIncludeUpperLevels( 1 );
+ aFmt.SetStart( 3 );
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - pArr0to2[4] ); // == 0.45cm
+ aFmt.SetAbsLSpace( pArr0to2[5] ); // == 1.55 cm
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetFirstLineIndent( -pArr0to2[4] );
+ aFmt.SetListtabPos( pArr0to2[5] );
+ aFmt.SetIndentAt( pArr0to2[5] );
+ }
+ // <--
+ pNewRule->Set( 2, aFmt );
+
+
+ aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ aFmt.SetCharFmt( pBullCFmt );
+ // --> OD 2006-06-29 #6440955#
+ aFmt.SetBulletFont( &numfunc::GetDefBulletFont() );
+ // <--
+ aFmt.SetBulletChar( cBulletChar );
+ sal_uInt16 nOffs = GetMetricVal( CM_01 ) * 4,
+ nOffs2 = GetMetricVal( CM_1 ) * 2;
+
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - nOffs );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetFirstLineIndent( - nOffs );
+ }
+ // <--
+ aFmt.SetSuffix( aEmptyStr );
+ for( n = 3; n < MAXLEVEL; ++n )
+ {
+ aFmt.SetStart( n+1 );
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( nOffs2 + ((n-3) * nOffs) );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( nOffs2 + ((n-3) * nOffs) );
+ aFmt.SetIndentAt( nOffs2 + ((n-3) * nOffs) );
+ }
+ // <--
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+
+ case RES_POOLNUMRULE_BUL1:
+ {
+ SwNumFmt aFmt;
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ // <--
+ aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ aFmt.SetCharFmt( pBullCFmt );
+ aFmt.SetStart( 1 );
+ aFmt.SetIncludeUpperLevels( 1 );
+ // --> OD 2006-06-29 #6440955#
+ aFmt.SetBulletFont( &numfunc::GetDefBulletFont() );
+ // <--
+ aFmt.SetBulletChar( cBulletChar );
+
+ static const sal_uInt16 aAbsSpace[ MAXLEVEL ] =
+ {
+// cm: 0,4 0,8 1,2 1,6 2,0 2,4 2,8 3,2 3,6 4,0
+ 227, 454, 680, 907, 1134, 1361, 1587, 1814, 2041, 2268
+ };
+#ifdef USE_MEASUREMENT
+ static const sal_uInt16 aAbsSpaceInch[ MAXLEVEL ] =
+ {
+ 227, 454, 680, 907, 1134, 1361, 1587, 1814, 2041, 2268
+ };
+ const sal_uInt16* pArr = MEASURE_METRIC ==
+ SvtSysLocale().GetLocaleData().getMeasurementSystemEnum()
+ ? aAbsSpace
+ : aAbsSpaceInch;
+#else
+ const sal_uInt16* pArr = aAbsSpace;
+#endif
+
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - (*pArr) );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ aFmt.SetFirstLineIndent( - (*pArr) );
+ }
+ // <--
+ for( n = 0; n < MAXLEVEL; ++n, ++pArr )
+ {
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( *pArr );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( *pArr );
+ aFmt.SetIndentAt( *pArr );
+ }
+ // <--
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+ case RES_POOLNUMRULE_BUL2:
+ {
+ SwNumFmt aFmt;
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ // <--
+ aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ aFmt.SetCharFmt( pBullCFmt );
+ aFmt.SetStart( 1 );
+ aFmt.SetIncludeUpperLevels( 1 );
+ // --> OD 2006-06-29 #6440955#
+ aFmt.SetBulletFont( &numfunc::GetDefBulletFont() );
+ // <--
+ aFmt.SetBulletChar( 0x2013 );
+
+ static const sal_uInt16 aAbsSpace[ MAXLEVEL ] =
+ {
+// cm: 0,3 0,6 0,9 1,2 1,5 1,8 2,1 2,4 2,7 3,0
+ 170, 340, 510, 680, 850, 1020, 1191, 1361, 1531, 1701
+ };
+#ifdef USE_MEASUREMENT
+ static const sal_uInt16 aAbsSpaceInch[ MAXLEVEL ] =
+ {
+ 170, 340, 510, 680, 850, 1020, 1191, 1361, 1531, 1701
+ };
+ const sal_uInt16* pArr = MEASURE_METRIC ==
+ SvtSysLocale().GetLocaleData().getMeasurementSystemEnum()
+ ? aAbsSpace
+ : aAbsSpaceInch;
+#else
+ const sal_uInt16* pArr = aAbsSpace;
+#endif
+
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - (*pArr) );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ aFmt.SetFirstLineIndent( - (*pArr) );
+ }
+ // <--
+ for( n = 0; n < MAXLEVEL; ++n, ++pArr )
+ {
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( *pArr );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( *pArr );
+ aFmt.SetIndentAt( *pArr );
+ }
+ // <--
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+ case RES_POOLNUMRULE_BUL3:
+ {
+ SwNumFmt aFmt;
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ // <--
+ aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ aFmt.SetCharFmt( pBullCFmt );
+ aFmt.SetStart( 1 );
+ aFmt.SetIncludeUpperLevels( 1 );
+ // --> OD 2006-06-29 #6440955#
+ aFmt.SetBulletFont( &numfunc::GetDefBulletFont() );
+ // <--
+
+ sal_uInt16 nOffs = GetMetricVal( CM_01 ) * 4;
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - nOffs );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ aFmt.SetFirstLineIndent( - nOffs );
+ }
+ // <--
+
+ for( n = 0; n < MAXLEVEL; ++n )
+ {
+ aFmt.SetBulletChar( ( n & 1 ? 0x25a1 : 0x2611 ) );
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( ((n & 1) +1) * nOffs );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( ((n & 1) +1) * nOffs );
+ aFmt.SetIndentAt( ((n & 1) +1) * nOffs );
+ }
+ // <--
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+ case RES_POOLNUMRULE_BUL4:
+ {
+ SwNumFmt aFmt;
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ // <--
+ aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ aFmt.SetCharFmt( pBullCFmt );
+ aFmt.SetStart( 1 );
+ aFmt.SetIncludeUpperLevels( 1 );
+ // --> OD 2006-06-29 #6440955#
+ aFmt.SetBulletFont( &numfunc::GetDefBulletFont() );
+ // <--
+
+ static const sal_uInt16 aAbsSpace[ MAXLEVEL ] =
+ {
+// cm: 0,4 0,8 1,2 1,6 2,0 2,4 2,8 3,2 3,6 4,0
+ 227, 454, 680, 907, 1134, 1361, 1587, 1814, 2041, 2268
+ };
+#ifdef USE_MEASUREMENT
+ static const sal_uInt16 aAbsSpaceInch[ MAXLEVEL ] =
+ {
+ 227, 454, 680, 907, 1134, 1361, 1587, 1814, 2041, 2268
+ };
+ const sal_uInt16* pArr = MEASURE_METRIC ==
+ SvtSysLocale().GetLocaleData().getMeasurementSystemEnum()
+ ? aAbsSpace
+ : aAbsSpaceInch;
+#else
+ const sal_uInt16* pArr = aAbsSpace;
+#endif
+
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - (*pArr) );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::SPACE );
+ aFmt.SetFirstLineIndent( - (*pArr) );
+ }
+ // <--
+ for( n = 0; n < MAXLEVEL; ++n, ++pArr )
+ {
+ switch( n )
+ {
+ case 0: aFmt.SetBulletChar( 0x27a2 ); break;
+ case 1: aFmt.SetBulletChar( 0xE006 ); break;
+ default: aFmt.SetBulletChar( 0xE004 ); break;
+ }
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( *pArr );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( *pArr );
+ aFmt.SetIndentAt( *pArr );
+ }
+ // <--
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+ case RES_POOLNUMRULE_BUL5:
+ {
+ SwNumFmt aFmt;
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ // <--
+ aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ aFmt.SetCharFmt( pBullCFmt );
+ aFmt.SetStart( 1 );
+ aFmt.SetIncludeUpperLevels( 1 );
+ aFmt.SetBulletChar( 0x2717 );
+ // --> OD 2006-06-29 #6440955#
+ aFmt.SetBulletFont( &numfunc::GetDefBulletFont() );
+ // <--
+
+ static const sal_uInt16 aAbsSpace[ MAXLEVEL ] =
+ {
+// cm: 0,4 0,8 1,2 1,6 2,0 2,4 2,8 3,2 3,6 4,0
+ 227, 454, 680, 907, 1134, 1361, 1587, 1814, 2041, 2268
+ };
+#ifdef USE_MEASUREMENT
+ static const sal_uInt16 aAbsSpaceInch[ MAXLEVEL ] =
+ {
+ 227, 454, 680, 907, 1134, 1361, 1587, 1814, 2041, 2268
+ };
+ const sal_uInt16* pArr = MEASURE_METRIC ==
+ SvtSysLocale().GetLocaleData().getMeasurementSystemEnum()
+ ? aAbsSpace
+ : aAbsSpaceInch;
+#else
+ const sal_uInt16* pArr = aAbsSpace;
+#endif
+
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - (*pArr) );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ aFmt.SetFirstLineIndent( - (*pArr) );
+ }
+ // <--
+ for( n = 0; n < MAXLEVEL; ++n, ++pArr )
+ {
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( *pArr );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( *pArr );
+ aFmt.SetIndentAt( *pArr );
+ }
+ // <--
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+ }
+
+ return pNewRule;
+}
+
+
+
+ // pruefe, ob diese "Auto-Collection" in Dokument schon/noch
+ // benutzt wird
+bool SwDoc::IsPoolPageDescUsed( sal_uInt16 nId ) const
+{
+ ASSERT( RES_POOLPAGE_BEGIN <= nId && nId < RES_POOLPAGE_END,
+ "Falsche AutoFormat-Id" );
+ SwPageDesc *pNewPgDsc = 0;
+ sal_Bool bFnd = sal_False;
+ for( sal_uInt16 n = 0; !bFnd && n < aPageDescs.Count(); ++n )
+ {
+ pNewPgDsc = aPageDescs[ n ];
+ if( nId == pNewPgDsc->GetPoolFmtId() )
+ bFnd = sal_True;
+ }
+
+ // nicht gefunden oder keine Abhaengigen ?
+ if( !bFnd || !pNewPgDsc->GetDepends() ) // ??????
+ return sal_False;
+
+ // dann teste mal, ob es abhaengige ContentNodes im Nodes Array gibt
+ // (auch indirekte fuer Format-Ableitung! )
+ SwAutoFmtGetDocNode aGetHt( &GetNodes() );
+ return !pNewPgDsc->GetInfo( aGetHt );
+}
+
+// erfrage ob die Absatz-/Zeichen-/Rahmen-/Seiten - Vorlage benutzt wird
+sal_Bool SwDoc::IsUsed( const SwModify& rModify ) const
+{
+ // dann teste mal, ob es abhaengige ContentNodes im Nodes Array gibt
+ // (auch indirekte fuer Format-Ableitung! )
+ SwAutoFmtGetDocNode aGetHt( &GetNodes() );
+ return !rModify.GetInfo( aGetHt );
+}
+
+// erfrage ob die NumRule benutzt wird
+sal_Bool SwDoc::IsUsed( const SwNumRule& rRule ) const
+{
+ // --> OD 2008-03-04 #refactorlists#
+// // dann teste mal, ob es abhaengige ContentNodes im Nodes Array gibt
+// // (auch indirekte fuer Format-Ableitung! )
+// sal_Bool bUsed = sal_False;
+// SwAutoFmtGetDocNode aGetHt( &aNodes );
+// SwModify* pMod;
+// const SfxPoolItem* pItem;
+// sal_uInt16 i, nMaxItems = GetAttrPool().GetItemCount( RES_PARATR_NUMRULE);
+// for( i = 0; i < nMaxItems; ++i )
+// {
+// if( 0 != (pItem = GetAttrPool().GetItem( RES_PARATR_NUMRULE, i ) ) &&
+// 0 != ( pMod = (SwModify*)((SwNumRuleItem*)pItem)->GetDefinedIn()) &&
+// ((SwNumRuleItem*)pItem)->GetValue().Len() &&
+// ((SwNumRuleItem*)pItem)->GetValue() == rRule.GetName() )
+// {
+// if( pMod->IsA( TYPE( SwFmt )) )
+// {
+// bUsed = !pMod->GetInfo( aGetHt );
+// if( bUsed )
+// break;
+// }
+// else if( ((SwTxtNode*)pMod)->GetNodes().IsDocNodes() )
+// {
+// bUsed = sal_True;
+// break;
+// }
+// }
+// }
+
+// return bUsed;
+ sal_Bool bUsed = rRule.GetTxtNodeListSize() > 0 ||
+ rRule.GetParagraphStyleListSize() > 0;
+
+ return bUsed;
+ // <--
+}
+
+ // Suche die Position vom Vorlagen-Namen. Ist nicht vorhanden
+ // dann fuege neu ein
+sal_uInt16 SwDoc::SetDocPattern( const String& rPatternName )
+{
+ ASSERT( rPatternName.Len(), "kein Dokument-Vorlagenname" );
+
+ sal_uInt16 nNewPos = aPatternNms.Count();
+ for( sal_uInt16 n = 0; n < aPatternNms.Count(); ++n )
+ if( !aPatternNms[n] )
+ {
+ if( nNewPos == aPatternNms.Count() )
+ nNewPos = n;
+ }
+ else if( rPatternName == *aPatternNms[n] )
+ return n;
+
+ if( nNewPos < aPatternNms.Count() )
+ aPatternNms.Remove( nNewPos ); // Platz wieder frei machen
+
+ String* pNewNm = new String( rPatternName );
+ aPatternNms.Insert( pNewNm, nNewPos );
+ SetModified();
+ return nNewPos;
+}
+
+sal_uInt16 GetPoolParent( sal_uInt16 nId )
+{
+ sal_uInt16 nRet = USHRT_MAX;
+ if( POOLGRP_NOCOLLID & nId ) // 1 == Formate / 0 == Collections
+ {
+ switch( ( COLL_GET_RANGE_BITS | POOLGRP_NOCOLLID ) & nId )
+ {
+ case POOLGRP_CHARFMT:
+ case POOLGRP_FRAMEFMT:
+ nRet = 0; // vom default abgeleitet
+ break;
+ case POOLGRP_PAGEDESC:
+ case POOLGRP_NUMRULE:
+ break; // es gibt keine Ableitung
+ }
+ }
+ else
+ {
+ switch( COLL_GET_RANGE_BITS & nId )
+ {
+ case COLL_TEXT_BITS:
+ switch( nId )
+ {
+ case RES_POOLCOLL_STANDARD:
+ nRet = 0; break;
+ case RES_POOLCOLL_TEXT_IDENT:
+ case RES_POOLCOLL_TEXT_NEGIDENT:
+ case RES_POOLCOLL_TEXT_MOVE:
+ case RES_POOLCOLL_CONFRONTATION:
+ case RES_POOLCOLL_MARGINAL:
+ nRet = RES_POOLCOLL_TEXT; break;
+
+ case RES_POOLCOLL_TEXT:
+ case RES_POOLCOLL_GREETING:
+ case RES_POOLCOLL_SIGNATURE:
+ case RES_POOLCOLL_HEADLINE_BASE:
+ nRet = RES_POOLCOLL_STANDARD; break;
+
+ case RES_POOLCOLL_HEADLINE1:
+ case RES_POOLCOLL_HEADLINE2:
+ case RES_POOLCOLL_HEADLINE3:
+ case RES_POOLCOLL_HEADLINE4:
+ case RES_POOLCOLL_HEADLINE5:
+ case RES_POOLCOLL_HEADLINE6:
+ case RES_POOLCOLL_HEADLINE7:
+ case RES_POOLCOLL_HEADLINE8:
+ case RES_POOLCOLL_HEADLINE9:
+ case RES_POOLCOLL_HEADLINE10:
+ nRet = RES_POOLCOLL_HEADLINE_BASE; break;
+ }
+ break;
+
+ case COLL_LISTS_BITS:
+ switch( nId )
+ {
+ case RES_POOLCOLL_NUMBUL_BASE:
+ nRet = RES_POOLCOLL_TEXT; break;
+
+ default:
+ nRet = RES_POOLCOLL_NUMBUL_BASE; break;
+ }
+ break;
+
+ case COLL_EXTRA_BITS:
+ switch( nId )
+ {
+ case RES_POOLCOLL_FRAME:
+ nRet = RES_POOLCOLL_TEXT; break;
+
+ case RES_POOLCOLL_TABLE_HDLN:
+ nRet = RES_POOLCOLL_TABLE; break;
+
+ case RES_POOLCOLL_TABLE:
+ case RES_POOLCOLL_FOOTNOTE:
+ case RES_POOLCOLL_ENDNOTE:
+ case RES_POOLCOLL_JAKETADRESS:
+ case RES_POOLCOLL_SENDADRESS:
+ case RES_POOLCOLL_HEADER:
+ case RES_POOLCOLL_HEADERL:
+ case RES_POOLCOLL_HEADERR:
+ case RES_POOLCOLL_FOOTER:
+ case RES_POOLCOLL_FOOTERL:
+ case RES_POOLCOLL_FOOTERR:
+ case RES_POOLCOLL_LABEL:
+ nRet = RES_POOLCOLL_STANDARD; break;
+
+ case RES_POOLCOLL_LABEL_ABB:
+ case RES_POOLCOLL_LABEL_TABLE:
+ case RES_POOLCOLL_LABEL_FRAME:
+ case RES_POOLCOLL_LABEL_DRAWING:
+ nRet = RES_POOLCOLL_LABEL; break;
+ }
+ break;
+
+ case COLL_REGISTER_BITS:
+ switch( nId )
+ {
+ case RES_POOLCOLL_REGISTER_BASE:
+ nRet = RES_POOLCOLL_STANDARD; break;
+
+ case RES_POOLCOLL_TOX_USERH:
+ case RES_POOLCOLL_TOX_CNTNTH:
+ case RES_POOLCOLL_TOX_IDXH:
+ case RES_POOLCOLL_TOX_ILLUSH:
+ case RES_POOLCOLL_TOX_OBJECTH:
+ case RES_POOLCOLL_TOX_TABLESH:
+ case RES_POOLCOLL_TOX_AUTHORITIESH:
+ nRet = RES_POOLCOLL_HEADLINE_BASE; break;
+
+ default:
+ nRet = RES_POOLCOLL_REGISTER_BASE; break;
+ }
+ break;
+
+ case COLL_DOC_BITS:
+ nRet = RES_POOLCOLL_HEADLINE_BASE;
+ break;
+
+ case COLL_HTML_BITS:
+ nRet = RES_POOLCOLL_STANDARD;
+ break;
+ }
+ }
+
+ return nRet;
+}
+
+void SwDoc::RemoveAllFmtLanguageDependencies()
+{
+ /* #106748# Restore the language independ pool defaults and styles. */
+ GetAttrPool().ResetPoolDefaultItem( RES_PARATR_ADJUST );
+
+ SwTxtFmtColl * pTxtFmtColl = GetTxtCollFromPool( RES_POOLCOLL_STANDARD );
+
+ pTxtFmtColl->ResetFmtAttr( RES_PARATR_ADJUST );
+ /* #111214# koreans do not like SvxScriptItem(sal_True) */
+ pTxtFmtColl->ResetFmtAttr( RES_PARATR_SCRIPTSPACE );
+
+ SvxFrameDirectionItem aFrameDir( FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR );
+
+ sal_uInt16 nCount = GetPageDescCnt();
+ for( sal_uInt16 i=0; i<nCount; ++i )
+ {
+ SwPageDesc& rDesc = _GetPageDesc( i );
+ rDesc.GetMaster().SetFmtAttr( aFrameDir );
+ rDesc.GetLeft().SetFmtAttr( aFrameDir );
+ }
+
+ // OD 09.10.2003 #i18732# - restore static pool default for item
+ // RES_FOLLOW_TEXT_FLOW.
+ GetAttrPool().ResetPoolDefaultItem( RES_FOLLOW_TEXT_FLOW );
+
+ //#i16874# AutoKerning as default for new documents
+ GetAttrPool().ResetPoolDefaultItem( RES_CHRATR_AUTOKERN );
+}
diff --git a/sw/source/core/doc/sortopt.cxx b/sw/source/core/doc/sortopt.cxx
new file mode 100644
index 000000000000..e845ec6f6897
--- /dev/null
+++ b/sw/source/core/doc/sortopt.cxx
@@ -0,0 +1,103 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <tools/debug.hxx>
+#include <i18npool/lang.h>
+#include <sortopt.hxx>
+
+
+SV_IMPL_PTRARR(SwSortKeys, SwSortKey*)
+
+/*--------------------------------------------------------------------
+ Beschreibung: Sortier-Schluessel
+ --------------------------------------------------------------------*/
+
+SwSortKey::SwSortKey() :
+ eSortOrder( SRT_ASCENDING ),
+ nColumnId( 0 ),
+ bIsNumeric( sal_True )
+{
+}
+
+SwSortKey::SwSortKey(sal_uInt16 nId, const String& rSrtType, SwSortOrder eOrder) :
+ sSortType( rSrtType ),
+ eSortOrder( eOrder ),
+ nColumnId( nId ),
+ bIsNumeric( 0 == rSrtType.Len() )
+{
+}
+
+
+SwSortKey::SwSortKey(const SwSortKey& rOld) :
+ sSortType( rOld.sSortType ),
+ eSortOrder( rOld.eSortOrder ),
+ nColumnId( rOld.nColumnId ),
+ bIsNumeric( rOld.bIsNumeric )
+{
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Sortieroptionen fuers Sortieren
+ --------------------------------------------------------------------*/
+
+
+SwSortOptions::SwSortOptions()
+ : eDirection( SRT_ROWS ),
+ cDeli( 9 ),
+ nLanguage( LANGUAGE_SYSTEM ),
+ bTable( sal_False ),
+ bIgnoreCase( sal_False )
+{
+}
+
+
+SwSortOptions::SwSortOptions(const SwSortOptions& rOpt) :
+ eDirection( rOpt.eDirection ),
+ cDeli( rOpt.cDeli ),
+ nLanguage( rOpt.nLanguage ),
+ bTable( rOpt.bTable ),
+ bIgnoreCase( rOpt.bIgnoreCase )
+{
+ for( sal_uInt16 i=0; i < rOpt.aKeys.Count(); ++i )
+ {
+ SwSortKey* pNew = new SwSortKey(*rOpt.aKeys[i]);
+ aKeys.C40_INSERT( SwSortKey, pNew, aKeys.Count());
+ }
+}
+
+
+SwSortOptions::~SwSortOptions()
+{
+ aKeys.DeleteAndDestroy(0, aKeys.Count());
+}
+
+
+
diff --git a/sw/source/core/doc/swserv.cxx b/sw/source/core/doc/swserv.cxx
new file mode 100644
index 000000000000..7903bffa2309
--- /dev/null
+++ b/sw/source/core/doc/swserv.cxx
@@ -0,0 +1,371 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <sot/storage.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <com/sun/star/uno/Sequence.h>
+#include <doc.hxx>
+#include <swtypes.hxx>
+#include <swserv.hxx>
+#include <swbaslnk.hxx>
+#include <mvsave.hxx>
+#include <IMark.hxx>
+#include <bookmrk.hxx>
+#include <pam.hxx>
+#include <shellio.hxx>
+#ifndef _SWERROR_H
+#include <swerror.h>
+#endif
+
+using namespace ::com::sun::star;
+
+SV_IMPL_REF( SwServerObject )
+
+SwServerObject::~SwServerObject()
+{
+}
+
+
+sal_Bool SwServerObject::GetData( uno::Any & rData,
+ const String & rMimeType, sal_Bool )
+{
+ sal_Bool bRet = sal_False;
+ WriterRef xWrt;
+ switch( SotExchange::GetFormatIdFromMimeType( rMimeType ) )
+ {
+ case FORMAT_STRING:
+ ::GetASCWriter( aEmptyStr, String(), xWrt );
+ break;
+
+ case FORMAT_RTF:
+ // mba: no BaseURL for data exchange
+ ::GetRTFWriter( aEmptyStr, String(), xWrt );
+ break;
+ }
+
+ if( xWrt.Is() )
+ {
+ SwPaM* pPam = 0;
+ switch( eType )
+ {
+ case BOOKMARK_SERVER:
+ if( CNTNT_TYPE.pBkmk->IsExpanded() )
+ {
+ // Bereich aufspannen
+ pPam = new SwPaM( CNTNT_TYPE.pBkmk->GetMarkPos(),
+ CNTNT_TYPE.pBkmk->GetOtherMarkPos() );
+ }
+ break;
+
+ case TABLE_SERVER:
+ pPam = new SwPaM( *CNTNT_TYPE.pTblNd,
+ *CNTNT_TYPE.pTblNd->EndOfSectionNode() );
+ break;
+
+ case SECTION_SERVER:
+ pPam = new SwPaM( SwPosition( *CNTNT_TYPE.pSectNd ) );
+ pPam->Move( fnMoveForward );
+ pPam->SetMark();
+ pPam->GetPoint()->nNode = *CNTNT_TYPE.pSectNd->EndOfSectionNode();
+ pPam->Move( fnMoveBackward );
+ break;
+ case NONE_SERVER: break;
+ }
+
+ if( pPam )
+ {
+ // Stream anlegen
+ SvMemoryStream aMemStm( 65535, 65535 );
+ SwWriter aWrt( aMemStm, *pPam, sal_False );
+ if( !IsError( aWrt.Write( xWrt )) )
+ {
+ aMemStm << '\0'; // append a zero char
+ rData <<= uno::Sequence< sal_Int8 >(
+ (sal_Int8*)aMemStm.GetData(),
+ aMemStm.Seek( STREAM_SEEK_TO_END ) );
+ bRet = sal_True;
+ }
+
+ delete pPam;
+ }
+ }
+ return bRet;
+}
+
+
+sal_Bool SwServerObject::SetData( const String & ,
+ const uno::Any& )
+{
+ // set new data into the "server" -> at first nothing to do
+ return sal_False;
+}
+
+
+void SwServerObject::SendDataChanged( const SwPosition& rPos )
+{
+ // ist an unseren Aenderungen jemand interessiert ?
+ if( HasDataLinks() )
+ {
+ int bCall = sal_False;
+ const SwStartNode* pNd = 0;
+ switch( eType )
+ {
+ case BOOKMARK_SERVER:
+ if( CNTNT_TYPE.pBkmk->IsExpanded() )
+ {
+ bCall = CNTNT_TYPE.pBkmk->GetMarkStart() <= rPos
+ && rPos < CNTNT_TYPE.pBkmk->GetMarkEnd();
+ }
+ break;
+
+ case TABLE_SERVER: pNd = CNTNT_TYPE.pTblNd; break;
+ case SECTION_SERVER: pNd = CNTNT_TYPE.pSectNd; break;
+ case NONE_SERVER: break;
+ }
+ if( pNd )
+ {
+ sal_uLong nNd = rPos.nNode.GetIndex();
+ bCall = pNd->GetIndex() < nNd && nNd < pNd->EndOfSectionIndex();
+ }
+
+ if( bCall )
+ {
+ // Recursionen erkennen und flaggen
+ IsLinkInServer( 0 );
+ SvLinkSource::NotifyDataChanged();
+ }
+ }
+ // sonst melden wir uns ab !!
+// ????? JP 27.06.95: geht das so ????
+// else
+// Closed();
+}
+
+
+void SwServerObject::SendDataChanged( const SwPaM& rRange )
+{
+ // ist an unseren Aenderungen jemand interessiert ?
+ if( HasDataLinks() )
+ {
+ int bCall = sal_False;
+ const SwStartNode* pNd = 0;
+ const SwPosition* pStt = rRange.Start(), *pEnd = rRange.End();
+ switch( eType )
+ {
+ case BOOKMARK_SERVER:
+ if(CNTNT_TYPE.pBkmk->IsExpanded())
+ {
+ bCall = *pStt <= CNTNT_TYPE.pBkmk->GetMarkEnd()
+ && *pEnd > CNTNT_TYPE.pBkmk->GetMarkStart();
+ }
+ break;
+
+ case TABLE_SERVER: pNd = CNTNT_TYPE.pTblNd; break;
+ case SECTION_SERVER: pNd = CNTNT_TYPE.pSectNd; break;
+ case NONE_SERVER: break;
+ }
+ if( pNd )
+ {
+ // liegt der Start-Bereich im Node Bereich ?
+ bCall = pStt->nNode.GetIndex() < pNd->EndOfSectionIndex() &&
+ pEnd->nNode.GetIndex() >= pNd->GetIndex();
+ }
+
+ if( bCall )
+ {
+ // Recursionen erkennen und flaggen
+ IsLinkInServer( 0 );
+ SvLinkSource::NotifyDataChanged();
+ }
+ }
+ // sonst melden wir uns ab !!
+// ????? JP 27.06.95: geht das so ????
+// else
+// Closed();
+}
+
+
+sal_Bool SwServerObject::IsLinkInServer( const SwBaseLink* pChkLnk ) const
+{
+ sal_uLong nSttNd = 0, nEndNd = 0;
+ xub_StrLen nStt = 0;
+ xub_StrLen nEnd = 0;
+ const SwNode* pNd = 0;
+ const SwNodes* pNds = 0;
+
+ switch( eType )
+ {
+ case BOOKMARK_SERVER:
+ if( CNTNT_TYPE.pBkmk->IsExpanded() )
+ {
+ const SwPosition* pStt = &CNTNT_TYPE.pBkmk->GetMarkStart(),
+ * pEnd = &CNTNT_TYPE.pBkmk->GetMarkEnd();
+
+ nSttNd = pStt->nNode.GetIndex();
+ nStt = pStt->nContent.GetIndex();
+ nEndNd = pEnd->nNode.GetIndex();
+ nEnd = pEnd->nContent.GetIndex();
+ pNds = &pStt->nNode.GetNodes();
+ }
+ break;
+
+ case TABLE_SERVER: pNd = CNTNT_TYPE.pTblNd; break;
+ case SECTION_SERVER: pNd = CNTNT_TYPE.pSectNd; break;
+
+ case SECTION_SERVER+1:
+ return sal_True;
+ }
+
+ if( pNd )
+ {
+ nSttNd = pNd->GetIndex();
+ nEndNd = pNd->EndOfSectionIndex();
+ nStt = 0, nEnd = USHRT_MAX;
+ pNds = &pNd->GetNodes();
+ }
+
+ if( nSttNd && nEndNd )
+ {
+ // LinkManager besorgen:
+ const ::sfx2::SvBaseLinks& rLnks = pNds->GetDoc()->GetLinkManager().GetLinks();
+
+// um Rekursionen zu Verhindern: ServerType umsetzen!
+SwServerObject::ServerModes eSave = eType;
+if( !pChkLnk )
+// sowas sollte man nicht tun, wer weiss schon, wie gross ein enum ist
+// ICC nimmt keinen int
+// #41723#
+// *((int*)&eType) = SECTION_SERVER+1;
+ ((SwServerObject*)this)->eType = NONE_SERVER;
+ for( sal_uInt16 n = rLnks.Count(); n; )
+ {
+ const ::sfx2::SvBaseLink* pLnk = &(*rLnks[ --n ]);
+ if( pLnk && OBJECT_CLIENT_GRF != pLnk->GetObjType() &&
+ pLnk->ISA( SwBaseLink ) &&
+ !((SwBaseLink*)pLnk)->IsNoDataFlag() &&
+ ((SwBaseLink*)pLnk)->IsInRange( nSttNd, nEndNd, nStt, nEnd ))
+ {
+ if( pChkLnk )
+ {
+ if( pLnk == pChkLnk ||
+ ((SwBaseLink*)pLnk)->IsRecursion( pChkLnk ) )
+ return sal_True;
+ }
+ else if( ((SwBaseLink*)pLnk)->IsRecursion( (SwBaseLink*)pLnk ) )
+ ((SwBaseLink*)pLnk)->SetNoDataFlag();
+ }
+ }
+if( !pChkLnk )
+ // *((int*)&eType) = eSave;
+ ((SwServerObject*)this)->eType = eSave;
+ }
+
+ return sal_False;
+}
+
+void SwServerObject::SetNoServer()
+{
+ if(eType == BOOKMARK_SERVER && CNTNT_TYPE.pBkmk)
+ {
+ ::sw::mark::DdeBookmark* const pDdeBookmark = dynamic_cast< ::sw::mark::DdeBookmark* >(CNTNT_TYPE.pBkmk);
+ if(pDdeBookmark)
+ {
+ CNTNT_TYPE.pBkmk = 0, eType = NONE_SERVER;
+ pDdeBookmark->SetRefObject(NULL);
+ }
+ }
+}
+
+void SwServerObject::SetDdeBookmark( ::sw::mark::IMark& rBookmark)
+{
+ ::sw::mark::DdeBookmark* const pDdeBookmark = dynamic_cast< ::sw::mark::DdeBookmark* >(&rBookmark);
+ if(pDdeBookmark)
+ {
+ eType = BOOKMARK_SERVER;
+ CNTNT_TYPE.pBkmk = &rBookmark;
+ pDdeBookmark->SetRefObject(this);
+ }
+ else
+ OSL_ENSURE(false,
+ "SwServerObject::SetNoServer(..)"
+ " - setting an bookmark that is not DDE-capable");
+}
+
+/* */
+
+
+SwDataChanged::SwDataChanged( const SwPaM& rPam, sal_uInt16 nTyp )
+ : pPam( &rPam ), pPos( 0 ), pDoc( rPam.GetDoc() ), nType( nTyp )
+{
+ nNode = rPam.GetPoint()->nNode.GetIndex();
+ nCntnt = rPam.GetPoint()->nContent.GetIndex();
+}
+
+
+SwDataChanged::SwDataChanged( SwDoc* pDc, const SwPosition& rPos, sal_uInt16 nTyp )
+ : pPam( 0 ), pPos( &rPos ), pDoc( pDc ), nType( nTyp )
+{
+ nNode = rPos.nNode.GetIndex();
+ nCntnt = rPos.nContent.GetIndex();
+}
+
+SwDataChanged::~SwDataChanged()
+{
+ // JP 09.04.96: nur wenn das Layout vorhanden ist ( also waehrend der
+ // Eingabe)
+ if( pDoc->GetRootFrm() )
+ {
+ const ::sfx2::SvLinkSources& rServers = pDoc->GetLinkManager().GetServers();
+
+ for( sal_uInt16 nCnt = rServers.Count(); nCnt; )
+ {
+ ::sfx2::SvLinkSourceRef refObj( rServers[ --nCnt ] );
+ // noch jemand am Object interessiert ?
+ if( refObj->HasDataLinks() && refObj->ISA( SwServerObject ))
+ {
+ SwServerObject& rObj = *(SwServerObject*)&refObj;
+ if( pPos )
+ rObj.SendDataChanged( *pPos );
+ else
+ rObj.SendDataChanged( *pPam );
+ }
+
+ // sollte jetzt gar keine Verbindung mehr bestehen
+ if( !refObj->HasDataLinks() )
+ {
+ // dann raus aus der Liste (Object bleibt aber bestehen!)
+ // falls es noch da ist !!
+ if( nCnt < rServers.Count() && &refObj == rServers[ nCnt ] )
+ pDoc->GetLinkManager().RemoveServer( nCnt, 1 );
+ }
+ }
+ }
+}
diff --git a/sw/source/core/doc/swstylemanager.cxx b/sw/source/core/doc/swstylemanager.cxx
new file mode 100644
index 000000000000..ea8ba9366c75
--- /dev/null
+++ b/sw/source/core/doc/swstylemanager.cxx
@@ -0,0 +1,173 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include "swstylemanager.hxx"
+#include <hash_map>
+#include <svl/stylepool.hxx>
+#include <doc.hxx>
+#include <charfmt.hxx>
+#include <docary.hxx>
+#include <swtypes.hxx>
+#include <istyleaccess.hxx>
+
+typedef ::std::hash_map< const ::rtl::OUString,
+ StylePool::SfxItemSet_Pointer_t,
+ ::rtl::OUStringHash,
+ ::std::equal_to< ::rtl::OUString > > SwStyleNameCache;
+
+class SwStyleCache
+{
+ SwStyleNameCache mMap;
+public:
+ SwStyleCache() {}
+ void addStyleName( StylePool::SfxItemSet_Pointer_t pStyle )
+ { mMap[ StylePool::nameOf(pStyle) ] = pStyle; }
+ void addCompletePool( StylePool& rPool );
+ StylePool::SfxItemSet_Pointer_t getByName( const rtl::OUString& rName ) { return mMap[rName]; }
+};
+
+void SwStyleCache::addCompletePool( StylePool& rPool )
+{
+ IStylePoolIteratorAccess *pIter = rPool.createIterator();
+ StylePool::SfxItemSet_Pointer_t pStyle = pIter->getNext();
+ while( pStyle.get() )
+ {
+ rtl::OUString aName( StylePool::nameOf(pStyle) );
+ mMap[ aName ] = pStyle;
+ pStyle = pIter->getNext();
+ }
+ delete pIter;
+}
+
+class SwStyleManager : public IStyleAccess
+{
+ StylePool aAutoCharPool;
+ StylePool aAutoParaPool;
+ SwStyleCache *mpCharCache;
+ SwStyleCache *mpParaCache;
+
+public:
+ // --> OD 2008-03-07 #refactorlists#
+ // accept empty item set for ignorable paragraph items.
+ SwStyleManager( SfxItemSet* pIgnorableParagraphItems )
+ : aAutoCharPool(),
+ aAutoParaPool( pIgnorableParagraphItems ),
+ mpCharCache(0),
+ mpParaCache(0)
+ {}
+ // <--
+ virtual ~SwStyleManager();
+ virtual StylePool::SfxItemSet_Pointer_t getAutomaticStyle( const SfxItemSet& rSet,
+ IStyleAccess::SwAutoStyleFamily eFamily );
+ virtual StylePool::SfxItemSet_Pointer_t getByName( const rtl::OUString& rName,
+ IStyleAccess::SwAutoStyleFamily eFamily );
+ virtual void getAllStyles( std::vector<StylePool::SfxItemSet_Pointer_t> &rStyles,
+ IStyleAccess::SwAutoStyleFamily eFamily );
+ virtual StylePool::SfxItemSet_Pointer_t cacheAutomaticStyle( const SfxItemSet& rSet,
+ SwAutoStyleFamily eFamily );
+ virtual void clearCaches();
+};
+
+IStyleAccess *createStyleManager( SfxItemSet* pIgnorableParagraphItems )
+{
+ return new SwStyleManager( pIgnorableParagraphItems );
+}
+
+SwStyleManager::~SwStyleManager()
+{
+ delete mpCharCache;
+ delete mpParaCache;
+}
+
+void SwStyleManager::clearCaches()
+{
+ delete mpCharCache;
+ mpCharCache = 0;
+ delete mpParaCache;
+ mpParaCache = 0;
+}
+
+StylePool::SfxItemSet_Pointer_t SwStyleManager::getAutomaticStyle( const SfxItemSet& rSet,
+ IStyleAccess::SwAutoStyleFamily eFamily )
+{
+ StylePool& rAutoPool = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? aAutoCharPool : aAutoParaPool;
+ return rAutoPool.insertItemSet( rSet );
+}
+
+StylePool::SfxItemSet_Pointer_t SwStyleManager::cacheAutomaticStyle( const SfxItemSet& rSet,
+ IStyleAccess::SwAutoStyleFamily eFamily )
+{
+ StylePool& rAutoPool = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? aAutoCharPool : aAutoParaPool;
+ StylePool::SfxItemSet_Pointer_t pStyle = rAutoPool.insertItemSet( rSet );
+ SwStyleCache* &rpCache = eFamily == IStyleAccess::AUTO_STYLE_CHAR ?
+ mpCharCache : mpParaCache;
+ if( !rpCache )
+ rpCache = new SwStyleCache();
+ rpCache->addStyleName( pStyle );
+ return pStyle;
+}
+
+StylePool::SfxItemSet_Pointer_t SwStyleManager::getByName( const rtl::OUString& rName,
+ IStyleAccess::SwAutoStyleFamily eFamily )
+{
+ StylePool& rAutoPool = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? aAutoCharPool : aAutoParaPool;
+ SwStyleCache* &rpCache = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? mpCharCache : mpParaCache;
+ if( !rpCache )
+ rpCache = new SwStyleCache();
+ StylePool::SfxItemSet_Pointer_t pStyle = rpCache->getByName( rName );
+ if( !pStyle.get() )
+ {
+ // Ok, ok, it's allowed to ask for uncached styles (from UNO) but it should not be done
+ // during loading a document
+ ASSERT( false, "Don't ask for uncached styles" );
+ rpCache->addCompletePool( rAutoPool );
+ pStyle = rpCache->getByName( rName );
+ }
+ return pStyle;
+}
+
+void SwStyleManager::getAllStyles( std::vector<StylePool::SfxItemSet_Pointer_t> &rStyles,
+ IStyleAccess::SwAutoStyleFamily eFamily )
+{
+ StylePool& rAutoPool = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? aAutoCharPool : aAutoParaPool;
+ // --> OD 2008-03-07 #refactorlists#
+ // setup <StylePool> iterator, which skips unused styles and ignorable items
+ IStylePoolIteratorAccess *pIter = rAutoPool.createIterator( true, true );
+ // <--
+ StylePool::SfxItemSet_Pointer_t pStyle = pIter->getNext();
+ while( pStyle.get() )
+ {
+ rStyles.push_back( pStyle );
+
+ pStyle = pIter->getNext();
+ }
+ delete pIter;
+}
diff --git a/sw/source/core/doc/swstylemanager.hxx b/sw/source/core/doc/swstylemanager.hxx
new file mode 100644
index 000000000000..4997ce5c0770
--- /dev/null
+++ b/sw/source/core/doc/swstylemanager.hxx
@@ -0,0 +1,38 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 _SWSTYLEMANAGER_HXX
+#define _SWSTYLEMANAGER_HXX
+
+class IStyleAccess;
+// --> OD 2008-03-07 #refactorlists#
+class SfxItemSet;
+// <--
+
+// --> OD 2008-03-07 #refactorlists#
+IStyleAccess *createStyleManager( SfxItemSet* pIgnorableParagraphItems = 0 );
+// <--
+#endif //_SWSTYLEMANAGER_HXX
diff --git a/sw/source/core/doc/tblafmt.cxx b/sw/source/core/doc/tblafmt.cxx
new file mode 100755
index 000000000000..3d4a21584f9a
--- /dev/null
+++ b/sw/source/core/doc/tblafmt.cxx
@@ -0,0 +1,1106 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <tools/resid.hxx>
+#include <tools/stream.hxx>
+#include <tools/shl.hxx>
+#include <vcl/svapp.hxx>
+#include <sfx2/docfile.hxx>
+#include <svl/urihelper.hxx>
+#include <svl/zforlist.hxx>
+#include <svl/zformat.hxx>
+#include <unotools/pathoptions.hxx>
+#include <sfx2/app.hxx>
+#include <svx/dialmgr.hxx>
+#ifndef _SVX_DIALOGS_HRC
+#include <svx/dialogs.hrc>
+#endif
+
+#define READ_OLDVERS // erstmal noch alte Versionen lesen
+#include <swtypes.hxx>
+#include <doc.hxx>
+#include <poolfmt.hxx>
+#include <tblafmt.hxx>
+#include <cellatr.hxx>
+#include <SwStyleNameMapper.hxx>
+
+// bis SO5PF
+const sal_uInt16 AUTOFORMAT_ID_X = 9501;
+const sal_uInt16 AUTOFORMAT_ID_358 = 9601;
+const sal_uInt16 AUTOFORMAT_DATA_ID_X = 9502;
+
+// ab SO5
+//! in nachfolgenden Versionen muss der Betrag dieser IDs groesser sein
+const sal_uInt16 AUTOFORMAT_ID_504 = 9801;
+const sal_uInt16 AUTOFORMAT_DATA_ID_504 = 9802;
+
+const sal_uInt16 AUTOFORMAT_ID_552 = 9901;
+const sal_uInt16 AUTOFORMAT_DATA_ID_552 = 9902;
+
+// --- from 641 on: CJK and CTL font settings
+const sal_uInt16 AUTOFORMAT_ID_641 = 10001;
+const sal_uInt16 AUTOFORMAT_DATA_ID_641 = 10002;
+
+// --- from 680/dr14 on: diagonal frame lines
+const sal_uInt16 AUTOFORMAT_ID_680DR14 = 10011;
+const sal_uInt16 AUTOFORMAT_DATA_ID_680DR14 = 10012;
+
+// --- from 680/dr25 on: #21549# store strings as UTF-8
+const sal_uInt16 AUTOFORMAT_ID_680DR25 = 10021;
+const sal_uInt16 AUTOFORMAT_DATA_ID_680DR25 = 10022;
+
+// --- from DEV300/overline2 on: #5991# overline
+const sal_uInt16 AUTOFORMAT_ID_300OVRLN = 10031;
+const sal_uInt16 AUTOFORMAT_DATA_ID_300OVRLN = 10032;
+
+// current version
+const sal_uInt16 AUTOFORMAT_ID = AUTOFORMAT_ID_300OVRLN;
+const sal_uInt16 AUTOFORMAT_DATA_ID = AUTOFORMAT_DATA_ID_300OVRLN;
+
+
+#ifdef READ_OLDVERS
+const sal_uInt16 AUTOFORMAT_OLD_ID = 8201;
+const sal_uInt16 AUTOFORMAT_OLD_ID1 = 8301;
+const sal_uInt16 AUTOFORMAT_OLD_DATA_ID = 8202;
+#endif
+
+
+SwBoxAutoFmt* SwTableAutoFmt::pDfltBoxAutoFmt = 0;
+
+#define sAutoTblFmtName "autotbl.fmt"
+
+// SwTable Auto-Format-Tabelle
+SV_IMPL_PTRARR( _SwTableAutoFmtTbl, SwTableAutoFmt* )
+
+
+// Struct mit Versionsnummern der Items
+
+struct SwAfVersions
+{
+public:
+ sal_uInt16 nFontVersion;
+ sal_uInt16 nFontHeightVersion;
+ sal_uInt16 nWeightVersion;
+ sal_uInt16 nPostureVersion;
+ sal_uInt16 nUnderlineVersion;
+ sal_uInt16 nOverlineVersion;
+ sal_uInt16 nCrossedOutVersion;
+ sal_uInt16 nContourVersion;
+ sal_uInt16 nShadowedVersion;
+ sal_uInt16 nColorVersion;
+ sal_uInt16 nBoxVersion;
+ sal_uInt16 nLineVersion;
+ sal_uInt16 nBrushVersion;
+
+ sal_uInt16 nAdjustVersion;
+
+ sal_uInt16 nHorJustifyVersion;
+ sal_uInt16 nVerJustifyVersion;
+ sal_uInt16 nOrientationVersion;
+ sal_uInt16 nMarginVersion;
+ sal_uInt16 nBoolVersion;
+ sal_uInt16 nInt32Version;
+ sal_uInt16 nRotateModeVersion;
+
+ sal_uInt16 nNumFmtVersion;
+
+ SwAfVersions();
+ void Load( SvStream& rStream, sal_uInt16 nVer );
+};
+
+SwAfVersions::SwAfVersions() :
+ nFontVersion(0),
+ nFontHeightVersion(0),
+ nWeightVersion(0),
+ nPostureVersion(0),
+ nUnderlineVersion(0),
+ nOverlineVersion(0),
+ nCrossedOutVersion(0),
+ nContourVersion(0),
+ nShadowedVersion(0),
+ nColorVersion(0),
+ nBoxVersion(0),
+ nLineVersion(0),
+ nBrushVersion(0),
+ nAdjustVersion(0),
+ nHorJustifyVersion(0),
+ nVerJustifyVersion(0),
+ nOrientationVersion(0),
+ nMarginVersion(0),
+ nBoolVersion(0),
+ nInt32Version(0),
+ nRotateModeVersion(0),
+ nNumFmtVersion(0)
+{
+}
+
+void SwAfVersions::Load( SvStream& rStream, sal_uInt16 nVer )
+{
+ rStream >> nFontVersion;
+ rStream >> nFontHeightVersion;
+ rStream >> nWeightVersion;
+ rStream >> nPostureVersion;
+ rStream >> nUnderlineVersion;
+ if ( nVer >= AUTOFORMAT_ID_300OVRLN )
+ rStream >> nOverlineVersion;
+ rStream >> nCrossedOutVersion;
+ rStream >> nContourVersion;
+ rStream >> nShadowedVersion;
+ rStream >> nColorVersion;
+ rStream >> nBoxVersion;
+ if ( nVer >= AUTOFORMAT_ID_680DR14 )
+ rStream >> nLineVersion;
+ rStream >> nBrushVersion;
+ rStream >> nAdjustVersion;
+ rStream >> nHorJustifyVersion;
+ rStream >> nVerJustifyVersion;
+ rStream >> nOrientationVersion;
+ rStream >> nMarginVersion;
+ rStream >> nBoolVersion;
+ if ( nVer >= AUTOFORMAT_ID_504 )
+ {
+ rStream >> nInt32Version;
+ rStream >> nRotateModeVersion;
+ }
+ rStream >> nNumFmtVersion;
+}
+
+// ---------------------------------------------------------------------------
+
+SwBoxAutoFmt::SwBoxAutoFmt()
+ : aFont( *(SvxFontItem*)GetDfltAttr( RES_CHRATR_FONT ) ),
+ aHeight( 240, 100, RES_CHRATR_FONTSIZE ),
+ aWeight( WEIGHT_NORMAL, RES_CHRATR_WEIGHT ),
+ aPosture( ITALIC_NONE, RES_CHRATR_POSTURE ),
+
+ aCJKFont( *(SvxFontItem*)GetDfltAttr( RES_CHRATR_CJK_FONT ) ),
+ aCJKHeight( 240, 100, RES_CHRATR_CJK_FONTSIZE ),
+ aCJKWeight( WEIGHT_NORMAL, RES_CHRATR_CJK_WEIGHT ),
+ aCJKPosture( ITALIC_NONE, RES_CHRATR_CJK_POSTURE ),
+
+ aCTLFont( *(SvxFontItem*)GetDfltAttr( RES_CHRATR_CTL_FONT ) ),
+ aCTLHeight( 240, 100, RES_CHRATR_CTL_FONTSIZE ),
+ aCTLWeight( WEIGHT_NORMAL, RES_CHRATR_CTL_WEIGHT ),
+ aCTLPosture( ITALIC_NONE, RES_CHRATR_CTL_POSTURE ),
+
+ aUnderline( UNDERLINE_NONE, RES_CHRATR_UNDERLINE ),
+ aOverline( UNDERLINE_NONE, RES_CHRATR_OVERLINE ),
+ aCrossedOut( STRIKEOUT_NONE, RES_CHRATR_CROSSEDOUT ),
+ aContour( sal_False, RES_CHRATR_CONTOUR ),
+ aShadowed( sal_False, RES_CHRATR_SHADOWED ),
+ aColor( RES_CHRATR_COLOR ),
+ aBox( RES_BOX ),
+ aTLBR( 0 ),
+ aBLTR( 0 ),
+ aBackground( RES_BACKGROUND ),
+ aAdjust( SVX_ADJUST_LEFT, RES_PARATR_ADJUST ),
+ aHorJustify( SVX_HOR_JUSTIFY_STANDARD, 0),
+ aVerJustify( SVX_VER_JUSTIFY_STANDARD, 0),
+ aStacked( 0 ),
+ aMargin( 0 ),
+ aLinebreak( 0 ),
+ aRotateAngle( 0 ),
+
+// FIXME - add attribute IDs for the diagonal line items
+// aTLBR( RES_... ),
+// aBLTR( RES_... ),
+ aRotateMode( SVX_ROTATE_MODE_STANDARD, 0 )
+{
+ eSysLanguage = eNumFmtLanguage = static_cast<LanguageType>(::GetAppLanguage());
+ aBox.SetDistance( 55 );
+}
+
+
+SwBoxAutoFmt::SwBoxAutoFmt( const SwBoxAutoFmt& rNew )
+ : aFont( rNew.aFont ),
+ aHeight( rNew.aHeight ),
+ aWeight( rNew.aWeight ),
+ aPosture( rNew.aPosture ),
+ aCJKFont( rNew.aCJKFont ),
+ aCJKHeight( rNew.aCJKHeight ),
+ aCJKWeight( rNew.aCJKWeight ),
+ aCJKPosture( rNew.aCJKPosture ),
+ aCTLFont( rNew.aCTLFont ),
+ aCTLHeight( rNew.aCTLHeight ),
+ aCTLWeight( rNew.aCTLWeight ),
+ aCTLPosture( rNew.aCTLPosture ),
+ aUnderline( rNew.aUnderline ),
+ aOverline( rNew.aOverline ),
+ aCrossedOut( rNew.aCrossedOut ),
+ aContour( rNew.aContour ),
+ aShadowed( rNew.aShadowed ),
+ aColor( rNew.aColor ),
+ aBox( rNew.aBox ),
+ aTLBR( rNew.aTLBR ),
+ aBLTR( rNew.aBLTR ),
+ aBackground( rNew.aBackground ),
+ aAdjust( rNew.aAdjust ),
+ aHorJustify( rNew.aHorJustify ),
+ aVerJustify( rNew.aVerJustify ),
+ aStacked( rNew.aStacked ),
+ aMargin( rNew.aMargin ),
+ aLinebreak( rNew.aLinebreak ),
+ aRotateAngle( rNew.aRotateAngle ),
+ aRotateMode( rNew.aRotateMode ),
+ sNumFmtString( rNew.sNumFmtString ),
+ eSysLanguage( rNew.eSysLanguage ),
+ eNumFmtLanguage( rNew.eNumFmtLanguage )
+{
+}
+
+
+SwBoxAutoFmt::~SwBoxAutoFmt()
+{
+}
+
+SwBoxAutoFmt& SwBoxAutoFmt::operator=( const SwBoxAutoFmt& rNew )
+{
+ aFont = rNew.aFont;
+ aHeight = rNew.aHeight;
+ aWeight = rNew.aWeight;
+ aPosture = rNew.aPosture;
+ aCJKFont = rNew.aCJKFont;
+ aCJKHeight = rNew.aCJKHeight;
+ aCJKWeight = rNew.aCJKWeight;
+ aCJKPosture = rNew.aCJKPosture;
+ aCTLFont = rNew.aCTLFont;
+ aCTLHeight = rNew.aCTLHeight;
+ aCTLWeight = rNew.aCTLWeight;
+ aCTLPosture = rNew.aCTLPosture;
+ aUnderline = rNew.aUnderline;
+ aOverline = rNew.aOverline;
+ aCrossedOut = rNew.aCrossedOut;
+ aContour = rNew.aContour;
+ aShadowed = rNew.aShadowed;
+ aColor = rNew.aColor;
+ SetAdjust( rNew.aAdjust );
+ aBox = rNew.aBox;
+ aTLBR = rNew.aTLBR;
+ aBLTR = rNew.aBLTR;
+ aBackground = rNew.aBackground;
+
+ aHorJustify = rNew.aHorJustify;
+ aVerJustify = rNew.aVerJustify;
+ aStacked.SetValue( rNew.aStacked.GetValue() );
+ aMargin = rNew.aMargin;
+ aLinebreak.SetValue( rNew.aLinebreak.GetValue() );
+ aRotateAngle.SetValue( rNew.aRotateAngle.GetValue() );
+ aRotateMode.SetValue( rNew.aRotateMode.GetValue() );
+
+ sNumFmtString = rNew.sNumFmtString;
+ eSysLanguage = rNew.eSysLanguage;
+ eNumFmtLanguage = rNew.eNumFmtLanguage;
+
+ return *this;
+}
+
+
+#define READ( aItem, aItemType, nVers )\
+ pNew = aItem.Create(rStream, nVers ); \
+ aItem = *(aItemType*)pNew; \
+ delete pNew;
+
+sal_Bool SwBoxAutoFmt::Load( SvStream& rStream, const SwAfVersions& rVersions, sal_uInt16 nVer )
+{
+ SfxPoolItem* pNew;
+ SvxOrientationItem aOrientation( SVX_ORIENTATION_STANDARD, 0);
+
+ READ( aFont, SvxFontItem , rVersions.nFontVersion)
+
+ if( rStream.GetStreamCharSet() == aFont.GetCharSet() )
+ aFont.SetCharSet(::gsl_getSystemTextEncoding());
+
+ READ( aHeight, SvxFontHeightItem , rVersions.nFontHeightVersion)
+ READ( aWeight, SvxWeightItem , rVersions.nWeightVersion)
+ READ( aPosture, SvxPostureItem , rVersions.nPostureVersion)
+ // --- from 641 on: CJK and CTL font settings
+ if( AUTOFORMAT_DATA_ID_641 <= nVer )
+ {
+ READ( aCJKFont, SvxFontItem , rVersions.nFontVersion)
+ READ( aCJKHeight, SvxFontHeightItem , rVersions.nFontHeightVersion)
+ READ( aCJKWeight, SvxWeightItem , rVersions.nWeightVersion)
+ READ( aCJKPosture, SvxPostureItem , rVersions.nPostureVersion)
+ READ( aCTLFont, SvxFontItem , rVersions.nFontVersion)
+ READ( aCTLHeight, SvxFontHeightItem , rVersions.nFontHeightVersion)
+ READ( aCTLWeight, SvxWeightItem , rVersions.nWeightVersion)
+ READ( aCTLPosture, SvxPostureItem , rVersions.nPostureVersion)
+ }
+ READ( aUnderline, SvxUnderlineItem , rVersions.nUnderlineVersion)
+ if( nVer >= AUTOFORMAT_DATA_ID_300OVRLN )
+ {
+ READ( aOverline, SvxOverlineItem , rVersions.nOverlineVersion)
+ }
+ READ( aCrossedOut, SvxCrossedOutItem , rVersions.nCrossedOutVersion)
+ READ( aContour, SvxContourItem , rVersions.nContourVersion)
+ READ( aShadowed, SvxShadowedItem , rVersions.nShadowedVersion)
+ READ( aColor, SvxColorItem , rVersions.nColorVersion)
+
+ READ( aBox, SvxBoxItem , rVersions.nBoxVersion)
+
+ // --- from 680/dr14 on: diagonal frame lines
+ if( nVer >= AUTOFORMAT_DATA_ID_680DR14 )
+ {
+ READ( aTLBR, SvxLineItem, rVersions.nLineVersion)
+ READ( aBLTR, SvxLineItem, rVersions.nLineVersion)
+ }
+
+ READ( aBackground, SvxBrushItem , rVersions.nBrushVersion)
+
+ pNew = aAdjust.Create(rStream, rVersions.nAdjustVersion );
+ SetAdjust( *(SvxAdjustItem*)pNew );
+ delete pNew;
+
+ READ( aHorJustify, SvxHorJustifyItem , rVersions.nHorJustifyVersion)
+ READ( aVerJustify, SvxVerJustifyItem , rVersions.nVerJustifyVersion)
+ READ( aOrientation, SvxOrientationItem , rVersions.nOrientationVersion)
+ READ( aMargin, SvxMarginItem , rVersions.nMarginVersion)
+
+ pNew = aLinebreak.Create(rStream, rVersions.nBoolVersion );
+ aLinebreak.SetValue( ((SfxBoolItem*)pNew)->GetValue() );
+ delete pNew;
+
+ if ( nVer >= AUTOFORMAT_DATA_ID_504 )
+ {
+ pNew = aRotateAngle.Create( rStream, rVersions.nInt32Version );
+ aRotateAngle.SetValue( ((SfxInt32Item*)pNew)->GetValue() );
+ delete pNew;
+ pNew = aRotateMode.Create( rStream, rVersions.nRotateModeVersion );
+ aRotateMode.SetValue( ((SvxRotateModeItem*)pNew)->GetValue() );
+ delete pNew;
+ }
+
+ if( 0 == rVersions.nNumFmtVersion )
+ {
+ sal_uInt16 eSys, eLge;
+ // --- from 680/dr25 on: #21549# store strings as UTF-8
+ CharSet eCharSet = (nVer >= AUTOFORMAT_ID_680DR25) ? RTL_TEXTENCODING_UTF8 : rStream.GetStreamCharSet();
+ rStream.ReadByteString( sNumFmtString, eCharSet )
+ >> eSys >> eLge;
+ eSysLanguage = (LanguageType) eSys;
+ eNumFmtLanguage = (LanguageType) eLge;
+ if ( eSysLanguage == LANGUAGE_SYSTEM ) // von alten Versionen (Calc)
+ eSysLanguage = static_cast<LanguageType>(::GetAppLanguage());
+ }
+
+ aStacked.SetValue( aOrientation.IsStacked() );
+ aRotateAngle.SetValue( aOrientation.GetRotation( aRotateAngle.GetValue() ) );
+
+ return 0 == rStream.GetError();
+}
+
+#ifdef READ_OLDVERS
+
+sal_Bool SwBoxAutoFmt::LoadOld( SvStream& rStream, sal_uInt16 aLoadVer[] )
+{
+ SfxPoolItem* pNew;
+ READ( aFont, SvxFontItem , 0)
+
+ if( rStream.GetStreamCharSet() == aFont.GetCharSet() )
+ aFont.SetCharSet(::gsl_getSystemTextEncoding());
+
+ READ( aHeight, SvxFontHeightItem , 1)
+ READ( aWeight, SvxWeightItem , 2)
+ READ( aPosture, SvxPostureItem , 3)
+ READ( aUnderline, SvxUnderlineItem , 4)
+ READ( aCrossedOut, SvxCrossedOutItem , 5)
+ READ( aContour, SvxContourItem , 6)
+ READ( aShadowed, SvxShadowedItem , 7)
+ READ( aColor, SvxColorItem , 8)
+
+ pNew = aAdjust.Create(rStream, aLoadVer[ 9 ] );
+ SetAdjust( *(SvxAdjustItem*)pNew );
+ delete pNew;
+
+ READ( aBox, SvxBoxItem , 10)
+ READ( aBackground, SvxBrushItem , 11)
+
+ return 0 == rStream.GetError();
+}
+
+#endif
+
+
+sal_Bool SwBoxAutoFmt::Save( SvStream& rStream ) const
+{
+ SvxOrientationItem aOrientation( aRotateAngle.GetValue(), aStacked.GetValue(), 0 );
+
+ aFont.Store( rStream, aFont.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aHeight.Store( rStream, aHeight.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aWeight.Store( rStream, aWeight.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aPosture.Store( rStream, aPosture.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCJKFont.Store( rStream, aCJKFont.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCJKHeight.Store( rStream, aCJKHeight.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCJKWeight.Store( rStream, aCJKWeight.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCJKPosture.Store( rStream, aCJKPosture.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCTLFont.Store( rStream, aCTLFont.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCTLHeight.Store( rStream, aCTLHeight.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCTLWeight.Store( rStream, aCTLWeight.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCTLPosture.Store( rStream, aCTLPosture.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aUnderline.Store( rStream, aUnderline.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aOverline.Store( rStream, aOverline.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCrossedOut.Store( rStream, aCrossedOut.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aContour.Store( rStream, aContour.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aShadowed.Store( rStream, aShadowed.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aColor.Store( rStream, aColor.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aBox.Store( rStream, aBox.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aTLBR.Store( rStream, aTLBR.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aBLTR.Store( rStream, aBLTR.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aBackground.Store( rStream, aBackground.GetVersion(SOFFICE_FILEFORMAT_40) );
+
+ aAdjust.Store( rStream, aAdjust.GetVersion(SOFFICE_FILEFORMAT_40) );
+
+ aHorJustify.Store( rStream, aHorJustify.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aVerJustify.Store( rStream, aVerJustify.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aOrientation.Store( rStream, aOrientation.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aMargin.Store( rStream, aMargin.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aLinebreak.Store( rStream, aLinebreak.GetVersion(SOFFICE_FILEFORMAT_40) );
+ // Calc Rotation ab SO5
+ aRotateAngle.Store( rStream, aRotateAngle.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aRotateMode.Store( rStream, aRotateMode.GetVersion(SOFFICE_FILEFORMAT_40) );
+
+ // --- from 680/dr25 on: #21549# store strings as UTF-8
+ rStream.WriteByteString( sNumFmtString, RTL_TEXTENCODING_UTF8 )
+ << (sal_uInt16)eSysLanguage << (sal_uInt16)eNumFmtLanguage;
+
+ return 0 == rStream.GetError();
+}
+
+
+sal_Bool SwBoxAutoFmt::SaveVerionNo( SvStream& rStream ) const
+{
+ rStream << aFont.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aHeight.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aWeight.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aPosture.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aUnderline.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aOverline.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aCrossedOut.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aContour.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aShadowed.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aColor.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aBox.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aTLBR.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aBackground.GetVersion( SOFFICE_FILEFORMAT_40 );
+
+ rStream << aAdjust.GetVersion( SOFFICE_FILEFORMAT_40 );
+
+ rStream << aHorJustify.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aVerJustify.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << SvxOrientationItem(SVX_ORIENTATION_STANDARD, 0).GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aMargin.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aLinebreak.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aRotateAngle.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aRotateMode.GetVersion( SOFFICE_FILEFORMAT_40 );
+
+ rStream << (sal_uInt16)0; // NumberFormat
+
+ return 0 == rStream.GetError();
+}
+
+/* */
+
+
+SwTableAutoFmt::SwTableAutoFmt( const String& rName )
+ : aName( rName ), nStrResId( USHRT_MAX )
+{
+ bInclFont = sal_True;
+ bInclJustify = sal_True;
+ bInclFrame = sal_True;
+ bInclBackground = sal_True;
+ bInclValueFormat = sal_True;
+ bInclWidthHeight = sal_True;
+
+ memset( aBoxAutoFmt, 0, sizeof( aBoxAutoFmt ) );
+}
+
+
+SwTableAutoFmt::SwTableAutoFmt( const SwTableAutoFmt& rNew )
+{
+ for( sal_uInt8 n = 0; n < 16; ++n )
+ aBoxAutoFmt[ n ] = 0;
+ *this = rNew;
+}
+
+SwTableAutoFmt& SwTableAutoFmt::operator=( const SwTableAutoFmt& rNew )
+{
+ for( sal_uInt8 n = 0; n < 16; ++n )
+ {
+ if( aBoxAutoFmt[ n ] )
+ delete aBoxAutoFmt[ n ];
+
+ SwBoxAutoFmt* pFmt = rNew.aBoxAutoFmt[ n ];
+ if( pFmt ) // ist gesetzt -> kopieren
+ aBoxAutoFmt[ n ] = new SwBoxAutoFmt( *pFmt );
+ else // sonst default
+ aBoxAutoFmt[ n ] = 0;
+ }
+
+ aName = rNew.aName;
+ nStrResId = rNew.nStrResId;
+ bInclFont = rNew.bInclFont;
+ bInclJustify = rNew.bInclJustify;
+ bInclFrame = rNew.bInclFrame;
+ bInclBackground = rNew.bInclBackground;
+ bInclValueFormat = rNew.bInclValueFormat;
+ bInclWidthHeight = rNew.bInclWidthHeight;
+
+ return *this;
+}
+
+
+SwTableAutoFmt::~SwTableAutoFmt()
+{
+ SwBoxAutoFmt** ppFmt = aBoxAutoFmt;
+ for( sal_uInt8 n = 0; n < 16; ++n, ++ppFmt )
+ if( *ppFmt )
+ delete *ppFmt;
+}
+
+
+void SwTableAutoFmt::SetBoxFmt( const SwBoxAutoFmt& rNew, sal_uInt8 nPos )
+{
+ ASSERT( nPos < 16, "falscher Bereich" );
+
+ SwBoxAutoFmt* pFmt = aBoxAutoFmt[ nPos ];
+ if( pFmt ) // ist gesetzt -> kopieren
+ *aBoxAutoFmt[ nPos ] = rNew;
+ else // sonst neu setzen
+ aBoxAutoFmt[ nPos ] = new SwBoxAutoFmt( rNew );
+}
+
+
+const SwBoxAutoFmt& SwTableAutoFmt::GetBoxFmt( sal_uInt8 nPos ) const
+{
+ ASSERT( nPos < 16, "falscher Bereich" );
+
+ SwBoxAutoFmt* pFmt = aBoxAutoFmt[ nPos ];
+ if( pFmt ) // ist gesetzt -> kopieren
+ return *pFmt;
+ else // sonst den default returnen
+ {
+ // falls noch nicht vorhanden:
+ if( !pDfltBoxAutoFmt )
+ pDfltBoxAutoFmt = new SwBoxAutoFmt;
+ return *pDfltBoxAutoFmt;
+ }
+}
+
+
+
+SwBoxAutoFmt& SwTableAutoFmt::UpdateFromSet( sal_uInt8 nPos,
+ const SfxItemSet& rSet,
+ UpdateFlags eFlags,
+ SvNumberFormatter* pNFmtr )
+{
+ ASSERT( nPos < 16, "falscher Bereich" );
+
+ SwBoxAutoFmt* pFmt = aBoxAutoFmt[ nPos ];
+ if( !pFmt ) // ist gesetzt -> kopieren
+ {
+ pFmt = new SwBoxAutoFmt;
+ aBoxAutoFmt[ nPos ] = pFmt;
+ }
+
+ if( UPDATE_CHAR & eFlags )
+ {
+ pFmt->SetFont( (SvxFontItem&)rSet.Get( RES_CHRATR_FONT ) );
+ pFmt->SetHeight( (SvxFontHeightItem&)rSet.Get( RES_CHRATR_FONTSIZE ) );
+ pFmt->SetWeight( (SvxWeightItem&)rSet.Get( RES_CHRATR_WEIGHT ) );
+ pFmt->SetPosture( (SvxPostureItem&)rSet.Get( RES_CHRATR_POSTURE ) );
+ pFmt->SetCJKFont( (SvxFontItem&)rSet.Get( RES_CHRATR_CJK_FONT ) );
+ pFmt->SetCJKHeight( (SvxFontHeightItem&)rSet.Get( RES_CHRATR_CJK_FONTSIZE ) );
+ pFmt->SetCJKWeight( (SvxWeightItem&)rSet.Get( RES_CHRATR_CJK_WEIGHT ) );
+ pFmt->SetCJKPosture( (SvxPostureItem&)rSet.Get( RES_CHRATR_CJK_POSTURE ) );
+ pFmt->SetCTLFont( (SvxFontItem&)rSet.Get( RES_CHRATR_CTL_FONT ) );
+ pFmt->SetCTLHeight( (SvxFontHeightItem&)rSet.Get( RES_CHRATR_CTL_FONTSIZE ) );
+ pFmt->SetCTLWeight( (SvxWeightItem&)rSet.Get( RES_CHRATR_CTL_WEIGHT ) );
+ pFmt->SetCTLPosture( (SvxPostureItem&)rSet.Get( RES_CHRATR_CTL_POSTURE ) );
+ pFmt->SetUnderline( (SvxUnderlineItem&)rSet.Get( RES_CHRATR_UNDERLINE ) );
+ pFmt->SetOverline( (SvxOverlineItem&)rSet.Get( RES_CHRATR_OVERLINE ) );
+ pFmt->SetCrossedOut( (SvxCrossedOutItem&)rSet.Get( RES_CHRATR_CROSSEDOUT ) );
+ pFmt->SetContour( (SvxContourItem&)rSet.Get( RES_CHRATR_CONTOUR ) );
+ pFmt->SetShadowed( (SvxShadowedItem&)rSet.Get( RES_CHRATR_SHADOWED ) );
+ pFmt->SetColor( (SvxColorItem&)rSet.Get( RES_CHRATR_COLOR ) );
+ pFmt->SetAdjust( (SvxAdjustItem&)rSet.Get( RES_PARATR_ADJUST ) );
+ }
+ if( UPDATE_BOX & eFlags )
+ {
+ pFmt->SetBox( (SvxBoxItem&)rSet.Get( RES_BOX ) );
+// FIXME - add attribute IDs for the diagonal line items
+// pFmt->SetTLBR( (SvxLineItem&)rSet.Get( RES_... ) );
+// pFmt->SetBLTR( (SvxLineItem&)rSet.Get( RES_... ) );
+ pFmt->SetBackground( (SvxBrushItem&)rSet.Get( RES_BACKGROUND ) );
+
+ const SwTblBoxNumFormat* pNumFmtItem;
+ const SvNumberformat* pNumFormat = 0;
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMAT, sal_True,
+ (const SfxPoolItem**)&pNumFmtItem ) && pNFmtr &&
+ 0 != (pNumFormat = pNFmtr->GetEntry( pNumFmtItem->GetValue() )) )
+ pFmt->SetValueFormat( ((SvNumberformat*)pNumFormat)->GetFormatstring(),
+ pNumFormat->GetLanguage(),
+ static_cast<LanguageType>(::GetAppLanguage()));
+ else
+ {
+ // defaulten
+ pFmt->SetValueFormat( aEmptyStr, LANGUAGE_SYSTEM,
+ static_cast<LanguageType>(::GetAppLanguage() ));
+ }
+ }
+ // den Rest koennen wir nicht, StarCalc spezifisch
+
+ return *pFmt;
+}
+
+
+void SwTableAutoFmt::UpdateToSet( sal_uInt8 nPos, SfxItemSet& rSet,
+ UpdateFlags eFlags, SvNumberFormatter* pNFmtr ) const
+{
+ const SwBoxAutoFmt& rChg = GetBoxFmt( nPos );
+
+ if( UPDATE_CHAR & eFlags )
+ {
+ if( IsFont() )
+ {
+ rSet.Put( rChg.GetFont() );
+ rSet.Put( rChg.GetHeight() );
+ rSet.Put( rChg.GetWeight() );
+ rSet.Put( rChg.GetPosture() );
+ // #103065# do not insert empty CJK font
+ const SvxFontItem& rCJKFont = rChg.GetCJKFont();
+ if( rCJKFont.GetStyleName().Len() )
+ {
+ rSet.Put( rChg.GetCJKFont() );
+ rSet.Put( rChg.GetCJKHeight() );
+ rSet.Put( rChg.GetCJKWeight() );
+ rSet.Put( rChg.GetCJKPosture() );
+ }
+ else
+ {
+ rSet.Put( rChg.GetHeight(), RES_CHRATR_CJK_FONTSIZE );
+ rSet.Put( rChg.GetWeight(), RES_CHRATR_CJK_WEIGHT );
+ rSet.Put( rChg.GetPosture(), RES_CHRATR_CJK_POSTURE );
+ }
+ // #103065# do not insert empty CTL font
+ const SvxFontItem& rCTLFont = rChg.GetCTLFont();
+ if( rCTLFont.GetStyleName().Len() )
+ {
+ rSet.Put( rChg.GetCTLFont() );
+ rSet.Put( rChg.GetCTLHeight() );
+ rSet.Put( rChg.GetCTLWeight() );
+ rSet.Put( rChg.GetCTLPosture() );
+ }
+ else
+ {
+ rSet.Put( rChg.GetHeight(), RES_CHRATR_CTL_FONTSIZE );
+ rSet.Put( rChg.GetWeight(), RES_CHRATR_CTL_WEIGHT );
+ rSet.Put( rChg.GetPosture(), RES_CHRATR_CTL_POSTURE );
+ }
+ rSet.Put( rChg.GetUnderline() );
+ rSet.Put( rChg.GetOverline() );
+ rSet.Put( rChg.GetCrossedOut() );
+ rSet.Put( rChg.GetContour() );
+ rSet.Put( rChg.GetShadowed() );
+ rSet.Put( rChg.GetColor() );
+ }
+ if( IsJustify() )
+ rSet.Put( rChg.GetAdjust() );
+ }
+
+ if( UPDATE_BOX & eFlags )
+ {
+ if( IsFrame() )
+ {
+ rSet.Put( rChg.GetBox() );
+// FIXME - uncomment the lines to put the diagonal line items
+// rSet.Put( rChg.GetTLBR() );
+// rSet.Put( rChg.GetBLTR() );
+ }
+ if( IsBackground() )
+ rSet.Put( rChg.GetBackground() );
+
+ if( IsValueFormat() && pNFmtr )
+ {
+ String sFmt; LanguageType eLng, eSys;
+ rChg.GetValueFormat( sFmt, eLng, eSys );
+ if( sFmt.Len() )
+ {
+ short nType;
+ sal_Bool bNew;
+ xub_StrLen nCheckPos;
+ sal_uInt32 nKey = pNFmtr->GetIndexPuttingAndConverting( sFmt, eLng,
+ eSys, nType, bNew, nCheckPos);
+ rSet.Put( SwTblBoxNumFormat( nKey ));
+ }
+ else
+ rSet.ClearItem( RES_BOXATR_FORMAT );
+ }
+ }
+
+ // den Rest koennen wir nicht, StarCalc spezifisch
+}
+
+
+sal_Bool SwTableAutoFmt::Load( SvStream& rStream, const SwAfVersions& rVersions )
+{
+ sal_Bool bRet = sal_True;
+ sal_uInt16 nVal = 0;
+ rStream >> nVal;
+ bRet = 0 == rStream.GetError();
+
+ if( bRet && (nVal == AUTOFORMAT_DATA_ID_X ||
+ (AUTOFORMAT_DATA_ID_504 <= nVal && nVal <= AUTOFORMAT_DATA_ID)) )
+ {
+ sal_Bool b;
+ // --- from 680/dr25 on: #21549# store strings as UTF-8
+ CharSet eCharSet = (nVal >= AUTOFORMAT_ID_680DR25) ? RTL_TEXTENCODING_UTF8 : rStream.GetStreamCharSet();
+ rStream.ReadByteString( aName, eCharSet );
+ if( AUTOFORMAT_DATA_ID_552 <= nVal )
+ {
+ rStream >> nStrResId;
+ sal_uInt16 nId = RID_SVXSTR_TBLAFMT_BEGIN + nStrResId;
+ if( RID_SVXSTR_TBLAFMT_BEGIN <= nId &&
+ nId < RID_SVXSTR_TBLAFMT_END )
+ {
+ aName = SVX_RESSTR( nId );
+ }
+ else
+ nStrResId = USHRT_MAX;
+ }
+ rStream >> b; bInclFont = b;
+ rStream >> b; bInclJustify = b;
+ rStream >> b; bInclFrame = b;
+ rStream >> b; bInclBackground = b;
+ rStream >> b; bInclValueFormat = b;
+ rStream >> b; bInclWidthHeight = b;
+
+ bRet = 0 == rStream.GetError();
+
+ for( sal_uInt8 i = 0; i < 16; ++i )
+ {
+ SwBoxAutoFmt* pFmt = new SwBoxAutoFmt;
+ bRet = pFmt->Load( rStream, rVersions, nVal );
+ if( bRet )
+ aBoxAutoFmt[ i ] = pFmt;
+ else
+ {
+ delete pFmt;
+ break;
+ }
+ }
+ }
+ return bRet;
+}
+
+#ifdef READ_OLDVERS
+
+sal_Bool SwTableAutoFmt::LoadOld( SvStream& rStream, sal_uInt16 aLoadVer[] )
+{
+ sal_Bool bRet = sal_True;
+ sal_uInt16 nVal = 0;
+ rStream >> nVal;
+ bRet = 0 == rStream.GetError();
+
+ if( bRet && ( AUTOFORMAT_OLD_DATA_ID == nVal ))
+ {
+ sal_Bool b;
+ rStream.ReadByteString( aName, rStream.GetStreamCharSet() );
+ rStream >> b; bInclFont = b;
+ rStream >> b; bInclJustify = b;
+ rStream >> b; bInclFrame = b;
+ rStream >> b; bInclBackground = b;
+ bRet = (rStream.GetError() == 0);
+
+ for( int i = 0; i < 16; i++)
+ {
+ SwBoxAutoFmt* pFmt = new SwBoxAutoFmt;
+ bRet = pFmt->LoadOld( rStream, aLoadVer );
+ if( bRet )
+ aBoxAutoFmt[ i ] = pFmt;
+ else
+ {
+ delete pFmt;
+ break;
+ }
+ }
+ }
+ return bRet;
+}
+#endif
+
+
+sal_Bool SwTableAutoFmt::Save( SvStream& rStream ) const
+{
+ sal_uInt16 nVal = AUTOFORMAT_DATA_ID;
+ sal_Bool b;
+ rStream << nVal;
+ // --- from 680/dr25 on: #21549# store strings as UTF-8
+ rStream.WriteByteString( aName, RTL_TEXTENCODING_UTF8 );
+ rStream << nStrResId;
+ rStream << ( b = bInclFont );
+ rStream << ( b = bInclJustify );
+ rStream << ( b = bInclFrame );
+ rStream << ( b = bInclBackground );
+ rStream << ( b = bInclValueFormat );
+ rStream << ( b = bInclWidthHeight );
+
+ sal_Bool bRet = 0 == rStream.GetError();
+
+ for( int i = 0; bRet && i < 16; ++i )
+ {
+ SwBoxAutoFmt* pFmt = aBoxAutoFmt[ i ];
+ if( !pFmt ) // nicht gesetzt -> default schreiben
+ {
+ // falls noch nicht vorhanden:
+ if( !pDfltBoxAutoFmt )
+ pDfltBoxAutoFmt = new SwBoxAutoFmt;
+ pFmt = pDfltBoxAutoFmt;
+ }
+ bRet = pFmt->Save( rStream );
+ }
+ return bRet;
+}
+
+
+SwTableAutoFmtTbl::SwTableAutoFmtTbl()
+{
+ String sNm;
+ SwTableAutoFmt* pNew = new SwTableAutoFmt(
+ SwStyleNameMapper::GetUIName( RES_POOLCOLL_STANDARD, sNm ) );
+
+ SwBoxAutoFmt aNew;
+
+ sal_uInt8 i;
+
+ Color aColor( COL_BLUE );
+ SvxBrushItem aBrushItem( aColor, RES_BACKGROUND );
+ aNew.SetBackground( aBrushItem );
+ aNew.SetColor( SvxColorItem(Color( COL_WHITE ), RES_CHRATR_COLOR) );
+
+ for( i = 0; i < 4; ++i )
+ pNew->SetBoxFmt( aNew, i );
+
+ // 70% Grau
+ aBrushItem.SetColor( RGB_COLORDATA( 0x4d, 0x4d, 0x4d ) );
+ aNew.SetBackground( aBrushItem );
+ for( i = 4; i <= 12; i += 4 )
+ pNew->SetBoxFmt( aNew, i );
+
+ // 20% Grau
+ aBrushItem.SetColor( RGB_COLORDATA( 0xcc, 0xcc, 0xcc ) );
+ aNew.SetBackground( aBrushItem );
+ aColor.SetColor( COL_BLACK );
+ aNew.SetColor( SvxColorItem( aColor, RES_CHRATR_COLOR) );
+ for( i = 7; i <= 15; i += 4 )
+ pNew->SetBoxFmt( aNew, i );
+ for( i = 13; i <= 14; ++i )
+ pNew->SetBoxFmt( aNew, i );
+
+ aBrushItem.SetColor( Color( COL_WHITE ) );
+ aNew.SetBackground( aBrushItem );
+ for( i = 5; i <= 6; ++i )
+ pNew->SetBoxFmt( aNew, i );
+ for( i = 9; i <= 10; ++i )
+ pNew->SetBoxFmt( aNew, i );
+
+
+ SvxBoxItem aBox( RES_BOX );
+ aBox.SetDistance( 55 );
+ SvxBorderLine aLn( &aColor, DEF_LINE_WIDTH_0 );
+ aBox.SetLine( &aLn, BOX_LINE_LEFT );
+ aBox.SetLine( &aLn, BOX_LINE_BOTTOM );
+
+ for( i = 0; i <= 15; ++i )
+ {
+ aBox.SetLine( i <= 3 ? &aLn : 0, BOX_LINE_TOP );
+ aBox.SetLine( (3 == ( i & 3 )) ? &aLn : 0, BOX_LINE_RIGHT );
+ ((SwBoxAutoFmt&)pNew->GetBoxFmt( i )).SetBox( aBox );
+ }
+
+ Insert( pNew, Count() );
+}
+
+sal_Bool SwTableAutoFmtTbl::Load()
+{
+ sal_Bool bRet = sal_False;
+ String sNm( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( sAutoTblFmtName )));
+ SvtPathOptions aOpt;
+ if( aOpt.SearchFile( sNm, SvtPathOptions::PATH_USERCONFIG ))
+ {
+ SfxMedium aStream( sNm, STREAM_STD_READ, sal_True );
+ bRet = Load( *aStream.GetInStream() );
+ }
+ else
+ bRet = sal_False;
+ return bRet;
+}
+
+sal_Bool SwTableAutoFmtTbl::Save() const
+{
+ SvtPathOptions aPathOpt;
+ String sNm( aPathOpt.GetUserConfigPath() );
+ sNm += INET_PATH_TOKEN;
+ sNm.AppendAscii( RTL_CONSTASCII_STRINGPARAM( sAutoTblFmtName ));
+ SfxMedium aStream(sNm, STREAM_STD_WRITE, sal_True );
+ return Save( *aStream.GetOutStream() ) && aStream.Commit();
+}
+
+sal_Bool SwTableAutoFmtTbl::Load( SvStream& rStream )
+{
+ sal_Bool bRet = 0 == rStream.GetError();
+ if (bRet)
+ {
+ // Achtung hier muss ein allgemeiner Header gelesen werden
+ sal_uInt16 nVal = 0;
+ rStream >> nVal;
+ bRet = 0 == rStream.GetError();
+
+ if( bRet )
+ {
+ SwAfVersions aVersions;
+
+ if( nVal == AUTOFORMAT_ID_358 ||
+ (AUTOFORMAT_ID_504 <= nVal && nVal <= AUTOFORMAT_ID) )
+ {
+ sal_uInt16 nFileVers = SOFFICE_FILEFORMAT_40;
+ sal_uInt8 nChrSet, nCnt;
+ long nPos = rStream.Tell();
+ rStream >> nCnt >> nChrSet;
+// if( 4 <= nCnt )
+// rStream >> nFileVers;
+ if( rStream.Tell() != sal_uLong(nPos + nCnt) )
+ {
+ ASSERT( !this, "Der Header enthaelt mehr/neuere Daten" );
+ rStream.Seek( nPos + nCnt );
+ }
+ rStream.SetStreamCharSet( (CharSet)nChrSet );
+ rStream.SetVersion( nFileVers );
+ }
+
+ if( nVal == AUTOFORMAT_ID_358 || nVal == AUTOFORMAT_ID_X ||
+ (AUTOFORMAT_ID_504 <= nVal && nVal <= AUTOFORMAT_ID) )
+ {
+ aVersions.Load( rStream, nVal ); // Item-Versionen
+
+ SwTableAutoFmt* pNew;
+ sal_uInt16 nAnz = 0;
+ rStream >> nAnz;
+
+ bRet = 0 == rStream.GetError();
+
+ for( sal_uInt16 i = 0; i < nAnz; ++i )
+ {
+ pNew = new SwTableAutoFmt( aEmptyStr );
+ bRet = pNew->Load( rStream, aVersions );
+ if( bRet )
+ {
+ Insert( pNew, Count() );
+ }
+ else
+ {
+ delete pNew;
+ break;
+ }
+ }
+ }
+#ifdef READ_OLDVERS
+ else if( AUTOFORMAT_OLD_ID == nVal || AUTOFORMAT_OLD_ID1 == nVal )
+ {
+ SwTableAutoFmt* pNew;
+ sal_uInt16 nAnz = 0;
+ rStream >> nAnz;
+
+ sal_uInt16 aArr[ 12 ];
+ memset( aArr, 0, 12 * sizeof( sal_uInt16 ) );
+ if( AUTOFORMAT_OLD_ID1 == nVal )
+ for( sal_uInt16 n = 0; n < 12; ++n )
+ rStream >> aArr[ n ];
+
+ bRet = 0 == rStream.GetError();
+
+ for( sal_uInt16 i = 0; i < nAnz; ++i )
+ {
+ pNew = new SwTableAutoFmt( aEmptyStr );
+ bRet = pNew->LoadOld( rStream, aArr );
+ if( bRet )
+ {
+ Insert( pNew, Count() );
+ }
+ else
+ {
+ delete pNew;
+ break;
+ }
+ }
+ }
+#endif
+ }
+ }
+ return bRet;
+}
+
+
+sal_Bool SwTableAutoFmtTbl::Save( SvStream& rStream ) const
+{
+ sal_Bool bRet = 0 == rStream.GetError();
+ if (bRet)
+ {
+ rStream.SetVersion( SOFFICE_FILEFORMAT_40 );
+
+ // Achtung hier muss ein allgemeiner Header gespeichert werden
+ sal_uInt16 nVal = AUTOFORMAT_ID;
+ rStream << nVal
+ << (sal_uInt8)2 // Anzahl von Zeichen des Headers incl. diesem
+ << (sal_uInt8)GetStoreCharSet( ::gsl_getSystemTextEncoding() );
+// << (sal_uInt8)4 // Anzahl von Zeichen des Headers incl. diesem
+// << (sal_uInt8)::GetSystemCharSet()
+// << (UNIT16)SOFFICE_FILEFORMAT_NOW;
+ bRet = 0 == rStream.GetError();
+
+ //-----------------------------------------------------------
+ // die VersionsNummer fuer alle Attribute schreiben
+ (*this)[ 0 ]->GetBoxFmt( 0 ).SaveVerionNo( rStream );
+
+ rStream << (sal_uInt16)(Count() - 1);
+ bRet = 0 == rStream.GetError();
+
+ for( sal_uInt16 i = 1; bRet && i < Count(); ++i )
+ {
+ SwTableAutoFmt* pFmt = (*this)[ i ];
+ bRet = pFmt->Save( rStream );
+ }
+ }
+ rStream.Flush();
+ return bRet;
+}
+
+
+
diff --git a/sw/source/core/doc/tblcpy.cxx b/sw/source/core/doc/tblcpy.cxx
new file mode 100644
index 000000000000..51e1d455beb5
--- /dev/null
+++ b/sw/source/core/doc/tblcpy.cxx
@@ -0,0 +1,1099 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#define _ZFORLIST_DECLARE_TABLE
+#include <svl/zforlist.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <cntfrm.hxx>
+#include <pam.hxx>
+#include <swtable.hxx>
+#include <ndtxt.hxx>
+#include <fldbas.hxx>
+#include <tblsel.hxx>
+#include <tabfrm.hxx>
+#include <poolfmt.hxx>
+#include <cellatr.hxx>
+#include <mvsave.hxx>
+#include <docary.hxx>
+#include <fmtanchr.hxx>
+#include <hints.hxx>
+#include <UndoTable.hxx>
+#include <redline.hxx>
+#include <fmtfsize.hxx>
+#include <list>
+
+sal_Bool _FndCntntLine( const SwTableLine*& rpLine, void* pPara );
+sal_Bool _FndCntntBox( const SwTableBox*& rpBox, void* pPara );
+void lcl_CpyBox( const SwTable& rCpyTbl, const SwTableBox* pCpyBox,
+ SwTable& rDstTbl, SwTableBox* pDstBox,
+ sal_Bool bDelCntnt, SwUndoTblCpyTbl* pUndo );
+
+// The following type will be used by table copy functions to describe
+// the structure of tables (or parts of tables).
+// It's for new table model only.
+
+namespace
+{
+ struct BoxSpanInfo
+ {
+ SwTableBox* mpBox;
+ SwTableBox* mpCopy;
+ sal_uInt16 mnColSpan;
+ bool mbSelected;
+ };
+
+ typedef std::vector< BoxSpanInfo > BoxStructure;
+ typedef std::vector< BoxStructure > LineStructure;
+ typedef std::list< sal_uLong > ColumnStructure;
+
+ struct SubBox
+ {
+ SwTableBox *mpBox;
+ bool mbCovered;
+ };
+
+ typedef std::list< SubBox > SubLine;
+ typedef std::list< SubLine > SubTable;
+
+ class TableStructure
+ {
+ public:
+ LineStructure maLines;
+ ColumnStructure maCols;
+ sal_uInt16 mnStartCol;
+ sal_uInt16 mnAddLine;
+ void addLine( sal_uInt16 &rLine, const SwTableBoxes&, const SwSelBoxes*,
+ bool bNewModel );
+ void addBox( sal_uInt16 nLine, const SwSelBoxes*, SwTableBox *pBox,
+ sal_uLong &rnB, sal_uInt16 &rnC, ColumnStructure::iterator& rpCl,
+ BoxStructure::iterator& rpSel, bool &rbSel, bool bCover );
+ void incColSpan( sal_uInt16 nLine, sal_uInt16 nCol );
+ TableStructure( const SwTable& rTable );
+ TableStructure( const SwTable& rTable, _FndBox &rFndBox,
+ const SwSelBoxes& rSelBoxes,
+ LineStructure::size_type nMinSize );
+ LineStructure::size_type getLineCount() const
+ { return maLines.size(); }
+ void moreLines( const SwTable& rTable );
+ void assignBoxes( const TableStructure &rSource );
+ void copyBoxes( const SwTable& rSource, SwTable& rDstTbl,
+ SwUndoTblCpyTbl* pUndo ) const;
+ };
+
+ SubTable::iterator insertSubLine( SubTable& rSubTable, SwTableLine& rLine,
+ SubTable::iterator pStartLn );
+
+ SubTable::iterator insertSubBox( SubTable& rSubTable, SwTableBox& rBox,
+ SubTable::iterator pStartLn, SubTable::iterator pEndLn )
+ {
+ if( rBox.GetTabLines().Count() )
+ {
+ SubTable::difference_type nSize = std::distance( pStartLn, pEndLn );
+ if( nSize < rBox.GetTabLines().Count() )
+ {
+ SubLine aSubLine;
+ SubLine::iterator pBox = pStartLn->begin();
+ SubLine::iterator pEnd = pStartLn->end();
+ while( pBox != pEnd )
+ {
+ SubBox aSub;
+ aSub.mpBox = pBox->mpBox;
+ aSub.mbCovered = true;
+ aSubLine.push_back( aSub );
+ ++pBox;
+ }
+ do
+ {
+ rSubTable.insert( pEndLn, aSubLine );
+ } while( ++nSize < rBox.GetTabLines().Count() );
+ }
+ for( sal_uInt16 nLine = 0; nLine < rBox.GetTabLines().Count(); ++nLine )
+ pStartLn = insertSubLine( rSubTable, *rBox.GetTabLines()[nLine],
+ pStartLn );
+ ASSERT( pStartLn == pEndLn, "Sub line confusion" );
+ }
+ else
+ {
+ SubBox aSub;
+ aSub.mpBox = &rBox;
+ aSub.mbCovered = false;
+ while( pStartLn != pEndLn )
+ {
+ pStartLn->push_back( aSub );
+ aSub.mbCovered = true;
+ ++pStartLn;
+ }
+ }
+ return pStartLn;
+ }
+
+ SubTable::iterator insertSubLine( SubTable& rSubTable, SwTableLine& rLine,
+ SubTable::iterator pStartLn )
+ {
+ SubTable::iterator pMax = pStartLn;
+ ++pMax;
+ SubTable::difference_type nMax = 1;
+ for( sal_uInt16 nBox = 0; nBox < rLine.GetTabBoxes().Count(); ++nBox )
+ {
+ SubTable::iterator pTmp = insertSubBox( rSubTable,
+ *rLine.GetTabBoxes()[nBox], pStartLn, pMax );
+ SubTable::difference_type nTmp = std::distance( pStartLn, pTmp );
+ if( nTmp > nMax )
+ {
+ pMax = pTmp;
+ nMax = nTmp;
+ }
+ }
+ return pMax;
+ }
+
+ TableStructure::TableStructure( const SwTable& rTable ) :
+ maLines( rTable.GetTabLines().Count() ), mnStartCol(USHRT_MAX),
+ mnAddLine(0)
+ {
+ maCols.push_front(0);
+ const SwTableLines &rLines = rTable.GetTabLines();
+ sal_uInt16 nCnt = 0;
+ for( sal_uInt16 nLine = 0; nLine < rLines.Count(); ++nLine )
+ addLine( nCnt, rLines[nLine]->GetTabBoxes(), 0, rTable.IsNewModel() );
+ }
+
+ TableStructure::TableStructure( const SwTable& rTable,
+ _FndBox &rFndBox, const SwSelBoxes& rSelBoxes,
+ LineStructure::size_type nMinSize )
+ : mnStartCol(USHRT_MAX), mnAddLine(0)
+ {
+ if( rFndBox.GetLines().Count() )
+ {
+ bool bNoSelection = rSelBoxes.Count() < 2;
+ _FndLines &rFndLines = rFndBox.GetLines();
+ maCols.push_front(0);
+ const SwTableLine* pLine = rFndLines[0]->GetLine();
+ sal_uInt16 nStartLn = rTable.GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ sal_uInt16 nEndLn = nStartLn;
+ if( rFndLines.Count() > 1 )
+ {
+ pLine = rFndLines[ rFndLines.Count()-1 ]->GetLine();
+ nEndLn = rTable.GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ }
+ if( nStartLn < USHRT_MAX && nEndLn < USHRT_MAX )
+ {
+ const SwTableLines &rLines = rTable.GetTabLines();
+ if( bNoSelection &&
+ (sal_uInt16)nMinSize > nEndLn - nStartLn + 1 )
+ {
+ sal_uInt16 nNewEndLn = nStartLn + (sal_uInt16)nMinSize - 1;
+ if( nNewEndLn >= rLines.Count() )
+ {
+ mnAddLine = nNewEndLn - rLines.Count() + 1;
+ nNewEndLn = rLines.Count() - 1;
+ }
+ while( nEndLn < nNewEndLn )
+ {
+ SwTableLine *pLine2 = rLines[ ++nEndLn ];
+ SwTableBox *pTmpBox = pLine2->GetTabBoxes()[0];
+ _FndLine *pInsLine = new _FndLine( pLine2, &rFndBox );
+ _FndBox *pFndBox = new _FndBox( pTmpBox, pInsLine );
+ pInsLine->GetBoxes().C40_INSERT( _FndBox, pFndBox, 0 );
+ rFndLines.C40_INSERT( _FndLine, pInsLine, rFndLines.Count() );
+ }
+ }
+ maLines.resize( nEndLn - nStartLn + 1 );
+ const SwSelBoxes* pSelBoxes = &rSelBoxes;
+ sal_uInt16 nCnt = 0;
+ for( sal_uInt16 nLine = nStartLn; nLine <= nEndLn; ++nLine )
+ {
+ addLine( nCnt, rLines[nLine]->GetTabBoxes(),
+ pSelBoxes, rTable.IsNewModel() );
+ if( bNoSelection )
+ pSelBoxes = 0;
+ }
+ }
+ if( bNoSelection && mnStartCol < USHRT_MAX )
+ {
+ BoxStructure::iterator pC = maLines[0].begin();
+ BoxStructure::iterator pEnd = maLines[0].end();
+ sal_uInt16 nIdx = mnStartCol;
+ mnStartCol = 0;
+ while( nIdx && pC != pEnd )
+ {
+ mnStartCol = mnStartCol + pC->mnColSpan;
+ --nIdx;
+ ++pC;
+ }
+ }
+ else
+ mnStartCol = USHRT_MAX;
+ }
+ }
+
+ void TableStructure::addLine( sal_uInt16 &rLine, const SwTableBoxes& rBoxes,
+ const SwSelBoxes* pSelBoxes, bool bNewModel )
+ {
+ bool bComplex = false;
+ if( !bNewModel )
+ for( sal_uInt16 nBox = 0; !bComplex && nBox < rBoxes.Count(); ++nBox )
+ bComplex = rBoxes[nBox]->GetTabLines().Count() > 0;
+ if( bComplex )
+ {
+ SubTable aSubTable;
+ SubLine aSubLine;
+ aSubTable.push_back( aSubLine );
+ SubTable::iterator pStartLn = aSubTable.begin();
+ SubTable::iterator pEndLn = aSubTable.end();
+ for( sal_uInt16 nBox = 0; nBox < rBoxes.Count(); ++nBox )
+ insertSubBox( aSubTable, *rBoxes[nBox], pStartLn, pEndLn );
+ SubTable::size_type nSize = aSubTable.size();
+ if( nSize )
+ {
+ maLines.resize( maLines.size() + nSize - 1 );
+ while( pStartLn != pEndLn )
+ {
+ bool bSelected = false;
+ sal_uLong nBorder = 0;
+ sal_uInt16 nCol = 0;
+ maLines[rLine].reserve( pStartLn->size() );
+ BoxStructure::iterator pSel = maLines[rLine].end();
+ ColumnStructure::iterator pCol = maCols.begin();
+ SubLine::iterator pBox = pStartLn->begin();
+ SubLine::iterator pEnd = pStartLn->end();
+ while( pBox != pEnd )
+ {
+ addBox( rLine, pSelBoxes, pBox->mpBox, nBorder, nCol,
+ pCol, pSel, bSelected, pBox->mbCovered );
+ ++pBox;
+ }
+ ++rLine;
+ ++pStartLn;
+ }
+ }
+ }
+ else
+ {
+ bool bSelected = false;
+ sal_uLong nBorder = 0;
+ sal_uInt16 nCol = 0;
+ maLines[rLine].reserve( rBoxes.Count() );
+ ColumnStructure::iterator pCol = maCols.begin();
+ BoxStructure::iterator pSel = maLines[rLine].end();
+ for( sal_uInt16 nBox = 0; nBox < rBoxes.Count(); ++nBox )
+ addBox( rLine, pSelBoxes, rBoxes[nBox], nBorder, nCol,
+ pCol, pSel, bSelected, false );
+ ++rLine;
+ }
+ }
+
+ void TableStructure::addBox( sal_uInt16 nLine, const SwSelBoxes* pSelBoxes,
+ SwTableBox *pBox, sal_uLong &rnBorder, sal_uInt16 &rnCol,
+ ColumnStructure::iterator& rpCol, BoxStructure::iterator& rpSel,
+ bool &rbSelected, bool bCovered )
+ {
+ BoxSpanInfo aInfo;
+ if( pSelBoxes &&
+ USHRT_MAX != pSelBoxes->GetPos( pBox ) )
+ {
+ aInfo.mbSelected = true;
+ if( mnStartCol == USHRT_MAX )
+ {
+ mnStartCol = (sal_uInt16)maLines[nLine].size();
+ if( pSelBoxes->Count() < 2 )
+ {
+ pSelBoxes = 0;
+ aInfo.mbSelected = false;
+ }
+ }
+ }
+ else
+ aInfo.mbSelected = false;
+ rnBorder += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ sal_uInt16 nLeftCol = rnCol;
+ while( rpCol != maCols.end() && *rpCol < rnBorder )
+ {
+ ++rnCol;
+ ++rpCol;
+ }
+ if( rpCol == maCols.end() || *rpCol > rnBorder )
+ {
+ maCols.insert( rpCol, rnBorder );
+ --rpCol;
+ incColSpan( nLine, rnCol );
+ }
+ aInfo.mnColSpan = rnCol - nLeftCol;
+ aInfo.mpCopy = 0;
+ aInfo.mpBox = bCovered ? 0 : pBox;
+ maLines[nLine].push_back( aInfo );
+ if( aInfo.mbSelected )
+ {
+ if( rbSelected )
+ {
+ while( rpSel != maLines[nLine].end() )
+ {
+ rpSel->mbSelected = true;
+ ++rpSel;
+ }
+ }
+ else
+ {
+ rpSel = maLines[nLine].end();
+ rbSelected = true;
+ }
+ --rpSel;
+ }
+ }
+
+ void TableStructure::moreLines( const SwTable& rTable )
+ {
+ if( mnAddLine )
+ {
+ const SwTableLines &rLines = rTable.GetTabLines();
+ sal_uInt16 nLineCount = rLines.Count();
+ if( nLineCount < mnAddLine )
+ mnAddLine = nLineCount;
+ sal_uInt16 nLine = (sal_uInt16)maLines.size();
+ maLines.resize( nLine + mnAddLine );
+ while( mnAddLine )
+ {
+ SwTableLine *pLine = rLines[ nLineCount - mnAddLine ];
+ addLine( nLine, pLine->GetTabBoxes(), 0, rTable.IsNewModel() );
+ --mnAddLine;
+ }
+ }
+ }
+
+ void TableStructure::incColSpan( sal_uInt16 nLineMax, sal_uInt16 nNewCol )
+ {
+ for( sal_uInt16 nLine = 0; nLine < nLineMax; ++nLine )
+ {
+ BoxStructure::iterator pInfo = maLines[nLine].begin();
+ BoxStructure::iterator pEnd = maLines[nLine].end();
+ long nCol = pInfo->mnColSpan;
+ while( nNewCol > nCol && ++pInfo != pEnd )
+ nCol += pInfo->mnColSpan;
+ if( pInfo != pEnd )
+ ++(pInfo->mnColSpan);
+ }
+ }
+
+ void TableStructure::assignBoxes( const TableStructure &rSource )
+ {
+ LineStructure::const_iterator pFirstLine = rSource.maLines.begin();
+ LineStructure::const_iterator pLastLine = rSource.maLines.end();
+ if( pFirstLine == pLastLine )
+ return;
+ LineStructure::const_iterator pCurrLine = pFirstLine;
+ LineStructure::size_type nLineCount = maLines.size();
+ sal_uInt16 nFirstStartCol = 0;
+ {
+ BoxStructure::const_iterator pFirstBox = pFirstLine->begin();
+ if( pFirstBox != pFirstLine->end() && pFirstBox->mpBox &&
+ pFirstBox->mpBox->getDummyFlag() )
+ nFirstStartCol = pFirstBox->mnColSpan;
+ }
+ for( LineStructure::size_type nLine = 0; nLine < nLineCount; ++nLine )
+ {
+ BoxStructure::const_iterator pFirstBox = pCurrLine->begin();
+ BoxStructure::const_iterator pLastBox = pCurrLine->end();
+ sal_uInt16 nCurrStartCol = mnStartCol;
+ if( pFirstBox != pLastBox )
+ {
+ BoxStructure::const_iterator pTmpBox = pLastBox;
+ --pTmpBox;
+ if( pTmpBox->mpBox && pTmpBox->mpBox->getDummyFlag() )
+ --pLastBox;
+ if( pFirstBox != pLastBox && pFirstBox->mpBox &&
+ pFirstBox->mpBox->getDummyFlag() )
+ {
+ if( nCurrStartCol < USHRT_MAX )
+ {
+ if( pFirstBox->mnColSpan > nFirstStartCol )
+ nCurrStartCol = pFirstBox->mnColSpan - nFirstStartCol
+ + nCurrStartCol;
+ }
+ ++pFirstBox;
+ }
+ }
+ if( pFirstBox != pLastBox )
+ {
+ BoxStructure::const_iterator pCurrBox = pFirstBox;
+ BoxStructure &rBox = maLines[nLine];
+ BoxStructure::size_type nBoxCount = rBox.size();
+ sal_uInt16 nCol = 0;
+ for( BoxStructure::size_type nBox = 0; nBox < nBoxCount; ++nBox )
+ {
+ BoxSpanInfo& rInfo = rBox[nBox];
+ nCol = nCol + rInfo.mnColSpan;
+ if( rInfo.mbSelected || nCol > nCurrStartCol )
+ {
+ rInfo.mpCopy = pCurrBox->mpBox;
+ if( rInfo.mbSelected && rInfo.mpCopy->getDummyFlag() )
+ {
+ ++pCurrBox;
+ if( pCurrBox == pLastBox )
+ {
+ pCurrBox = pFirstBox;
+ if( pCurrBox->mpBox->getDummyFlag() )
+ ++pCurrBox;
+ }
+ rInfo.mpCopy = pCurrBox->mpBox;
+ }
+ ++pCurrBox;
+ if( pCurrBox == pLastBox )
+ {
+ if( rInfo.mbSelected )
+ pCurrBox = pFirstBox;
+ else
+ {
+ rInfo.mbSelected = rInfo.mpCopy == 0;
+ break;
+ }
+ }
+ rInfo.mbSelected = rInfo.mpCopy == 0;
+ }
+ }
+ }
+ ++pCurrLine;
+ if( pCurrLine == pLastLine )
+ pCurrLine = pFirstLine;
+ }
+ }
+
+ void TableStructure::copyBoxes( const SwTable& rSource, SwTable& rDstTbl,
+ SwUndoTblCpyTbl* pUndo ) const
+ {
+ LineStructure::size_type nLineCount = maLines.size();
+ for( LineStructure::size_type nLine = 0; nLine < nLineCount; ++nLine )
+ {
+ const BoxStructure &rBox = maLines[nLine];
+ BoxStructure::size_type nBoxCount = rBox.size();
+ for( BoxStructure::size_type nBox = 0; nBox < nBoxCount; ++nBox )
+ {
+ const BoxSpanInfo& rInfo = rBox[nBox];
+ if( ( rInfo.mpCopy && !rInfo.mpCopy->getDummyFlag() )
+ || rInfo.mbSelected )
+ {
+ SwTableBox *pBox = rInfo.mpBox;
+ if( pBox && pBox->getRowSpan() > 0 )
+ lcl_CpyBox( rSource, rInfo.mpCopy, rDstTbl, pBox,
+ sal_True, pUndo );
+ /* Idea: If target cell is a covered cell, append content
+ to master cell.
+ sal_Bool bReplace = sal_True;
+ if( pBox->getRowSpan() < 0 )
+ {
+ if( rInfo.mpCopy->getRowSpan() < 0 )
+ continue;
+ pBox = &pBox->FindStartOfRowSpan( rDstTbl );
+ bReplace = sal_False;
+ }
+ lcl_CpyBox( rSource, rInfo.mpCopy, rDstTbl, pBox,
+ bReplace, pUndo );
+ */
+ }
+ }
+ }
+ }
+}
+
+// ---------------------------------------------------------------
+
+// kopiere die Tabelle in diese.
+// Kopiere alle Boxen einer Line in entsprechenden Boxen. Der alte Inhalt
+// wird dabei geloescht.
+// Ist keine mehr vorhanden, kommt der restliche Inhalt in die letzte
+// Box einer "GrundLine".
+// Ist auch keine Line mehr vorhanden, -> auch in die letzte Box
+// einer "GrundLine"
+
+
+void lcl_CpyBox( const SwTable& rCpyTbl, const SwTableBox* pCpyBox,
+ SwTable& rDstTbl, SwTableBox* pDstBox,
+ sal_Bool bDelCntnt, SwUndoTblCpyTbl* pUndo )
+{
+ ASSERT( ( !pCpyBox || pCpyBox->GetSttNd() ) && pDstBox->GetSttNd(),
+ "Keine inhaltstragende Box" );
+
+ SwDoc* pCpyDoc = rCpyTbl.GetFrmFmt()->GetDoc();
+ SwDoc* pDoc = rDstTbl.GetFrmFmt()->GetDoc();
+
+ // kopiere erst den neuen und loeschen dann den alten Inhalt
+ // (keine leeren Section erzeugen; werden sonst geloescht!)
+ std::auto_ptr< SwNodeRange > pRg( pCpyBox ?
+ new SwNodeRange ( *pCpyBox->GetSttNd(), 1,
+ *pCpyBox->GetSttNd()->EndOfSectionNode() ) : 0 );
+
+ SwNodeIndex aInsIdx( *pDstBox->GetSttNd(), bDelCntnt ? 1 :
+ pDstBox->GetSttNd()->EndOfSectionIndex() -
+ pDstBox->GetSttIdx() );
+
+ if( pUndo )
+ pUndo->AddBoxBefore( *pDstBox, bDelCntnt );
+
+ bool bUndoRedline = pUndo && pDoc->IsRedlineOn();
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ SwNodeIndex aSavePos( aInsIdx, -1 );
+ if( pRg.get() )
+ pCpyDoc->CopyWithFlyInFly( *pRg, 0, aInsIdx, sal_False );
+ else
+ pDoc->GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
+ aSavePos++;
+
+ SwTableLine* pLine = pDstBox->GetUpper();
+ while( pLine->GetUpper() )
+ pLine = pLine->GetUpper()->GetUpper();
+
+ sal_Bool bReplaceColl = sal_True;
+ if( bDelCntnt && !bUndoRedline )
+ {
+ // zuerst die Fly loeschen, dann die entsprechenden Nodes
+ SwNodeIndex aEndNdIdx( *aInsIdx.GetNode().EndOfSectionNode() );
+
+ // Bookmarks usw. verschieben
+ {
+ SwPosition aMvPos( aInsIdx );
+ SwCntntNode* pCNd = pDoc->GetNodes().GoPrevious( &aMvPos.nNode );
+ aMvPos.nContent.Assign( pCNd, pCNd->Len() );
+ pDoc->CorrAbs( aInsIdx, aEndNdIdx, aMvPos, /*sal_True*/sal_False );
+ }
+
+ // stehen noch FlyFrames rum, loesche auch diese
+ for( sal_uInt16 n = 0; n < pDoc->GetSpzFrmFmts()->Count(); ++n )
+ {
+ SwFrmFmt *const pFly = (*pDoc->GetSpzFrmFmts())[n];
+ SwFmtAnchor const*const pAnchor = &pFly->GetAnchor();
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
+ (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
+ aInsIdx <= pAPos->nNode && pAPos->nNode <= aEndNdIdx )
+ {
+ pDoc->DelLayoutFmt( pFly );
+ }
+ }
+
+ // ist DestBox eine Headline-Box und hat Tabellen-Vorlage gesetzt,
+ // dann NICHT die TabellenHeadline-Vorlage automatisch setzen
+ if( 1 < rDstTbl.GetTabLines().Count() &&
+ pLine == rDstTbl.GetTabLines()[0] )
+ {
+ SwCntntNode* pCNd = aInsIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ {
+ SwNodeIndex aTmp( aInsIdx );
+ pCNd = pDoc->GetNodes().GoNext( &aTmp );
+ }
+
+ if( pCNd &&
+ /*RES_POOLCOLL_TABLE == */
+ RES_POOLCOLL_TABLE_HDLN !=
+ pCNd->GetFmtColl()->GetPoolFmtId() )
+ bReplaceColl = sal_False;
+ }
+
+ pDoc->GetNodes().Delete( aInsIdx, aEndNdIdx.GetIndex() - aInsIdx.GetIndex() );
+ }
+
+ //b6341295: Table copy redlining will be managed by AddBoxAfter()
+ if( pUndo )
+ pUndo->AddBoxAfter( *pDstBox, aInsIdx, bDelCntnt );
+
+ // heading
+ SwTxtNode *const pTxtNd = aSavePos.GetNode().GetTxtNode();
+ if( pTxtNd )
+ {
+ sal_uInt16 nPoolId = pTxtNd->GetTxtColl()->GetPoolFmtId();
+ if( bReplaceColl &&
+ (( 1 < rDstTbl.GetTabLines().Count() &&
+ pLine == rDstTbl.GetTabLines()[0] )
+ // gilt noch die Tabellen-Inhalt ??
+ ? RES_POOLCOLL_TABLE == nPoolId
+ : RES_POOLCOLL_TABLE_HDLN == nPoolId ) )
+ {
+ SwTxtFmtColl* pColl = pDoc->GetTxtCollFromPool(
+ static_cast<sal_uInt16>(
+ RES_POOLCOLL_TABLE == nPoolId
+ ? RES_POOLCOLL_TABLE_HDLN
+ : RES_POOLCOLL_TABLE ) );
+ if( pColl ) // Vorlage umsetzen
+ {
+ SwPaM aPam( aSavePos );
+ aPam.SetMark();
+ aPam.Move( fnMoveForward, fnGoSection );
+ pDoc->SetTxtFmtColl( aPam, pColl );
+ }
+ }
+
+ // loesche die akt. Formel/Format/Value Werte
+ if( SFX_ITEM_SET == pDstBox->GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT ) ||
+ SFX_ITEM_SET == pDstBox->GetFrmFmt()->GetItemState( RES_BOXATR_FORMULA ) ||
+ SFX_ITEM_SET == pDstBox->GetFrmFmt()->GetItemState( RES_BOXATR_VALUE ) )
+ {
+ pDstBox->ClaimFrmFmt()->ResetFmtAttr( RES_BOXATR_FORMAT,
+ RES_BOXATR_VALUE );
+ }
+
+ // kopiere die TabellenBoxAttribute - Formel/Format/Value
+ if( pCpyBox )
+ {
+ SfxItemSet aBoxAttrSet( pCpyDoc->GetAttrPool(), RES_BOXATR_FORMAT,
+ RES_BOXATR_VALUE );
+ aBoxAttrSet.Put( pCpyBox->GetFrmFmt()->GetAttrSet() );
+ if( aBoxAttrSet.Count() )
+ {
+ const SfxPoolItem* pItem;
+ SvNumberFormatter* pN = pDoc->GetNumberFormatter( sal_False );
+ if( pN && pN->HasMergeFmtTbl() && SFX_ITEM_SET == aBoxAttrSet.
+ GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem ) )
+ {
+ sal_uLong nOldIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
+ sal_uLong nNewIdx = pN->GetMergeFmtIndex( nOldIdx );
+ if( nNewIdx != nOldIdx )
+ aBoxAttrSet.Put( SwTblBoxNumFormat( nNewIdx ));
+ }
+ pDstBox->ClaimFrmFmt()->SetFmtAttr( aBoxAttrSet );
+ }
+ }
+ }
+}
+
+sal_Bool SwTable::InsNewTable( const SwTable& rCpyTbl, const SwSelBoxes& rSelBoxes,
+ SwUndoTblCpyTbl* pUndo )
+{
+ SwDoc* pDoc = GetFrmFmt()->GetDoc();
+ SwDoc* pCpyDoc = rCpyTbl.GetFrmFmt()->GetDoc();
+
+ SwTblNumFmtMerge aTNFM( *pCpyDoc, *pDoc );
+
+ // analyse source structure
+ TableStructure aCopyStruct( rCpyTbl );
+
+ // analyse target structure (from start box) and selected substructure
+ _FndBox aFndBox( 0, 0 );
+ { // get all boxes/lines
+ _FndPara aPara( rSelBoxes, &aFndBox );
+ GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ }
+ TableStructure aTarget( *this, aFndBox, rSelBoxes, aCopyStruct.getLineCount() );
+
+ bool bClear = false;
+ if( aTarget.mnAddLine && IsNewModel() )
+ {
+ SwSelBoxes aBoxes;
+ aBoxes.Insert( GetTabLines()[ GetTabLines().Count()-1 ]->GetTabBoxes()[0] );
+ if( pUndo )
+ pUndo->InsertRow( *this, aBoxes, aTarget.mnAddLine );
+ else
+ InsertRow( pDoc, aBoxes, aTarget.mnAddLine, sal_True );
+
+ aTarget.moreLines( *this );
+ bClear = true;
+ }
+
+ // find mapping, if needed extend target table and/or selection
+ aTarget.assignBoxes( aCopyStruct );
+
+ {
+ // Change table formulas into relative representation
+ SwTableFmlUpdate aMsgHnt( &rCpyTbl );
+ aMsgHnt.eFlags = TBL_RELBOXNAME;
+ pCpyDoc->UpdateTblFlds( &aMsgHnt );
+ }
+
+ // delete frames
+ aFndBox.SetTableLines( *this );
+ if( bClear )
+ aFndBox.ClearLineBehind();
+ aFndBox.DelFrms( *this );
+
+ // copy boxes
+ aTarget.copyBoxes( rCpyTbl, *this, pUndo );
+
+ // adjust row span attributes accordingly
+
+ // make frames
+ aFndBox.MakeFrms( *this );
+
+ return sal_True;
+}
+
+// ---------------------------------------------------------------
+
+// kopiere die Tabelle in diese.
+// Kopiere alle Boxen einer Line in entsprechenden Boxen. Der alte Inhalt
+// wird dabei geloescht.
+// Ist keine mehr vorhanden, kommt der restliche Inhalt in die letzte
+// Box einer "GrundLine".
+// Ist auch keine Line mehr vorhanden, -> auch in die letzte Box
+// einer "GrundLine"
+
+
+sal_Bool SwTable::InsTable( const SwTable& rCpyTbl, const SwNodeIndex& rSttBox,
+ SwUndoTblCpyTbl* pUndo )
+{
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ SwDoc* pDoc = GetFrmFmt()->GetDoc();
+
+ SwTableNode* pTblNd = pDoc->IsIdxInTbl( rSttBox );
+
+ // suche erstmal die Box, in die kopiert werden soll:
+ SwTableBox* pMyBox = (SwTableBox*)GetTblBox(
+ rSttBox.GetNode().FindTableBoxStartNode()->GetIndex() );
+
+ ASSERT( pMyBox, "Index steht nicht in dieser Tabelle in einer Box" );
+
+ // loesche erstmal die Frames der Tabelle
+ _FndBox aFndBox( 0, 0 );
+ aFndBox.DelFrms( pTblNd->GetTable() );
+
+ SwDoc* pCpyDoc = rCpyTbl.GetFrmFmt()->GetDoc();
+
+ {
+ // Tabellen-Formeln in die relative Darstellung umwandeln
+ SwTableFmlUpdate aMsgHnt( &rCpyTbl );
+ aMsgHnt.eFlags = TBL_RELBOXNAME;
+ pCpyDoc->UpdateTblFlds( &aMsgHnt );
+ }
+
+ SwTblNumFmtMerge aTNFM( *pCpyDoc, *pDoc );
+
+ sal_Bool bDelCntnt = sal_True;
+ const SwTableBox* pTmp;
+
+ for( sal_uInt16 nLines = 0; nLines < rCpyTbl.GetTabLines().Count(); ++nLines )
+ {
+ // hole die erste Box von der Copy-Line
+ const SwTableBox* pCpyBox = rCpyTbl.GetTabLines()[nLines]
+ ->GetTabBoxes()[0];
+ while( pCpyBox->GetTabLines().Count() )
+ pCpyBox = pCpyBox->GetTabLines()[0]->GetTabBoxes()[0];
+
+ do {
+ // kopiere erst den neuen und loeschen dann den alten Inhalt
+ // (keine leeren Section erzeugen, werden sonst geloescht!)
+ lcl_CpyBox( rCpyTbl, pCpyBox, *this, pMyBox, bDelCntnt, pUndo );
+
+ if( 0 == (pTmp = pCpyBox->FindNextBox( rCpyTbl, pCpyBox, sal_False )))
+ break; // es folgt keine weitere Box mehr
+ pCpyBox = pTmp;
+
+ if( 0 == ( pTmp = pMyBox->FindNextBox( *this, pMyBox, sal_False )))
+ bDelCntnt = sal_False; // kein Platz mehr ??
+ else
+ pMyBox = (SwTableBox*)pTmp;
+
+ } while( sal_True );
+
+ // suche die oberste Line
+ SwTableLine* pNxtLine = pMyBox->GetUpper();
+ while( pNxtLine->GetUpper() )
+ pNxtLine = pNxtLine->GetUpper()->GetUpper();
+ sal_uInt16 nPos = GetTabLines().C40_GETPOS( SwTableLine, pNxtLine );
+ // gibt es eine naechste ??
+ if( nPos + 1 >= GetTabLines().Count() )
+ bDelCntnt = sal_False; // es gibt keine, alles in die letzte Box
+ else
+ {
+ // suche die naechste "Inhaltstragende Box"
+ pNxtLine = GetTabLines()[ nPos+1 ];
+ pMyBox = pNxtLine->GetTabBoxes()[0];
+ while( pMyBox->GetTabLines().Count() )
+ pMyBox = pMyBox->GetTabLines()[0]->GetTabBoxes()[0];
+ bDelCntnt = sal_True;
+ }
+ }
+
+ aFndBox.MakeFrms( pTblNd->GetTable() ); // erzeuge die Frames neu
+ return sal_True;
+}
+
+
+sal_Bool SwTable::InsTable( const SwTable& rCpyTbl, const SwSelBoxes& rSelBoxes,
+ SwUndoTblCpyTbl* pUndo )
+{
+ ASSERT( rSelBoxes.Count(), "Missing selection" )
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ if( IsNewModel() || rCpyTbl.IsNewModel() )
+ return InsNewTable( rCpyTbl, rSelBoxes, pUndo );
+
+ ASSERT( !rCpyTbl.IsTblComplex(), "Table too complex" )
+
+ SwDoc* pDoc = GetFrmFmt()->GetDoc();
+ SwDoc* pCpyDoc = rCpyTbl.GetFrmFmt()->GetDoc();
+
+ SwTblNumFmtMerge aTNFM( *pCpyDoc, *pDoc );
+
+ SwTableBox *pTmpBox, *pSttBox = (SwTableBox*)rSelBoxes[0];
+
+ sal_uInt16 nLn, nBx;
+ _FndLine *pFLine, *pInsFLine = 0;
+ _FndBox aFndBox( 0, 0 );
+ // suche alle Boxen / Lines
+ {
+ _FndPara aPara( rSelBoxes, &aFndBox );
+ ((SwTableLines&)GetTabLines()).ForEach( &_FndLineCopyCol, &aPara );
+ }
+
+ // JP 06.09.96: Sonderfall - eine Box in der Tabelle -> in alle
+ // selektierten Boxen kopieren!
+ if( 1 != rCpyTbl.GetTabSortBoxes().Count() )
+ {
+ SwTableLine* pSttLine = pSttBox->GetUpper();
+ sal_uInt16 nSttBox = pSttLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSttBox );
+ sal_uInt16 nSttLine = GetTabLines().C40_GETPOS( SwTableLine, pSttLine );
+ _FndBox* pFndBox;
+
+ sal_uInt16 nFndCnt = aFndBox.GetLines().Count();
+ if( !nFndCnt )
+ return sal_False;
+
+ // teste ob genug Platz fuer die einzelnen Lines und Boxen ist:
+ sal_uInt16 nTstLns = 0;
+ pFLine = aFndBox.GetLines()[ 0 ];
+ pSttLine = pFLine->GetLine();
+ nSttLine = GetTabLines().C40_GETPOS( SwTableLine, pSttLine );
+ // sind ueberhaupt soviele Zeilen vorhanden
+ if( 1 == nFndCnt )
+ {
+ // in der Tabelle noch genug Platz ??
+ if( (GetTabLines().Count() - nSttLine ) <
+ rCpyTbl.GetTabLines().Count() )
+ {
+ // sollte nicht mehr soviele Lines vorhanden sein, dann
+ // teste, ob man durch einfuegen neuer zum Ziel kommt. Aber
+ // nur wenn die SSelection eine Box umfasst !!
+ if( 1 < rSelBoxes.Count() )
+ return sal_False;
+
+ sal_uInt16 nNewLns = rCpyTbl.GetTabLines().Count() -
+ (GetTabLines().Count() - nSttLine );
+
+ // Dann teste mal ob die Anzahl der Boxen fuer die Lines reicht
+ SwTableLine* pLastLn = GetTabLines()[ GetTabLines().Count()-1 ];
+
+ pSttBox = pFLine->GetBoxes()[0]->GetBox();
+ nSttBox = pFLine->GetLine()->GetTabBoxes().C40_GETPOS( SwTableBox, pSttBox );
+ for( sal_uInt16 n = rCpyTbl.GetTabLines().Count() - nNewLns;
+ n < rCpyTbl.GetTabLines().Count(); ++n )
+ {
+ SwTableLine* pCpyLn = rCpyTbl.GetTabLines()[ n ];
+
+ if( pLastLn->GetTabBoxes().Count() < nSttBox ||
+ ( pLastLn->GetTabBoxes().Count() - nSttBox ) <
+ pCpyLn->GetTabBoxes().Count() )
+ return sal_False;
+
+ // Test auf Verschachtelungen
+ for( nBx = 0; nBx < pCpyLn->GetTabBoxes().Count(); ++nBx )
+ if( !( pTmpBox = pLastLn->GetTabBoxes()[ nSttBox + nBx ])
+ ->GetSttNd() )
+ return sal_False;
+ }
+ // es ist also Platz fuer das zu kopierende vorhanden, also
+ // fuege entsprechend neue Zeilen ein.
+ SwTableBox* pInsBox = pLastLn->GetTabBoxes()[ nSttBox ];
+ ASSERT( pInsBox && pInsBox->GetSttNd(),
+ "kein CntntBox oder steht nicht in dieser Tabelle" );
+ SwSelBoxes aBoxes;
+
+ if( pUndo
+ ? !pUndo->InsertRow( *this, SelLineFromBox( pInsBox,
+ aBoxes, sal_True ), nNewLns )
+ : !InsertRow( pDoc, SelLineFromBox( pInsBox,
+ aBoxes, sal_True ), nNewLns, sal_True ) )
+ return sal_False;
+ }
+
+ nTstLns = rCpyTbl.GetTabLines().Count(); // soviele Kopieren
+ }
+ else if( 0 == (nFndCnt % rCpyTbl.GetTabLines().Count()) )
+ nTstLns = nFndCnt;
+ else
+ return sal_False; // kein Platz fuer die Zeilen
+
+ for( nLn = 0; nLn < nTstLns; ++nLn )
+ {
+ // Zeilen sind genug vorhanden, dann ueberpruefe die Boxen
+ // je Zeile
+ pFLine = aFndBox.GetLines()[ nLn % nFndCnt ];
+ SwTableLine* pLine = pFLine->GetLine();
+ pSttBox = pFLine->GetBoxes()[0]->GetBox();
+ nSttBox = pLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSttBox );
+ if( nLn >= nFndCnt )
+ {
+ // es sind im ClipBoard mehr Zeilen als selectiert wurden
+ pInsFLine = new _FndLine( GetTabLines()[ nSttLine + nLn ],
+ &aFndBox );
+ pLine = pInsFLine->GetLine();
+ }
+ SwTableLine* pCpyLn = rCpyTbl.GetTabLines()[ nLn %
+ rCpyTbl.GetTabLines().Count() ];
+
+ // zu wenig Zeilen selektiert ?
+ if( pInsFLine )
+ {
+ // eine neue Zeile wird in die FndBox eingefuegt,
+ if( pLine->GetTabBoxes().Count() < nSttBox ||
+ ( pLine->GetTabBoxes().Count() - nSttBox ) <
+ pFLine->GetBoxes().Count() )
+ return sal_False;
+
+ // Test auf Verschachtelungen
+ for( nBx = 0; nBx < pFLine->GetBoxes().Count(); ++nBx )
+ {
+ if( !( pTmpBox = pLine->GetTabBoxes()[ nSttBox + nBx ])
+ ->GetSttNd() )
+ return sal_False;
+ // wenn Ok, fuege die Box in die FndLine zu
+ pFndBox = new _FndBox( pTmpBox, pInsFLine );
+ pInsFLine->GetBoxes().C40_INSERT( _FndBox, pFndBox, nBx );
+ }
+ aFndBox.GetLines().C40_INSERT( _FndLine, pInsFLine, nLn );
+ }
+ else if( pFLine->GetBoxes().Count() == 1 )
+ {
+ if( pLine->GetTabBoxes().Count() < nSttBox ||
+ ( pLine->GetTabBoxes().Count() - nSttBox ) <
+ pCpyLn->GetTabBoxes().Count() )
+ return sal_False;
+
+ // Test auf Verschachtelungen
+ for( nBx = 0; nBx < pCpyLn->GetTabBoxes().Count(); ++nBx )
+ {
+ if( !( pTmpBox = pLine->GetTabBoxes()[ nSttBox + nBx ])
+ ->GetSttNd() )
+ return sal_False;
+ // wenn Ok, fuege die Box in die FndLine zu
+ if( nBx == pFLine->GetBoxes().Count() )
+ {
+ pFndBox = new _FndBox( pTmpBox, pFLine );
+ pFLine->GetBoxes().C40_INSERT( _FndBox, pFndBox, nBx );
+ }
+ }
+ }
+ else
+ {
+ // ueberpruefe die selektierten Boxen mit denen im Clipboard
+ // (n-Fach)
+ if( 0 != ( pFLine->GetBoxes().Count() %
+ pCpyLn->GetTabBoxes().Count() ))
+ return sal_False;
+
+ // Test auf Verschachtelungen
+ for( nBx = 0; nBx < pFLine->GetBoxes().Count(); ++nBx )
+ if( !pFLine->GetBoxes()[ nBx ]->GetBox()->GetSttNd() )
+ return sal_False;
+ }
+ }
+
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+ }
+
+ {
+ // Tabellen-Formeln in die relative Darstellung umwandeln
+ SwTableFmlUpdate aMsgHnt( &rCpyTbl );
+ aMsgHnt.eFlags = TBL_RELBOXNAME;
+ pCpyDoc->UpdateTblFlds( &aMsgHnt );
+ }
+
+ // loesche die Frames
+ aFndBox.SetTableLines( *this );
+ aFndBox.DelFrms( *this );
+
+ if( 1 == rCpyTbl.GetTabSortBoxes().Count() )
+ {
+ SwTableBox *pTmpBx = rCpyTbl.GetTabSortBoxes()[0];
+ for( sal_uInt16 n = 0; n < rSelBoxes.Count(); ++n )
+ lcl_CpyBox( rCpyTbl, pTmpBx, *this,
+ (SwTableBox*)rSelBoxes[n], sal_True, pUndo );
+ }
+ else
+ for( nLn = 0; nLn < aFndBox.GetLines().Count(); ++nLn )
+ {
+ pFLine = aFndBox.GetLines()[ nLn ];
+ SwTableLine* pCpyLn = rCpyTbl.GetTabLines()[
+ nLn % rCpyTbl.GetTabLines().Count() ];
+ for( nBx = 0; nBx < pFLine->GetBoxes().Count(); ++nBx )
+ {
+ // Kopiere in pMyBox die pCpyBox
+ lcl_CpyBox( rCpyTbl, pCpyLn->GetTabBoxes()[
+ nBx % pCpyLn->GetTabBoxes().Count() ],
+ *this, pFLine->GetBoxes()[ nBx ]->GetBox(), sal_True, pUndo );
+ }
+ }
+
+ aFndBox.MakeFrms( *this );
+ return sal_True;
+}
+
+
+
+sal_Bool _FndCntntBox( const SwTableBox*& rpBox, void* pPara )
+{
+ SwTableBox* pBox = (SwTableBox*)rpBox;
+ if( rpBox->GetTabLines().Count() )
+ pBox->GetTabLines().ForEach( &_FndCntntLine, pPara );
+ else
+ ((SwSelBoxes*)pPara)->Insert( pBox );
+ return sal_True;
+}
+
+
+sal_Bool _FndCntntLine( const SwTableLine*& rpLine, void* pPara )
+{
+ ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &_FndCntntBox, pPara );
+ return sal_True;
+}
+
+
+// suche alle Inhaltstragenden-Boxen dieser Box
+SwSelBoxes& SwTable::SelLineFromBox( const SwTableBox* pBox,
+ SwSelBoxes& rBoxes, sal_Bool bToTop ) const
+{
+ SwTableLine* pLine = (SwTableLine*)pBox->GetUpper();
+ if( bToTop )
+ while( pLine->GetUpper() )
+ pLine = pLine->GetUpper()->GetUpper();
+
+ // alle alten loeschen
+ rBoxes.Remove( sal_uInt16(0), rBoxes.Count() );
+ pLine->GetTabBoxes().ForEach( &_FndCntntBox, &rBoxes );
+ return rBoxes;
+}
+
+
diff --git a/sw/source/core/doc/tblrwcl.cxx b/sw/source/core/doc/tblrwcl.cxx
new file mode 100644
index 000000000000..e4a522ce2960
--- /dev/null
+++ b/sw/source/core/doc/tblrwcl.cxx
@@ -0,0 +1,4770 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <hintids.hxx>
+
+#define _ZFORLIST_DECLARE_TABLE
+#include <editeng/brshitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/protitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <tools/fract.hxx>
+#include <fmtfsize.hxx>
+#include <fmtornt.hxx>
+#include <doc.hxx>
+#include <cntfrm.hxx>
+#include <tabfrm.hxx>
+#include <frmtool.hxx>
+#include <pam.hxx>
+#include <swtable.hxx>
+#include <ndtxt.hxx>
+#include <tblsel.hxx>
+#include <fldbas.hxx>
+#include <swundo.hxx>
+#include <rowfrm.hxx>
+#include <ddefld.hxx>
+#include <hints.hxx>
+#include <UndoTable.hxx>
+#include <cellatr.hxx>
+#include <mvsave.hxx>
+#include <swtblfmt.hxx>
+#include <swddetbl.hxx>
+#include <poolfmt.hxx>
+#include <tblrwcl.hxx>
+#include <unochart.hxx>
+#include <boost/shared_ptr.hpp>
+
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+
+
+#define COLFUZZY 20
+#define ROWFUZZY 10
+
+using namespace ::com::sun::star;
+
+#ifndef DBG_UTIL
+#define CHECK_TABLE(t)
+#else
+#ifdef DEBUG
+#define CHECK_TABLE(t) (t).CheckConsistency();
+#else
+#define CHECK_TABLE(t)
+#endif
+#endif
+
+typedef SwTableLine* SwTableLinePtr;
+SV_DECL_PTRARR_SORT( SwSortTableLines, SwTableLinePtr, 16, 16 )
+SV_IMPL_PTRARR_SORT( SwSortTableLines, SwTableLinePtr );
+
+SV_IMPL_PTRARR( _SwShareBoxFmts, SwShareBoxFmt* )
+
+// fuers setzen der Frame-Formate an den Boxen reicht es, das aktuelle
+// im Array zu suchen. Ist es vorhanden, so gebe das neue zurueck
+struct _CpyTabFrm
+{
+ union {
+ SwTableBoxFmt *pFrmFmt; // fuer CopyCol
+ SwTwips nSize; // fuer DelCol
+ } Value;
+ SwTableBoxFmt *pNewFrmFmt;
+
+ _CpyTabFrm( SwTableBoxFmt* pAktFrmFmt ) : pNewFrmFmt( 0 )
+ { Value.pFrmFmt = pAktFrmFmt; }
+
+ _CpyTabFrm& operator=( const _CpyTabFrm& );
+
+ sal_Bool operator==( const _CpyTabFrm& rCpyTabFrm )
+ { return (sal_uLong)Value.nSize == (sal_uLong)rCpyTabFrm.Value.nSize; }
+ sal_Bool operator<( const _CpyTabFrm& rCpyTabFrm )
+ { return (sal_uLong)Value.nSize < (sal_uLong)rCpyTabFrm.Value.nSize; }
+};
+
+struct CR_SetBoxWidth
+{
+ SwSelBoxes aBoxes;
+ SwSortTableLines aLines;
+ SvUShorts aLinesWidth;
+ SwShareBoxFmts aShareFmts;
+ SwTableNode* pTblNd;
+ SwUndoTblNdsChg* pUndo;
+ SwTwips nDiff, nSide, nMaxSize, nLowerDiff;
+ TblChgMode nMode;
+ sal_uInt16 nTblWidth, nRemainWidth, nBoxWidth;
+ sal_Bool bBigger, bLeft, bSplittBox, bAnyBoxFnd;
+
+ CR_SetBoxWidth( sal_uInt16 eType, SwTwips nDif, SwTwips nSid, SwTwips nTblW,
+ SwTwips nMax, SwTableNode* pTNd )
+ : pTblNd( pTNd ),
+ nDiff( nDif ), nSide( nSid ), nMaxSize( nMax ), nLowerDiff( 0 ),
+ nTblWidth( (sal_uInt16)nTblW ), nRemainWidth( 0 ), nBoxWidth( 0 ),
+ bSplittBox( sal_False ), bAnyBoxFnd( sal_False )
+ {
+ bLeft = nsTblChgWidthHeightType::WH_COL_LEFT == ( eType & 0xff ) ||
+ nsTblChgWidthHeightType::WH_CELL_LEFT == ( eType & 0xff );
+ bBigger = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_BIGGER );
+ nMode = pTblNd->GetTable().GetTblChgMode();
+ }
+ CR_SetBoxWidth( const CR_SetBoxWidth& rCpy )
+ : pTblNd( rCpy.pTblNd ),
+ pUndo( rCpy.pUndo ),
+ nDiff( rCpy.nDiff ), nSide( rCpy.nSide ),
+ nMaxSize( rCpy.nMaxSize ), nLowerDiff( 0 ),
+ nMode( rCpy.nMode ), nTblWidth( rCpy.nTblWidth ),
+ nRemainWidth( rCpy.nRemainWidth ), nBoxWidth( nBoxWidth ),
+ bBigger( rCpy.bBigger ), bLeft( rCpy.bLeft ),
+ bSplittBox( rCpy.bSplittBox ), bAnyBoxFnd( rCpy.bAnyBoxFnd )
+ {
+ aLines.Insert( &rCpy.aLines );
+ aLinesWidth.Insert( &rCpy.aLinesWidth, 0 );
+ }
+
+ SwUndoTblNdsChg* CreateUndo( SwUndoId eUndoType )
+ {
+ return pUndo = new SwUndoTblNdsChg( eUndoType, aBoxes, *pTblNd );
+ }
+
+ void LoopClear()
+ {
+ nLowerDiff = 0; nRemainWidth = 0;
+ }
+
+ void AddBoxWidth( const SwTableBox& rBox, sal_uInt16 nWidth )
+ {
+ SwTableLinePtr p = (SwTableLine*)rBox.GetUpper();
+ sal_uInt16 nFndPos;
+ if( aLines.Insert( p, nFndPos ))
+ aLinesWidth.Insert( nWidth, nFndPos );
+ else
+ aLinesWidth[ nFndPos ] = aLinesWidth[ nFndPos ] + nWidth;
+ }
+
+ sal_uInt16 GetBoxWidth( const SwTableLine& rLn ) const
+ {
+ SwTableLinePtr p = (SwTableLine*)&rLn;
+ sal_uInt16 nFndPos;
+ if( aLines.Seek_Entry( p, &nFndPos ) )
+ nFndPos = aLinesWidth[ nFndPos ];
+ else
+ nFndPos = 0;
+ return nFndPos;
+ }
+};
+
+sal_Bool lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+sal_Bool lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+sal_Bool lcl_InsSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+sal_Bool lcl_InsOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+sal_Bool lcl_DelSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+sal_Bool lcl_DelOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+
+typedef sal_Bool (*FN_lcl_SetBoxWidth)(SwTableLine*, CR_SetBoxWidth&, SwTwips, sal_Bool );
+
+#if defined(DBG_UTIL) || defined( JP_DEBUG )
+
+void _CheckBoxWidth( const SwTableLine& rLine, SwTwips nSize );
+
+#define CHECKBOXWIDTH \
+ { \
+ SwTwips nSize = GetFrmFmt()->GetFrmSize().GetWidth(); \
+ for( sal_uInt16 nTmp = 0; nTmp < aLines.Count(); ++nTmp ) \
+ ::_CheckBoxWidth( *aLines[ nTmp ], nSize ); \
+ }
+
+#define CHECKTABLELAYOUT \
+ { \
+ for ( sal_uInt16 i = 0; i < GetTabLines().Count(); ++i ) \
+ { \
+ SwFrmFmt* pFmt = GetTabLines()[i]->GetFrmFmt(); \
+ SwClientIter aIter( *pFmt ); \
+ SwClient* pLast = aIter.GoStart(); \
+ if( pLast ) \
+ { \
+ do \
+ { \
+ SwFrm *pFrm = PTR_CAST( SwFrm, pLast ); \
+ if ( pFrm && \
+ ((SwRowFrm*)pFrm)->GetTabLine() == GetTabLines()[i] ) \
+ { \
+ ASSERT( pFrm->GetUpper()->IsTabFrm(), \
+ "Table layout does not match table structure" ) \
+ } \
+ } while ( 0 != ( pLast = aIter++ ) ); \
+ } \
+ } \
+ }
+
+#else
+
+#define CHECKBOXWIDTH
+#define CHECKTABLELAYOUT
+
+#endif
+
+
+struct CR_SetLineHeight
+{
+ SwSelBoxes aBoxes;
+ SwShareBoxFmts aShareFmts;
+ SwTableNode* pTblNd;
+ SwUndoTblNdsChg* pUndo;
+ SwTwips nMaxSpace, nMaxHeight;
+ TblChgMode nMode;
+ sal_uInt16 nLines;
+ sal_Bool bBigger, bTop, bSplittBox, bAnyBoxFnd;
+
+ CR_SetLineHeight( sal_uInt16 eType, SwTableNode* pTNd )
+ : pTblNd( pTNd ), pUndo( 0 ),
+ nMaxSpace( 0 ), nMaxHeight( 0 ), nLines( 0 ),
+ bSplittBox( sal_False ), bAnyBoxFnd( sal_False )
+ {
+ bTop = nsTblChgWidthHeightType::WH_ROW_TOP == ( eType & 0xff ) || nsTblChgWidthHeightType::WH_CELL_TOP == ( eType & 0xff );
+ bBigger = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_BIGGER );
+ if( eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL )
+ bBigger = !bBigger;
+ nMode = pTblNd->GetTable().GetTblChgMode();
+ }
+ CR_SetLineHeight( const CR_SetLineHeight& rCpy )
+ : pTblNd( rCpy.pTblNd ), pUndo( rCpy.pUndo ),
+ nMaxSpace( rCpy.nMaxSpace ), nMaxHeight( rCpy.nMaxHeight ),
+ nMode( rCpy.nMode ), nLines( rCpy.nLines ),
+ bBigger( rCpy.bBigger ), bTop( rCpy.bTop ),
+ bSplittBox( rCpy.bSplittBox ), bAnyBoxFnd( rCpy.bAnyBoxFnd )
+ {}
+
+ SwUndoTblNdsChg* CreateUndo( SwUndoId nUndoType )
+ {
+ return pUndo = new SwUndoTblNdsChg( nUndoType, aBoxes, *pTblNd );
+ }
+};
+
+sal_Bool lcl_SetSelLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+sal_Bool lcl_SetOtherLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+sal_Bool lcl_InsDelSelLine( SwTableLine* pLine, CR_SetLineHeight& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+
+typedef sal_Bool (*FN_lcl_SetLineHeight)(SwTableLine*, CR_SetLineHeight&, SwTwips, sal_Bool );
+
+_CpyTabFrm& _CpyTabFrm::operator=( const _CpyTabFrm& rCpyTabFrm )
+{
+ pNewFrmFmt = rCpyTabFrm.pNewFrmFmt;
+ Value = rCpyTabFrm.Value;
+ return *this;
+}
+
+SV_DECL_VARARR_SORT( _CpyTabFrms, _CpyTabFrm, 0, 50 )
+SV_IMPL_VARARR_SORT( _CpyTabFrms, _CpyTabFrm )
+
+void lcl_DelCpyTabFrmFmts( _CpyTabFrm& rArr );
+
+// ---------------------------------------------------------------
+
+struct _CpyPara
+{
+ boost::shared_ptr< std::vector< std::vector< sal_uLong > > > pWidths;
+ SwDoc* pDoc;
+ SwTableNode* pTblNd;
+ _CpyTabFrms& rTabFrmArr;
+ SwTableLine* pInsLine;
+ SwTableBox* pInsBox;
+ sal_uLong nOldSize, nNewSize; // zum Korrigieren der Size-Attribute
+ sal_uLong nMinLeft, nMaxRight;
+ sal_uInt16 nCpyCnt, nInsPos;
+ sal_uInt16 nLnIdx, nBoxIdx;
+ sal_uInt8 nDelBorderFlag;
+ sal_Bool bCpyCntnt;
+
+ _CpyPara( SwTableNode* pNd, sal_uInt16 nCopies, _CpyTabFrms& rFrmArr,
+ sal_Bool bCopyContent = sal_True )
+ : pDoc( pNd->GetDoc() ), pTblNd( pNd ), rTabFrmArr(rFrmArr),
+ pInsLine(0), pInsBox(0), nOldSize(0), nNewSize(0),
+ nMinLeft(ULONG_MAX), nMaxRight(0),
+ nCpyCnt(nCopies), nInsPos(0),
+ nLnIdx(0), nBoxIdx(0),
+ nDelBorderFlag(0), bCpyCntnt( bCopyContent )
+ {}
+ _CpyPara( const _CpyPara& rPara, SwTableLine* pLine )
+ : pWidths( rPara.pWidths ), pDoc(rPara.pDoc), pTblNd(rPara.pTblNd),
+ rTabFrmArr(rPara.rTabFrmArr), pInsLine(pLine), pInsBox(rPara.pInsBox),
+ nOldSize(0), nNewSize(rPara.nNewSize), nMinLeft( rPara.nMinLeft ),
+ nMaxRight( rPara.nMaxRight ), nCpyCnt(rPara.nCpyCnt), nInsPos(0),
+ nLnIdx( rPara.nLnIdx), nBoxIdx( rPara.nBoxIdx ),
+ nDelBorderFlag( rPara.nDelBorderFlag ), bCpyCntnt( rPara.bCpyCntnt )
+ {}
+ _CpyPara( const _CpyPara& rPara, SwTableBox* pBox )
+ : pWidths( rPara.pWidths ), pDoc(rPara.pDoc), pTblNd(rPara.pTblNd),
+ rTabFrmArr(rPara.rTabFrmArr), pInsLine(rPara.pInsLine), pInsBox(pBox),
+ nOldSize(rPara.nOldSize), nNewSize(rPara.nNewSize),
+ nMinLeft( rPara.nMinLeft ), nMaxRight( rPara.nMaxRight ),
+ nCpyCnt(rPara.nCpyCnt), nInsPos(0), nLnIdx(rPara.nLnIdx), nBoxIdx(rPara.nBoxIdx),
+ nDelBorderFlag( rPara.nDelBorderFlag ), bCpyCntnt( rPara.bCpyCntnt )
+ {}
+ void SetBoxWidth( SwTableBox* pBox );
+};
+
+
+sal_Bool lcl_CopyCol( const _FndBox*& rpFndBox, void* pPara )
+{
+ _CpyPara* pCpyPara = (_CpyPara*)pPara;
+
+ // suche das FrmFmt im Array aller Frame-Formate
+ SwTableBox* pBox = (SwTableBox*)rpFndBox->GetBox();
+ _CpyTabFrm aFindFrm( (SwTableBoxFmt*)pBox->GetFrmFmt() );
+
+ sal_uInt16 nFndPos;
+ if( pCpyPara->nCpyCnt )
+ {
+ if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ))
+ {
+ // fuer das verschachtelte Kopieren sicher auch das neue Format
+ // als alt.
+ SwTableBoxFmt* pNewFmt = (SwTableBoxFmt*)pBox->ClaimFrmFmt();
+
+ // suche die selektierten Boxen in der Line:
+ _FndLine* pCmpLine = NULL;
+ SwFmtFrmSize aFrmSz( pNewFmt->GetFrmSize() );
+
+ bool bDiffCount = false;
+ if( pBox->GetTabLines().Count() )
+ {
+ pCmpLine = rpFndBox->GetLines()[ 0 ];
+ if ( pCmpLine->GetBoxes().Count() != pCmpLine->GetLine()->GetTabBoxes().Count() )
+ bDiffCount = true;
+ }
+
+ if( bDiffCount )
+ {
+ // die erste Line sollte reichen
+ _FndBoxes& rFndBoxes = pCmpLine->GetBoxes();
+ long nSz = 0;
+ for( sal_uInt16 n = rFndBoxes.Count(); n; )
+ nSz += rFndBoxes[ --n ]->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
+ aFrmSz.SetWidth( aFrmSz.GetWidth() -
+ nSz / ( pCpyPara->nCpyCnt + 1 ) );
+ pNewFmt->SetFmtAttr( aFrmSz );
+ aFrmSz.SetWidth( nSz / ( pCpyPara->nCpyCnt + 1 ) );
+
+ // fuer die neue Box ein neues Format mit der Groesse anlegen!
+ aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pNewFmt->GetDoc()->
+ MakeTableLineFmt();
+ *aFindFrm.pNewFrmFmt = *pNewFmt;
+ aFindFrm.pNewFrmFmt->SetFmtAttr( aFrmSz );
+ }
+ else
+ {
+ aFrmSz.SetWidth( aFrmSz.GetWidth() / ( pCpyPara->nCpyCnt + 1 ) );
+ pNewFmt->SetFmtAttr( aFrmSz );
+
+ aFindFrm.pNewFrmFmt = pNewFmt;
+ pCpyPara->rTabFrmArr.Insert( aFindFrm );
+ aFindFrm.Value.pFrmFmt = pNewFmt;
+ pCpyPara->rTabFrmArr.Insert( aFindFrm );
+ }
+ }
+ else
+ {
+ aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ];
+// aFindFrm.pNewFrmFmt->Add( pBox );
+ pBox->ChgFrmFmt( (SwTableBoxFmt*)aFindFrm.pNewFrmFmt );
+ }
+ }
+ else
+ {
+ if( pCpyPara->nDelBorderFlag &&
+ pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ))
+ aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ];
+ else
+ aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
+ }
+
+ if( rpFndBox->GetLines().Count() )
+ {
+ pBox = new SwTableBox( aFindFrm.pNewFrmFmt,
+ rpFndBox->GetLines().Count(), pCpyPara->pInsLine );
+ pCpyPara->pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, pCpyPara->nInsPos++);
+ _CpyPara aPara( *pCpyPara, pBox );
+ aPara.nDelBorderFlag &= 7;
+
+ ((_FndBox*)rpFndBox)->GetLines().ForEach( &lcl_CopyRow, &aPara );
+ }
+ else
+ {
+ ::_InsTblBox( pCpyPara->pDoc, pCpyPara->pTblNd, pCpyPara->pInsLine,
+ aFindFrm.pNewFrmFmt, pBox, pCpyPara->nInsPos++ );
+
+ const _FndBoxes& rFndBxs = rpFndBox->GetUpper()->GetBoxes();
+ if( 8 > pCpyPara->nDelBorderFlag
+ ? pCpyPara->nDelBorderFlag
+ : rpFndBox == rFndBxs[ rFndBxs.Count() - 1 ] )
+ {
+ const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox();
+ if( 8 > pCpyPara->nDelBorderFlag
+ ? rBoxItem.GetTop()
+ : rBoxItem.GetRight() )
+ {
+ aFindFrm.Value.pFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
+
+ SvxBoxItem aNew( rBoxItem );
+ if( 8 > pCpyPara->nDelBorderFlag )
+ aNew.SetLine( 0, BOX_LINE_TOP );
+ else
+ aNew.SetLine( 0, BOX_LINE_RIGHT );
+
+ if( 1 == pCpyPara->nDelBorderFlag ||
+ 8 == pCpyPara->nDelBorderFlag )
+ {
+ // es wird dahinter kopiert, bei allen Boxen die
+ // TopBorderLine loeschen
+ pBox = pCpyPara->pInsLine->GetTabBoxes()[
+ pCpyPara->nInsPos - 1 ];
+ }
+
+ aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
+
+ // ansonsten wird davor kopiert und die erste Line behaelt
+ // die TopLine und an der originalen wird sie entfernt
+ pBox->ClaimFrmFmt()->SetFmtAttr( aNew );
+
+ if( !pCpyPara->nCpyCnt )
+ pCpyPara->rTabFrmArr.Insert( aFindFrm );
+ }
+ }
+ }
+ return sal_True;
+}
+
+sal_Bool lcl_CopyRow( const _FndLine*& rpFndLine, void* pPara )
+{
+ _CpyPara* pCpyPara = (_CpyPara*)pPara;
+ SwTableLine* pNewLine = new SwTableLine(
+ (SwTableLineFmt*)rpFndLine->GetLine()->GetFrmFmt(),
+ rpFndLine->GetBoxes().Count(), pCpyPara->pInsBox );
+ if( pCpyPara->pInsBox )
+ {
+ pCpyPara->pInsBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, pCpyPara->nInsPos++ );
+ }
+ else
+ {
+ pCpyPara->pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pNewLine,
+ pCpyPara->nInsPos++ );
+ }
+
+ _CpyPara aPara( *pCpyPara, pNewLine );
+ ((_FndLine*)rpFndLine)->GetBoxes().ForEach( &lcl_CopyCol, &aPara );
+
+ pCpyPara->nDelBorderFlag &= 0xf8;
+ return sal_True;
+}
+
+//-----------------------------------------------------------
+
+void lcl_InsCol( _FndLine* pFndLn, _CpyPara& rCpyPara, sal_uInt16 nCpyCnt,
+ sal_Bool bBehind )
+{
+ // Bug 29124: nicht nur in den Grundlines kopieren. Wenns geht, so weit
+ // runter wie moeglich.
+ _FndBox* pFBox;
+ if( 1 == pFndLn->GetBoxes().Count() &&
+ !( pFBox = pFndLn->GetBoxes()[ 0 ] )->GetBox()->GetSttNd() )
+ {
+ // eine Box mit mehreren Lines, also in diese Lines einfuegen
+ for( sal_uInt16 n = 0; n < pFBox->GetLines().Count(); ++n )
+ lcl_InsCol( pFBox->GetLines()[ n ], rCpyPara, nCpyCnt, bBehind );
+ }
+ else
+ {
+ rCpyPara.pInsLine = pFndLn->GetLine();
+ SwTableBox* pBox = pFndLn->GetBoxes()[ bBehind ?
+ pFndLn->GetBoxes().Count()-1 : 0 ]->GetBox();
+ rCpyPara.nInsPos = pFndLn->GetLine()->GetTabBoxes().C40_GETPOS( SwTableBox, pBox );
+ if( bBehind )
+ ++rCpyPara.nInsPos;
+
+ for( sal_uInt16 n = 0; n < nCpyCnt; ++n )
+ {
+ if( n + 1 == nCpyCnt && bBehind )
+ rCpyPara.nDelBorderFlag = 9;
+ else
+ rCpyPara.nDelBorderFlag = 8;
+ pFndLn->GetBoxes().ForEach( &lcl_CopyCol, &rCpyPara );
+ }
+ }
+}
+
+SwRowFrm* GetRowFrm( SwTableLine& rLine )
+{
+ SwClientIter aIter( *rLine.GetFrmFmt() );
+ for( SwClient* pFrm = aIter.First( TYPE( SwRowFrm )); pFrm;
+ pFrm = aIter.Next() )
+ if( ((SwRowFrm*)pFrm)->GetTabLine() == &rLine )
+ return (SwRowFrm*)pFrm;
+ return 0;
+}
+
+
+sal_Bool SwTable::InsertCol( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt, sal_Bool bBehind )
+{
+ ASSERT( rBoxes.Count() && nCnt, "keine gueltige Box-Liste" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ sal_Bool bRes = sal_True;
+ if( IsNewModel() )
+ bRes = NewInsertCol( pDoc, rBoxes, nCnt, bBehind );
+ else
+ {
+ // suche alle Boxen / Lines
+ _FndBox aFndBox( 0, 0 );
+ {
+ _FndPara aPara( rBoxes, &aFndBox );
+ GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ }
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ //Lines fuer das Layout-Update herausuchen.
+ aFndBox.SetTableLines( *this );
+ aFndBox.DelFrms( *this );
+
+ // TL_CHART2: nothing to be done since chart2 currently does not want to
+ // get notified about new rows/cols.
+
+ _CpyTabFrms aTabFrmArr;
+ _CpyPara aCpyPara( pTblNd, nCnt, aTabFrmArr );
+
+ for( sal_uInt16 n = 0; n < aFndBox.GetLines().Count(); ++n )
+ lcl_InsCol( aFndBox.GetLines()[ n ], aCpyPara, nCnt, bBehind );
+
+ // dann raeume die Struktur dieser Line noch mal auf, generell alle
+ GCLines();
+
+ //Layout updaten
+ aFndBox.MakeFrms( *this );
+
+ CHECKBOXWIDTH
+ CHECKTABLELAYOUT
+ bRes = sal_True;
+ }
+
+ SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
+ if (pPCD && nCnt)
+ pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind );
+ pDoc->UpdateCharts( GetFrmFmt()->GetName() );
+
+ return bRes;
+}
+
+sal_Bool SwTable::_InsertRow( SwDoc* pDoc, const SwSelBoxes& rBoxes,
+ sal_uInt16 nCnt, sal_Bool bBehind )
+{
+ ASSERT( pDoc && rBoxes.Count() && nCnt, "keine gueltige Box-Liste" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ // suche alle Boxen / Lines
+ _FndBox aFndBox( 0, 0 );
+ {
+ _FndPara aPara( rBoxes, &aFndBox );
+ GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ }
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ _FndBox* pFndBox = &aFndBox;
+ {
+ _FndLine* pFndLine;
+ while( 1 == pFndBox->GetLines().Count() &&
+ 1 == ( pFndLine = pFndBox->GetLines()[ 0 ])->GetBoxes().Count() )
+ {
+ // nicht zu weit runter, eine Line mit Boxen muss nachbleiben!!
+ _FndBox* pTmpBox = pFndLine->GetBoxes()[ 0 ];
+ if( pTmpBox->GetLines().Count() )
+ pFndBox = pTmpBox;
+ else
+ break;
+ }
+ }
+
+ //Lines fuer das Layout-Update herausuchen.
+ const sal_Bool bLayout = !IsNewModel() &&
+ 0 != SwClientIter( *GetFrmFmt() ).First( TYPE(SwTabFrm) );
+
+ if ( bLayout )
+ {
+ aFndBox.SetTableLines( *this );
+ if( pFndBox != &aFndBox )
+ aFndBox.DelFrms( *this );
+ // TL_CHART2: nothing to be done since chart2 currently does not want to
+ // get notified about new rows/cols.
+ }
+
+ _CpyTabFrms aTabFrmArr;
+ _CpyPara aCpyPara( pTblNd, 0, aTabFrmArr );
+
+ SwTableLine* pLine = pFndBox->GetLines()[ bBehind ?
+ pFndBox->GetLines().Count()-1 : 0 ]->GetLine();
+ if( &aFndBox == pFndBox )
+ aCpyPara.nInsPos = GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ else
+ {
+ aCpyPara.pInsBox = pFndBox->GetBox();
+ aCpyPara.nInsPos = pFndBox->GetBox()->GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ }
+
+ if( bBehind )
+ {
+ ++aCpyPara.nInsPos;
+ aCpyPara.nDelBorderFlag = 1;
+ }
+ else
+ aCpyPara.nDelBorderFlag = 2;
+
+ for( sal_uInt16 nCpyCnt = 0; nCpyCnt < nCnt; ++nCpyCnt )
+ {
+ if( bBehind )
+ aCpyPara.nDelBorderFlag = 1;
+ pFndBox->GetLines().ForEach( &lcl_CopyRow, &aCpyPara );
+ }
+
+ // dann raeume die Struktur dieser Line noch mal auf, generell alle
+ if( !pDoc->IsInReading() )
+ GCLines();
+
+ //Layout updaten
+ if ( bLayout )
+ {
+ if( pFndBox != &aFndBox )
+ aFndBox.MakeFrms( *this );
+ else
+ aFndBox.MakeNewFrms( *this, nCnt, bBehind );
+ }
+
+ CHECKBOXWIDTH
+ CHECKTABLELAYOUT
+
+ SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
+ if (pPCD && nCnt)
+ pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind );
+ pDoc->UpdateCharts( GetFrmFmt()->GetName() );
+
+ return sal_True;
+}
+
+sal_Bool _FndBoxAppendRowLine( const SwTableLine*& rpLine, void* pPara );
+
+sal_Bool _FndBoxAppendRowBox( const SwTableBox*& rpBox, void* pPara )
+{
+ _FndPara* pFndPara = (_FndPara*)pPara;
+ _FndBox* pFndBox = new _FndBox( (SwTableBox*)rpBox, pFndPara->pFndLine );
+ if( rpBox->GetTabLines().Count() )
+ {
+ _FndPara aPara( *pFndPara, pFndBox );
+ pFndBox->GetBox()->GetTabLines().ForEach( &_FndBoxAppendRowLine, &aPara );
+ if( !pFndBox->GetLines().Count() )
+ delete pFndBox;
+ }
+ else
+ pFndPara->pFndLine->GetBoxes().C40_INSERT( _FndBox, pFndBox,
+ pFndPara->pFndLine->GetBoxes().Count() );
+ return sal_True;
+}
+
+sal_Bool _FndBoxAppendRowLine( const SwTableLine*& rpLine, void* pPara )
+{
+ _FndPara* pFndPara = (_FndPara*)pPara;
+ _FndLine* pFndLine = new _FndLine( (SwTableLine*)rpLine, pFndPara->pFndBox );
+ _FndPara aPara( *pFndPara, pFndLine );
+ pFndLine->GetLine()->GetTabBoxes().ForEach( &_FndBoxAppendRowBox, &aPara );
+ if( pFndLine->GetBoxes().Count() )
+ {
+ pFndPara->pFndBox->GetLines().C40_INSERT( _FndLine, pFndLine,
+ pFndPara->pFndBox->GetLines().Count() );
+ }
+ else
+ delete pFndLine;
+ return sal_True;
+}
+
+
+sal_Bool SwTable::AppendRow( SwDoc* pDoc, sal_uInt16 nCnt )
+{
+ SwTableNode* pTblNd = (SwTableNode*)aSortCntBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ // suche alle Boxen / Lines
+ _FndBox aFndBox( 0, 0 );
+ {
+ const SwTableLine* pLLine = GetTabLines()[ GetTabLines().Count()-1 ];
+
+ const SwSelBoxes* pBxs = 0; // Dummy !!!
+ _FndPara aPara( *pBxs, &aFndBox );
+
+ _FndBoxAppendRowLine( pLLine, &aPara );
+ }
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ //Lines fuer das Layout-Update herausuchen.
+ const sal_Bool bLayout = 0 != SwClientIter( *GetFrmFmt() ).First( TYPE(SwTabFrm) );
+ if( bLayout )
+ {
+ aFndBox.SetTableLines( *this );
+ // TL_CHART2: nothing to be done since chart2 currently does not want to
+ // get notified about new rows/cols.
+ }
+
+ _CpyTabFrms aTabFrmArr;
+ _CpyPara aCpyPara( pTblNd, 0, aTabFrmArr );
+ aCpyPara.nInsPos = GetTabLines().Count();
+ aCpyPara.nDelBorderFlag = 1;
+
+ for( sal_uInt16 nCpyCnt = 0; nCpyCnt < nCnt; ++nCpyCnt )
+ {
+ aCpyPara.nDelBorderFlag = 1;
+ aFndBox.GetLines().ForEach( &lcl_CopyRow, &aCpyPara );
+ }
+
+ // dann raeume die Struktur dieser Line noch mal auf, generell alle
+ if( !pDoc->IsInReading() )
+ GCLines();
+
+ //Layout updaten
+ if ( bLayout )
+ {
+ aFndBox.MakeNewFrms( *this, nCnt, sal_True );
+ }
+ // TL_CHART2: need to inform chart of probably changed cell names
+ pDoc->UpdateCharts( GetFrmFmt()->GetName() );
+
+ CHECKBOXWIDTH
+ CHECKTABLELAYOUT
+
+ return sal_True;
+}
+
+
+void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const long nOffset,
+ sal_Bool bFirst, SwShareBoxFmts& rShareFmts );
+
+void lcl_LastBoxSetWidthLine( SwTableLines &rLines, const long nOffset,
+ sal_Bool bFirst, SwShareBoxFmts& rShareFmts )
+{
+ for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
+ ::lcl_LastBoxSetWidth( rLines[i]->GetTabBoxes(), nOffset, bFirst,
+ rShareFmts );
+}
+
+void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const long nOffset,
+ sal_Bool bFirst, SwShareBoxFmts& rShareFmts )
+{
+ SwTableBox& rBox = *rBoxes[ bFirst ? 0 : rBoxes.Count() - 1 ];
+ if( !rBox.GetSttNd() )
+ ::lcl_LastBoxSetWidthLine( rBox.GetTabLines(), nOffset,
+ bFirst, rShareFmts );
+
+ //Die Box anpassen
+ SwFrmFmt *pBoxFmt = rBox.GetFrmFmt();
+ SwFmtFrmSize aNew( pBoxFmt->GetFrmSize() );
+ aNew.SetWidth( aNew.GetWidth() + nOffset );
+ SwFrmFmt *pFmt = rShareFmts.GetFormat( *pBoxFmt, aNew );
+ if( pFmt )
+ rBox.ChgFrmFmt( (SwTableBoxFmt*)pFmt );
+ else
+ {
+ pFmt = rBox.ClaimFrmFmt();
+
+ pFmt->LockModify();
+ pFmt->SetFmtAttr( aNew );
+ pFmt->UnlockModify();
+
+ rShareFmts.AddFormat( *pBoxFmt, *pFmt );
+ }
+}
+
+void _DeleteBox( SwTable& rTbl, SwTableBox* pBox, SwUndo* pUndo,
+ sal_Bool bCalcNewSize, const sal_Bool bCorrBorder,
+ SwShareBoxFmts* pShareFmts )
+{
+ do {
+ SwTwips nBoxSz = bCalcNewSize ?
+ pBox->GetFrmFmt()->GetFrmSize().GetWidth() : 0;
+ SwTableLine* pLine = pBox->GetUpper();
+ SwTableBoxes& rTblBoxes = pLine->GetTabBoxes();
+ sal_uInt16 nDelPos = rTblBoxes.C40_GETPOS( SwTableBox, pBox );
+ SwTableBox* pUpperBox = pBox->GetUpper()->GetUpper();
+
+ // Sonderbehandlung fuer Umrandung:
+ if( bCorrBorder && 1 < rTblBoxes.Count() )
+ {
+ sal_Bool bChgd = sal_False;
+ const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox();
+
+ if( rBoxItem.GetLeft() || rBoxItem.GetRight() )
+ {
+ //JP 02.04.97: 1.Teil fuer Bug 36271
+ // zuerst die linken/rechten Kanten
+ if( nDelPos + 1 < rTblBoxes.Count() )
+ {
+ SwTableBox* pNxtBox = rTblBoxes[ nDelPos + 1 ];
+ const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrmFmt()->GetBox();
+
+ SwTableBox* pPrvBox = nDelPos ? rTblBoxes[ nDelPos - 1 ] : 0;
+
+ if( pNxtBox->GetSttNd() && !rNxtBoxItem.GetLeft() &&
+ ( !pPrvBox || !pPrvBox->GetFrmFmt()->GetBox().GetRight()) )
+ {
+ SvxBoxItem aTmp( rNxtBoxItem );
+ aTmp.SetLine( rBoxItem.GetLeft() ? rBoxItem.GetLeft()
+ : rBoxItem.GetRight(),
+ BOX_LINE_LEFT );
+ if( pShareFmts )
+ pShareFmts->SetAttr( *pNxtBox, aTmp );
+ else
+ pNxtBox->ClaimFrmFmt()->SetFmtAttr( aTmp );
+ bChgd = sal_True;
+ }
+ }
+ if( !bChgd && nDelPos )
+ {
+ SwTableBox* pPrvBox = rTblBoxes[ nDelPos - 1 ];
+ const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrmFmt()->GetBox();
+
+ SwTableBox* pNxtBox = nDelPos + 1 < rTblBoxes.Count()
+ ? rTblBoxes[ nDelPos + 1 ] : 0;
+
+ if( pPrvBox->GetSttNd() && !rPrvBoxItem.GetRight() &&
+ ( !pNxtBox || !pNxtBox->GetFrmFmt()->GetBox().GetLeft()) )
+ {
+ SvxBoxItem aTmp( rPrvBoxItem );
+ aTmp.SetLine( rBoxItem.GetLeft() ? rBoxItem.GetLeft()
+ : rBoxItem.GetRight(),
+ BOX_LINE_RIGHT );
+ if( pShareFmts )
+ pShareFmts->SetAttr( *pPrvBox, aTmp );
+ else
+ pPrvBox->ClaimFrmFmt()->SetFmtAttr( aTmp );
+ }
+ }
+ }
+
+ }
+
+ // erst die Box, dann die Nodes loeschen!!
+ SwStartNode* pSttNd = (SwStartNode*)pBox->GetSttNd();
+ if( pShareFmts )
+ pShareFmts->RemoveFormat( *rTblBoxes[ nDelPos ]->GetFrmFmt() );
+ rTblBoxes.DeleteAndDestroy( nDelPos );
+
+ if( pSttNd )
+ {
+ // ist das UndoObject zum speichern der Section vorbereitet?
+ if( pUndo && pUndo->IsDelBox() )
+ ((SwUndoTblNdsChg*)pUndo)->SaveSection( pSttNd );
+ else
+ pSttNd->GetDoc()->DeleteSection( pSttNd );
+ }
+
+ // auch die Zeile noch loeschen ??
+ if( rTblBoxes.Count() )
+ {
+ // dann passe noch die Frame-SSize an
+ sal_Bool bLastBox = nDelPos == rTblBoxes.Count();
+ if( bLastBox )
+ --nDelPos;
+ pBox = rTblBoxes[nDelPos];
+ if( bCalcNewSize )
+ {
+ SwFmtFrmSize aNew( pBox->GetFrmFmt()->GetFrmSize() );
+ aNew.SetWidth( aNew.GetWidth() + nBoxSz );
+ if( pShareFmts )
+ pShareFmts->SetSize( *pBox, aNew );
+ else
+ pBox->ClaimFrmFmt()->SetFmtAttr( aNew );
+
+ if( !pBox->GetSttNd() )
+ {
+ // dann muss es auch rekursiv in allen Zeilen, in allen
+ // Zellen erfolgen!
+ SwShareBoxFmts aShareFmts;
+ ::lcl_LastBoxSetWidthLine( pBox->GetTabLines(), nBoxSz,
+ !bLastBox,
+ pShareFmts ? *pShareFmts
+ : aShareFmts );
+ }
+ }
+ break; // nichts mehr loeschen
+ }
+ // loesche die Line aus Tabelle/Box
+ if( !pUpperBox )
+ {
+ // dann loesche auch noch die Line aus der Tabelle
+ nDelPos = rTbl.GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ if( pShareFmts )
+ pShareFmts->RemoveFormat( *rTbl.GetTabLines()[ nDelPos ]->GetFrmFmt() );
+ rTbl.GetTabLines().DeleteAndDestroy( nDelPos );
+ break; // mehr kann nicht geloescht werden
+ }
+
+ // dann loesche auch noch die Line
+ pBox = pUpperBox;
+ nDelPos = pBox->GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ if( pShareFmts )
+ pShareFmts->RemoveFormat( *pBox->GetTabLines()[ nDelPos ]->GetFrmFmt() );
+ pBox->GetTabLines().DeleteAndDestroy( nDelPos );
+ } while( !pBox->GetTabLines().Count() );
+}
+
+SwTableBox* lcl_FndNxtPrvDelBox( const SwTableLines& rTblLns,
+ SwTwips nBoxStt, SwTwips nBoxWidth,
+ sal_uInt16 nLinePos, sal_Bool bNxt,
+ SwSelBoxes* pAllDelBoxes, sal_uInt16* pCurPos )
+{
+ SwTableBox* pFndBox = 0;
+ do {
+ if( bNxt )
+ ++nLinePos;
+ else
+ --nLinePos;
+ SwTableLine* pLine = rTblLns[ nLinePos ];
+ SwTwips nFndBoxWidth = 0;
+ SwTwips nFndWidth = nBoxStt + nBoxWidth;
+ sal_uInt16 nBoxCnt = pLine->GetTabBoxes().Count();
+
+ pFndBox = pLine->GetTabBoxes()[ 0 ];
+ for( sal_uInt16 n = 0; 0 < nFndWidth && n < nBoxCnt; ++n )
+ {
+ pFndBox = pLine->GetTabBoxes()[ n ];
+ nFndWidth -= (nFndBoxWidth = pFndBox->GetFrmFmt()->
+ GetFrmSize().GetWidth());
+ }
+
+ // suche die erste ContentBox
+ while( !pFndBox->GetSttNd() )
+ {
+ const SwTableLines& rLowLns = pFndBox->GetTabLines();
+ if( bNxt )
+ pFndBox = rLowLns[ 0 ]->GetTabBoxes()[ 0 ];
+ else
+ pFndBox = rLowLns[ rLowLns.Count() - 1 ]->GetTabBoxes()[ 0 ];
+ }
+
+ if( Abs( nFndWidth ) > COLFUZZY ||
+ Abs( nBoxWidth - nFndBoxWidth ) > COLFUZZY )
+ pFndBox = 0;
+ else if( pAllDelBoxes )
+ {
+ // falls der Vorganger auch geloscht wird, ist nicht zu tun
+ sal_uInt16 nFndPos;
+ if( !pAllDelBoxes->Seek_Entry( pFndBox, &nFndPos ) )
+ break;
+
+ // sonst noch mal weitersuchen
+ // Die Box muessen wir aber nicht nochmal abpruefen
+ pFndBox = 0;
+ if( nFndPos <= *pCurPos )
+ --*pCurPos;
+ pAllDelBoxes->Remove( nFndPos );
+ }
+ } while( bNxt ? ( nLinePos + 1 < rTblLns.Count() ) : nLinePos );
+ return pFndBox;
+}
+
+void lcl_SaveUpperLowerBorder( SwTable& rTbl, const SwTableBox& rBox,
+ SwShareBoxFmts& rShareFmts,
+ SwSelBoxes* pAllDelBoxes = 0,
+ sal_uInt16* pCurPos = 0 )
+{
+//JP 16.04.97: 2.Teil fuer Bug 36271
+ sal_Bool bChgd = sal_False;
+ const SwTableLine* pLine = rBox.GetUpper();
+ const SwTableBoxes& rTblBoxes = pLine->GetTabBoxes();
+ const SwTableBox* pUpperBox = &rBox;
+ sal_uInt16 nDelPos = rTblBoxes.C40_GETPOS( SwTableBox, pUpperBox );
+ pUpperBox = rBox.GetUpper()->GetUpper();
+ const SvxBoxItem& rBoxItem = rBox.GetFrmFmt()->GetBox();
+
+ // dann die unteren/oberen Kanten
+ if( rBoxItem.GetTop() || rBoxItem.GetBottom() )
+ {
+ bChgd = sal_False;
+ const SwTableLines* pTblLns;
+ if( pUpperBox )
+ pTblLns = &pUpperBox->GetTabLines();
+ else
+ pTblLns = &rTbl.GetTabLines();
+
+ sal_uInt16 nLnPos = pTblLns->GetPos( pLine );
+
+ // bestimme die Attr.Position der akt. zu loeschenden Box
+ // und suche dann in der unteren / oberen Line die entspr.
+ // Gegenstuecke
+ SwTwips nBoxStt = 0;
+ for( sal_uInt16 n = 0; n < nDelPos; ++n )
+ nBoxStt += rTblBoxes[ n ]->GetFrmFmt()->GetFrmSize().GetWidth();
+ SwTwips nBoxWidth = rBox.GetFrmFmt()->GetFrmSize().GetWidth();
+
+ SwTableBox *pPrvBox = 0, *pNxtBox = 0;
+ if( nLnPos ) // Vorgaenger?
+ pPrvBox = ::lcl_FndNxtPrvDelBox( *pTblLns, nBoxStt, nBoxWidth,
+ nLnPos, sal_False, pAllDelBoxes, pCurPos );
+
+ if( nLnPos + 1 < pTblLns->Count() ) // Nachfolger?
+ pNxtBox = ::lcl_FndNxtPrvDelBox( *pTblLns, nBoxStt, nBoxWidth,
+ nLnPos, sal_True, pAllDelBoxes, pCurPos );
+
+ if( pNxtBox && pNxtBox->GetSttNd() )
+ {
+ const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrmFmt()->GetBox();
+ if( !rNxtBoxItem.GetTop() && ( !pPrvBox ||
+ !pPrvBox->GetFrmFmt()->GetBox().GetBottom()) )
+ {
+ SvxBoxItem aTmp( rNxtBoxItem );
+ aTmp.SetLine( rBoxItem.GetTop() ? rBoxItem.GetTop()
+ : rBoxItem.GetBottom(),
+ BOX_LINE_TOP );
+ rShareFmts.SetAttr( *pNxtBox, aTmp );
+ bChgd = sal_True;
+ }
+ }
+ if( !bChgd && pPrvBox && pPrvBox->GetSttNd() )
+ {
+ const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrmFmt()->GetBox();
+ if( !rPrvBoxItem.GetTop() && ( !pNxtBox ||
+ !pNxtBox->GetFrmFmt()->GetBox().GetTop()) )
+ {
+ SvxBoxItem aTmp( rPrvBoxItem );
+ aTmp.SetLine( rBoxItem.GetTop() ? rBoxItem.GetTop()
+ : rBoxItem.GetBottom(),
+ BOX_LINE_BOTTOM );
+ rShareFmts.SetAttr( *pPrvBox, aTmp );
+ }
+ }
+
+ }
+}
+
+
+sal_Bool SwTable::DeleteSel(
+ SwDoc* pDoc
+ ,
+ const SwSelBoxes& rBoxes,
+ const SwSelBoxes* pMerged, SwUndo* pUndo,
+ const sal_Bool bDelMakeFrms, const sal_Bool bCorrBorder )
+{
+ ASSERT( pDoc, "No doc?" );
+ SwTableNode* pTblNd = 0;
+ if( rBoxes.Count() )
+ {
+ pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+ }
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ //Lines fuer das Layout-Update herausuchen.
+ _FndBox aFndBox( 0, 0 );
+ if ( bDelMakeFrms )
+ {
+ if( pMerged && pMerged->Count() )
+ aFndBox.SetTableLines( *pMerged, *this );
+ else if( rBoxes.Count() )
+ aFndBox.SetTableLines( rBoxes, *this );
+ aFndBox.DelFrms( *this );
+ }
+
+ SwShareBoxFmts aShareFmts;
+
+ // erst die Umrandung umsetzen, dann loeschen
+ if( bCorrBorder )
+ {
+ SwSelBoxes aBoxes;
+ aBoxes.Insert( &rBoxes );
+ for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n )
+ ::lcl_SaveUpperLowerBorder( *this, *rBoxes[ n ], aShareFmts,
+ &aBoxes, &n );
+ }
+
+ PrepareDelBoxes( rBoxes );
+
+ SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
+ //
+ // delete boxes from last to first
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ sal_uInt16 nIdx = rBoxes.Count() - 1 - n;
+
+ // first adapt the data-sequence for chart if necessary
+ // (needed to move the implementation cursor properly to it's new
+ // position which can't be done properly if the cell is already gone)
+ if (pPCD && pTblNd)
+ pPCD->DeleteBox( &pTblNd->GetTable(), *rBoxes[nIdx] );
+
+ // ... then delete the boxes
+ _DeleteBox( *this, rBoxes[nIdx], pUndo, sal_True, bCorrBorder, &aShareFmts );
+ }
+
+ // dann raeume die Struktur aller Lines auf
+ GCLines();
+
+ if( bDelMakeFrms && aFndBox.AreLinesToRestore( *this ) )
+ aFndBox.MakeFrms( *this );
+
+ // TL_CHART2: now inform chart that sth has changed
+ pDoc->UpdateCharts( GetFrmFmt()->GetName() );
+
+ CHECKTABLELAYOUT
+ CHECK_TABLE( *this )
+
+ return sal_True;
+}
+
+
+// ---------------------------------------------------------------
+
+sal_Bool SwTable::OldSplitRow( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt,
+ sal_Bool bSameHeight )
+{
+ ASSERT( pDoc && rBoxes.Count() && nCnt, "keine gueltigen Werte" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ // TL_CHART2: splitting/merging of a number of cells or rows will usually make
+ // the table to complex to be handled with chart.
+ // Thus we tell the charts to use their own data provider and forget about this table
+ pDoc->CreateChartInternalDataProviders( this );
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ // If the rows should get the same (min) height, we first have
+ // to store the old row heights before deleting the frames
+ long* pRowHeights = 0;
+ if ( bSameHeight )
+ {
+ pRowHeights = new long[ rBoxes.Count() ];
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTableBox* pSelBox = *( rBoxes.GetData() + n );
+ const SwRowFrm* pRow = GetRowFrm( *pSelBox->GetUpper() );
+ ASSERT( pRow, "wo ist der Frm von der SwTableLine?" )
+ SWRECTFN( pRow )
+ pRowHeights[ n ] = (pRow->Frm().*fnRect->fnGetHeight)();
+ }
+ }
+
+ //Lines fuer das Layout-Update herausuchen.
+ _FndBox aFndBox( 0, 0 );
+ aFndBox.SetTableLines( rBoxes, *this );
+ aFndBox.DelFrms( *this );
+
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTableBox* pSelBox = *( rBoxes.GetData() + n );
+ ASSERT( pSelBox, "Box steht nicht in der Tabelle" );
+
+ // dann fuege in die Box nCnt neue Zeilen ein
+ SwTableLine* pInsLine = pSelBox->GetUpper();
+ SwTableBoxFmt* pFrmFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt();
+
+ // Hoehe der Line beachten, gegebenenfalls neu setzen
+ SwFmtFrmSize aFSz( pInsLine->GetFrmFmt()->GetFrmSize() );
+ if ( bSameHeight && ATT_VAR_SIZE == aFSz.GetHeightSizeType() )
+ aFSz.SetHeightSizeType( ATT_MIN_SIZE );
+
+ sal_Bool bChgLineSz = 0 != aFSz.GetHeight() || bSameHeight;
+ if ( bChgLineSz )
+ aFSz.SetHeight( ( bSameHeight ? pRowHeights[ n ] : aFSz.GetHeight() ) /
+ (nCnt + 1) );
+
+ SwTableBox* pNewBox = new SwTableBox( pFrmFmt, nCnt, pInsLine );
+ sal_uInt16 nBoxPos = pInsLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSelBox );
+ pInsLine->GetTabBoxes().Remove( nBoxPos ); // alte loeschen
+ pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pNewBox, nBoxPos );
+
+ // Hintergrund- / Rand Attribut loeschen
+ SwTableBox* pLastBox = pSelBox; // zum verteilen der TextNodes !!
+ // sollte Bereiche in der Box stehen, dann bleibt sie so bestehen
+ // !! FALLS DAS GEAENDERT WIRD MUSS DAS UNDO ANGEPASST WERDEN !!!
+ sal_Bool bMoveNodes = sal_True;
+ {
+ sal_uLong nSttNd = pLastBox->GetSttIdx() + 1,
+ nEndNd = pLastBox->GetSttNd()->EndOfSectionIndex();
+ while( nSttNd < nEndNd )
+ if( !pDoc->GetNodes()[ nSttNd++ ]->IsTxtNode() )
+ {
+ bMoveNodes = sal_False;
+ break;
+ }
+ }
+
+ SwTableBoxFmt* pCpyBoxFrmFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt();
+ sal_Bool bChkBorder = 0 != pCpyBoxFrmFmt->GetBox().GetTop();
+ if( bChkBorder )
+ pCpyBoxFrmFmt = (SwTableBoxFmt*)pSelBox->ClaimFrmFmt();
+
+ for( sal_uInt16 i = 0; i <= nCnt; ++i )
+ {
+ // also erstmal eine neue Linie in der neuen Box
+ SwTableLine* pNewLine = new SwTableLine(
+ (SwTableLineFmt*)pInsLine->GetFrmFmt(), 1, pNewBox );
+ if( bChgLineSz )
+ {
+ pNewLine->ClaimFrmFmt()->SetFmtAttr( aFSz );
+ }
+
+ pNewBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, i );
+ // dann eine neue Box in der Line
+ if( !i ) // haenge die originale Box ein
+ {
+ pSelBox->SetUpper( pNewLine );
+ pNewLine->GetTabBoxes().C40_INSERT( SwTableBox, pSelBox, 0 );
+ }
+ else
+ {
+ ::_InsTblBox( pDoc, pTblNd, pNewLine, pCpyBoxFrmFmt,
+ pLastBox, 0 );
+
+ if( bChkBorder )
+ {
+ pCpyBoxFrmFmt = (SwTableBoxFmt*)pNewLine->GetTabBoxes()[ 0 ]->ClaimFrmFmt();
+ SvxBoxItem aTmp( pCpyBoxFrmFmt->GetBox() );
+ aTmp.SetLine( 0, BOX_LINE_TOP );
+ pCpyBoxFrmFmt->SetFmtAttr( aTmp );
+ bChkBorder = sal_False;
+ }
+
+ if( bMoveNodes )
+ {
+ const SwNode* pEndNd = pLastBox->GetSttNd()->EndOfSectionNode();
+ if( pLastBox->GetSttIdx()+2 != pEndNd->GetIndex() )
+ {
+ // TextNodes verschieben
+ SwNodeRange aRg( *pLastBox->GetSttNd(), +2, *pEndNd );
+ pLastBox = pNewLine->GetTabBoxes()[0]; // neu setzen
+ SwNodeIndex aInsPos( *pLastBox->GetSttNd(), 1 );
+ pDoc->GetNodes()._MoveNodes(aRg, pDoc->GetNodes(), aInsPos, sal_False);
+ pDoc->GetNodes().Delete( aInsPos, 1 ); // den leeren noch loeschen
+ }
+ }
+ }
+ }
+ // in Boxen mit Lines darf es nur noch Size/Fillorder geben
+ pFrmFmt = (SwTableBoxFmt*)pNewBox->ClaimFrmFmt();
+ pFrmFmt->ResetFmtAttr( RES_LR_SPACE, RES_FRMATR_END - 1 );
+ pFrmFmt->ResetFmtAttr( RES_BOXATR_BEGIN, RES_BOXATR_END - 1 );
+ }
+
+ delete[] pRowHeights;
+
+ GCLines();
+
+ aFndBox.MakeFrms( *this );
+
+ CHECKBOXWIDTH
+ CHECKTABLELAYOUT
+ return sal_True;
+}
+
+sal_Bool SwTable::SplitCol( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt )
+{
+ ASSERT( pDoc && rBoxes.Count() && nCnt, "keine gueltigen Werte" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ // TL_CHART2: splitting/merging of a number of cells or rows will usually make
+ // the table to complex to be handled with chart.
+ // Thus we tell the charts to use their own data provider and forget about this table
+ pDoc->CreateChartInternalDataProviders( this );
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+ SwSelBoxes aSelBoxes;
+ aSelBoxes.Insert(rBoxes.GetData(), rBoxes.Count());
+ ExpandSelection( aSelBoxes );
+
+ //Lines fuer das Layout-Update herausuchen.
+ _FndBox aFndBox( 0, 0 );
+ aFndBox.SetTableLines( aSelBoxes, *this );
+ aFndBox.DelFrms( *this );
+
+ _CpyTabFrms aFrmArr;
+ SvPtrarr aLastBoxArr;
+ sal_uInt16 nFndPos;
+ for( sal_uInt16 n = 0; n < aSelBoxes.Count(); ++n )
+ {
+ SwTableBox* pSelBox = *( aSelBoxes.GetData() + n );
+ ASSERT( pSelBox, "Box steht nicht in der Tabelle" );
+
+ // We don't want to split small table cells into very very small cells
+ if( pSelBox->GetFrmFmt()->GetFrmSize().GetWidth()/( nCnt + 1 ) < 10 )
+ continue;
+
+ // dann teile die Box nCnt in nCnt Boxen
+ SwTableLine* pInsLine = pSelBox->GetUpper();
+ sal_uInt16 nBoxPos = pInsLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSelBox );
+
+ // suche das FrmFmt im Array aller Frame-Formate
+ SwTableBoxFmt* pLastBoxFmt;
+ _CpyTabFrm aFindFrm( (SwTableBoxFmt*)pSelBox->GetFrmFmt() );
+ if( !aFrmArr.Seek_Entry( aFindFrm, &nFndPos ))
+ {
+ // aender das FrmFmt
+ aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pSelBox->ClaimFrmFmt();
+ SwTwips nBoxSz = aFindFrm.pNewFrmFmt->GetFrmSize().GetWidth();
+ SwTwips nNewBoxSz = nBoxSz / ( nCnt + 1 );
+ aFindFrm.pNewFrmFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE,
+ nNewBoxSz, 0 ) );
+ aFrmArr.Insert( aFindFrm );
+
+ pLastBoxFmt = aFindFrm.pNewFrmFmt;
+ if( nBoxSz != ( nNewBoxSz * (nCnt + 1)))
+ {
+ // es bleibt ein Rest, also muss fuer die letzte Box ein
+ // eigenes Format definiert werden
+ pLastBoxFmt = new SwTableBoxFmt( *aFindFrm.pNewFrmFmt );
+ pLastBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE,
+ nBoxSz - ( nNewBoxSz * nCnt ), 0 ) );
+ }
+ void* p = pLastBoxFmt;
+ aLastBoxArr.Insert( p, nFndPos );
+ }
+ else
+ {
+ aFindFrm = aFrmArr[ nFndPos ];
+ pSelBox->ChgFrmFmt( (SwTableBoxFmt*)aFindFrm.pNewFrmFmt );
+ pLastBoxFmt = (SwTableBoxFmt*)aLastBoxArr[ nFndPos ];
+ }
+
+ // dann fuege mal an der Position die neuen Boxen ein
+ for( sal_uInt16 i = 1; i < nCnt; ++i )
+ ::_InsTblBox( pDoc, pTblNd, pInsLine, aFindFrm.pNewFrmFmt,
+ pSelBox, nBoxPos + i ); // dahinter einfuegen
+
+ ::_InsTblBox( pDoc, pTblNd, pInsLine, pLastBoxFmt,
+ pSelBox, nBoxPos + nCnt ); // dahinter einfuegen
+
+ // Sonderbehandlung fuer die Umrandung:
+ const SvxBoxItem& aSelBoxItem = aFindFrm.pNewFrmFmt->GetBox();
+ if( aSelBoxItem.GetRight() )
+ {
+ pInsLine->GetTabBoxes()[ nBoxPos + nCnt ]->ClaimFrmFmt();
+
+ SvxBoxItem aTmp( aSelBoxItem );
+ aTmp.SetLine( 0, BOX_LINE_RIGHT );
+ aFindFrm.pNewFrmFmt->SetFmtAttr( aTmp );
+
+ // und dann das Format aus dem "cache" entfernen
+ for( sal_uInt16 i = aFrmArr.Count(); i; )
+ {
+ const _CpyTabFrm& rCTF = aFrmArr[ --i ];
+ if( rCTF.pNewFrmFmt == aFindFrm.pNewFrmFmt ||
+ rCTF.Value.pFrmFmt == aFindFrm.pNewFrmFmt )
+ {
+ aFrmArr.Remove( i );
+ aLastBoxArr.Remove( i );
+ }
+ }
+ }
+ }
+
+ //Layout updaten
+ aFndBox.MakeFrms( *this );
+
+ CHECKBOXWIDTH
+ CHECKTABLELAYOUT
+ return sal_True;
+}
+
+// ---------------------------------------------------------------
+
+/*
+ ----------------------- >> MERGE << ------------------------
+ Algorithmus:
+ ist in der _FndBox nur eine Line angegeben, nehme die Line
+ und teste die Anzahl der Boxen
+ - ist mehr als 1 Box angegeben, so wird auf Boxenebene zusammen-
+ gefasst, d.H. die neue Box wird so Breit wie die alten.
+ - Alle Lines die ueber/unter dem Bereich liegen werden in die
+ Box als Line + Box mit Lines eingefuegt
+ - Alle Lines die vor/hinter dem Bereich liegen werden in
+ die Boxen Left/Right eingetragen
+
+ ----------------------- >> MERGE << ------------------------
+*/
+
+void lcl_CpyLines( sal_uInt16 nStt, sal_uInt16 nEnd,
+ SwTableLines& rLines,
+ SwTableBox* pInsBox,
+ sal_uInt16 nPos = USHRT_MAX )
+{
+ for( sal_uInt16 n = nStt; n < nEnd; ++n )
+ rLines[n]->SetUpper( pInsBox );
+ if( USHRT_MAX == nPos )
+ nPos = pInsBox->GetTabLines().Count();
+ pInsBox->GetTabLines().Insert( &rLines, nPos, nStt, nEnd );
+ rLines.Remove( nStt, nEnd - nStt );
+}
+
+void lcl_CpyBoxes( sal_uInt16 nStt, sal_uInt16 nEnd,
+ SwTableBoxes& rBoxes,
+ SwTableLine* pInsLine,
+ sal_uInt16 nPos = USHRT_MAX )
+{
+ for( sal_uInt16 n = nStt; n < nEnd; ++n )
+ rBoxes[n]->SetUpper( pInsLine );
+ if( USHRT_MAX == nPos )
+ nPos = pInsLine->GetTabBoxes().Count();
+ pInsLine->GetTabBoxes().Insert( &rBoxes, nPos, nStt, nEnd );
+ rBoxes.Remove( nStt, nEnd - nStt );
+}
+
+void lcl_CalcWidth( SwTableBox* pBox )
+{
+ // Annahme: jede Line in der Box ist gleich gross
+ SwFrmFmt* pFmt = pBox->ClaimFrmFmt();
+ ASSERT( pBox->GetTabLines().Count(), "Box hat keine Lines" );
+
+ SwTableLine* pLine = pBox->GetTabLines()[0];
+ ASSERT( pLine, "Box steht in keiner Line" );
+
+ long nWidth = 0;
+ for( sal_uInt16 n = 0; n < pLine->GetTabBoxes().Count(); ++n )
+ nWidth += pLine->GetTabBoxes()[n]->GetFrmFmt()->GetFrmSize().GetWidth();
+
+ pFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth, 0 ));
+
+ // in Boxen mit Lines darf es nur noch Size/Fillorder geben
+ pFmt->ResetFmtAttr( RES_LR_SPACE, RES_FRMATR_END - 1 );
+ pFmt->ResetFmtAttr( RES_BOXATR_BEGIN, RES_BOXATR_END - 1 );
+}
+
+
+
+struct _InsULPara
+{
+ SwTableNode* pTblNd;
+ SwTableLine* pInsLine;
+ SwTableBox* pInsBox;
+ sal_Bool bUL_LR : 1; // Upper-Lower(sal_True) oder Left-Right(sal_False) ?
+ sal_Bool bUL : 1; // Upper-Left(sal_True) oder Lower-Right(sal_False) ?
+
+ SwTableBox* pLeftBox;
+ SwTableBox* pRightBox;
+ SwTableBox* pMergeBox;
+
+ _InsULPara( SwTableNode* pTNd, sal_Bool bUpperLower, sal_Bool bUpper,
+ SwTableBox* pLeft, SwTableBox* pMerge, SwTableBox* pRight,
+ SwTableLine* pLine=0, SwTableBox* pBox=0 )
+ : pTblNd( pTNd ), pInsLine( pLine ), pInsBox( pBox ),
+ pLeftBox( pLeft ), pRightBox( pRight ), pMergeBox( pMerge )
+ { bUL_LR = bUpperLower; bUL = bUpper; }
+
+ void SetLeft( SwTableBox* pBox=0 )
+ { bUL_LR = sal_False; bUL = sal_True; if( pBox ) pInsBox = pBox; }
+ void SetRight( SwTableBox* pBox=0 )
+ { bUL_LR = sal_False; bUL = sal_False; if( pBox ) pInsBox = pBox; }
+ void SetUpper( SwTableLine* pLine=0 )
+ { bUL_LR = sal_True; bUL = sal_True; if( pLine ) pInsLine = pLine; }
+ void SetLower( SwTableLine* pLine=0 )
+ { bUL_LR = sal_True; bUL = sal_False; if( pLine ) pInsLine = pLine; }
+};
+
+
+sal_Bool lcl_Merge_MoveBox( const _FndBox*& rpFndBox, void* pPara )
+{
+ _InsULPara* pULPara = (_InsULPara*)pPara;
+ SwTableBoxes* pBoxes;
+
+ sal_uInt16 nStt = 0, nEnd = rpFndBox->GetLines().Count();
+ sal_uInt16 nInsPos = USHRT_MAX;
+ if( !pULPara->bUL_LR ) // Left/Right
+ {
+ sal_uInt16 nPos;
+ SwTableBox* pFndBox = (SwTableBox*)rpFndBox->GetBox();
+ pBoxes = &pFndBox->GetUpper()->GetTabBoxes();
+ if( pULPara->bUL ) // Left ?
+ {
+ // gibt es noch davor Boxen, dann move sie
+ if( 0 != ( nPos = pBoxes->C40_GETPOS( SwTableBox, pFndBox )) )
+ lcl_CpyBoxes( 0, nPos, *pBoxes, pULPara->pInsLine );
+ }
+ else // Right
+ // gibt es noch dahinter Boxen, dann move sie
+ if( (nPos = pBoxes->C40_GETPOS( SwTableBox, pFndBox )) +1 < pBoxes->Count() )
+ {
+ nInsPos = pULPara->pInsLine->GetTabBoxes().Count();
+ lcl_CpyBoxes( nPos+1, pBoxes->Count(),
+ *pBoxes, pULPara->pInsLine );
+ }
+ }
+ // Upper/Lower und gehts noch tiefer ??
+ else if( rpFndBox->GetLines().Count() )
+ {
+ // suche nur die Line, ab der Verschoben werden muss
+ nStt = pULPara->bUL ? 0 : rpFndBox->GetLines().Count()-1;
+ nEnd = nStt+1;
+ }
+
+ pBoxes = &pULPara->pInsLine->GetTabBoxes();
+
+ // geht es noch eine weitere Stufe runter?
+ if( rpFndBox->GetBox()->GetTabLines().Count() )
+ {
+ SwTableBox* pBox = new SwTableBox(
+ (SwTableBoxFmt*)rpFndBox->GetBox()->GetFrmFmt(), 0, pULPara->pInsLine );
+ _InsULPara aPara( *pULPara );
+ aPara.pInsBox = pBox;
+ ((_FndBox*)rpFndBox)->GetLines().ForEach( nStt, nEnd,
+ &lcl_Merge_MoveLine, &aPara );
+ if( pBox->GetTabLines().Count() )
+ {
+ if( USHRT_MAX == nInsPos )
+ nInsPos = pBoxes->Count();
+ pBoxes->C40_INSERT( SwTableBox, pBox, nInsPos );
+ lcl_CalcWidth( pBox ); // bereche die Breite der Box
+ }
+ else
+ delete pBox;
+ }
+ return sal_True;
+}
+
+sal_Bool lcl_Merge_MoveLine( const _FndLine*& rpFndLine, void* pPara )
+{
+ _InsULPara* pULPara = (_InsULPara*)pPara;
+ SwTableLines* pLines;
+
+ sal_uInt16 nStt = 0, nEnd = rpFndLine->GetBoxes().Count();
+ sal_uInt16 nInsPos = USHRT_MAX;
+ if( pULPara->bUL_LR ) // UpperLower ?
+ {
+ sal_uInt16 nPos;
+ SwTableLine* pFndLn = (SwTableLine*)rpFndLine->GetLine();
+ pLines = pFndLn->GetUpper() ?
+ &pFndLn->GetUpper()->GetTabLines() :
+ &pULPara->pTblNd->GetTable().GetTabLines();
+
+ SwTableBox* pLBx = rpFndLine->GetBoxes()[0]->GetBox();
+ SwTableBox* pRBx = rpFndLine->GetBoxes()[
+ rpFndLine->GetBoxes().Count()-1]->GetBox();
+ sal_uInt16 nLeft = pFndLn->GetTabBoxes().C40_GETPOS( SwTableBox, pLBx );
+ sal_uInt16 nRight = pFndLn->GetTabBoxes().C40_GETPOS( SwTableBox, pRBx );
+
+// if( ( nLeft && nRight+1 < pFndLn->GetTabBoxes().Count() ) ||
+// ( !nLeft && nRight+1 >= pFndLn->GetTabBoxes().Count() ) )
+ if( !nLeft || nRight == pFndLn->GetTabBoxes().Count() )
+ {
+ if( pULPara->bUL ) // Upper ?
+ {
+ // gibt es noch davor Zeilen, dann move sie
+ if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) )
+ lcl_CpyLines( 0, nPos, *pLines, pULPara->pInsBox );
+ }
+ else
+ // gibt es noch dahinter Zeilen, dann move sie
+ if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() )
+ {
+ nInsPos = pULPara->pInsBox->GetTabLines().Count();
+ lcl_CpyLines( nPos+1, pLines->Count(), *pLines,
+ pULPara->pInsBox );
+ }
+ }
+ else if( nLeft )
+ {
+ // es gibt links noch weitere Boxen, also setze Left-
+ // und Merge-Box in eine Box und Line, fuege davor/dahinter
+ // eine Line mit Box ein, in die die oberen/unteren Lines
+ // eingefuegt werden
+ SwTableLine* pInsLine = pULPara->pLeftBox->GetUpper();
+ SwTableBox* pLMBox = new SwTableBox(
+ (SwTableBoxFmt*)pULPara->pLeftBox->GetFrmFmt(), 0, pInsLine );
+ SwTableLine* pLMLn = new SwTableLine(
+ (SwTableLineFmt*)pInsLine->GetFrmFmt(), 2, pLMBox );
+ pLMLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
+
+ pLMBox->GetTabLines().C40_INSERT( SwTableLine, pLMLn, 0 );
+
+ lcl_CpyBoxes( 0, 2, pInsLine->GetTabBoxes(), pLMLn );
+
+ pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pLMBox, 0 );
+
+ if( pULPara->bUL ) // Upper ?
+ {
+ // gibt es noch davor Zeilen, dann move sie
+ if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) )
+ lcl_CpyLines( 0, nPos, *pLines, pLMBox, 0 );
+ }
+ else
+ // gibt es noch dahinter Zeilen, dann move sie
+ if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() )
+ lcl_CpyLines( nPos+1, pLines->Count(), *pLines,
+ pLMBox );
+ lcl_CalcWidth( pLMBox ); // bereche die Breite der Box
+ }
+ else if( nRight+1 < pFndLn->GetTabBoxes().Count() )
+ {
+ // es gibt rechts noch weitere Boxen, also setze Right-
+ // und Merge-Box in eine Box und Line, fuege davor/dahinter
+ // eine Line mit Box ein, in die die oberen/unteren Lines
+ // eingefuegt werden
+ SwTableLine* pInsLine = pULPara->pRightBox->GetUpper();
+ SwTableBox* pRMBox;
+ if( pULPara->pLeftBox->GetUpper() == pInsLine )
+ {
+ pRMBox = new SwTableBox(
+ (SwTableBoxFmt*)pULPara->pRightBox->GetFrmFmt(), 0, pInsLine );
+ SwTableLine* pRMLn = new SwTableLine(
+ (SwTableLineFmt*)pInsLine->GetFrmFmt(), 2, pRMBox );
+ pRMLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
+ pRMBox->GetTabLines().C40_INSERT( SwTableLine, pRMLn, 0 );
+
+ lcl_CpyBoxes( 1, 3, pInsLine->GetTabBoxes(), pRMLn );
+
+ pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox, 0 );
+ }
+ else
+ {
+ // Left und Merge wurden schon zusammengefuegt, also move
+ // Right auch mit in die Line
+
+ pInsLine = pULPara->pLeftBox->GetUpper();
+ sal_uInt16 nMvPos = pULPara->pRightBox->GetUpper()->GetTabBoxes().
+ C40_GETPOS( SwTableBox, pULPara->pRightBox );
+ lcl_CpyBoxes( nMvPos, nMvPos+1,
+ pULPara->pRightBox->GetUpper()->GetTabBoxes(),
+ pInsLine );
+ pRMBox = pInsLine->GetUpper();
+
+ // sind schon Lines vorhanden, dann muessen diese in eine
+ // neue Line und Box
+ nMvPos = pRMBox->GetTabLines().C40_GETPOS( SwTableLine, pInsLine );
+ if( pULPara->bUL ? nMvPos
+ : nMvPos+1 < pRMBox->GetTabLines().Count() )
+ {
+ // alle Lines zu einer neuen Line und Box zusammenfassen
+ SwTableLine* pNewLn = new SwTableLine(
+ (SwTableLineFmt*)pInsLine->GetFrmFmt(), 1, pRMBox );
+ pNewLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
+ pRMBox->GetTabLines().C40_INSERT( SwTableLine, pNewLn,
+ pULPara->bUL ? nMvPos : nMvPos+1 );
+ pRMBox = new SwTableBox( (SwTableBoxFmt*)pRMBox->GetFrmFmt(), 0, pNewLn );
+ pNewLn->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox, 0 );
+
+ sal_uInt16 nPos1, nPos2;
+ if( pULPara->bUL )
+ nPos1 = 0,
+ nPos2 = nMvPos;
+ else
+ nPos1 = nMvPos+2,
+ nPos2 = pNewLn->GetUpper()->GetTabLines().Count();
+
+ lcl_CpyLines( nPos1, nPos2,
+ pNewLn->GetUpper()->GetTabLines(), pRMBox );
+ lcl_CalcWidth( pRMBox ); // bereche die Breite der Box
+
+ pRMBox = new SwTableBox( (SwTableBoxFmt*)pRMBox->GetFrmFmt(), 0, pNewLn );
+ pNewLn->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox,
+ pNewLn->GetTabBoxes().Count() );
+ }
+ }
+ if( pULPara->bUL ) // Upper ?
+ {
+ // gibt es noch davor Zeilen, dann move sie
+ if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) )
+ lcl_CpyLines( 0, nPos, *pLines, pRMBox, 0 );
+ }
+ else
+ // gibt es noch dahinter Zeilen, dann move sie
+ if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() )
+ lcl_CpyLines( nPos+1, pLines->Count(), *pLines,
+ pRMBox );
+ lcl_CalcWidth( pRMBox ); // bereche die Breite der Box
+ }
+ else {
+ ASSERT( sal_False , "Was denn nun" );
+ }
+ }
+ // Left/Right
+ else
+ {
+ // suche nur die Line, ab der Verschoben werden muss
+ nStt = pULPara->bUL ? 0 : rpFndLine->GetBoxes().Count()-1;
+ nEnd = nStt+1;
+ }
+ pLines = &pULPara->pInsBox->GetTabLines();
+
+ SwTableLine* pNewLine = new SwTableLine(
+ (SwTableLineFmt*)rpFndLine->GetLine()->GetFrmFmt(), 0, pULPara->pInsBox );
+ _InsULPara aPara( *pULPara ); // kopieren
+ aPara.pInsLine = pNewLine;
+ ((_FndLine*)rpFndLine)->GetBoxes().ForEach( nStt, nEnd,
+ &lcl_Merge_MoveBox, &aPara );
+ if( pNewLine->GetTabBoxes().Count() )
+ {
+ if( USHRT_MAX == nInsPos )
+ nInsPos = pLines->Count();
+ pLines->C40_INSERT( SwTableLine, pNewLine, nInsPos );
+ }
+ else
+ delete pNewLine;
+
+ return sal_True;
+}
+
+
+sal_Bool SwTable::OldMerge( SwDoc* pDoc, const SwSelBoxes& rBoxes,
+ SwTableBox* pMergeBox, SwUndoTblMerge* pUndo )
+{
+ ASSERT( rBoxes.Count() && pMergeBox, "keine gueltigen Werte" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ // suche alle Boxen / Lines
+ _FndBox aFndBox( 0, 0 );
+ {
+ _FndPara aPara( rBoxes, &aFndBox );
+ GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ }
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+
+ // TL_CHART2: splitting/merging of a number of cells or rows will usually make
+ // the table to complex to be handled with chart.
+ // Thus we tell the charts to use their own data provider and forget about this table
+ pDoc->CreateChartInternalDataProviders( this );
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ if( pUndo )
+ pUndo->SetSelBoxes( rBoxes );
+
+ //Lines fuer das Layout-Update herausuchen.
+ aFndBox.SetTableLines( *this );
+ aFndBox.DelFrms( *this );
+
+ _FndBox* pFndBox = &aFndBox;
+ while( 1 == pFndBox->GetLines().Count() &&
+ 1 == pFndBox->GetLines()[0]->GetBoxes().Count() )
+ pFndBox = pFndBox->GetLines()[0]->GetBoxes()[0];
+
+ SwTableLine* pInsLine = new SwTableLine(
+ (SwTableLineFmt*)pFndBox->GetLines()[0]->GetLine()->GetFrmFmt(), 0,
+ !pFndBox->GetUpper() ? 0 : pFndBox->GetBox() );
+ pInsLine->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
+
+ // trage die neue Line ein
+ SwTableLines* pLines = pFndBox->GetUpper() ?
+ &pFndBox->GetBox()->GetTabLines() : &GetTabLines();
+
+ SwTableLine* pNewLine = pFndBox->GetLines()[0]->GetLine();
+ sal_uInt16 nInsPos = pLines->C40_GETPOS( SwTableLine, pNewLine );
+ pLines->C40_INSERT( SwTableLine, pInsLine, nInsPos );
+
+ SwTableBox* pLeftBox = new SwTableBox( (SwTableBoxFmt*)pMergeBox->GetFrmFmt(), 0, pInsLine );
+ SwTableBox* pRightBox = new SwTableBox( (SwTableBoxFmt*)pMergeBox->GetFrmFmt(), 0, pInsLine );
+ pMergeBox->SetUpper( pInsLine );
+ pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pLeftBox, 0 );
+ pLeftBox->ClaimFrmFmt();
+ pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pMergeBox, 1 );
+ pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pRightBox, 2 );
+ pRightBox->ClaimFrmFmt();
+
+ // in diese kommen alle Lines, die ueber dem selektierten Bereich stehen
+ // Sie bilden also eine Upper/Lower Line
+ _InsULPara aPara( pTblNd, sal_True, sal_True, pLeftBox, pMergeBox, pRightBox, pInsLine );
+
+ // move die oben/unten ueberhaengenden Lines vom selektierten Bereich
+ pFndBox->GetLines()[0]->GetBoxes().ForEach( &lcl_Merge_MoveBox,
+ &aPara );
+ aPara.SetLower( pInsLine );
+ sal_uInt16 nEnd = pFndBox->GetLines().Count()-1;
+ pFndBox->GetLines()[nEnd]->GetBoxes().ForEach( &lcl_Merge_MoveBox,
+ &aPara );
+
+ // move die links/rechts hereinreichenden Boxen vom selektierten Bereich
+ aPara.SetLeft( pLeftBox );
+ pFndBox->GetLines().ForEach( &lcl_Merge_MoveLine, &aPara );
+
+ aPara.SetRight( pRightBox );
+ pFndBox->GetLines().ForEach( &lcl_Merge_MoveLine, &aPara );
+
+ if( !pLeftBox->GetTabLines().Count() )
+ _DeleteBox( *this, pLeftBox, 0, sal_False, sal_False );
+ else
+ {
+ lcl_CalcWidth( pLeftBox ); // bereche die Breite der Box
+ if( pUndo && pLeftBox->GetSttNd() )
+ pUndo->AddNewBox( pLeftBox->GetSttIdx() );
+ }
+ if( !pRightBox->GetTabLines().Count() )
+ _DeleteBox( *this, pRightBox, 0, sal_False, sal_False );
+ else
+ {
+ lcl_CalcWidth( pRightBox ); // bereche die Breite der Box
+ if( pUndo && pRightBox->GetSttNd() )
+ pUndo->AddNewBox( pRightBox->GetSttIdx() );
+ }
+
+ DeleteSel( pDoc, rBoxes, 0, 0, sal_False, sal_False );
+
+ // dann raeume die Struktur dieser Line noch mal auf:
+ // generell alle Aufraeumen
+ GCLines();
+
+ GetTabLines()[0]->GetTabBoxes().ForEach( &lcl_BoxSetHeadCondColl, 0 );
+
+ aFndBox.MakeFrms( *this );
+
+ CHECKBOXWIDTH
+ CHECKTABLELAYOUT
+
+ return sal_True;
+}
+
+// ---------------------------------------------------------------
+
+void lcl_CheckRowSpan( SwTable &rTbl )
+{
+ sal_uInt16 nLineCount = rTbl.GetTabLines().Count();
+ sal_uInt16 nMaxSpan = nLineCount;
+ long nMinSpan = 1;
+ while( nMaxSpan )
+ {
+ SwTableLine* pLine = rTbl.GetTabLines()[ nLineCount - nMaxSpan ];
+ for( sal_uInt16 nBox = 0; nBox < pLine->GetTabBoxes().Count(); ++nBox )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[nBox];
+ long nRowSpan = pBox->getRowSpan();
+ if( nRowSpan > nMaxSpan )
+ pBox->setRowSpan( nMaxSpan );
+ else if( nRowSpan < nMinSpan )
+ pBox->setRowSpan( nMinSpan > 0 ? nMaxSpan : nMinSpan );
+ }
+ --nMaxSpan;
+ nMinSpan = -nMaxSpan;
+ }
+}
+
+sal_uInt16 lcl_GetBoxOffset( const _FndBox& rBox )
+{
+ // suche die erste Box
+ const _FndBox* pFirstBox = &rBox;
+ while( pFirstBox->GetLines().Count() )
+ pFirstBox = pFirstBox->GetLines()[ 0 ]->GetBoxes()[ 0 ];
+
+ sal_uInt16 nRet = 0;
+ // dann ueber die Lines nach oben die Position bestimmen
+ const SwTableBox* pBox = pFirstBox->GetBox();
+ do {
+ const SwTableBoxes& rBoxes = pBox->GetUpper()->GetTabBoxes();
+ const SwTableBox* pCmp;
+ for( sal_uInt16 n = 0; pBox != ( pCmp = rBoxes[ n ] ); ++n )
+ nRet = nRet + (sal_uInt16) pCmp->GetFrmFmt()->GetFrmSize().GetWidth();
+ pBox = pBox->GetUpper()->GetUpper();
+ } while( pBox );
+ return nRet;
+}
+
+sal_uInt16 lcl_GetLineWidth( const _FndLine& rLine )
+{
+ sal_uInt16 nRet = 0;
+ for( sal_uInt16 n = rLine.GetBoxes().Count(); n; )
+ nRet = nRet + (sal_uInt16)rLine.GetBoxes()[ --n ]->GetBox()->GetFrmFmt()
+ ->GetFrmSize().GetWidth();
+ return nRet;
+}
+
+void lcl_CalcNewWidths( const _FndLines& rFndLines, _CpyPara& rPara )
+{
+ rPara.pWidths.reset();
+ sal_uInt16 nLineCount = rFndLines.Count();
+ if( nLineCount )
+ {
+ rPara.pWidths = boost::shared_ptr< std::vector< std::vector< sal_uLong > > >
+ ( new std::vector< std::vector< sal_uLong > >( nLineCount ));
+ // First we collect information about the left/right borders of all
+ // selected cells
+ for( sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine )
+ {
+ std::vector< sal_uLong > &rWidth = (*rPara.pWidths.get())[ nLine ];
+ const _FndLine *pFndLine = rFndLines[ nLine ];
+ if( pFndLine && pFndLine->GetBoxes().Count() )
+ {
+ const SwTableLine *pLine = pFndLine->GetLine();
+ if( pLine && pLine->GetTabBoxes().Count() )
+ {
+ sal_uInt16 nBoxCount = pLine->GetTabBoxes().Count();
+ sal_uLong nPos = 0;
+ // The first selected box...
+ const SwTableBox *pSel = pFndLine->GetBoxes()[0]->GetBox();
+ sal_uInt16 nBox = 0;
+ // Sum up the width of all boxes before the first selected box
+ while( nBox < nBoxCount )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[nBox++];
+ if( pBox != pSel )
+ nPos += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ else
+ break;
+ }
+ // nPos is now the left border of the first selceted box
+ if( rPara.nMinLeft > nPos )
+ rPara.nMinLeft = nPos;
+ nBoxCount = pFndLine->GetBoxes().Count();
+ rWidth = std::vector< sal_uLong >( nBoxCount+2 );
+ rWidth[ 0 ] = nPos;
+ // Add now the widths of all selected boxes and store
+ // the positions in the vector
+ for( nBox = 0; nBox < nBoxCount; )
+ {
+ nPos += pFndLine->GetBoxes()[nBox]
+ ->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
+ rWidth[ ++nBox ] = nPos;
+ }
+ // nPos: The right border of the last selected box
+ if( rPara.nMaxRight < nPos )
+ rPara.nMaxRight = nPos;
+ if( nPos <= rWidth[ 0 ] )
+ rWidth.clear();
+ }
+ }
+ }
+ }
+ // Second step: calculate the new widths for the copied cells
+ sal_uLong nSelSize = rPara.nMaxRight - rPara.nMinLeft;
+ if( nSelSize )
+ {
+ for( sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine )
+ {
+ std::vector< sal_uLong > &rWidth = (*rPara.pWidths.get())[ nLine ];
+ sal_uInt16 nCount = (sal_uInt16)rWidth.size();
+ if( nCount > 2 )
+ {
+ rWidth[ nCount - 1 ] = rPara.nMaxRight;
+ sal_uLong nLastPos = 0;
+ for( sal_uInt16 nBox = 0; nBox < nCount; ++nBox )
+ {
+ sal_uInt64 nNextPos = rWidth[ nBox ];
+ nNextPos -= rPara.nMinLeft;
+ nNextPos *= rPara.nNewSize;
+ nNextPos /= nSelSize;
+ rWidth[ nBox ] = (sal_uLong)(nNextPos - nLastPos);
+ nLastPos = (sal_uLong)nNextPos;
+ }
+ }
+ }
+ }
+}
+
+sal_Bool lcl_CopyBoxToDoc( const _FndBox*& rpFndBox, void* pPara )
+{
+ _CpyPara* pCpyPara = (_CpyPara*)pPara;
+
+ // Calculation of new size
+ sal_uLong nRealSize;
+ sal_uLong nDummy1 = 0;
+ sal_uLong nDummy2 = 0;
+ if( pCpyPara->pTblNd->GetTable().IsNewModel() )
+ {
+ if( pCpyPara->nBoxIdx == 1 )
+ nDummy1 = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][0];
+ nRealSize = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][pCpyPara->nBoxIdx++];
+ if( pCpyPara->nBoxIdx == (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx].size()-1 )
+ nDummy2 = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][pCpyPara->nBoxIdx];
+ }
+ else
+ {
+ nRealSize = pCpyPara->nNewSize;
+ nRealSize *= rpFndBox->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
+ nRealSize /= pCpyPara->nOldSize;
+ }
+
+ sal_uLong nSize;
+ bool bDummy = nDummy1 > 0;
+ if( bDummy )
+ nSize = nDummy1;
+ else
+ {
+ nSize = nRealSize;
+ nRealSize = 0;
+ }
+ do
+ {
+ // suche das Frame-Format in der Liste aller Frame-Formate
+ _CpyTabFrm aFindFrm( (SwTableBoxFmt*)rpFndBox->GetBox()->GetFrmFmt() );
+
+ SwFmtFrmSize aFrmSz;
+ sal_uInt16 nFndPos;
+ if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ) ||
+ ( aFrmSz = ( aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ]).pNewFrmFmt->
+ GetFrmSize()).GetWidth() != (SwTwips)nSize )
+ {
+ // es ist noch nicht vorhanden, also kopiere es
+ aFindFrm.pNewFrmFmt = pCpyPara->pDoc->MakeTableBoxFmt();
+ aFindFrm.pNewFrmFmt->CopyAttrs( *rpFndBox->GetBox()->GetFrmFmt() );
+ if( !pCpyPara->bCpyCntnt )
+ aFindFrm.pNewFrmFmt->ResetFmtAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE );
+ aFrmSz.SetWidth( nSize );
+ aFindFrm.pNewFrmFmt->SetFmtAttr( aFrmSz );
+ pCpyPara->rTabFrmArr.Insert( aFindFrm );
+ }
+
+ SwTableBox* pBox;
+ if( rpFndBox->GetLines().Count() )
+ {
+ pBox = new SwTableBox( aFindFrm.pNewFrmFmt,
+ rpFndBox->GetLines().Count(), pCpyPara->pInsLine );
+ pCpyPara->pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, pCpyPara->nInsPos++ );
+ _CpyPara aPara( *pCpyPara, pBox );
+ aPara.nNewSize = nSize; // hole die Groesse
+ ((_FndBox*)rpFndBox)->GetLines().ForEach( &lcl_CopyLineToDoc, &aPara );
+ }
+ else
+ {
+ // erzeuge eine leere Box
+ pCpyPara->pDoc->GetNodes().InsBoxen( pCpyPara->pTblNd, pCpyPara->pInsLine,
+ aFindFrm.pNewFrmFmt,
+ (SwTxtFmtColl*)pCpyPara->pDoc->GetDfltTxtFmtColl(),
+ 0, pCpyPara->nInsPos );
+ pBox = pCpyPara->pInsLine->GetTabBoxes()[ pCpyPara->nInsPos ];
+ if( bDummy )
+ pBox->setDummyFlag( true );
+ else if( pCpyPara->bCpyCntnt )
+ {
+ // dann kopiere mal den Inhalt in diese leere Box
+ pBox->setRowSpan( rpFndBox->GetBox()->getRowSpan() );
+
+ // der Inhalt kopiert wird, dann koennen auch Formeln&Values
+ // kopiert werden.
+ {
+ SfxItemSet aBoxAttrSet( pCpyPara->pDoc->GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+ aBoxAttrSet.Put( rpFndBox->GetBox()->GetFrmFmt()->GetAttrSet() );
+ if( aBoxAttrSet.Count() )
+ {
+ const SfxPoolItem* pItem;
+ SvNumberFormatter* pN = pCpyPara->pDoc->GetNumberFormatter( sal_False );
+ if( pN && pN->HasMergeFmtTbl() && SFX_ITEM_SET == aBoxAttrSet.
+ GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem ) )
+ {
+ sal_uLong nOldIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
+ sal_uLong nNewIdx = pN->GetMergeFmtIndex( nOldIdx );
+ if( nNewIdx != nOldIdx )
+ aBoxAttrSet.Put( SwTblBoxNumFormat( nNewIdx ));
+ }
+ pBox->ClaimFrmFmt()->SetFmtAttr( aBoxAttrSet );
+ }
+ }
+ SwDoc* pFromDoc = rpFndBox->GetBox()->GetFrmFmt()->GetDoc();
+ SwNodeRange aCpyRg( *rpFndBox->GetBox()->GetSttNd(), 1,
+ *rpFndBox->GetBox()->GetSttNd()->EndOfSectionNode() );
+ SwNodeIndex aInsIdx( *pBox->GetSttNd(), 1 );
+
+ pFromDoc->CopyWithFlyInFly( aCpyRg, 0, aInsIdx, sal_False );
+ // den initialen TextNode loeschen
+ pCpyPara->pDoc->GetNodes().Delete( aInsIdx, 1 );
+ }
+ ++pCpyPara->nInsPos;
+ }
+ if( nRealSize )
+ {
+ bDummy = false;
+ nSize = nRealSize;
+ nRealSize = 0;
+ }
+ else
+ {
+ bDummy = true;
+ nSize = nDummy2;
+ nDummy2 = 0;
+ }
+ }
+ while( nSize );
+ return sal_True;
+}
+
+sal_Bool lcl_CopyLineToDoc( const _FndLine*& rpFndLine, void* pPara )
+{
+ _CpyPara* pCpyPara = (_CpyPara*)pPara;
+
+ // suche das Format in der Liste aller Formate
+ _CpyTabFrm aFindFrm( (SwTableBoxFmt*)rpFndLine->GetLine()->GetFrmFmt() );
+ sal_uInt16 nFndPos;
+ if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ))
+ {
+ // es ist noch nicht vorhanden, also kopiere es
+ aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pCpyPara->pDoc->MakeTableLineFmt();
+ aFindFrm.pNewFrmFmt->CopyAttrs( *rpFndLine->GetLine()->GetFrmFmt() );
+ pCpyPara->rTabFrmArr.Insert( aFindFrm );
+ }
+ else
+ aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ];
+
+ SwTableLine* pNewLine = new SwTableLine( (SwTableLineFmt*)aFindFrm.pNewFrmFmt,
+ rpFndLine->GetBoxes().Count(), pCpyPara->pInsBox );
+ if( pCpyPara->pInsBox )
+ {
+ pCpyPara->pInsBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, pCpyPara->nInsPos++ );
+ }
+ else
+ {
+ pCpyPara->pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pNewLine,
+ pCpyPara->nInsPos++ );
+ }
+
+ _CpyPara aPara( *pCpyPara, pNewLine );
+
+ if( pCpyPara->pTblNd->GetTable().IsNewModel() )
+ {
+ aPara.nOldSize = 0; // will not be used
+ aPara.nBoxIdx = 1;
+ }
+ else if( rpFndLine->GetBoxes().Count() ==
+ rpFndLine->GetLine()->GetTabBoxes().Count() )
+ {
+ // hole die Size vom Parent
+ const SwFrmFmt* pFmt;
+
+ if( rpFndLine->GetLine()->GetUpper() )
+ pFmt = rpFndLine->GetLine()->GetUpper()->GetFrmFmt();
+ else
+ pFmt = pCpyPara->pTblNd->GetTable().GetFrmFmt();
+ aPara.nOldSize = pFmt->GetFrmSize().GetWidth();
+ }
+ else
+ // errechne sie
+ for( sal_uInt16 n = 0; n < rpFndLine->GetBoxes().Count(); ++n )
+ aPara.nOldSize += rpFndLine->GetBoxes()[n]
+ ->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
+
+ ((_FndLine*)rpFndLine)->GetBoxes().ForEach( &lcl_CopyBoxToDoc, &aPara );
+ if( pCpyPara->pTblNd->GetTable().IsNewModel() )
+ ++pCpyPara->nLnIdx;
+ return sal_True;
+}
+
+sal_Bool SwTable::CopyHeadlineIntoTable( SwTableNode& rTblNd )
+{
+ // suche alle Boxen / Lines
+ SwSelBoxes aSelBoxes;
+ SwTableBox* pBox = GetTabSortBoxes()[ 0 ];
+ pBox = GetTblBox( pBox->GetSttNd()->StartOfSectionNode()->GetIndex() + 1 );
+ SelLineFromBox( pBox, aSelBoxes, sal_True );
+
+ _FndBox aFndBox( 0, 0 );
+ {
+ _FndPara aPara( aSelBoxes, &aFndBox );
+ ((SwTableLines&)GetTabLines()).ForEach( &_FndLineCopyCol, &aPara );
+ }
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+
+ {
+ // Tabellen-Formeln in die relative Darstellung umwandeln
+ SwTableFmlUpdate aMsgHnt( this );
+ aMsgHnt.eFlags = TBL_RELBOXNAME;
+ GetFrmFmt()->GetDoc()->UpdateTblFlds( &aMsgHnt );
+ }
+
+ _CpyTabFrms aCpyFmt;
+ _CpyPara aPara( &rTblNd, 1, aCpyFmt, sal_True );
+ aPara.nNewSize = aPara.nOldSize = rTblNd.GetTable().GetFrmFmt()->GetFrmSize().GetWidth();
+ // dann kopiere mal
+ if( IsNewModel() )
+ lcl_CalcNewWidths( aFndBox.GetLines(), aPara );
+ aFndBox.GetLines().ForEach( &lcl_CopyLineToDoc, &aPara );
+ if( rTblNd.GetTable().IsNewModel() )
+ { // The copied line must not contain any row span attributes > 1
+ SwTableLine* pLine = rTblNd.GetTable().GetTabLines()[0];
+ sal_uInt16 nColCount = pLine->GetTabBoxes().Count();
+ ASSERT( nColCount, "Empty Table Line" )
+ for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
+ {
+ SwTableBox* pTableBox = pLine->GetTabBoxes()[nCurrCol];
+ ASSERT( pTableBox, "Missing Table Box" );
+ pTableBox->setRowSpan( 1 );
+ }
+ }
+
+ return sal_True;
+}
+
+sal_Bool SwTable::MakeCopy( SwDoc* pInsDoc, const SwPosition& rPos,
+ const SwSelBoxes& rSelBoxes, sal_Bool bCpyNds,
+ sal_Bool bCpyName ) const
+{
+ // suche alle Boxen / Lines
+ _FndBox aFndBox( 0, 0 );
+ {
+ _FndPara aPara( rSelBoxes, &aFndBox );
+ ((SwTableLines&)GetTabLines()).ForEach( &_FndLineCopyCol, &aPara );
+ }
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+
+ // erst die Poolvorlagen fuer die Tabelle kopieren, damit die dann
+ // wirklich kopiert und damit die gueltigen Werte haben.
+ SwDoc* pSrcDoc = GetFrmFmt()->GetDoc();
+ if( pSrcDoc != pInsDoc )
+ {
+ pInsDoc->CopyTxtColl( *pSrcDoc->GetTxtCollFromPool( RES_POOLCOLL_TABLE ) );
+ pInsDoc->CopyTxtColl( *pSrcDoc->GetTxtCollFromPool( RES_POOLCOLL_TABLE_HDLN ) );
+ }
+
+ SwTable* pNewTbl = (SwTable*)pInsDoc->InsertTable(
+ SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER, 1 ),
+ rPos, 1, 1, GetFrmFmt()->GetHoriOrient().GetHoriOrient(),
+ 0, 0, sal_False, IsNewModel() );
+ if( !pNewTbl )
+ return sal_False;
+
+ SwNodeIndex aIdx( rPos.nNode, -1 );
+ SwTableNode* pTblNd = aIdx.GetNode().FindTableNode();
+ aIdx++;
+ ASSERT( pTblNd, "wo ist denn nun der TableNode?" );
+
+ pTblNd->GetTable().SetRowsToRepeat( GetRowsToRepeat() );
+
+ if( IS_TYPE( SwDDETable, this ))
+ {
+ // es wird eine DDE-Tabelle kopiert
+ // ist im neuen Dokument ueberhaupt der FeldTyp vorhanden ?
+ SwFieldType* pFldType = pInsDoc->InsertFldType(
+ *((SwDDETable*)this)->GetDDEFldType() );
+ ASSERT( pFldType, "unbekannter FieldType" );
+
+ // tauschen am Node den Tabellen-Pointer aus
+ pNewTbl = new SwDDETable( *pNewTbl,
+ (SwDDEFieldType*)pFldType );
+ pTblNd->SetNewTable( pNewTbl, sal_False );
+ }
+
+ pNewTbl->GetFrmFmt()->CopyAttrs( *GetFrmFmt() );
+ pNewTbl->SetTblChgMode( GetTblChgMode() );
+
+ //Vernichten der Frms die bereits angelegt wurden.
+ pTblNd->DelFrms();
+
+ {
+ // Tabellen-Formeln in die relative Darstellung umwandeln
+ SwTableFmlUpdate aMsgHnt( this );
+ aMsgHnt.eFlags = TBL_RELBOXNAME;
+ pSrcDoc->UpdateTblFlds( &aMsgHnt );
+ }
+
+ SwTblNumFmtMerge aTNFM( *pSrcDoc, *pInsDoc );
+
+ // Namen auch kopieren oder neuen eindeutigen erzeugen
+ if( bCpyName )
+ pNewTbl->GetFrmFmt()->SetName( GetFrmFmt()->GetName() );
+
+ _CpyTabFrms aCpyFmt;
+ _CpyPara aPara( pTblNd, 1, aCpyFmt, bCpyNds );
+ aPara.nNewSize = aPara.nOldSize = GetFrmFmt()->GetFrmSize().GetWidth();
+
+ if( IsNewModel() )
+ lcl_CalcNewWidths( aFndBox.GetLines(), aPara );
+ // dann kopiere mal
+ aFndBox.GetLines().ForEach( &lcl_CopyLineToDoc, &aPara );
+
+ // dann setze oben und unten noch die "richtigen" Raender:
+ {
+ _FndLine* pFndLn = aFndBox.GetLines()[ 0 ];
+ SwTableLine* pLn = pFndLn->GetLine();
+ const SwTableLine* pTmp = pLn;
+ sal_uInt16 nLnPos = GetTabLines().GetPos( pTmp );
+ if( USHRT_MAX != nLnPos && nLnPos )
+ {
+ // es gibt eine Line davor
+ SwCollectTblLineBoxes aLnPara( sal_False, HEADLINE_BORDERCOPY );
+
+ pLn = GetTabLines()[ nLnPos - 1 ];
+ pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aLnPara );
+
+ if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ),
+ lcl_GetLineWidth( *pFndLn )) )
+ {
+ aLnPara.SetValues( sal_True );
+ pLn = pNewTbl->GetTabLines()[ 0 ];
+ pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aLnPara );
+ }
+ }
+
+ pFndLn = aFndBox.GetLines()[ aFndBox.GetLines().Count() -1 ];
+ pLn = pFndLn->GetLine();
+ pTmp = pLn;
+ nLnPos = GetTabLines().GetPos( pTmp );
+ if( nLnPos < GetTabLines().Count() - 1 )
+ {
+ // es gibt eine Line dahinter
+ SwCollectTblLineBoxes aLnPara( sal_True, HEADLINE_BORDERCOPY );
+
+ pLn = GetTabLines()[ nLnPos + 1 ];
+ pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aLnPara );
+
+ if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ),
+ lcl_GetLineWidth( *pFndLn )) )
+ {
+ aLnPara.SetValues( sal_False );
+ pLn = pNewTbl->GetTabLines()[ pNewTbl->GetTabLines().Count()-1 ];
+ pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aLnPara );
+ }
+ }
+ }
+
+ // die initiale Box muss noch geloescht werden
+ _DeleteBox( *pNewTbl, pNewTbl->GetTabLines()[
+ pNewTbl->GetTabLines().Count() - 1 ]->GetTabBoxes()[0],
+ 0, sal_False, sal_False );
+
+ if( pNewTbl->IsNewModel() )
+ lcl_CheckRowSpan( *pNewTbl );
+ // Mal kurz aufraeumen:
+ pNewTbl->GCLines();
+
+ pTblNd->MakeFrms( &aIdx ); // erzeuge die Frames neu
+
+ CHECKTABLELAYOUT
+
+ return sal_True;
+}
+
+
+
+// ---------------------------------------------------------------
+
+// suche ab dieser Line nach der naechsten Box mit Inhalt
+SwTableBox* SwTableLine::FindNextBox( const SwTable& rTbl,
+ const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const
+{
+ const SwTableLine* pLine = this; // fuer M800
+ SwTableBox* pBox;
+ sal_uInt16 nFndPos;
+ if( GetTabBoxes().Count() && pSrchBox &&
+ USHRT_MAX != ( nFndPos = GetTabBoxes().GetPos( pSrchBox )) &&
+ nFndPos + 1 != GetTabBoxes().Count() )
+ {
+ pBox = GetTabBoxes()[ nFndPos + 1 ];
+ while( pBox->GetTabLines().Count() )
+ pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
+ return pBox;
+ }
+
+ if( GetUpper() )
+ {
+ nFndPos = GetUpper()->GetTabLines().GetPos( pLine );
+ ASSERT( USHRT_MAX != nFndPos, "Line nicht in der Tabelle" );
+ // gibts eine weitere Line
+ if( nFndPos+1 >= GetUpper()->GetTabLines().Count() )
+ return GetUpper()->GetUpper()->FindNextBox( rTbl, GetUpper(), bOvrTblLns );
+ pLine = GetUpper()->GetTabLines()[nFndPos+1];
+ }
+ else if( bOvrTblLns ) // ueber die "GrundLines" einer Tabelle ?
+ {
+ // suche in der Tabelle nach der naechsten Line
+ nFndPos = rTbl.GetTabLines().GetPos( pLine );
+ if( nFndPos + 1 >= rTbl.GetTabLines().Count() )
+ return 0; // es gibt keine weitere Box mehr
+
+ pLine = rTbl.GetTabLines()[ nFndPos+1 ];
+ }
+ else
+ return 0;
+
+ if( pLine->GetTabBoxes().Count() )
+ {
+ pBox = pLine->GetTabBoxes()[0];
+ while( pBox->GetTabLines().Count() )
+ pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
+ return pBox;
+ }
+ return pLine->FindNextBox( rTbl, 0, bOvrTblLns );
+}
+
+// suche ab dieser Line nach der vorherigen Box
+SwTableBox* SwTableLine::FindPreviousBox( const SwTable& rTbl,
+ const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const
+{
+ const SwTableLine* pLine = this; // fuer M800
+ SwTableBox* pBox;
+ sal_uInt16 nFndPos;
+ if( GetTabBoxes().Count() && pSrchBox &&
+ USHRT_MAX != ( nFndPos = GetTabBoxes().GetPos( pSrchBox )) &&
+ nFndPos )
+ {
+ pBox = GetTabBoxes()[ nFndPos - 1 ];
+ while( pBox->GetTabLines().Count() )
+ {
+ pLine = pBox->GetTabLines()[pBox->GetTabLines().Count()-1];
+ pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1];
+ }
+ return pBox;
+ }
+
+ if( GetUpper() )
+ {
+ nFndPos = GetUpper()->GetTabLines().GetPos( pLine );
+ ASSERT( USHRT_MAX != nFndPos, "Line nicht in der Tabelle" );
+ // gibts eine weitere Line
+ if( !nFndPos )
+ return GetUpper()->GetUpper()->FindPreviousBox( rTbl, GetUpper(), bOvrTblLns );
+ pLine = GetUpper()->GetTabLines()[nFndPos-1];
+ }
+ else if( bOvrTblLns ) // ueber die "GrundLines" einer Tabelle ?
+ {
+ // suche in der Tabelle nach der naechsten Line
+ nFndPos = rTbl.GetTabLines().GetPos( pLine );
+ if( !nFndPos )
+ return 0; // es gibt keine weitere Box mehr
+
+ pLine = rTbl.GetTabLines()[ nFndPos-1 ];
+ }
+ else
+ return 0;
+
+ if( pLine->GetTabBoxes().Count() )
+ {
+ pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1];
+ while( pBox->GetTabLines().Count() )
+ {
+ pLine = pBox->GetTabLines()[pBox->GetTabLines().Count()-1];
+ pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1];
+ }
+ return pBox;
+ }
+ return pLine->FindPreviousBox( rTbl, 0, bOvrTblLns );
+}
+
+// suche ab dieser Line nach der naechsten Box mit Inhalt
+SwTableBox* SwTableBox::FindNextBox( const SwTable& rTbl,
+ const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const
+{
+ if( !pSrchBox && !GetTabLines().Count() )
+ return (SwTableBox*)this;
+ return GetUpper()->FindNextBox( rTbl, pSrchBox ? pSrchBox : this,
+ bOvrTblLns );
+
+}
+
+// suche ab dieser Line nach der naechsten Box mit Inhalt
+SwTableBox* SwTableBox::FindPreviousBox( const SwTable& rTbl,
+ const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const
+{
+ if( !pSrchBox && !GetTabLines().Count() )
+ return (SwTableBox*)this;
+ return GetUpper()->FindPreviousBox( rTbl, pSrchBox ? pSrchBox : this,
+ bOvrTblLns );
+}
+
+
+sal_Bool lcl_BoxSetHeadCondColl( const SwTableBox*& rpBox, void* )
+{
+ // in der HeadLine sind die Absaetze mit BedingtenVorlage anzupassen
+ const SwStartNode* pSttNd = rpBox->GetSttNd();
+ if( pSttNd )
+ pSttNd->CheckSectionCondColl();
+ else
+ ((SwTableBox*)rpBox)->GetTabLines().ForEach( &lcl_LineSetHeadCondColl, 0 );
+ return sal_True;
+}
+
+sal_Bool lcl_LineSetHeadCondColl( const SwTableLine*& rpLine, void* )
+{
+ ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_BoxSetHeadCondColl, 0 );
+ return sal_True;
+}
+
+/* */
+
+SwTwips lcl_GetDistance( SwTableBox* pBox, sal_Bool bLeft )
+{
+ sal_Bool bFirst = sal_True;
+ SwTwips nRet = 0;
+ SwTableLine* pLine;
+ while( pBox && 0 != ( pLine = pBox->GetUpper() ) )
+ {
+ sal_uInt16 nStt = 0, nPos = pLine->GetTabBoxes().C40_GETPOS( SwTableBox, pBox );
+
+ if( bFirst && !bLeft )
+ ++nPos;
+ bFirst = sal_False;
+
+ while( nStt < nPos )
+ nRet += pLine->GetTabBoxes()[ nStt++ ]->GetFrmFmt()
+ ->GetFrmSize().GetWidth();
+ pBox = pLine->GetUpper();
+ }
+ return nRet;
+}
+
+sal_Bool lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck )
+{
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTableBox* pBox = rBoxes[ n ];
+ SwFrmFmt* pFmt = pBox->GetFrmFmt();
+ const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
+ SwTwips nWidth = rSz.GetWidth();
+ sal_Bool bGreaterBox = sal_False;
+
+ if( bCheck )
+ {
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ if( !::lcl_SetSelBoxWidth( pBox->GetTabLines()[ i ], rParam,
+ nDist, sal_True ))
+ return sal_False;
+
+ // dann noch mal alle "ContentBoxen" sammeln
+ if( ( 0 != ( bGreaterBox = TBLFIX_CHGABS != rParam.nMode && ( nDist + ( rParam.bLeft ? 0 : nWidth ) ) >= rParam.nSide)) ||
+ ( !rParam.bBigger && ( Abs( nDist + (( rParam.nMode && rParam.bLeft ) ? 0 : nWidth ) - rParam.nSide ) < COLFUZZY ) ) )
+ {
+ rParam.bAnyBoxFnd = sal_True;
+ SwTwips nLowerDiff;
+ if( bGreaterBox && TBLFIX_CHGPROP == rParam.nMode )
+ {
+ // die "anderen Boxen" wurden angepasst,
+ // also sich um diesen Betrag aendern
+ nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide;
+ nLowerDiff *= rParam.nDiff;
+ nLowerDiff /= rParam.nMaxSize;
+ nLowerDiff = rParam.nDiff - nLowerDiff;
+ }
+ else
+ nLowerDiff = rParam.nDiff;
+
+ if( nWidth < nLowerDiff || nWidth - nLowerDiff < MINLAY )
+ return sal_False;
+ }
+ }
+ else
+ {
+ SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ {
+ rParam.nLowerDiff = 0;
+ lcl_SetSelBoxWidth( pBox->GetTabLines()[ i ], rParam, nDist, sal_False );
+
+ if( nLowerDiff < rParam.nLowerDiff )
+ nLowerDiff = rParam.nLowerDiff;
+ }
+ rParam.nLowerDiff = nOldLower;
+
+
+ if( nLowerDiff ||
+ ( 0 != ( bGreaterBox = !nOldLower && TBLFIX_CHGABS != rParam.nMode &&
+ ( nDist + ( rParam.bLeft ? 0 : nWidth ) ) >= rParam.nSide)) ||
+ ( Abs( nDist + ( (rParam.nMode && rParam.bLeft) ? 0 : nWidth )
+ - rParam.nSide ) < COLFUZZY ))
+ {
+ // in dieser Spalte ist der Cursor - also verkleinern / vergroessern
+ SwFmtFrmSize aNew( rSz );
+
+ if( !nLowerDiff )
+ {
+ if( bGreaterBox && TBLFIX_CHGPROP == rParam.nMode )
+ {
+ // die "anderen Boxen" wurden angepasst,
+ // also sich um diesen Betrag aendern
+ nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide;
+ nLowerDiff *= rParam.nDiff;
+ nLowerDiff /= rParam.nMaxSize;
+ nLowerDiff = rParam.nDiff - nLowerDiff;
+ }
+ else
+ nLowerDiff = rParam.nDiff;
+ }
+
+ rParam.nLowerDiff += nLowerDiff;
+
+ if( rParam.bBigger )
+ aNew.SetWidth( nWidth + nLowerDiff );
+ else
+ aNew.SetWidth( nWidth - nLowerDiff );
+ rParam.aShareFmts.SetSize( *pBox, aNew );
+ break;
+ }
+ }
+
+ if( rParam.bLeft && rParam.nMode && nDist >= rParam.nSide )
+ break;
+
+ nDist += nWidth;
+
+ // wenns groesser wird, dann wars das
+ if( ( TBLFIX_CHGABS == rParam.nMode || !rParam.bLeft ) &&
+ nDist >= rParam.nSide )
+ break;
+ }
+ return sal_True;
+}
+
+sal_Bool lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck )
+{
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTableBox* pBox = rBoxes[ n ];
+ SwFrmFmt* pFmt = pBox->GetFrmFmt();
+ const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
+ SwTwips nWidth = rSz.GetWidth();
+
+ if( bCheck )
+ {
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ if( !::lcl_SetOtherBoxWidth( pBox->GetTabLines()[ i ],
+ rParam, nDist, sal_True ))
+ return sal_False;
+
+ if( rParam.bBigger && ( TBLFIX_CHGABS == rParam.nMode
+ ? Abs( nDist - rParam.nSide ) < COLFUZZY
+ : ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY
+ : nDist >= rParam.nSide - COLFUZZY )) )
+ {
+ rParam.bAnyBoxFnd = sal_True;
+ SwTwips nDiff;
+ if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport.
+ {
+ // relativ berechnen
+ nDiff = nWidth;
+ nDiff *= rParam.nDiff;
+ nDiff /= rParam.nMaxSize;
+ }
+ else
+ nDiff = rParam.nDiff;
+
+ if( nWidth < nDiff || nWidth - nDiff < MINLAY )
+ return sal_False;
+ }
+ }
+ else
+ {
+ SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ {
+ rParam.nLowerDiff = 0;
+ lcl_SetOtherBoxWidth( pBox->GetTabLines()[ i ], rParam,
+ nDist, sal_False );
+
+ if( nLowerDiff < rParam.nLowerDiff )
+ nLowerDiff = rParam.nLowerDiff;
+ }
+ rParam.nLowerDiff = nOldLower;
+
+ if( nLowerDiff ||
+ ( TBLFIX_CHGABS == rParam.nMode
+ ? Abs( nDist - rParam.nSide ) < COLFUZZY
+ : ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY
+ : nDist >= rParam.nSide - COLFUZZY)
+ ) )
+ {
+ SwFmtFrmSize aNew( rSz );
+
+ if( !nLowerDiff )
+ {
+ if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport.
+ {
+ // relativ berechnen
+ nLowerDiff = nWidth;
+ nLowerDiff *= rParam.nDiff;
+ nLowerDiff /= rParam.nMaxSize;
+ }
+ else
+ nLowerDiff = rParam.nDiff;
+ }
+
+ rParam.nLowerDiff += nLowerDiff;
+
+ if( rParam.bBigger )
+ aNew.SetWidth( nWidth - nLowerDiff );
+ else
+ aNew.SetWidth( nWidth + nLowerDiff );
+
+ rParam.aShareFmts.SetSize( *pBox, aNew );
+ }
+ }
+
+ nDist += nWidth;
+ if( ( TBLFIX_CHGABS == rParam.nMode || rParam.bLeft ) &&
+ nDist > rParam.nSide )
+ break;
+ }
+ return sal_True;
+}
+
+/* */
+
+sal_Bool lcl_InsSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck )
+{
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ sal_uInt16 n, nCmp;
+ for( n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTableBox* pBox = rBoxes[ n ];
+ SwTableBoxFmt* pFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
+ const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
+ SwTwips nWidth = rSz.GetWidth();
+
+ if( bCheck )
+ {
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ if( !::lcl_InsSelBox( pBox->GetTabLines()[ i ], rParam,
+ nDist, sal_True ))
+ return sal_False;
+
+ // dann noch mal alle "ContentBoxen" sammeln
+ if( Abs( nDist + ( rParam.bLeft ? 0 : nWidth )
+ - rParam.nSide ) < COLFUZZY )
+ nCmp = 1;
+ else if( nDist + ( rParam.bLeft ? 0 : nWidth/2 ) > rParam.nSide )
+ nCmp = 2;
+ else
+ nCmp = 0;
+
+ if( nCmp )
+ {
+ rParam.bAnyBoxFnd = sal_True;
+ if( pFmt->GetProtect().IsCntntProtected() )
+ return sal_False;
+
+ if( rParam.bSplittBox &&
+ nWidth - rParam.nDiff <= COLFUZZY +
+ ( 567 / 2 /* min. 0,5 cm Platz lassen*/) )
+ return sal_False;
+
+ if( pBox->GetSttNd() )
+ rParam.aBoxes.Insert( pBox );
+
+ break;
+ }
+ }
+ else
+ {
+ SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ {
+ rParam.nLowerDiff = 0;
+ lcl_InsSelBox( pBox->GetTabLines()[ i ], rParam, nDist, sal_False );
+
+ if( nLowerDiff < rParam.nLowerDiff )
+ nLowerDiff = rParam.nLowerDiff;
+ }
+ rParam.nLowerDiff = nOldLower;
+
+ if( nLowerDiff )
+ nCmp = 1;
+ else if( Abs( nDist + ( rParam.bLeft ? 0 : nWidth )
+ - rParam.nSide ) < COLFUZZY )
+ nCmp = 2;
+ else if( nDist + nWidth / 2 > rParam.nSide )
+ nCmp = 3;
+ else
+ nCmp = 0;
+
+ if( nCmp )
+ {
+ // in dieser Spalte ist der Cursor - also verkleinern / vergroessern
+ if( 1 == nCmp )
+ {
+ if( !rParam.bSplittBox )
+ {
+ // die akt. Box auf
+ SwFmtFrmSize aNew( rSz );
+ aNew.SetWidth( nWidth + rParam.nDiff );
+ rParam.aShareFmts.SetSize( *pBox, aNew );
+ }
+ }
+ else
+ {
+ ASSERT( pBox->GetSttNd(), "Das muss eine EndBox sein!");
+
+ if( !rParam.bLeft && 3 != nCmp )
+ ++n;
+
+ ::_InsTblBox( pFmt->GetDoc(), rParam.pTblNd,
+ pLine, pFmt, pBox, n );
+
+ SwTableBox* pNewBox = rBoxes[ n ];
+ SwFmtFrmSize aNew( rSz );
+ aNew.SetWidth( rParam.nDiff );
+ rParam.aShareFmts.SetSize( *pNewBox, aNew );
+
+ // Sonderfall: kein Platz in den anderen Boxen
+ // aber in der Zelle
+ if( rParam.bSplittBox )
+ {
+ // die akt. Box auf
+ SwFmtFrmSize aNewSize( rSz );
+ aNewSize.SetWidth( nWidth - rParam.nDiff );
+ rParam.aShareFmts.SetSize( *pBox, aNewSize );
+ }
+
+ // Sonderbehandlung fuer Umrandung die Rechte muss
+ // entfernt werden
+ {
+ const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox();
+ if( rBoxItem.GetRight() )
+ {
+ SvxBoxItem aTmp( rBoxItem );
+ aTmp.SetLine( 0, BOX_LINE_RIGHT );
+ rParam.aShareFmts.SetAttr( rParam.bLeft
+ ? *pNewBox
+ : *pBox, aTmp );
+ }
+ }
+ }
+
+ rParam.nLowerDiff = rParam.nDiff;
+ break;
+ }
+ }
+
+ if( rParam.bLeft && rParam.nMode && nDist >= rParam.nSide )
+ break;
+
+ nDist += nWidth;
+ }
+ return sal_True;
+}
+
+sal_Bool lcl_InsOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck )
+{
+ // Sonderfall: kein Platz in den anderen Boxen aber in der Zelle
+ if( rParam.bSplittBox )
+ return sal_True;
+
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ sal_uInt16 n;
+
+ // Tabelle fix, proport.
+ if( !rParam.nRemainWidth && TBLFIX_CHGPROP == rParam.nMode )
+ {
+ // dann die richtige Breite suchen, auf die sich die relative
+ // Breitenanpassung bezieht.
+ SwTwips nTmpDist = nDist;
+ for( n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTwips nWidth = rBoxes[ n ]->GetFrmFmt()->GetFrmSize().GetWidth();
+ if( (nTmpDist + nWidth / 2 ) > rParam.nSide )
+ {
+ rParam.nRemainWidth = rParam.bLeft
+ ? sal_uInt16(nTmpDist)
+ : sal_uInt16(rParam.nTblWidth - nTmpDist);
+ break;
+ }
+ nTmpDist += nWidth;
+ }
+ }
+
+ for( n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTableBox* pBox = rBoxes[ n ];
+ SwFrmFmt* pFmt = pBox->GetFrmFmt();
+ const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
+ SwTwips nWidth = rSz.GetWidth();
+
+ if( bCheck )
+ {
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ if( !::lcl_InsOtherBox( pBox->GetTabLines()[ i ],
+ rParam, nDist, sal_True ))
+ return sal_False;
+
+ if(
+ rParam.bLeft ? ((nDist + nWidth / 2 ) <= rParam.nSide &&
+ (TBLFIX_CHGABS != rParam.nMode ||
+ (n < rBoxes.Count() &&
+ (nDist + nWidth + rBoxes[ n+1 ]->
+ GetFrmFmt()->GetFrmSize().GetWidth() / 2)
+ > rParam.nSide) ))
+ : (nDist + nWidth / 2 ) > rParam.nSide
+ )
+ {
+ rParam.bAnyBoxFnd = sal_True;
+ SwTwips nDiff;
+ if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport.
+ {
+ // relativ berechnen
+ nDiff = nWidth;
+ nDiff *= rParam.nDiff;
+ nDiff /= rParam.nRemainWidth;
+
+ if( nWidth < nDiff || nWidth - nDiff < MINLAY )
+ return sal_False;
+ }
+ else
+ {
+ nDiff = rParam.nDiff;
+
+ // teste ob die linke oder rechte Box gross genug
+ // ist, um den Platz abzugeben!
+ // es wird davor oder dahinter eine Box eingefuegt!
+ SwTwips nTmpWidth = nWidth;
+ if( rParam.bLeft && pBox->GetUpper()->GetUpper() )
+ {
+ const SwTableBox* pTmpBox = pBox;
+ sal_uInt16 nBoxPos = n;
+ while( !nBoxPos && pTmpBox->GetUpper()->GetUpper() )
+ {
+ pTmpBox = pTmpBox->GetUpper()->GetUpper();
+ nBoxPos = pTmpBox->GetUpper()->GetTabBoxes().GetPos( pTmpBox );
+ }
+// if( nBoxPos )
+ nTmpWidth = pTmpBox->GetFrmFmt()->GetFrmSize().GetWidth();
+// else
+// nTmpWidth = 0;
+ }
+
+ if( nTmpWidth < nDiff || nTmpWidth - nDiff < MINLAY )
+ return sal_False;
+ break;
+ }
+ }
+ }
+ else
+ {
+ SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ {
+ rParam.nLowerDiff = 0;
+ lcl_InsOtherBox( pBox->GetTabLines()[ i ], rParam,
+ nDist, sal_False );
+
+ if( nLowerDiff < rParam.nLowerDiff )
+ nLowerDiff = rParam.nLowerDiff;
+ }
+ rParam.nLowerDiff = nOldLower;
+
+ if( nLowerDiff ||
+ (rParam.bLeft ? ((nDist + nWidth / 2 ) <= rParam.nSide &&
+ (TBLFIX_CHGABS != rParam.nMode ||
+ (n < rBoxes.Count() &&
+ (nDist + nWidth + rBoxes[ n+1 ]->
+ GetFrmFmt()->GetFrmSize().GetWidth() / 2)
+ > rParam.nSide) ))
+ : (nDist + nWidth / 2 ) > rParam.nSide ))
+ {
+ if( !nLowerDiff )
+ {
+ if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport.
+ {
+ // relativ berechnen
+ nLowerDiff = nWidth;
+ nLowerDiff *= rParam.nDiff;
+ nLowerDiff /= rParam.nRemainWidth;
+ }
+ else
+ nLowerDiff = rParam.nDiff;
+ }
+
+ SwFmtFrmSize aNew( rSz );
+ rParam.nLowerDiff += nLowerDiff;
+
+ if( rParam.bBigger )
+ aNew.SetWidth( nWidth - nLowerDiff );
+ else
+ aNew.SetWidth( nWidth + nLowerDiff );
+ rParam.aShareFmts.SetSize( *pBox, aNew );
+
+ if( TBLFIX_CHGABS == rParam.nMode )
+ break;
+ }
+ }
+
+ nDist += nWidth;
+ }
+ return sal_True;
+}
+
+
+// das Ergebnis des Positions Vergleiches
+// POS_BEFORE, // Box liegt davor
+// POS_BEHIND, // Box liegt dahinter
+// POS_INSIDE, // Box liegt vollstaendig in Start/End
+// POS_OUTSIDE, // Box ueberlappt Start/End vollstaendig
+// POS_EQUAL, // Box und Start/End sind gleich
+// POS_OVERLAP_BEFORE, // Box ueberlappt den Start
+// POS_OVERLAP_BEHIND // Box ueberlappt das Ende
+
+SwComparePosition _CheckBoxInRange( sal_uInt16 nStt, sal_uInt16 nEnd,
+ sal_uInt16 nBoxStt, sal_uInt16 nBoxEnd )
+{
+// COLFUZZY noch beachten!!
+ SwComparePosition nRet;
+ if( nBoxStt + COLFUZZY < nStt )
+ {
+ if( nBoxEnd > nStt + COLFUZZY )
+ {
+ if( nBoxEnd >= nEnd + COLFUZZY )
+ nRet = POS_OUTSIDE;
+ else
+ nRet = POS_OVERLAP_BEFORE;
+ }
+ else
+ nRet = POS_BEFORE;
+ }
+ else if( nEnd > nBoxStt + COLFUZZY )
+ {
+ if( nEnd + COLFUZZY >= nBoxEnd )
+ {
+ if( COLFUZZY > Abs( long(nEnd) - long(nBoxEnd) ) &&
+ COLFUZZY > Abs( long(nStt) - long(nBoxStt) ) )
+ nRet = POS_EQUAL;
+ else
+ nRet = POS_INSIDE;
+ }
+ else
+ nRet = POS_OVERLAP_BEHIND;
+ }
+ else
+ nRet = POS_BEHIND;
+
+ return nRet;
+}
+
+void lcl_DelSelBox_CorrLowers( SwTableLine& rLine, CR_SetBoxWidth& rParam,
+ SwTwips nWidth )
+{
+ // 1. Schritt die eigene Breite feststellen
+ SwTableBoxes& rBoxes = rLine.GetTabBoxes();
+ SwTwips nBoxWidth = 0;
+ sal_uInt16 n;
+
+ for( n = rBoxes.Count(); n; )
+ nBoxWidth += rBoxes[ --n ]->GetFrmFmt()->GetFrmSize().GetWidth();
+
+ if( COLFUZZY < Abs( nWidth - nBoxWidth ))
+ {
+ // sie muessen also angepasst werden
+ for( n = rBoxes.Count(); n; )
+ {
+ SwTableBox* pBox = rBoxes[ --n ];
+ SwFmtFrmSize aNew( pBox->GetFrmFmt()->GetFrmSize() );
+ long nDiff = aNew.GetWidth();
+ nDiff *= nWidth;
+ nDiff /= nBoxWidth;
+ aNew.SetWidth( nDiff );
+
+ rParam.aShareFmts.SetSize( *pBox, aNew );
+
+ if( !pBox->GetSttNd() )
+ {
+ // hat selbst auch Lower, also auch die anpassen
+ for( sal_uInt16 i = pBox->GetTabLines().Count(); i; )
+ ::lcl_DelSelBox_CorrLowers( *pBox->GetTabLines()[ --i ],
+ rParam, nDiff );
+ }
+ }
+ }
+}
+
+void lcl_ChgBoxSize( SwTableBox& rBox, CR_SetBoxWidth& rParam,
+ const SwFmtFrmSize& rOldSz,
+ sal_uInt16& rDelWidth, SwTwips nDist )
+{
+ long nDiff = 0;
+ sal_Bool bSetSize = sal_False;
+
+ switch( rParam.nMode )
+ {
+ case TBLFIX_CHGABS: // Tabelle feste Breite, den Nachbar andern
+ nDiff = rDelWidth + rParam.nLowerDiff;
+ bSetSize = sal_True;
+ break;
+
+ case TBLFIX_CHGPROP: // Tabelle feste Breite, alle Nachbarn aendern
+ if( !rParam.nRemainWidth )
+ {
+ // dann kurz berechnen:
+ if( rParam.bLeft )
+ rParam.nRemainWidth = sal_uInt16(nDist);
+ else
+ rParam.nRemainWidth = sal_uInt16(rParam.nTblWidth - nDist);
+ }
+
+ // relativ berechnen
+ nDiff = rOldSz.GetWidth();
+ nDiff *= rDelWidth + rParam.nLowerDiff;
+ nDiff /= rParam.nRemainWidth;
+
+ bSetSize = sal_True;
+ break;
+
+ case TBLVAR_CHGABS: // Tabelle variable, alle Nachbarn aendern
+ if( COLFUZZY < Abs( rParam.nBoxWidth -
+ ( rDelWidth + rParam.nLowerDiff )))
+ {
+ nDiff = rDelWidth + rParam.nLowerDiff - rParam.nBoxWidth;
+ if( 0 < nDiff )
+ rDelWidth = rDelWidth - sal_uInt16(nDiff);
+ else
+ rDelWidth = rDelWidth + sal_uInt16(-nDiff);
+ bSetSize = sal_True;
+ }
+ break;
+ }
+
+ if( bSetSize )
+ {
+ SwFmtFrmSize aNew( rOldSz );
+ aNew.SetWidth( aNew.GetWidth() + nDiff );
+ rParam.aShareFmts.SetSize( rBox, aNew );
+
+ // dann leider nochmals die Lower anpassen
+ for( sal_uInt16 i = rBox.GetTabLines().Count(); i; )
+ ::lcl_DelSelBox_CorrLowers( *rBox.GetTabLines()[ --i ], rParam,
+ aNew.GetWidth() );
+ }
+}
+
+sal_Bool lcl_DeleteBox_Rekursiv( CR_SetBoxWidth& rParam, SwTableBox& rBox,
+ sal_Bool bCheck )
+{
+ sal_Bool bRet = sal_True;
+ if( rBox.GetSttNd() )
+ {
+ if( bCheck )
+ {
+ rParam.bAnyBoxFnd = sal_True;
+ if( rBox.GetFrmFmt()->GetProtect().IsCntntProtected() )
+ bRet = sal_False;
+ else
+ {
+ SwTableBox* pBox = &rBox;
+ rParam.aBoxes.Insert( pBox );
+ }
+ }
+ else
+ ::_DeleteBox( rParam.pTblNd->GetTable(), &rBox,
+ rParam.pUndo, sal_False, sal_True, &rParam.aShareFmts );
+ }
+ else
+ {
+ // die muessen leider alle sequentiel ueber die
+ // Contentboxen geloescht werden
+ for( sal_uInt16 i = rBox.GetTabLines().Count(); i; )
+ {
+ SwTableLine& rLine = *rBox.GetTabLines()[ --i ];
+ for( sal_uInt16 n = rLine.GetTabBoxes().Count(); n; )
+ if( !::lcl_DeleteBox_Rekursiv( rParam,
+ *rLine.GetTabBoxes()[ --n ], bCheck ))
+ return sal_False;
+ }
+ }
+ return bRet;
+}
+
+sal_Bool lcl_DelSelBox( SwTableLine* pTabLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck )
+{
+ SwTableBoxes& rBoxes = pTabLine->GetTabBoxes();
+ sal_uInt16 n, nCntEnd, nBoxChkStt, nBoxChkEnd, nDelWidth = 0;
+ if( rParam.bLeft )
+ {
+ n = rBoxes.Count();
+ nCntEnd = 0;
+ nBoxChkStt = (sal_uInt16)rParam.nSide;
+ nBoxChkEnd = static_cast<sal_uInt16>(rParam.nSide + rParam.nBoxWidth);
+ }
+ else
+ {
+ n = 0;
+ nCntEnd = rBoxes.Count();
+ nBoxChkStt = static_cast<sal_uInt16>(rParam.nSide - rParam.nBoxWidth);
+ nBoxChkEnd = (sal_uInt16)rParam.nSide;
+ }
+
+
+ while( n != nCntEnd )
+ {
+ SwTableBox* pBox;
+ if( rParam.bLeft )
+ pBox = rBoxes[ --n ];
+ else
+ pBox = rBoxes[ n++ ];
+
+ SwFrmFmt* pFmt = pBox->GetFrmFmt();
+ const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
+ long nWidth = rSz.GetWidth();
+ sal_Bool bDelBox = sal_False, bChgLowers = sal_False;
+
+ // die Boxenbreite testen und entpsrechend reagieren
+ SwComparePosition ePosType = ::_CheckBoxInRange(
+ nBoxChkStt, nBoxChkEnd,
+ sal_uInt16(rParam.bLeft ? nDist - nWidth : nDist),
+ sal_uInt16(rParam.bLeft ? nDist : nDist + nWidth));
+
+ switch( ePosType )
+ {
+ case POS_BEFORE:
+ if( bCheck )
+ {
+ if( rParam.bLeft )
+ return sal_True;
+ }
+ else if( rParam.bLeft )
+ {
+ ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist );
+ if( TBLFIX_CHGABS == rParam.nMode )
+ n = nCntEnd;
+ }
+ break;
+
+ case POS_BEHIND:
+ if( bCheck )
+ {
+ if( !rParam.bLeft )
+ return sal_True;
+ }
+ else if( !rParam.bLeft )
+ {
+ ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist );
+ if( TBLFIX_CHGABS == rParam.nMode )
+ n = nCntEnd;
+ }
+ break;
+
+ case POS_OUTSIDE: // Box ueberlappt Start/End vollstaendig
+ case POS_INSIDE: // Box liegt vollstaendig in Start/End
+ case POS_EQUAL: // Box und Start/End sind gleich
+ bDelBox = sal_True;
+ break;
+
+ case POS_OVERLAP_BEFORE: // Box ueberlappt den Start
+ if( nBoxChkStt <= ( nDist + (rParam.bLeft ? - nWidth / 2
+ : nWidth / 2 )))
+ {
+ if( !pBox->GetSttNd() )
+ bChgLowers = sal_True;
+ else
+ bDelBox = sal_True;
+ }
+ else if( !bCheck && rParam.bLeft )
+ {
+ if( !pBox->GetSttNd() )
+ bChgLowers = sal_True;
+ else
+ {
+ ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist );
+ if( TBLFIX_CHGABS == rParam.nMode )
+ n = nCntEnd;
+ }
+ }
+ break;
+
+ case POS_OVERLAP_BEHIND: // Box ueberlappt das Ende
+ // JP 10.02.99:
+ // generell loeschen oder wie beim OVERLAP_Before nur die, die
+ // bis zur Haelfte in die "Loesch-"Box reicht ???
+ if( !pBox->GetSttNd() )
+ bChgLowers = sal_True;
+ else
+ bDelBox = sal_True;
+ break;
+ default: break;
+ }
+
+ if( bDelBox )
+ {
+ nDelWidth = nDelWidth + sal_uInt16(nWidth);
+ if( bCheck )
+ {
+ // die letzte/erste Box kann nur bei Tbl-Var geloescht werden,
+ // wenn diese so gross ist, wie die Aenderung an der Tabelle
+ if( (( TBLVAR_CHGABS != rParam.nMode ||
+ nDelWidth != rParam.nBoxWidth ) &&
+ COLFUZZY > Abs( rParam.bLeft
+ ? nWidth - nDist
+ : (nDist + nWidth - rParam.nTblWidth )))
+ || !::lcl_DeleteBox_Rekursiv( rParam, *pBox, bCheck ) )
+ return sal_False;
+
+ if( pFmt->GetProtect().IsCntntProtected() )
+ return sal_False;
+ }
+ else
+ {
+ ::lcl_DeleteBox_Rekursiv( rParam, *pBox, bCheck );
+
+ if( !rParam.bLeft )
+ --n, --nCntEnd;
+ }
+ }
+ else if( bChgLowers )
+ {
+ sal_Bool bFirst = sal_True, bCorrLowers = sal_False;
+ long nLowerDiff = 0;
+ long nOldLower = rParam.nLowerDiff;
+ sal_uInt16 nOldRemain = rParam.nRemainWidth;
+ sal_uInt16 i;
+
+ for( i = pBox->GetTabLines().Count(); i; )
+ {
+ rParam.nLowerDiff = nDelWidth + nOldLower;
+ rParam.nRemainWidth = nOldRemain;
+ SwTableLine* pLine = pBox->GetTabLines()[ --i ];
+ if( !::lcl_DelSelBox( pLine, rParam, nDist, bCheck ))
+ return sal_False;
+
+ // gibt es die Box und die darin enthaltenen Lines noch??
+ if( n < rBoxes.Count() &&
+ pBox == rBoxes[ rParam.bLeft ? n : n-1 ] &&
+ i < pBox->GetTabLines().Count() &&
+ pLine == pBox->GetTabLines()[ i ] )
+ {
+ if( !bFirst && !bCorrLowers &&
+ COLFUZZY < Abs( nLowerDiff - rParam.nLowerDiff ) )
+ bCorrLowers = sal_True;
+
+ // die groesste "loesch" Breite entscheidet, aber nur wenn
+ // nicht die gesamte Line geloescht wurde
+ if( nLowerDiff < rParam.nLowerDiff )
+ nLowerDiff = rParam.nLowerDiff;
+
+ bFirst = sal_False;
+ }
+ }
+ rParam.nLowerDiff = nOldLower;
+ rParam.nRemainWidth = nOldRemain;
+
+ // wurden alle Boxen geloescht? Dann ist die DelBreite natuerlich
+ // die Boxenbreite
+ if( !nLowerDiff )
+ nLowerDiff = nWidth;
+
+ // DelBreite anpassen!!
+ nDelWidth = nDelWidth + sal_uInt16(nLowerDiff);
+
+ if( !bCheck )
+ {
+ // wurde die Box schon entfernt?
+ if( n > rBoxes.Count() ||
+ pBox != rBoxes[ ( rParam.bLeft ? n : n-1 ) ] )
+ {
+ // dann beim Loeschen nach rechts die Laufvar. anpassen
+ if( !rParam.bLeft )
+ --n, --nCntEnd;
+ }
+ else
+ {
+ // sonst muss die Groesse der Box angepasst werden
+ SwFmtFrmSize aNew( rSz );
+ sal_Bool bCorrRel = sal_False;
+
+ if( TBLVAR_CHGABS != rParam.nMode )
+ {
+ switch( ePosType )
+ {
+ case POS_OVERLAP_BEFORE: // Box ueberlappt den Start
+ if( TBLFIX_CHGPROP == rParam.nMode )
+ bCorrRel = rParam.bLeft;
+ else if( rParam.bLeft ) // TBLFIX_CHGABS
+ {
+ nLowerDiff = nLowerDiff - nDelWidth;
+ bCorrLowers = sal_True;
+ n = nCntEnd;
+ }
+ break;
+
+ case POS_OVERLAP_BEHIND: // Box ueberlappt das Ende
+ if( TBLFIX_CHGPROP == rParam.nMode )
+ bCorrRel = !rParam.bLeft;
+ else if( !rParam.bLeft ) // TBLFIX_CHGABS
+ {
+ nLowerDiff = nLowerDiff - nDelWidth;
+ bCorrLowers = sal_True;
+ n = nCntEnd;
+ }
+ break;
+
+ default:
+ ASSERT( !pBox, "hier sollte man nie hinkommen" );
+ break;
+ }
+ }
+
+ if( bCorrRel )
+ {
+ if( !rParam.nRemainWidth )
+ {
+ // dann kurz berechnen:
+ if( rParam.bLeft )
+ rParam.nRemainWidth = sal_uInt16(nDist - nLowerDiff);
+ else
+ rParam.nRemainWidth = sal_uInt16(rParam.nTblWidth - nDist
+ - nLowerDiff );
+ }
+
+ long nDiff = aNew.GetWidth() - nLowerDiff;
+ nDiff *= nDelWidth + rParam.nLowerDiff;
+ nDiff /= rParam.nRemainWidth;
+
+ aNew.SetWidth( aNew.GetWidth() - nLowerDiff + nDiff );
+ }
+ else
+ aNew.SetWidth( aNew.GetWidth() - nLowerDiff );
+ rParam.aShareFmts.SetSize( *pBox, aNew );
+
+ if( bCorrLowers )
+ {
+ // dann leider nochmals die Lower anpassen
+ for( i = pBox->GetTabLines().Count(); i; )
+ ::lcl_DelSelBox_CorrLowers( *pBox->
+ GetTabLines()[ --i ], rParam, aNew.GetWidth() );
+ }
+ }
+ }
+ }
+
+ if( rParam.bLeft )
+ nDist -= nWidth;
+ else
+ nDist += nWidth;
+ }
+ rParam.nLowerDiff = nDelWidth;
+ return sal_True;
+}
+
+// Dummy Funktion fuer die Methode SetColWidth
+sal_Bool lcl_DelOtherBox( SwTableLine* , CR_SetBoxWidth& , SwTwips , sal_Bool )
+{
+ return sal_True;
+}
+
+/* */
+
+void lcl_AjustLines( SwTableLine* pLine, CR_SetBoxWidth& rParam )
+{
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTableBox* pBox = rBoxes[ n ];
+
+ SwFmtFrmSize aSz( pBox->GetFrmFmt()->GetFrmSize() );
+ SwTwips nWidth = aSz.GetWidth();
+ nWidth *= rParam.nDiff;
+ nWidth /= rParam.nMaxSize;
+ aSz.SetWidth( nWidth );
+ rParam.aShareFmts.SetSize( *pBox, aSz );
+
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ ::lcl_AjustLines( pBox->GetTabLines()[ i ], rParam );
+ }
+}
+
+#if defined(DBG_UTIL) || defined( JP_DEBUG )
+
+void _CheckBoxWidth( const SwTableLine& rLine, SwTwips nSize )
+{
+ const SwTableBoxes& rBoxes = rLine.GetTabBoxes();
+
+ SwTwips nAktSize = 0;
+ // checke doch mal ob die Tabellen korrekte Breiten haben
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ const SwTableBox* pBox = rBoxes[ n ];
+ const SwTwips nBoxW = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ nAktSize += nBoxW;
+
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ _CheckBoxWidth( *pBox->GetTabLines()[ i ], nBoxW );
+ }
+
+ if( Abs( nAktSize - nSize ) > ( COLFUZZY * rBoxes.Count() ) )
+ {
+ DBG_ERROR( "Boxen der Line zu klein/gross" );
+#if defined( WNT ) && defined( JP_DEBUG )
+ __asm int 3;
+#endif
+ }
+}
+
+#endif
+
+_FndBox* lcl_SaveInsDelData( CR_SetBoxWidth& rParam, SwUndo** ppUndo,
+ SwTableSortBoxes& rTmpLst, SwTwips nDistStt )
+{
+ // suche alle Boxen / Lines
+ SwTable& rTbl = rParam.pTblNd->GetTable();
+
+ if( !rParam.aBoxes.Count() )
+ {
+ // erstmal die Boxen besorgen !
+ if( rParam.bBigger )
+ for( sal_uInt16 n = 0; n < rTbl.GetTabLines().Count(); ++n )
+ ::lcl_DelSelBox( rTbl.GetTabLines()[ n ], rParam, nDistStt, sal_True );
+ else
+ for( sal_uInt16 n = 0; n < rTbl.GetTabLines().Count(); ++n )
+ ::lcl_InsSelBox( rTbl.GetTabLines()[ n ], rParam, nDistStt, sal_True );
+ }
+
+ // loeschen der gesamten Tabelle verhindern
+ if( rParam.bBigger && rParam.aBoxes.Count() ==
+ rTbl.GetTabSortBoxes().Count() )
+ return 0;
+
+ _FndBox* pFndBox = new _FndBox( 0, 0 );
+ if( rParam.bBigger )
+ pFndBox->SetTableLines( rParam.aBoxes, rTbl );
+ else
+ {
+ _FndPara aPara( rParam.aBoxes, pFndBox );
+ rTbl.GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ ASSERT( pFndBox->GetLines().Count(), "Wo sind die Boxen" );
+ pFndBox->SetTableLines( rTbl );
+
+ if( ppUndo )
+ rTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
+ }
+
+ //Lines fuer das Layout-Update herausuchen.
+ pFndBox->DelFrms( rTbl );
+
+ // TL_CHART2: this function gest called from SetColWidth exclusively,
+ // thus it is currently speculated that nothing needs to be done here.
+ // Note: that SetColWidth is currently not completely understood though :-(
+
+ return pFndBox;
+}
+
+sal_Bool SwTable::SetColWidth( SwTableBox& rAktBox, sal_uInt16 eType,
+ SwTwips nAbsDiff, SwTwips nRelDiff, SwUndo** ppUndo )
+{
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ const SwFmtFrmSize& rSz = GetFrmFmt()->GetFrmSize();
+ const SvxLRSpaceItem& rLR = GetFrmFmt()->GetLRSpace();
+
+ _FndBox* pFndBox = 0; // fuers Einfuegen/Loeschen
+ SwTableSortBoxes aTmpLst( 0, 5 ); // fuers Undo
+ sal_Bool bBigger,
+ bRet = sal_False,
+ bLeft = nsTblChgWidthHeightType::WH_COL_LEFT == ( eType & 0xff ) ||
+ nsTblChgWidthHeightType::WH_CELL_LEFT == ( eType & 0xff ),
+ bInsDel = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL );
+ sal_uInt16 n;
+ sal_uLong nBoxIdx = rAktBox.GetSttIdx();
+
+ // bestimme die akt. Kante der Box
+ // wird nur fuer die Breitenmanipulation benoetigt!
+ const SwTwips nDist = ::lcl_GetDistance( &rAktBox, bLeft );
+ SwTwips nDistStt = 0;
+ CR_SetBoxWidth aParam( eType, nRelDiff, nDist, rSz.GetWidth(),
+ bLeft ? nDist : rSz.GetWidth() - nDist,
+ (SwTableNode*)rAktBox.GetSttNd()->FindTableNode() );
+ bBigger = aParam.bBigger;
+
+ FN_lcl_SetBoxWidth fnSelBox, fnOtherBox;
+ if( bInsDel )
+ {
+ if( bBigger )
+ {
+ fnSelBox = lcl_DelSelBox;
+ fnOtherBox = lcl_DelOtherBox;
+ aParam.nBoxWidth = (sal_uInt16)rAktBox.GetFrmFmt()->GetFrmSize().GetWidth();
+ if( bLeft )
+ nDistStt = rSz.GetWidth();
+ }
+ else
+ {
+ fnSelBox = lcl_InsSelBox;
+ fnOtherBox = lcl_InsOtherBox;
+ }
+ }
+ else
+ {
+ fnSelBox = lcl_SetSelBoxWidth;
+ fnOtherBox = lcl_SetOtherBoxWidth;
+ }
+
+
+ switch( eType & 0xff )
+ {
+ case nsTblChgWidthHeightType::WH_COL_RIGHT:
+ case nsTblChgWidthHeightType::WH_COL_LEFT:
+ if( TBLVAR_CHGABS == eTblChgMode )
+ {
+ if( bInsDel )
+ bBigger = !bBigger;
+
+ // erstmal testen, ob ueberhaupt Platz ist
+ sal_Bool bChgLRSpace = sal_True;
+ if( bBigger )
+ {
+ if( GetFrmFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) &&
+ !rSz.GetWidthPercent() )
+ {
+ bRet = rSz.GetWidth() < USHRT_MAX - nRelDiff;
+ bChgLRSpace = bLeft ? rLR.GetLeft() >= nAbsDiff
+ : rLR.GetRight() >= nAbsDiff;
+ }
+ else
+ bRet = bLeft ? rLR.GetLeft() >= nAbsDiff
+ : rLR.GetRight() >= nAbsDiff;
+
+ if( !bRet && bInsDel &&
+ // auf der anderen Seite Platz?
+ ( bLeft ? rLR.GetRight() >= nAbsDiff
+ : rLR.GetLeft() >= nAbsDiff ))
+ {
+ bRet = sal_True; bLeft = !bLeft;
+ }
+
+ if( !bRet )
+ {
+ // dann sich selbst rekursiv aufrufen; nur mit
+ // einem anderen Mode -> proprotional
+ TblChgMode eOld = eTblChgMode;
+ eTblChgMode = TBLFIX_CHGPROP;
+
+ bRet = SetColWidth( rAktBox, eType, nAbsDiff, nRelDiff,
+ ppUndo );
+ eTblChgMode = eOld;
+ return bRet;
+ }
+ }
+ else
+ {
+ bRet = sal_True;
+ for( n = 0; n < aLines.Count(); ++n )
+ {
+ aParam.LoopClear();
+ if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True ))
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+
+ if( bRet )
+ {
+ if( bInsDel )
+ {
+ pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo,
+ aTmpLst, nDistStt );
+ if( aParam.bBigger && aParam.aBoxes.Count() ==
+ aSortCntBoxes.Count() )
+ {
+ // dies gesamte Tabelle soll geloescht werden!!
+ GetFrmFmt()->GetDoc()->DeleteRowCol( aParam.aBoxes );
+ return sal_False;
+ }
+
+ if( ppUndo )
+ *ppUndo = aParam.CreateUndo(
+ aParam.bBigger ? UNDO_COL_DELETE
+ : UNDO_TABLE_INSCOL );
+ }
+ else if( ppUndo )
+ *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True );
+
+ long nFrmWidth = LONG_MAX;
+ LockModify();
+ SwFmtFrmSize aSz( rSz );
+ SvxLRSpaceItem aLR( rLR );
+ if( bBigger )
+ {
+ // falls die Tabelle keinen Platz zum Wachsen hat, dann
+ // muessen wir welchen schaffen!
+ if( aSz.GetWidth() + nRelDiff > USHRT_MAX )
+ {
+ // dann mal herunterbrechen auf USHRT_MAX / 2
+ CR_SetBoxWidth aTmpPara( 0, aSz.GetWidth() / 2,
+ 0, aSz.GetWidth(), aSz.GetWidth(), aParam.pTblNd );
+ for( sal_uInt16 nLn = 0; nLn < aLines.Count(); ++nLn )
+ ::lcl_AjustLines( aLines[ nLn ], aTmpPara );
+ aSz.SetWidth( aSz.GetWidth() / 2 );
+ aParam.nDiff = nRelDiff /= 2;
+ aParam.nSide /= 2;
+ aParam.nMaxSize /= 2;
+ }
+
+ if( bLeft )
+ aLR.SetLeft( sal_uInt16( aLR.GetLeft() - nAbsDiff ) );
+ else
+ aLR.SetRight( sal_uInt16( aLR.GetRight() - nAbsDiff ) );
+ }
+ else if( bLeft )
+ aLR.SetLeft( sal_uInt16( aLR.GetLeft() + nAbsDiff ) );
+ else
+ aLR.SetRight( sal_uInt16( aLR.GetRight() + nAbsDiff ) );
+
+ if( bChgLRSpace )
+ GetFrmFmt()->SetFmtAttr( aLR );
+ const SwFmtHoriOrient& rHOri = GetFrmFmt()->GetHoriOrient();
+ if( text::HoriOrientation::FULL == rHOri.GetHoriOrient() ||
+ (text::HoriOrientation::LEFT == rHOri.GetHoriOrient() && aLR.GetLeft()) ||
+ (text::HoriOrientation::RIGHT == rHOri.GetHoriOrient() && aLR.GetRight()))
+ {
+ SwFmtHoriOrient aHOri( rHOri );
+ aHOri.SetHoriOrient( text::HoriOrientation::NONE );
+ GetFrmFmt()->SetFmtAttr( aHOri );
+
+ // sollte die Tabelle noch auf relativen Werten
+ // (USHRT_MAX) stehen dann muss es jetzt auf absolute
+ // umgerechnet werden. Bug 61494
+ if( GetFrmFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) &&
+ !rSz.GetWidthPercent() )
+ {
+ SwTabFrm* pTabFrm = (SwTabFrm*)SwClientIter(
+ *GetFrmFmt() ).First( TYPE( SwTabFrm ));
+ if( pTabFrm &&
+ pTabFrm->Prt().Width() != rSz.GetWidth() )
+ {
+ nFrmWidth = pTabFrm->Prt().Width();
+ if( bBigger )
+ nFrmWidth += nAbsDiff;
+ else
+ nFrmWidth -= nAbsDiff;
+ }
+ }
+ }
+
+ if( bBigger )
+ aSz.SetWidth( aSz.GetWidth() + nRelDiff );
+ else
+ aSz.SetWidth( aSz.GetWidth() - nRelDiff );
+
+ if( rSz.GetWidthPercent() )
+ aSz.SetWidthPercent( static_cast<sal_uInt8>(( aSz.GetWidth() * 100 ) /
+ ( aSz.GetWidth() + aLR.GetRight() + aLR.GetLeft())));
+
+ GetFrmFmt()->SetFmtAttr( aSz );
+ aParam.nTblWidth = sal_uInt16( aSz.GetWidth() );
+
+ UnlockModify();
+
+ for( n = aLines.Count(); n; )
+ {
+ --n;
+ aParam.LoopClear();
+ (*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_False );
+ }
+
+ // sollte die Tabelle noch auf relativen Werten
+ // (USHRT_MAX) stehen dann muss es jetzt auf absolute
+ // umgerechnet werden. Bug 61494
+ if( LONG_MAX != nFrmWidth )
+ {
+ SwFmtFrmSize aAbsSz( aSz );
+ aAbsSz.SetWidth( nFrmWidth );
+ GetFrmFmt()->SetFmtAttr( aAbsSz );
+ }
+ }
+ }
+ else if( bInsDel ||
+ ( bLeft ? nDist : Abs( rSz.GetWidth() - nDist ) > COLFUZZY ) )
+ {
+ bRet = sal_True;
+ if( bLeft && TBLFIX_CHGABS == eTblChgMode && !bInsDel )
+ aParam.bBigger = !bBigger;
+
+ // erstmal testen, ob ueberhaupt Platz ist
+ if( bInsDel )
+ {
+ if( aParam.bBigger )
+ {
+ for( n = 0; n < aLines.Count(); ++n )
+ {
+ aParam.LoopClear();
+ if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True ))
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if( 0 != ( bRet = bLeft ? nDist != 0
+ : ( rSz.GetWidth() - nDist ) > COLFUZZY ) )
+ {
+ for( n = 0; n < aLines.Count(); ++n )
+ {
+ aParam.LoopClear();
+ if( !(*fnOtherBox)( aLines[ n ], aParam, 0, sal_True ))
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ if( bRet && !aParam.bAnyBoxFnd )
+ bRet = sal_False;
+ }
+
+ if( !bRet && rAktBox.GetFrmFmt()->GetFrmSize().GetWidth()
+ - nRelDiff > COLFUZZY +
+ ( 567 / 2 /* min. 0,5 cm Platz lassen*/) )
+ {
+ // dann den Platz von der akt. Zelle nehmen
+ aParam.bSplittBox = sal_True;
+ // aber das muss auch mal getestet werden!
+ bRet = sal_True;
+
+ for( n = 0; n < aLines.Count(); ++n )
+ {
+ aParam.LoopClear();
+ if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True ))
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if( aParam.bBigger )
+ {
+ for( n = 0; n < aLines.Count(); ++n )
+ {
+ aParam.LoopClear();
+ if( !(*fnOtherBox)( aLines[ n ], aParam, 0, sal_True ))
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+ else
+ {
+ for( n = 0; n < aLines.Count(); ++n )
+ {
+ aParam.LoopClear();
+ if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True ))
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+
+ // wenn ja, dann setzen
+ if( bRet )
+ {
+ CR_SetBoxWidth aParam1( aParam );
+ if( bInsDel )
+ {
+ aParam1.bBigger = !aParam.bBigger;
+ pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo,
+ aTmpLst, nDistStt );
+ if( ppUndo )
+ *ppUndo = aParam.CreateUndo(
+ aParam.bBigger ? UNDO_TABLE_DELBOX
+ : UNDO_TABLE_INSCOL );
+ }
+ else if( ppUndo )
+ *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True );
+
+ if( bInsDel
+ ? ( TBLFIX_CHGABS == eTblChgMode ? bLeft : bLeft )
+ : ( TBLFIX_CHGABS != eTblChgMode && bLeft ) )
+ {
+ for( n = aLines.Count(); n; )
+ {
+ --n;
+ aParam.LoopClear();
+ aParam1.LoopClear();
+ (*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_False );
+ (*fnOtherBox)( aLines[ n ], aParam1, nDistStt, sal_False );
+ }
+ }
+ else
+ for( n = aLines.Count(); n; )
+ {
+ --n;
+ aParam.LoopClear();
+ aParam1.LoopClear();
+ (*fnOtherBox)( aLines[ n ], aParam1, nDistStt, sal_False );
+ (*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_False );
+ }
+ }
+ }
+ break;
+
+ case nsTblChgWidthHeightType::WH_CELL_RIGHT:
+ case nsTblChgWidthHeightType::WH_CELL_LEFT:
+ if( TBLVAR_CHGABS == eTblChgMode )
+ {
+ // dann sich selbst rekursiv aufrufen; nur mit
+ // einem anderen Mode -> Nachbarn
+ TblChgMode eOld = eTblChgMode;
+ eTblChgMode = TBLFIX_CHGABS;
+
+ bRet = SetColWidth( rAktBox, eType, nAbsDiff, nRelDiff,
+ ppUndo );
+ eTblChgMode = eOld;
+ return bRet;
+ }
+ else if( bInsDel || ( bLeft ? nDist
+ : (rSz.GetWidth() - nDist) > COLFUZZY ))
+ {
+ if( bLeft && TBLFIX_CHGABS == eTblChgMode && !bInsDel )
+ aParam.bBigger = !bBigger;
+
+ // erstmal testen, ob ueberhaupt Platz ist
+ SwTableBox* pBox = &rAktBox;
+ SwTableLine* pLine = rAktBox.GetUpper();
+ while( pLine->GetUpper() )
+ {
+ sal_uInt16 nPos = pLine->GetTabBoxes().C40_GETPOS( SwTableBox, pBox );
+ if( bLeft ? nPos : nPos + 1 != pLine->GetTabBoxes().Count() )
+ break;
+
+ pBox = pLine->GetUpper();
+ pLine = pBox->GetUpper();
+ }
+
+ if( pLine->GetUpper() )
+ {
+ // dann muss die Distanz wieder korriegiert werden!
+ aParam.nSide -= ::lcl_GetDistance( pLine->GetUpper(), sal_True );
+
+ if( bLeft )
+ aParam.nMaxSize = aParam.nSide;
+ else
+ aParam.nMaxSize = pLine->GetUpper()->GetFrmFmt()->
+ GetFrmSize().GetWidth() - aParam.nSide;
+ }
+
+ // erstmal testen, ob ueberhaupt Platz ist
+ if( bInsDel )
+ {
+ if( 0 != ( bRet = bLeft ? nDist != 0
+ : ( rSz.GetWidth() - nDist ) > COLFUZZY ) &&
+ !aParam.bBigger )
+ {
+ bRet = (*fnOtherBox)( pLine, aParam, 0, sal_True );
+ if( bRet && !aParam.bAnyBoxFnd )
+ bRet = sal_False;
+ }
+
+ if( !bRet && !aParam.bBigger && rAktBox.GetFrmFmt()->
+ GetFrmSize().GetWidth() - nRelDiff > COLFUZZY +
+ ( 567 / 2 /* min. 0,5 cm Platz lassen*/) )
+ {
+ // dann den Platz von der akt. Zelle nehmen
+ aParam.bSplittBox = sal_True;
+ bRet = sal_True;
+ }
+ }
+ else
+ {
+ FN_lcl_SetBoxWidth fnTmp = aParam.bBigger ? fnOtherBox : fnSelBox;
+ bRet = (*fnTmp)( pLine, aParam, nDistStt, sal_True );
+ }
+
+ // wenn ja, dann setzen
+ if( bRet )
+ {
+ CR_SetBoxWidth aParam1( aParam );
+ if( bInsDel )
+ {
+ aParam1.bBigger = !aParam.bBigger;
+ pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst, nDistStt );
+ if( ppUndo )
+ *ppUndo = aParam.CreateUndo(
+ aParam.bBigger ? UNDO_TABLE_DELBOX
+ : UNDO_TABLE_INSCOL );
+ }
+ else if( ppUndo )
+ *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True );
+
+ if( bInsDel
+ ? ( TBLFIX_CHGABS == eTblChgMode ? (bBigger && bLeft) : bLeft )
+ : ( TBLFIX_CHGABS != eTblChgMode && bLeft ) )
+ {
+ (*fnSelBox)( pLine, aParam, nDistStt, sal_False );
+ (*fnOtherBox)( pLine, aParam1, nDistStt, sal_False );
+ }
+ else
+ {
+ (*fnOtherBox)( pLine, aParam1, nDistStt, sal_False );
+ (*fnSelBox)( pLine, aParam, nDistStt, sal_False );
+ }
+ }
+ }
+ break;
+
+ }
+
+ if( pFndBox )
+ {
+ // dann raeume die Struktur aller Lines auf
+ GCLines();
+
+ //Layout updaten
+ if( !bBigger || pFndBox->AreLinesToRestore( *this ) )
+ pFndBox->MakeFrms( *this );
+
+ // TL_CHART2: it is currently unclear if sth has to be done here.
+ // The function name hints that nothing needs to be done, on the other
+ // hand there is a case where sth gets deleted. :-(
+
+ delete pFndBox;
+
+ if( ppUndo && *ppUndo )
+ {
+ aParam.pUndo->SetColWidthParam( nBoxIdx, static_cast<sal_uInt16>(eTblChgMode), eType,
+ nAbsDiff, nRelDiff );
+ if( !aParam.bBigger )
+ aParam.pUndo->SaveNewBoxes( *aParam.pTblNd, aTmpLst );
+ }
+ }
+
+ if( bRet )
+ {
+ CHECKBOXWIDTH
+ CHECKTABLELAYOUT
+ }
+
+ return bRet;
+}
+/* */
+
+_FndBox* lcl_SaveInsDelData( CR_SetLineHeight& rParam, SwUndo** ppUndo,
+ SwTableSortBoxes& rTmpLst )
+{
+ // suche alle Boxen / Lines
+ SwTable& rTbl = rParam.pTblNd->GetTable();
+
+ ASSERT( rParam.aBoxes.Count(), "ohne Boxen ist nichts zu machen!" );
+
+ // loeschen der gesamten Tabelle verhindern
+ if( !rParam.bBigger && rParam.aBoxes.Count() ==
+ rTbl.GetTabSortBoxes().Count() )
+ return 0;
+
+ _FndBox* pFndBox = new _FndBox( 0, 0 );
+ if( !rParam.bBigger )
+ pFndBox->SetTableLines( rParam.aBoxes, rTbl );
+ else
+ {
+ _FndPara aPara( rParam.aBoxes, pFndBox );
+ rTbl.GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ ASSERT( pFndBox->GetLines().Count(), "Wo sind die Boxen" );
+ pFndBox->SetTableLines( rTbl );
+
+ if( ppUndo )
+ rTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
+ }
+
+ //Lines fuer das Layout-Update heraussuchen.
+ pFndBox->DelFrms( rTbl );
+
+ // TL_CHART2: it is currently unclear if sth has to be done here.
+
+ return pFndBox;
+}
+
+void SetLineHeight( SwTableLine& rLine, SwTwips nOldHeight, SwTwips nNewHeight,
+ sal_Bool bMinSize )
+{
+ SwLayoutFrm* pLineFrm = GetRowFrm( rLine );
+ ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" );
+
+ SwFrmFmt* pFmt = rLine.ClaimFrmFmt();
+
+ SwTwips nMyNewH, nMyOldH = pLineFrm->Frm().Height();
+ if( !nOldHeight ) // die BaseLine und absolut
+ nMyNewH = nMyOldH + nNewHeight;
+ else
+ {
+ // moeglichst genau rechnen
+ Fraction aTmp( nMyOldH );
+ aTmp *= Fraction( nNewHeight, nOldHeight );
+ aTmp += Fraction( 1, 2 ); // ggfs. aufrunden
+ nMyNewH = aTmp;
+ }
+
+ SwFrmSize eSize = ATT_MIN_SIZE;
+ if( !bMinSize &&
+ ( nMyOldH - nMyNewH ) > ( CalcRowRstHeight( pLineFrm ) + ROWFUZZY ))
+ eSize = ATT_FIX_SIZE;
+
+ pFmt->SetFmtAttr( SwFmtFrmSize( eSize, 0, nMyNewH ) );
+
+ // erst alle inneren anpassen
+ SwTableBoxes& rBoxes = rLine.GetTabBoxes();
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTableBox& rBox = *rBoxes[ n ];
+ for( sal_uInt16 i = 0; i < rBox.GetTabLines().Count(); ++i )
+ SetLineHeight( *rBox.GetTabLines()[ i ], nMyOldH, nMyNewH, bMinSize );
+ }
+}
+
+sal_Bool lcl_SetSelLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
+ SwTwips nDist, sal_Bool bCheck )
+{
+ sal_Bool bRet = sal_True;
+ if( !bCheck )
+ {
+ // Zeilenhoehe einstellen
+ SetLineHeight( *pLine, 0, rParam.bBigger ? nDist : -nDist,
+ rParam.bBigger );
+ }
+ else if( !rParam.bBigger )
+ {
+ // anhand der alten Size die neue relative errechnen
+ SwLayoutFrm* pLineFrm = GetRowFrm( *pLine );
+ ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" );
+ SwTwips nRstHeight = CalcRowRstHeight( pLineFrm );
+ if( (nRstHeight + ROWFUZZY) < nDist )
+ bRet = sal_False;
+ }
+ return bRet;
+}
+
+sal_Bool lcl_SetOtherLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
+ SwTwips nDist, sal_Bool bCheck )
+{
+ sal_Bool bRet = sal_True;
+ if( bCheck )
+ {
+ if( rParam.bBigger )
+ {
+ // anhand der alten Size die neue relative errechnen
+ SwLayoutFrm* pLineFrm = GetRowFrm( *pLine );
+ ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" );
+
+ if( TBLFIX_CHGPROP == rParam.nMode )
+ {
+ nDist *= pLineFrm->Frm().Height();
+ nDist /= rParam.nMaxHeight;
+ }
+ bRet = nDist <= CalcRowRstHeight( pLineFrm );
+ }
+ }
+ else
+ {
+ // Zeilenhoehe einstellen
+ // pLine ist die nachfolgende / vorhergehende -> also anpassen
+ if( TBLFIX_CHGPROP == rParam.nMode )
+ {
+ SwLayoutFrm* pLineFrm = GetRowFrm( *pLine );
+ ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" );
+
+ // aus der alten Size die neue relative errechnen
+ // Wird die selektierte Box groesser ueber den MaxSpace anpassen,
+ // sonst ueber die MaxHeight
+ if( 1 /*!rParam.bBigger*/ )
+ {
+ nDist *= pLineFrm->Frm().Height();
+ nDist /= rParam.nMaxHeight;
+ }
+ else
+ {
+ // aus der alten Size die neue relative errechnen
+ nDist *= CalcRowRstHeight( pLineFrm );
+ nDist /= rParam.nMaxSpace;
+ }
+ }
+ SetLineHeight( *pLine, 0, rParam.bBigger ? -nDist : nDist,
+ !rParam.bBigger );
+ }
+ return bRet;
+}
+
+sal_Bool lcl_InsDelSelLine( SwTableLine* pLine, CR_SetLineHeight& rParam,
+ SwTwips nDist, sal_Bool bCheck )
+{
+ sal_Bool bRet = sal_True;
+ if( !bCheck )
+ {
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ SwDoc* pDoc = pLine->GetFrmFmt()->GetDoc();
+ if( !rParam.bBigger )
+ {
+ sal_uInt16 n;
+
+ for( n = rBoxes.Count(); n; )
+ ::lcl_SaveUpperLowerBorder( rParam.pTblNd->GetTable(),
+ *rBoxes[ --n ],
+ rParam.aShareFmts );
+ for( n = rBoxes.Count(); n; )
+ ::_DeleteBox( rParam.pTblNd->GetTable(),
+ rBoxes[ --n ], rParam.pUndo, sal_False,
+ sal_False, &rParam.aShareFmts );
+ }
+ else
+ {
+ // Zeile einfuegen
+ SwTableLine* pNewLine = new SwTableLine( (SwTableLineFmt*)pLine->GetFrmFmt(),
+ rBoxes.Count(), pLine->GetUpper() );
+ SwTableLines* pLines;
+ if( pLine->GetUpper() )
+ pLines = &pLine->GetUpper()->GetTabLines();
+ else
+ pLines = &rParam.pTblNd->GetTable().GetTabLines();
+ sal_uInt16 nPos = pLines->C40_GETPOS( SwTableLine, pLine );
+ if( !rParam.bTop )
+ ++nPos;
+ pLines->C40_INSERT( SwTableLine, pNewLine, nPos );
+
+ SwFrmFmt* pNewFmt = pNewLine->ClaimFrmFmt();
+ pNewFmt->SetFmtAttr( SwFmtFrmSize( ATT_MIN_SIZE, 0, nDist ) );
+
+ // und noch mal die Anzahl Boxen erzeugen
+ SwTableBoxes& rNewBoxes = pNewLine->GetTabBoxes();
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTwips nWidth = 0;
+ SwTableBox* pOld = rBoxes[ n ];
+ if( !pOld->GetSttNd() )
+ {
+ // keine normale "Content"-Box also auf die 1. naechste
+ // Box zurueckfallen
+ nWidth = pOld->GetFrmFmt()->GetFrmSize().GetWidth();
+ while( !pOld->GetSttNd() )
+ pOld = pOld->GetTabLines()[ 0 ]->GetTabBoxes()[ 0 ];
+ }
+ ::_InsTblBox( pDoc, rParam.pTblNd, pNewLine,
+ (SwTableBoxFmt*)pOld->GetFrmFmt(), pOld, n );
+
+ // Sonderbehandlung fuer Umrandung die Obere muss
+ // entfernt werden
+ const SvxBoxItem& rBoxItem = pOld->GetFrmFmt()->GetBox();
+ if( rBoxItem.GetTop() )
+ {
+ SvxBoxItem aTmp( rBoxItem );
+ aTmp.SetLine( 0, BOX_LINE_TOP );
+ rParam.aShareFmts.SetAttr( rParam.bTop
+ ? *pOld
+ : *rNewBoxes[ n ], aTmp );
+ }
+
+ if( nWidth )
+ rParam.aShareFmts.SetAttr( *rNewBoxes[ n ],
+ SwFmtFrmSize( ATT_FIX_SIZE, nWidth, 0 ) );
+ }
+ }
+ }
+ else
+ {
+ // Boxen einsammeln!
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ for( sal_uInt16 n = rBoxes.Count(); n; )
+ {
+ SwTableBox* pBox = rBoxes[ --n ];
+ if( pBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
+ return sal_False;
+
+ if( pBox->GetSttNd() )
+ rParam.aBoxes.Insert( pBox );
+ else
+ {
+ for( sal_uInt16 i = pBox->GetTabLines().Count(); i; )
+ lcl_InsDelSelLine( pBox->GetTabLines()[ --i ],
+ rParam, 0, sal_True );
+ }
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwTable::SetRowHeight( SwTableBox& rAktBox, sal_uInt16 eType,
+ SwTwips nAbsDiff, SwTwips nRelDiff,SwUndo** ppUndo )
+{
+ SwTableLine* pLine = rAktBox.GetUpper();
+
+ SwTableLine* pBaseLine = pLine;
+ while( pBaseLine->GetUpper() )
+ pBaseLine = pBaseLine->GetUpper()->GetUpper();
+
+ _FndBox* pFndBox = 0; // fuers Einfuegen/Loeschen
+ SwTableSortBoxes aTmpLst( 0, 5 ); // fuers Undo
+ sal_Bool bBigger,
+ bRet = sal_False,
+ bTop = nsTblChgWidthHeightType::WH_ROW_TOP == ( eType & 0xff ) ||
+ nsTblChgWidthHeightType::WH_CELL_TOP == ( eType & 0xff ),
+ bInsDel = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL );
+ sal_uInt16 n, nBaseLinePos = GetTabLines().C40_GETPOS( SwTableLine, pBaseLine );
+ sal_uLong nBoxIdx = rAktBox.GetSttIdx();
+
+ CR_SetLineHeight aParam( eType,
+ (SwTableNode*)rAktBox.GetSttNd()->FindTableNode() );
+ bBigger = aParam.bBigger;
+
+ FN_lcl_SetLineHeight fnSelLine, fnOtherLine = lcl_SetOtherLineHeight;
+ if( bInsDel )
+ fnSelLine = lcl_InsDelSelLine;
+ else
+ fnSelLine = lcl_SetSelLineHeight;
+
+ SwTableLines* pLines = &aLines;
+
+ // wie kommt man an die Hoehen heran?
+ switch( eType & 0xff )
+ {
+ case nsTblChgWidthHeightType::WH_CELL_TOP:
+ case nsTblChgWidthHeightType::WH_CELL_BOTTOM:
+ if( pLine == pBaseLine )
+ break; // dann geht es nicht!
+
+ // ist eine verschachtelte Line (Box!)
+ pLines = &pLine->GetUpper()->GetTabLines();
+ nBaseLinePos = pLines->C40_GETPOS( SwTableLine, pLine );
+ pBaseLine = pLine;
+ // kein break!
+
+ case nsTblChgWidthHeightType::WH_ROW_TOP:
+ case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
+ {
+ if( bInsDel && !bBigger ) // um wieviel wird es Hoeher?
+ {
+ nAbsDiff = GetRowFrm( *pBaseLine )->Frm().Height();
+ }
+
+ if( TBLVAR_CHGABS == eTblChgMode )
+ {
+ // erstmal testen, ob ueberhaupt Platz ist
+ if( bBigger )
+ {
+ bRet = sal_True;
+// was ist mit Top, was ist mit Tabelle im Rahmen oder in Kopf-/Fusszeile
+// mit fester Hoehe ??
+ if( !bRet )
+ {
+ // dann sich selbst rekursiv aufrufen; nur mit
+ // einem anderen Mode -> proprotional
+ TblChgMode eOld = eTblChgMode;
+ eTblChgMode = TBLFIX_CHGPROP;
+
+ bRet = SetRowHeight( rAktBox, eType, nAbsDiff,
+ nRelDiff, ppUndo );
+
+ eTblChgMode = eOld;
+ return bRet;
+ }
+ }
+ else
+ bRet = (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
+ nAbsDiff, sal_True );
+
+ if( bRet )
+ {
+ if( bInsDel )
+ {
+ if( !aParam.aBoxes.Count() )
+ ::lcl_InsDelSelLine( (*pLines)[ nBaseLinePos ],
+ aParam, 0, sal_True );
+
+ pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst );
+
+ // #110525# delete complete table when last row is
+ // deleted
+ if( !bBigger &&
+ aParam.aBoxes.Count() == aSortCntBoxes.Count() )
+ {
+ GetFrmFmt()->GetDoc()->DeleteRowCol( aParam.aBoxes );
+ return sal_False;
+ }
+
+
+ if( ppUndo )
+ *ppUndo = aParam.CreateUndo(
+ bBigger ? UNDO_TABLE_INSROW
+ : UNDO_ROW_DELETE );
+ }
+ else if( ppUndo )
+ *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True );
+
+ (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
+ nAbsDiff, sal_False );
+ }
+ }
+ else
+ {
+ bRet = sal_True;
+ sal_uInt16 nStt, nEnd;
+ if( bTop )
+ nStt = 0, nEnd = nBaseLinePos;
+ else
+ nStt = nBaseLinePos + 1, nEnd = pLines->Count();
+
+ // die akt. Hoehe der Lines besorgen
+ if( TBLFIX_CHGPROP == eTblChgMode )
+ {
+ for( n = nStt; n < nEnd; ++n )
+ {
+ SwLayoutFrm* pLineFrm = GetRowFrm( *(*pLines)[ n ] );
+ ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" );
+ aParam.nMaxSpace += CalcRowRstHeight( pLineFrm );
+ aParam.nMaxHeight += pLineFrm->Frm().Height();
+ }
+ if( bBigger && aParam.nMaxSpace < nAbsDiff )
+ bRet = sal_False;
+ }
+ else
+ {
+ if( bTop ? nEnd : nStt < nEnd )
+ {
+ if( bTop )
+ nStt = nEnd - 1;
+ else
+ nEnd = nStt + 1;
+ }
+ else
+ bRet = sal_False;
+ }
+
+ if( bRet )
+ {
+ if( bBigger )
+ {
+ for( n = nStt; n < nEnd; ++n )
+ {
+ if( !(*fnOtherLine)( (*pLines)[ n ], aParam,
+ nAbsDiff, sal_True ))
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+ else
+ bRet = (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
+ nAbsDiff, sal_True );
+ }
+
+ if( bRet )
+ {
+ // dann mal anpassen
+ if( bInsDel )
+ {
+ if( !aParam.aBoxes.Count() )
+ ::lcl_InsDelSelLine( (*pLines)[ nBaseLinePos ],
+ aParam, 0, sal_True );
+ pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst );
+ if( ppUndo )
+ *ppUndo = aParam.CreateUndo(
+ bBigger ? UNDO_TABLE_INSROW
+ : UNDO_ROW_DELETE );
+ }
+ else if( ppUndo )
+ *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True );
+
+ CR_SetLineHeight aParam1( aParam );
+ if( TBLFIX_CHGPROP == eTblChgMode && !bBigger &&
+ !aParam.nMaxSpace )
+ {
+ // dann muss der gesamte Platz auf alle Lines
+ // gleichmaessig verteilt werden. Dafuer wird die
+ // Anzahl benoetigt
+ aParam1.nLines = nEnd - nStt;
+ }
+
+ if( bTop )
+ {
+ (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
+ nAbsDiff, sal_False );
+ for( n = nStt; n < nEnd; ++n )
+ (*fnOtherLine)( (*pLines)[ n ], aParam1,
+ nAbsDiff, sal_False );
+ }
+ else
+ {
+ for( n = nStt; n < nEnd; ++n )
+ (*fnOtherLine)( (*pLines)[ n ], aParam1,
+ nAbsDiff, sal_False );
+ (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
+ nAbsDiff, sal_False );
+ }
+ }
+ else
+ {
+ // dann sich selbst rekursiv aufrufen; nur mit
+ // einem anderen Mode -> proprotional
+ TblChgMode eOld = eTblChgMode;
+ eTblChgMode = TBLVAR_CHGABS;
+
+ bRet = SetRowHeight( rAktBox, eType, nAbsDiff,
+ nRelDiff, ppUndo );
+
+ eTblChgMode = eOld;
+ pFndBox = 0;
+ }
+ }
+ }
+ break;
+ }
+
+ if( pFndBox )
+ {
+ // dann raeume die Struktur aller Lines auf
+ GCLines();
+
+ //Layout updaten
+ if( bBigger || pFndBox->AreLinesToRestore( *this ) )
+ pFndBox->MakeFrms( *this );
+
+ // TL_CHART2: it is currently unclear if sth has to be done here.
+
+ delete pFndBox;
+
+ if( ppUndo && *ppUndo )
+ {
+ aParam.pUndo->SetColWidthParam( nBoxIdx, static_cast<sal_uInt16>(eTblChgMode), eType,
+ nAbsDiff, nRelDiff );
+ if( bBigger )
+ aParam.pUndo->SaveNewBoxes( *aParam.pTblNd, aTmpLst );
+ }
+ }
+
+ CHECKTABLELAYOUT
+
+ return bRet;
+}
+
+/* */
+
+SwFrmFmt* SwShareBoxFmt::GetFormat( long nWidth ) const
+{
+ SwFrmFmt *pRet = 0, *pTmp;
+ for( sal_uInt16 n = aNewFmts.Count(); n; )
+ if( ( pTmp = (SwFrmFmt*)aNewFmts[ --n ])->GetFrmSize().GetWidth()
+ == nWidth )
+ {
+ pRet = pTmp;
+ break;
+ }
+ return pRet;
+}
+
+SwFrmFmt* SwShareBoxFmt::GetFormat( const SfxPoolItem& rItem ) const
+{
+ const SfxPoolItem* pItem;
+ sal_uInt16 nWhich = rItem.Which();
+ SwFrmFmt *pRet = 0, *pTmp;
+ const SfxPoolItem& rFrmSz = pOldFmt->GetFmtAttr( RES_FRM_SIZE, sal_False );
+ for( sal_uInt16 n = aNewFmts.Count(); n; )
+ if( SFX_ITEM_SET == ( pTmp = (SwFrmFmt*)aNewFmts[ --n ])->
+ GetItemState( nWhich, sal_False, &pItem ) && *pItem == rItem &&
+ pTmp->GetFmtAttr( RES_FRM_SIZE, sal_False ) == rFrmSz )
+ {
+ pRet = pTmp;
+ break;
+ }
+ return pRet;
+}
+
+void SwShareBoxFmt::AddFormat( const SwFrmFmt& rNew )
+{
+ void* pFmt = (void*)&rNew;
+ aNewFmts.Insert( pFmt, aNewFmts.Count() );
+}
+
+sal_Bool SwShareBoxFmt::RemoveFormat( const SwFrmFmt& rFmt )
+{
+ // returnt sal_True, wenn geloescht werden kann
+ if( pOldFmt == &rFmt )
+ return sal_True;
+
+ void* p = (void*)&rFmt;
+ sal_uInt16 nFnd = aNewFmts.GetPos( p );
+ if( USHRT_MAX != nFnd )
+ aNewFmts.Remove( nFnd );
+ return 0 == aNewFmts.Count();
+}
+
+SwShareBoxFmts::~SwShareBoxFmts()
+{
+}
+
+SwFrmFmt* SwShareBoxFmts::GetFormat( const SwFrmFmt& rFmt, long nWidth ) const
+{
+ sal_uInt16 nPos;
+ return Seek_Entry( rFmt, &nPos )
+ ? aShareArr[ nPos ]->GetFormat( nWidth )
+ : 0;
+}
+SwFrmFmt* SwShareBoxFmts::GetFormat( const SwFrmFmt& rFmt,
+ const SfxPoolItem& rItem ) const
+{
+ sal_uInt16 nPos;
+ return Seek_Entry( rFmt, &nPos )
+ ? aShareArr[ nPos ]->GetFormat( rItem )
+ : 0;
+}
+
+void SwShareBoxFmts::AddFormat( const SwFrmFmt& rOld, const SwFrmFmt& rNew )
+{
+ // wenn das Format nicht geshared ist, braucht es auch nicht in die
+ // Liste aufgenommen werden. Denn es gibt keinen 2. der es sucht.
+//leider werden auch die CellFrms gefunden
+// if( !rOld.IsLastDepend() )
+ {
+ sal_uInt16 nPos;
+ SwShareBoxFmt* pEntry;
+ if( !Seek_Entry( rOld, &nPos ))
+ {
+ pEntry = new SwShareBoxFmt( rOld );
+ aShareArr.C40_INSERT( SwShareBoxFmt, pEntry, nPos );
+ }
+ else
+ pEntry = aShareArr[ nPos ];
+
+ pEntry->AddFormat( rNew );
+ }
+}
+void SwShareBoxFmts::ChangeFrmFmt( SwTableBox* pBox, SwTableLine* pLn,
+ SwFrmFmt& rFmt )
+{
+ SwClient aCl;
+ SwFrmFmt* pOld = 0;
+ if( pBox )
+ {
+ pOld = pBox->GetFrmFmt();
+ pOld->Add( &aCl );
+ pBox->ChgFrmFmt( (SwTableBoxFmt*)&rFmt );
+ }
+ else if( pLn )
+ {
+ pOld = pLn->GetFrmFmt();
+ pOld->Add( &aCl );
+ pLn->ChgFrmFmt( (SwTableLineFmt*)&rFmt );
+ }
+ if( pOld && pOld->IsLastDepend() )
+ {
+ RemoveFormat( *pOld );
+ delete pOld;
+ }
+}
+
+void SwShareBoxFmts::SetSize( SwTableBox& rBox, const SwFmtFrmSize& rSz )
+{
+ SwFrmFmt *pBoxFmt = rBox.GetFrmFmt(),
+ *pRet = GetFormat( *pBoxFmt, rSz.GetWidth() );
+ if( pRet )
+ ChangeFrmFmt( &rBox, 0, *pRet );
+ else
+ {
+ pRet = rBox.ClaimFrmFmt();
+ pRet->SetFmtAttr( rSz );
+ AddFormat( *pBoxFmt, *pRet );
+ }
+}
+
+void SwShareBoxFmts::SetAttr( SwTableBox& rBox, const SfxPoolItem& rItem )
+{
+ SwFrmFmt *pBoxFmt = rBox.GetFrmFmt(),
+ *pRet = GetFormat( *pBoxFmt, rItem );
+ if( pRet )
+ ChangeFrmFmt( &rBox, 0, *pRet );
+ else
+ {
+ pRet = rBox.ClaimFrmFmt();
+ pRet->SetFmtAttr( rItem );
+ AddFormat( *pBoxFmt, *pRet );
+ }
+}
+
+void SwShareBoxFmts::SetAttr( SwTableLine& rLine, const SfxPoolItem& rItem )
+{
+ SwFrmFmt *pLineFmt = rLine.GetFrmFmt(),
+ *pRet = GetFormat( *pLineFmt, rItem );
+ if( pRet )
+ ChangeFrmFmt( 0, &rLine, *pRet );
+ else
+ {
+ pRet = rLine.ClaimFrmFmt();
+ pRet->SetFmtAttr( rItem );
+ AddFormat( *pLineFmt, *pRet );
+ }
+}
+
+void SwShareBoxFmts::RemoveFormat( const SwFrmFmt& rFmt )
+{
+ for( sal_uInt16 i = aShareArr.Count(); i; )
+ if( aShareArr[ --i ]->RemoveFormat( rFmt ))
+ aShareArr.DeleteAndDestroy( i );
+}
+
+sal_Bool SwShareBoxFmts::Seek_Entry( const SwFrmFmt& rFmt, sal_uInt16* pPos ) const
+{
+ sal_uLong nIdx = (sal_uLong)&rFmt;
+ sal_uInt16 nO = aShareArr.Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ sal_uLong nFmt = (sal_uLong)&aShareArr[ nM ]->GetOldFormat();
+ if( nFmt == nIdx )
+ {
+ if( pPos )
+ *pPos = nM;
+ return sal_True;
+ }
+ else if( nFmt < nIdx )
+ nU = nM + 1;
+ else if( nM == 0 )
+ {
+ if( pPos )
+ *pPos = nU;
+ return sal_False;
+ }
+ else
+ nO = nM - 1;
+ }
+ }
+ if( pPos )
+ *pPos = nU;
+ return sal_False;
+}
+
+
diff --git a/sw/source/core/doc/visiturl.cxx b/sw/source/core/doc/visiturl.cxx
new file mode 100644
index 000000000000..b5ca141e1fa2
--- /dev/null
+++ b/sw/source/core/doc/visiturl.cxx
@@ -0,0 +1,139 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <sfx2/docfile.hxx>
+#include <svl/inethist.hxx>
+#include <fmtinfmt.hxx>
+#include <txtinet.hxx>
+#include <doc.hxx>
+#include <visiturl.hxx>
+#include <hints.hxx>
+#include <ndtxt.hxx>
+#include <editsh.hxx>
+#include <docsh.hxx>
+
+
+SwURLStateChanged::SwURLStateChanged( const SwDoc* pD )
+ : pDoc( pD )
+{
+ StartListening( *INetURLHistory::GetOrCreate() );
+}
+
+SwURLStateChanged::~SwURLStateChanged()
+{
+ EndListening( *INetURLHistory::GetOrCreate() );
+}
+
+void SwURLStateChanged::Notify( SfxBroadcaster& , const SfxHint& rHint )
+{
+ if( rHint.ISA( INetURLHistoryHint ) && pDoc->GetRootFrm() )
+ {
+ // diese URL wurde veraendert:
+ const INetURLObject* pIURL = ((INetURLHistoryHint&)rHint).GetObject();
+ String sURL( pIURL->GetMainURL( INetURLObject::NO_DECODE ) ), sBkmk;
+
+ SwEditShell* pESh = pDoc->GetEditShell();
+
+ if( pDoc->GetDocShell() && pDoc->GetDocShell()->GetMedium() &&
+ // falls das unser Doc ist, kann es auch lokale Spruenge geben!
+ sURL == pDoc->GetDocShell()->GetMedium()->GetName() )
+ (sBkmk = pIURL->GetMark()).Insert( INET_MARK_TOKEN, 0 );
+
+ sal_Bool bAction = sal_False, bUnLockView = sal_False;
+ const SwFmtINetFmt* pItem;
+ const SwTxtINetFmt* pTxtAttr;
+ const SwTxtNode* pTxtNd;
+ sal_uInt32 n, nMaxItems = pDoc->GetAttrPool().GetItemCount2( RES_TXTATR_INETFMT );
+ for( n = 0; n < nMaxItems; ++n )
+ if( 0 != (pItem = (SwFmtINetFmt*)pDoc->GetAttrPool().GetItem2(
+ RES_TXTATR_INETFMT, n ) ) &&
+ ( pItem->GetValue() == sURL ||
+ ( sBkmk.Len() && pItem->GetValue() == sBkmk )) &&
+ 0 != ( pTxtAttr = pItem->GetTxtINetFmt()) &&
+ 0 != ( pTxtNd = pTxtAttr->GetpTxtNode() ) )
+ {
+ if( !bAction && pESh )
+ {
+ pESh->StartAllAction();
+ bAction = sal_True;
+ bUnLockView = !pESh->IsViewLocked();
+ pESh->LockView( sal_True );
+ }
+ const_cast<SwTxtINetFmt*>(pTxtAttr)->SetVisitedValid( false );
+ const SwTxtAttr* pAttr = pTxtAttr;
+ SwUpdateAttr aUpdateAttr( *pAttr->GetStart(),
+ *pAttr->GetEnd(),
+ RES_FMT_CHG );
+ ((SwTxtNode*)pTxtNd)->Modify( &aUpdateAttr, &aUpdateAttr );
+ }
+
+ if( bAction )
+ pESh->EndAllAction();
+ if( bUnLockView )
+ pESh->LockView( sal_False );
+ }
+}
+
+ // erfrage ob die URL besucht war. Uebers Doc, falls nur ein Bookmark
+ // angegeben ist. Dann muss der Doc. Name davor gesetzt werden!
+sal_Bool SwDoc::IsVisitedURL( const String& rURL ) const
+{
+#if OSL_DEBUG_LEVEL > 1
+ static long nTmp = 0;
+ ++nTmp;
+#endif
+
+ sal_Bool bRet = sal_False;
+ if( rURL.Len() )
+ {
+ INetURLHistory *pHist = INetURLHistory::GetOrCreate();
+ if( '#' == rURL.GetChar( 0 ) && pDocShell && pDocShell->GetMedium() )
+ {
+ INetURLObject aIObj( pDocShell->GetMedium()->GetURLObject() );
+ aIObj.SetMark( rURL.Copy( 1 ) );
+ bRet = pHist->QueryUrl( aIObj );
+ }
+ else
+ bRet = pHist->QueryUrl( rURL );
+
+ // dann wollen wird auch ueber Statusaenderungen in der History
+ // informiert werden!
+ if( !pURLStateChgd )
+ {
+ SwDoc* pD = (SwDoc*)this;
+ pD->pURLStateChgd = new SwURLStateChanged( this );
+ }
+ }
+ return bRet;
+}
+
+
+