summaryrefslogtreecommitdiff
path: root/sw/source/filter/xml/XMLRedlineImportHelper.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/xml/XMLRedlineImportHelper.cxx')
-rw-r--r--sw/source/filter/xml/XMLRedlineImportHelper.cxx374
1 files changed, 304 insertions, 70 deletions
diff --git a/sw/source/filter/xml/XMLRedlineImportHelper.cxx b/sw/source/filter/xml/XMLRedlineImportHelper.cxx
index 4b7a0d2bd545..11f7f6152995 100644
--- a/sw/source/filter/xml/XMLRedlineImportHelper.cxx
+++ b/sw/source/filter/xml/XMLRedlineImportHelper.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: XMLRedlineImportHelper.cxx,v $
*
- * $Revision: 1.1 $
+ * $Revision: 1.2 $
*
- * last change: $Author: dvo $ $Date: 2001-01-10 21:01:48 $
+ * last change: $Author: dvo $ $Date: 2001-01-19 19:58:53 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -106,15 +106,25 @@
#include <com/sun/star/text/XWordCursor.hpp>
#endif
+#ifndef _COM_SUN_STAR_FRAME_XMODEL_HPP_
+#include <com/sun/star/frame/XModel.hpp>
+#endif
+
+#ifndef _COM_SUN_STAR_TEXT_XTEXTDOCUMENT_HPP_
+#include <com/sun/star/text/XTextDocument.hpp>
+#endif
+
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using ::rtl::OUString;
+using ::com::sun::star::frame::XModel;
using ::com::sun::star::text::XTextCursor;
using ::com::sun::star::text::XTextRange;
using ::com::sun::star::text::XText;
+using ::com::sun::star::text::XTextDocument;
using ::com::sun::star::text::XWordCursor;
using ::com::sun::star::lang::XUnoTunnel;
// collision with tools/DateTime: use UNO DateTime as util::DateTime
@@ -122,6 +132,139 @@ using ::com::sun::star::lang::XUnoTunnel;
//
+// a few helper functions
+//
+
+SwDoc* lcl_GetDocViaTunnel( Reference<XTextCursor> & rCursor )
+{
+ Reference<XUnoTunnel> xTunnel( rCursor, UNO_QUERY);
+ DBG_ASSERT( xTunnel.is(), "missing XUnoTunnel for Cursor" );
+ SwXTextCursor* pSwXCursor =
+ (SwXTextCursor*)xTunnel->getSomething(SwXTextCursor::getUnoTunnelId());
+ DBG_ASSERT( NULL != pSwXCursor, "SwXTextCursor missing" );
+ return pSwXCursor->GetDoc();
+}
+
+SwDoc* lcl_GetDocViaTunnel( Reference<XTextRange> & rRange )
+{
+ Reference<XUnoTunnel> xTunnel(rRange, UNO_QUERY);
+ DBG_ASSERT(xTunnel.is(), "Can't tunnel XTextRange");
+ SwXTextRange *pRange =
+ (SwXTextRange*)xTunnel->getSomething(SwXTextRange::getUnoTunnelId());
+ DBG_ASSERT( NULL != pRange, "SwXTextRange missing" );
+ return pRange->GetDoc();
+}
+
+
+//
+// XTextRangeOrNodeIndexPosition: store a position into the text
+// *either* as an XTextRange or as an SwNodeIndex. The reason is that
+// me must store either pointers to StartNodes (because redlines may
+// start on start nodes) or to a text position, and there appears to
+// be no existing type that could do both. Things are complicated by
+// the matter that (e.g in section import) we delete a few characters,
+// which may cause bookmarks (as used by XTextRange) to be deleted.
+//
+
+class XTextRangeOrNodeIndexPosition
+{
+ Reference<XTextRange> xRange;
+ SwNodeIndex* pIndex;
+
+public:
+ XTextRangeOrNodeIndexPosition();
+ ~XTextRangeOrNodeIndexPosition();
+
+ void Set( Reference<XTextRange> & rRange );
+ void Set( SwNodeIndex& rIndex );
+ void SetAsNodeIndex( Reference<XTextRange> & rRange );
+
+ void GetPosition(SwPosition& rPos);
+ SwDoc* GetDoc();
+
+ sal_Bool IsValid();
+};
+
+XTextRangeOrNodeIndexPosition::XTextRangeOrNodeIndexPosition() :
+ xRange(NULL),
+ pIndex(NULL)
+{
+}
+
+XTextRangeOrNodeIndexPosition::~XTextRangeOrNodeIndexPosition()
+{
+ delete pIndex;
+}
+
+void XTextRangeOrNodeIndexPosition::Set( Reference<XTextRange> & rRange )
+{
+ xRange = rRange;
+ if (NULL != pIndex)
+ {
+ delete pIndex;
+ pIndex = NULL;
+ }
+}
+
+void XTextRangeOrNodeIndexPosition::Set( SwNodeIndex& rIndex )
+{
+ if (NULL != pIndex)
+ delete pIndex;
+
+ pIndex = new SwNodeIndex(rIndex);
+ xRange = NULL;
+}
+
+void XTextRangeOrNodeIndexPosition::SetAsNodeIndex(
+ Reference<XTextRange> & rRange )
+{
+ // XTextRange -> XTunnel -> SwXTextRange
+ SwDoc* pDoc = lcl_GetDocViaTunnel(rRange);
+
+ // SwXTextRange -> PaM
+ SwUnoInternalPaM aPaM(*pDoc);
+ sal_Bool bSuccess = SwXTextRange::XTextRangeToSwPaM( aPaM, rRange);
+ DBG_ASSERT(bSuccess, "illegal range");
+
+ // PaM -> Index
+ Set(aPaM.GetPoint()->nNode);
+}
+
+void XTextRangeOrNodeIndexPosition::GetPosition(SwPosition& rPos)
+{
+ DBG_ASSERT(IsValid(), "Can't get Position");
+
+ // create PAM from start cursor (if no node index is present)
+ if (NULL == pIndex)
+ {
+ SwUnoInternalPaM aUnoPaM(*GetDoc());
+ sal_Bool bSuccess = SwXTextRange::XTextRangeToSwPaM(aUnoPaM, xRange);
+ DBG_ASSERT(bSuccess, "illegal range");
+
+ rPos = *aUnoPaM.GetPoint();
+ }
+ else
+ {
+ rPos.nNode = *pIndex;
+ rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), 0 );
+ }
+}
+
+SwDoc* XTextRangeOrNodeIndexPosition::GetDoc()
+{
+ DBG_ASSERT(IsValid(), "Can't get Doc");
+
+ return (NULL != pIndex) ? pIndex->GetNodes().GetDoc() : lcl_GetDocViaTunnel(xRange);
+}
+
+sal_Bool XTextRangeOrNodeIndexPosition::IsValid()
+{
+ return ( xRange.is() || (pIndex != NULL) );
+}
+
+
+
+//
// RedlineInfo: temporary storage for redline data
//
@@ -139,10 +282,13 @@ public:
OUString sComment; /// change comment string
util::DateTime aDateTime; /// change DateTime
- /// start pos of anchor (may be empty)
- Reference<XTextRange> xAnchorStartPos;
- /// end pos of anchor (may be empty)
- Reference<XTextRange> xAnchorEndPos;
+ // each position can may be either empty, an XTextRange, or an SwNodeIndex
+
+ // start pos of anchor (may be empty)
+ XTextRangeOrNodeIndexPosition aAnchorStart;
+
+ // end pos of anchor (may be empty)
+ XTextRangeOrNodeIndexPosition aAnchorEnd;
/// index of content node (maybe NULL)
SwNodeIndex* pContentIndex;
@@ -156,8 +302,8 @@ RedlineInfo::RedlineInfo() :
sAuthor(),
sComment(),
aDateTime(),
- xAnchorStartPos(),
- xAnchorEndPos(),
+ aAnchorStart(),
+ aAnchorEnd(),
pContentIndex(NULL),
pNextRedline(NULL)
{
@@ -170,17 +316,19 @@ RedlineInfo::~RedlineInfo()
}
-
//
// XMLRedlineImportHelper
//
-XMLRedlineImportHelper::XMLRedlineImportHelper() :
- sEmpty(),
- sInsertion(RTL_CONSTASCII_USTRINGPARAM(sXML_insertion)),
- sDeletion(RTL_CONSTASCII_USTRINGPARAM(sXML_deletion)),
- sFormatChange(RTL_CONSTASCII_USTRINGPARAM(sXML_format_change)),
- aRedlineMap()
+XMLRedlineImportHelper::XMLRedlineImportHelper(
+ sal_Bool bNoRedlinesPlease) :
+ sEmpty(),
+ sInsertion(RTL_CONSTASCII_USTRINGPARAM(sXML_insertion)),
+ sDeletion(RTL_CONSTASCII_USTRINGPARAM(sXML_deletion)),
+ sFormatChange(RTL_CONSTASCII_USTRINGPARAM(sXML_format_change)),
+ aRedlineMap(),
+ bIgnoreRedlines(bNoRedlinesPlease),
+ pSaveDoc(NULL)
{
}
@@ -196,6 +344,17 @@ XMLRedlineImportHelper::~XMLRedlineImportHelper()
delete pInfo;
}
aRedlineMap.clear();
+
+ // set redline mode; first set bogus redline mode with
+ // SetRedlineMode_intern(), so that the subsequent
+ // SetRedlineMode() is forced to update the data structures
+ if (NULL != pSaveDoc)
+ {
+ // TODO: get "real" Redline mode from the saved document
+ sal_uInt16 nRedlineMode = REDLINE_ON | REDLINE_SHOW_MASK;
+ pSaveDoc->SetRedlineMode_intern(~nRedlineMode);
+ pSaveDoc->SetRedlineMode(nRedlineMode);
+ }
}
void XMLRedlineImportHelper::Add(
@@ -275,12 +434,7 @@ Reference<XTextCursor> XMLRedlineImportHelper::CreateRedlineTextSection(
if (aRedlineMap.end() != aFind)
{
// get document from old cursor (via tunnel)
- Reference<XUnoTunnel> xTunnel( xOldCursor, UNO_QUERY);
- DBG_ASSERT( xTunnel.is(), "missing XUnoTunnel for Cursor" );
- SwXTextCursor* pOldCursor = (SwXTextCursor*)xTunnel->getSomething(
- SwXTextCursor::getUnoTunnelId());
- DBG_ASSERT( NULL != pOldCursor, "SwXTextCursor missing" );
- SwDoc* pDoc = pOldCursor->GetDoc();
+ SwDoc* pDoc = lcl_GetDocViaTunnel(xOldCursor);
// create text section for redline
SwTxtFmtColl *pColl = pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD);
@@ -313,20 +467,29 @@ Reference<XTextCursor> XMLRedlineImportHelper::CreateRedlineTextSection(
void XMLRedlineImportHelper::SetCursor(
const OUString& rId,
sal_Bool bStart,
- Reference<XTextRange> & rRange)
+ Reference<XTextRange> & rRange,
+ sal_Bool bIsOutsideOfParagraph)
{
RedlineMapType::iterator aFind = aRedlineMap.find(rId);
if (aRedlineMap.end() != aFind)
{
// RedlineInfo found; now set Cursor
RedlineInfo* pInfo = aFind->second;
- if (bStart)
+ if (bIsOutsideOfParagraph)
{
- pInfo->xAnchorStartPos = rRange;
+ // outside of paragraph: remember SwNodeIndex
+ if (bStart)
+ pInfo->aAnchorStart.SetAsNodeIndex(rRange);
+ else
+ pInfo->aAnchorEnd.SetAsNodeIndex(rRange);
}
else
{
- pInfo->xAnchorEndPos = rRange;
+ // inside of a paragraph: use regular XTextRanges (bookmarks)
+ if (bStart)
+ pInfo->aAnchorStart.Set(rRange);
+ else
+ pInfo->aAnchorEnd.Set(rRange);
}
// if this Cursor was the last missing info, we insert the
@@ -342,9 +505,78 @@ void XMLRedlineImportHelper::SetCursor(
// else: unknown Id -> ignore
}
+void XMLRedlineImportHelper::AdjustStartNodeCursor(
+ const OUString& rId, /// ID used in RedlineAdd() call
+ sal_Bool bStart,
+ Reference<XTextRange> & rRange)
+{
+ DBG_ASSERT(bStart,"End nodes not supported. Can't happen anyway, can it?");
+ if (!bStart)
+ return;
+
+ RedlineMapType::iterator aFind = aRedlineMap.find(rId);
+ if (aRedlineMap.end() != aFind)
+ {
+ // RedlineInfo found; now set Cursor
+ RedlineInfo* pInfo = aFind->second;
+
+ DBG_ASSERT(pInfo->aAnchorStart.IsValid(),
+ "AdjustStartNodeCursor may only be called after SetCursor");
+ if (!pInfo->aAnchorStart.IsValid())
+ return;
+
+ SwDoc* pDoc = pInfo->aAnchorStart.GetDoc();
+
+
+ // OK, we have the redline. Now find the proper start node for
+ // the range and do the necessary sanity checking. If
+ // successful, set the start node as the new redline start.
+ SwUnoInternalPaM aUnoPaM(*pDoc);
+ sal_Bool bSuccess = SwXTextRange::XTextRangeToSwPaM(aUnoPaM, rRange);
+ DBG_ASSERT(bSuccess, "illegal range");
+
+ // adjustment only supported for tables and sections
+ SwNode& rNode = aUnoPaM.GetPoint()->nNode.GetNode();
+ SwNode* pTblNode = rNode.FindTableNode();
+ SwNode* pSctnNode = rNode.FindSectionNode();
+ if ((NULL != pTblNode) || (NULL != pSctnNode))
+ {
+ // find the closest
+ SwNode* pStartNode = NULL;
+ if (pTblNode == NULL)
+ {
+ pStartNode = pSctnNode;
+ }
+ else if (pSctnNode == NULL)
+ {
+ pStartNode = pTblNode;
+ }
+ else
+ {
+ pStartNode = (pSctnNode->GetIndex() > pTblNode->GetIndex()) ?
+ pSctnNode : pTblNode;
+ }
+
+ // pStartNode is our start node candidate. Now check for distance
+ // between previous start node
+ // ...skip for now
+
+ SwNodeIndex aIndex(pStartNode->GetDoc()->GetNodes(),
+ pStartNode->GetIndex());
+ pInfo->aAnchorStart.Set(aIndex);
+ }
+ // else: we are neither inside a table nor a section -> ignore
+
+
+ }
+ // else: can't find redline -> ignore
+}
+
+
inline sal_Bool XMLRedlineImportHelper::IsReady(RedlineInfo* pRedline)
{
- return pRedline->xAnchorEndPos.is() && pRedline->xAnchorStartPos.is();
+ return ( pRedline->aAnchorEnd.IsValid() &&
+ pRedline->aAnchorStart.IsValid() );
}
void XMLRedlineImportHelper::InsertIntoDocument(RedlineInfo* pRedlineInfo)
@@ -352,55 +584,57 @@ void XMLRedlineImportHelper::InsertIntoDocument(RedlineInfo* pRedlineInfo)
DBG_ASSERT(NULL != pRedlineInfo, "need redline info");
DBG_ASSERT(IsReady(pRedlineInfo), "redline info not complete yet!");
- // get the document (from the XTextRange implementation object)
- Reference<XUnoTunnel> xTunnel(pRedlineInfo->xAnchorStartPos, UNO_QUERY);
- DBG_ASSERT(xTunnel.is(), "Can't tunnel -> can't get document");
- SwXTextRange *pRange = (SwXTextRange*)xTunnel->getSomething(
- SwXTextRange::getUnoTunnelId());
- SwDoc *pDoc = pRange->GetDoc();
-
- // create PAM from start+end cursors
- SwUnoInternalPaM aStartPaM(*pDoc);
- sal_Bool bSuccess =
- SwXTextRange::XTextRangeToSwPaM( aStartPaM,
- pRedlineInfo->xAnchorStartPos);
- DBG_ASSERT(bSuccess, "illegal range");
- SwUnoInternalPaM aEndPaM(*pDoc);
- bSuccess =
- SwXTextRange::XTextRangeToSwPaM( aEndPaM,
- pRedlineInfo->xAnchorEndPos);
- DBG_ASSERT(bSuccess, "illegal range");
+ // Insert the Redline as described by pRedlineInfo into the
+ // document. If we are in insert mode, don't insert any redlines
+ // (and delete 'deleted' inline redlines)
- // now create the PaM for the redline
- SwPaM aPaM(*aStartPaM.GetPoint(), *aEndPaM.GetPoint());
-
- // create redline (using redline data, which gets copied in SwRedline())
- SwRedlineData* pRedlineData = ConvertRedline(pRedlineInfo, pDoc);
- SwRedline* pRedline = new SwRedline(*pRedlineData, aPaM);
- delete pRedlineData;
+ // get the document (from one of the positions)
+ SwDoc* pDoc = pRedlineInfo->aAnchorStart.GetDoc();
- // set content node (if necessary)
- if (NULL != pRedlineInfo->pContentIndex)
+ // now create the PaM for the redline
+ SwPaM aPaM(pDoc->GetNodes().GetEndOfContent());
+ pRedlineInfo->aAnchorStart.GetPosition(*aPaM.GetPoint());
+ aPaM.SetMark();
+ pRedlineInfo->aAnchorEnd.GetPosition(*aPaM.GetPoint());
+
+ // check for:
+ // a) bIgnoreRedline (e.g. insert mode)
+ // b) illegal PaM range (CheckNodesRange())
+ if ( bIgnoreRedlines ||
+ !CheckNodesRange( aPaM.GetPoint()->nNode,
+ aPaM.GetMark()->nNode,
+ sal_True ) )
{
- pRedline->SetContentIdx(pRedlineInfo->pContentIndex);
+ // ignore redline (e.g. file loaded in insert mode):
+ // delete 'deleted' redlines and forget about the whole thing
+ if (REDLINE_DELETE == pRedlineInfo->eType)
+ {
+ pDoc->Delete(aPaM);
+ }
}
+ else
+ {
+ // regular file loading: insert redline
-// HACK: DO NOT COMMIT!
-// HACK: DO NOT COMMIT!
-// HACK: DO NOT COMMIT!
-// HACK: DO NOT COMMIT!
-// HACK: DO NOT COMMIT!
-// HACK: DO NOT COMMIT!
-// HACK: DO NOT COMMIT!
-// HACK: DO NOT COMMIT!
-// HACK: DO NOT COMMIT!
- pDoc->SetRedlineMode(REDLINE_ON);
- pDoc->AppendRedline(pRedline);
- pDoc->SetRedlineMode(REDLINE_IGNORE);
-
-// instead of:
- // and insert into document
- // pDoc->AppendRedline(pRedline);
+ // create redline (using pRedlineData which gets copied in SwRedline())
+ SwRedlineData* pRedlineData = ConvertRedline(pRedlineInfo, pDoc);
+ SwRedline* pRedline = new SwRedline(*pRedlineData, aPaM);
+ delete pRedlineData;
+
+ // set content node (if necessary)
+ if (NULL != pRedlineInfo->pContentIndex)
+ {
+ pRedline->SetContentIdx(pRedlineInfo->pContentIndex);
+ }
+
+ // set redline mode (withou doing the associated book-keeping)
+ pDoc->SetRedlineMode_intern(REDLINE_ON);
+ pDoc->AppendRedline(pRedline);
+ pDoc->SetRedlineMode_intern(REDLINE_NONE);
+
+ // also: save document
+ pSaveDoc = pDoc;
+ }
}
SwRedlineData* XMLRedlineImportHelper::ConvertRedline(