diff options
author | Miklos Vajna <vmiklos@suse.cz> | 2012-11-28 11:59:00 +0100 |
---|---|---|
committer | Michael Stahl <mstahl@redhat.com> | 2012-11-28 21:33:54 +0100 |
commit | 232ad2f2588beff50cb5c1f3b689c581ba317583 (patch) | |
tree | 40f7ebd9203de3e679b3578a552e28c7a2f09ee3 /sw/source | |
parent | 85693bffad5c863e5cd4d4b3664856a9fec607d5 (diff) |
API CHANGE: add a "position" parameter to XParagraph/TextPortionAppend methods
So we can use the new RTF import for clipboard pastes in Writer without
inserting text content to the end of the document only.
Notes:
- SwXText::insertTextPortion: the MovePara() call is removed, as all it did was
trying to move the cursor beyond the end of the document.
- SwRTFReader::Read: the double fake paragraph insertion / deletion is
motivated by the ODT filter.
- RtfFilter::filter: if TextInsertModeRange is not passed, then the behaviour
is not changed.
v2:
- added missing @since tags
- added insertTextContentWithProperties() method
- removed unused appendParagraph() method
Change-Id: I24cddb00a78e3b798e7d88764e59e6a77a6e98a4
Helped-by: Michael Stahl <mstahl@redhat.com>
Diffstat (limited to 'sw/source')
-rw-r--r-- | sw/source/core/unocore/unotext.cxx | 95 | ||||
-rw-r--r-- | sw/source/filter/rtf/swparrtf.cxx | 64 |
2 files changed, 122 insertions, 37 deletions
diff --git a/sw/source/core/unocore/unotext.cxx b/sw/source/core/unocore/unotext.cxx index 68e67c2bd81a..a5757192fe40 100644 --- a/sw/source/core/unocore/unotext.cxx +++ b/sw/source/core/unocore/unotext.cxx @@ -108,7 +108,8 @@ public: finishOrAppendParagraph( const bool bFinish, const uno::Sequence< beans::PropertyValue >& - rCharacterAndParagraphProperties) + rCharacterAndParagraphProperties, + const uno::Reference< text::XTextRange >& xInsertPosition) throw (lang::IllegalArgumentException, uno::RuntimeException); sal_Int16 ComparePositions( @@ -1251,29 +1252,31 @@ throw (uno::RuntimeException) } uno::Reference< text::XTextRange > SAL_CALL -SwXText::appendParagraph( +SwXText::finishParagraph( const uno::Sequence< beans::PropertyValue > & rProperties) throw (lang::IllegalArgumentException, uno::RuntimeException) { SolarMutexGuard g; - return m_pImpl->finishOrAppendParagraph(false, rProperties); + return m_pImpl->finishOrAppendParagraph(true, rProperties, uno::Reference< text::XTextRange >()); } uno::Reference< text::XTextRange > SAL_CALL -SwXText::finishParagraph( - const uno::Sequence< beans::PropertyValue > & rProperties) +SwXText::finishParagraphInsert( + const uno::Sequence< beans::PropertyValue > & rProperties, + const uno::Reference< text::XTextRange >& xInsertPosition) throw (lang::IllegalArgumentException, uno::RuntimeException) { SolarMutexGuard g; - return m_pImpl->finishOrAppendParagraph(true, rProperties); + return m_pImpl->finishOrAppendParagraph(true, rProperties, xInsertPosition); } uno::Reference< text::XTextRange > SwXText::Impl::finishOrAppendParagraph( const bool bFinish, - const uno::Sequence< beans::PropertyValue > & rProperties) + const uno::Sequence< beans::PropertyValue > & rProperties, + const uno::Reference< text::XTextRange >& xInsertPosition) throw (lang::IllegalArgumentException, uno::RuntimeException) { if (!m_bIsValid) @@ -1298,6 +1301,15 @@ throw (lang::IllegalArgumentException, uno::RuntimeException) SwPosition aInsertPosition( SwNodeIndex( *pStartNode->EndOfSectionNode(), -1 ) ); SwPaM aPam(aInsertPosition); + // If we got a position reference, then the insert point is not the end of + // the document. + if (xInsertPosition.is()) + { + SwUnoInternalPaM aStartPam(*m_rThis.GetDoc()); + ::sw::XTextRangeToSwPaM(aStartPam, xInsertPosition); + aPam = aStartPam; + aPam.SetMark(); + } m_pDoc->AppendTxtNode( *aPam.GetPoint() ); // remove attributes from the previous paragraph m_pDoc->ResetAttrs(aPam); @@ -1371,15 +1383,12 @@ throw (lang::IllegalArgumentException, uno::RuntimeException) return xRet; } -/*------------------------------------------------------------------------- - Append text portions at the end of the last paragraph of the text - interface. Support of import filters. - -----------------------------------------------------------------------*/ uno::Reference< text::XTextRange > SAL_CALL -SwXText::appendTextPortion( +SwXText::insertTextPortion( const ::rtl::OUString& rText, const uno::Sequence< beans::PropertyValue > & - rCharacterAndParagraphProperties) + rCharacterAndParagraphProperties, + const uno::Reference<text::XTextRange>& xInsertPosition) throw (lang::IllegalArgumentException, uno::RuntimeException) { SolarMutexGuard aGuard; @@ -1390,7 +1399,7 @@ throw (lang::IllegalArgumentException, uno::RuntimeException) } uno::Reference< text::XTextRange > xRet; const uno::Reference< text::XTextCursor > xTextCursor = CreateCursor(); - xTextCursor->gotoEnd(sal_False); + xTextCursor->gotoRange(xInsertPosition, sal_False); const uno::Reference< lang::XUnoTunnel > xRangeTunnel( xTextCursor, uno::UNO_QUERY_THROW ); @@ -1405,7 +1414,6 @@ throw (lang::IllegalArgumentException, uno::RuntimeException) // SwPaM aPam(*pStartNode->EndOfSectionNode()); //aPam.Move( fnMoveBackward, fnGoNode ); SwUnoCrsr *const pCursor = pTextCursor->GetCursor(); - pCursor->MovePara( fnParaCurr, fnParaEnd ); m_pImpl->m_pDoc->DontExpandFmt( *pCursor->Start() ); if (!rText.isEmpty()) @@ -1477,14 +1485,32 @@ throw (lang::IllegalArgumentException, uno::RuntimeException) } /*------------------------------------------------------------------------- - enable appending text contents like graphic objects, shapes and so on + Append text portions at the end of the last paragraph of the text + interface. Support of import filters. + -----------------------------------------------------------------------*/ +uno::Reference< text::XTextRange > SAL_CALL +SwXText::appendTextPortion( + const ::rtl::OUString& rText, + const uno::Sequence< beans::PropertyValue > & + rCharacterAndParagraphProperties) +throw (lang::IllegalArgumentException, uno::RuntimeException) +{ + // Right now this doesn't need a guard, as it's just calling the insert + // version, that has it already. + uno::Reference<text::XTextRange> xInsertPosition = getEnd(); + return insertTextPortion(rText, rCharacterAndParagraphProperties, xInsertPosition); +} + +/*------------------------------------------------------------------------- + enable inserting/appending text contents like graphic objects, shapes and so on to support import filters -----------------------------------------------------------------------*/ uno::Reference< text::XTextRange > SAL_CALL -SwXText::appendTextContent( +SwXText::insertTextContentWithProperties( const uno::Reference< text::XTextContent >& xTextContent, const uno::Sequence< beans::PropertyValue >& - rCharacterAndParagraphProperties) + rCharacterAndParagraphProperties, + const uno::Reference< text::XTextRange >& xInsertPosition) throw (lang::IllegalArgumentException, uno::RuntimeException) { SolarMutexGuard aGuard; @@ -1493,25 +1519,11 @@ throw (lang::IllegalArgumentException, uno::RuntimeException) { throw uno::RuntimeException(); } - SwStartNode const*const pStartNode = GetStartNode(); - if(!pStartNode) - { - throw uno::RuntimeException(); - } - uno::Reference< text::XTextRange > xRet; m_pImpl->m_pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_INSERT, NULL); - // find end node, go backward - don't skip tables because the - // new paragraph has to be the last node - SwPaM aPam(*pStartNode->EndOfSectionNode()); - aPam.Move( fnMoveBackward, fnGoNode ); - // set cursor to the end of the last text node - SwCursor aCursor( *aPam.Start(), 0, false ); - xRet = new SwXTextRange(aCursor, this); - aCursor.MovePara( fnParaCurr, fnParaEnd ); - m_pImpl->m_pDoc->DontExpandFmt( *aCursor.Start() ); + // now attach the text content here - insertTextContent( xRet, xTextContent, false ); + insertTextContent( xInsertPosition, xTextContent, false ); // now apply the properties to the anchor if (rCharacterAndParagraphProperties.getLength()) { @@ -1536,7 +1548,20 @@ throw (lang::IllegalArgumentException, uno::RuntimeException) } } m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_INSERT, NULL); - return xRet; + return xInsertPosition; +} + +uno::Reference< text::XTextRange > SAL_CALL +SwXText::appendTextContent( + const uno::Reference< text::XTextContent >& xTextContent, + const uno::Sequence< beans::PropertyValue >& + rCharacterAndParagraphProperties) +throw (lang::IllegalArgumentException, uno::RuntimeException) +{ + // Right now this doesn't need a guard, as it's just calling the insert + // version, that has it already. + uno::Reference<text::XTextRange> xInsertPosition = getEnd(); + return insertTextContentWithProperties(xTextContent, rCharacterAndParagraphProperties, xInsertPosition); } // move previously appended paragraphs into a text frames diff --git a/sw/source/filter/rtf/swparrtf.cxx b/sw/source/filter/rtf/swparrtf.cxx index d4d59c0b62b2..e06c02ba6208 100644 --- a/sw/source/filter/rtf/swparrtf.cxx +++ b/sw/source/filter/rtf/swparrtf.cxx @@ -89,6 +89,7 @@ #include <docsh.hxx> #include <fmtlsplt.hxx> // SwLayoutSplit +#include <unotextrange.hxx> #include <editeng/keepitem.hxx> #include <svx/svdopath.hxx> #include <svx/svdorect.hxx> @@ -117,6 +118,7 @@ #include <com/sun/star/document/XFilter.hpp> #include <com/sun/star/document/XImporter.hpp> #include <com/sun/star/document/XExporter.hpp> +#include <com/sun/star/text/XTextRange.hpp> using namespace ::com::sun::star; @@ -136,11 +138,31 @@ class SwRTFReader : public Reader virtual sal_uLong Read( SwDoc &, const String& rBaseURL, SwPaM &,const String &); }; -sal_uLong SwRTFReader::Read( SwDoc &rDoc, const String& /*rBaseURL*/, SwPaM& /*rPam*/, const String &) +sal_uLong SwRTFReader::Read( SwDoc &rDoc, const String& /*rBaseURL*/, SwPaM& rPam, const String &) { if (!pStrm) return ERR_SWG_READ_ERROR; + // We want to work in an empty paragraph. + // Step 1: XTextRange will be updated when content is inserted, so we know + // the end position. + const uno::Reference<text::XTextRange> xInsertPosition = + SwXTextRange::CreateXTextRange(rDoc, *rPam.GetPoint(), 0); + SwNodeIndex *pSttNdIdx = new SwNodeIndex(rDoc.GetNodes()); + const SwPosition* pPos = rPam.GetPoint(); + + // Step 2: Split once and remember the node that has been splitted. + rDoc.SplitNode( *pPos, false ); + *pSttNdIdx = pPos->nNode.GetIndex()-1; + + // Step 3: Split again. + rDoc.SplitNode( *pPos, false ); + + // Step 4: Insert all content into the new node + rPam.Move( fnMoveBackward ); + rDoc.SetTxtFmtColl + ( rPam, rDoc.GetTxtCollFromPool(RES_POOLCOLL_STANDARD, false ) ); + SwDocShell *pDocShell(rDoc.GetDocShell()); uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(comphelper::getProcessServiceFactory()); uno::Reference<uno::XInterface> xInterface(xMultiServiceFactory->createInstance( @@ -150,15 +172,53 @@ sal_uLong SwRTFReader::Read( SwDoc &rDoc, const String& /*rBaseURL*/, SwPaM& /*r uno::Reference<lang::XComponent> xDstDoc(pDocShell->GetModel(), uno::UNO_QUERY_THROW); xImporter->setTargetDocument(xDstDoc); + const uno::Reference<text::XTextRange> xInsertTextRange = + SwXTextRange::CreateXTextRange(rDoc, *rPam.GetPoint(), 0); + uno::Reference<document::XFilter> xFilter(xInterface, uno::UNO_QUERY_THROW); - uno::Sequence<beans::PropertyValue> aDescriptor(2); + uno::Sequence<beans::PropertyValue> aDescriptor(3); aDescriptor[0].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("InputStream")); uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(*pStrm)); aDescriptor[0].Value <<= xStream; aDescriptor[1].Name = "IsNewDoc"; aDescriptor[1].Value <<= sal_False; + aDescriptor[2].Name = "TextInsertModeRange"; + aDescriptor[2].Value <<= xInsertTextRange; xFilter->filter(aDescriptor); + // Clean up the fake paragraphs. + SwUnoInternalPaM aPam(rDoc); + ::sw::XTextRangeToSwPaM(aPam, xInsertPosition); + if (pSttNdIdx->GetIndex()) + { + // If we are in insert mode, join the splitted node that is in front + // of the new content with the first new node. Or in other words: + // Revert the first split node. + SwTxtNode* pTxtNode = pSttNdIdx->GetNode().GetTxtNode(); + SwNodeIndex aNxtIdx( *pSttNdIdx ); + if( pTxtNode && pTxtNode->CanJoinNext( &aNxtIdx ) && + pSttNdIdx->GetIndex() + 1 == aNxtIdx.GetIndex() ) + { + // If the PaM points to the first new node, move the PaM to the + // end of the previous node. + if( aPam.GetPoint()->nNode == aNxtIdx ) + { + aPam.GetPoint()->nNode = *pSttNdIdx; + aPam.GetPoint()->nContent.Assign( pTxtNode, + pTxtNode->GetTxt().Len() ); + } + // If the first new node isn't empty, convert the node's text + // attributes into hints. Otherwise, set the new node's + // paragraph style at the previous (empty) node. + SwTxtNode* pDelNd = aNxtIdx.GetNode().GetTxtNode(); + if( pTxtNode->GetTxt().Len() ) + pDelNd->FmtToTxtAttr( pTxtNode ); + else + pTxtNode->ChgFmtColl( pDelNd->GetTxtColl() ); + pTxtNode->JoinNext(); + } + } + return 0; } |