/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * 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 * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sw.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define _SVSTDARR_USHORTS #define _SVSTDARR_USHORTSSORT #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; using ::rtl::OUString; using ::rtl::OUStringBuffer; /**************************************************************************** static methods ****************************************************************************/ uno::Sequence< sal_Int8 > CreateUnoTunnelId() { static osl::Mutex aCreateMutex; osl::Guard aGuard( aCreateMutex ); uno::Sequence< sal_Int8 > aSeq( 16 ); rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); return aSeq; } /**************************************************************************** Hilfsklassen ****************************************************************************/ SwUnoInternalPaM::SwUnoInternalPaM(SwDoc& rDoc) : SwPaM(rDoc.GetNodes()) { } SwUnoInternalPaM::~SwUnoInternalPaM() { while( GetNext() != this) { delete GetNext(); } } SwUnoInternalPaM& SwUnoInternalPaM::operator=(const SwPaM& rPaM) { const SwPaM* pTmp = &rPaM; *GetPoint() = *rPaM.GetPoint(); if(rPaM.HasMark()) { SetMark(); *GetMark() = *rPaM.GetMark(); } else DeleteMark(); while(&rPaM != (pTmp = (const SwPaM*)pTmp->GetNext())) { if(pTmp->HasMark()) new SwPaM(*pTmp->GetMark(), *pTmp->GetPoint(), this); else new SwPaM(*pTmp->GetPoint(), this); } return *this; } void SwUnoCursorHelper::SelectPam(SwPaM & rPam, const bool bExpand) { if (bExpand) { if (!rPam.HasMark()) { rPam.SetMark(); } } else if (rPam.HasMark()) { rPam.DeleteMark(); } } void SwUnoCursorHelper::GetTextFromPam(SwPaM & rPam, OUString & rBuffer) { if (!rPam.HasMark()) { return; } SvCacheStream aStream( 20480 ); #ifdef OSL_BIGENDIAN aStream.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN ); #else aStream.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); #endif WriterRef xWrt; // TODO/MBA: looks like a BaseURL doesn't make sense here SwReaderWriter::GetWriter( C2S(FILTER_TEXT_DLG), String(), xWrt ); if( xWrt.Is() ) { SwWriter aWriter( aStream, rPam ); xWrt->bASCII_NoLastLineEnd = sal_True; xWrt->bExportPargraphNumbering = sal_False; SwAsciiOptions aOpt = xWrt->GetAsciiOptions(); aOpt.SetCharSet( RTL_TEXTENCODING_UNICODE ); xWrt->SetAsciiOptions( aOpt ); xWrt->bUCS2_WithStartChar = FALSE; // --> FME #i68522# const BOOL bOldShowProgress = xWrt->bShowProgress; xWrt->bShowProgress = FALSE; // <-- long lLen; if( !IsError( aWriter.Write( xWrt ) ) && 0x7ffffff > (( lLen = aStream.GetSize() ) / sizeof( sal_Unicode )) + 1 ) { aStream << (sal_Unicode)'\0'; long lUniLen = (lLen / sizeof( sal_Unicode )); ::rtl::OUStringBuffer aStrBuffer( lUniLen ); aStream.Seek( 0 ); aStream.ResetError(); while(lUniLen) { String sBuf; sal_Int32 nLocalLen = 0; if( lUniLen >= STRING_MAXLEN ) { nLocalLen = STRING_MAXLEN - 1; } else { nLocalLen = lUniLen; } sal_Unicode *const pStrBuf = sBuf.AllocBuffer( xub_StrLen( nLocalLen + 1)); aStream.Read( pStrBuf, 2 * nLocalLen ); pStrBuf[ nLocalLen ] = '\0'; aStrBuffer.append( pStrBuf, nLocalLen ); lUniLen -= nLocalLen; } rBuffer = aStrBuffer.makeStringAndClear(); } xWrt->bShowProgress = bOldShowProgress; } } static void lcl_setCharStyle(SwDoc *const pDoc, const uno::Any & rValue, SfxItemSet & rSet) throw (lang::IllegalArgumentException) { SwDocShell *const pDocSh = pDoc->GetDocShell(); if(pDocSh) { OUString uStyle; if (!(rValue >>= uStyle)) { throw lang::IllegalArgumentException(); } String sStyle; SwStyleNameMapper::FillUIName(uStyle, sStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True); SwDocStyleSheet *const pStyle = static_cast( pDocSh->GetStyleSheetPool()->Find(sStyle, SFX_STYLE_FAMILY_CHAR)); if (!pStyle) { throw lang::IllegalArgumentException(); } const SwFmtCharFmt aFmt(pStyle->GetCharFmt()); rSet.Put(aFmt); } }; static void lcl_setAutoStyle(IStyleAccess & rStyleAccess, const uno::Any & rValue, SfxItemSet & rSet, const bool bPara) throw (lang::IllegalArgumentException) { OUString uStyle; if (!(rValue >>= uStyle)) { throw lang::IllegalArgumentException(); } StylePool::SfxItemSet_Pointer_t pStyle = bPara ? rStyleAccess.getByName(uStyle, IStyleAccess::AUTO_STYLE_PARA ): rStyleAccess.getByName(uStyle, IStyleAccess::AUTO_STYLE_CHAR ); if(pStyle.get()) { SwFmtAutoFmt aFmt( (bPara) ? sal::static_int_cast< USHORT >(RES_AUTO_STYLE) : sal::static_int_cast< USHORT >(RES_TXTATR_AUTOFMT) ); aFmt.SetStyleHandle( pStyle ); rSet.Put(aFmt); } else { throw lang::IllegalArgumentException(); } }; void SwUnoCursorHelper::SetTxtFmtColl(const uno::Any & rAny, SwPaM & rPaM) throw (lang::IllegalArgumentException) { SwDoc *const pDoc = rPaM.GetDoc(); SwDocShell *const pDocSh = pDoc->GetDocShell(); if(!pDocSh) return; OUString uStyle; rAny >>= uStyle; String sStyle; SwStyleNameMapper::FillUIName(uStyle, sStyle, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True ); SwDocStyleSheet *const pStyle = static_cast( pDocSh->GetStyleSheetPool()->Find(sStyle, SFX_STYLE_FAMILY_PARA)); if (!pStyle) { throw lang::IllegalArgumentException(); } SwTxtFmtColl *const pLocal = pStyle->GetCollection(); UnoActionContext aAction(pDoc); pDoc->StartUndo( UNDO_START, NULL ); SwPaM *pTmpCrsr = &rPaM; do { pDoc->SetTxtFmtColl(*pTmpCrsr, pLocal); pTmpCrsr = static_cast(pTmpCrsr->GetNext()); } while ( pTmpCrsr != &rPaM ); pDoc->EndUndo( UNDO_END, NULL ); } bool SwUnoCursorHelper::SetPageDesc( const uno::Any& rValue, SwDoc & rDoc, SfxItemSet & rSet) { OUString uDescName; if (!(rValue >>= uDescName)) { return false; } ::std::auto_ptr pNewDesc; const SfxPoolItem* pItem; if(SFX_ITEM_SET == rSet.GetItemState( RES_PAGEDESC, sal_True, &pItem ) ) { pNewDesc.reset(new SwFmtPageDesc( *static_cast(pItem))); } if (!pNewDesc.get()) { pNewDesc.reset(new SwFmtPageDesc()); } String sDescName; SwStyleNameMapper::FillUIName(uDescName, sDescName, nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC, sal_True); if (!pNewDesc->GetPageDesc() || (pNewDesc->GetPageDesc()->GetName() != sDescName)) { sal_Bool bPut = sal_False; if(sDescName.Len()) { SwPageDesc *const pPageDesc = ::GetPageDescByName_Impl(rDoc, sDescName); if (!pPageDesc) { throw lang::IllegalArgumentException(); } pPageDesc->Add( pNewDesc.get() ); bPut = sal_True; } if(!bPut) { rSet.ClearItem(RES_BREAK); rSet.Put(SwFmtPageDesc()); } else { rSet.Put(*pNewDesc); } } return true; } static void lcl_SetNodeNumStart(SwPaM & rCrsr, uno::Any const& rValue) { sal_Int16 nTmp = 1; rValue >>= nTmp; sal_uInt16 nStt = (nTmp < 0 ? USHRT_MAX : (sal_uInt16)nTmp); SwDoc* pDoc = rCrsr.GetDoc(); UnoActionContext aAction(pDoc); if( rCrsr.GetNext() != &rCrsr ) // Mehrfachselektion ? { pDoc->StartUndo( UNDO_START, NULL ); SwPamRanges aRangeArr( rCrsr ); SwPaM aPam( *rCrsr.GetPoint() ); for( sal_uInt16 n = 0; n < aRangeArr.Count(); ++n ) { pDoc->SetNumRuleStart(*aRangeArr.SetPam( n, aPam ).GetPoint()); pDoc->SetNodeNumStart(*aRangeArr.SetPam( n, aPam ).GetPoint(), nStt ); } pDoc->EndUndo( UNDO_END, NULL); } else { pDoc->SetNumRuleStart( *rCrsr.GetPoint()); pDoc->SetNodeNumStart( *rCrsr.GetPoint(), nStt ); } } static bool lcl_setCharFmtSequence(SwPaM & rPam, uno::Any const& rValue) { uno::Sequence aCharStyles; if (!(rValue >>= aCharStyles)) { return false; } for (sal_Int32 nStyle = 0; nStyle < aCharStyles.getLength(); nStyle++) { uno::Any aStyle; rPam.GetDoc()->StartUndo(UNDO_START, NULL); aStyle <<= aCharStyles.getConstArray()[nStyle]; // create a local set and apply each format directly SfxItemSet aSet(rPam.GetDoc()->GetAttrPool(), RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT); lcl_setCharStyle(rPam.GetDoc(), aStyle, aSet); // the first style should replace the current attributes, // all other have to be added SwUnoCursorHelper::SetCrsrAttr(rPam, aSet, (nStyle) ? nsSetAttrMode::SETATTR_DONTREPLACE : nsSetAttrMode::SETATTR_DEFAULT); rPam.GetDoc()->EndUndo(UNDO_START, NULL); } return true; } static void lcl_setDropcapCharStyle(SwPaM & rPam, SfxItemSet & rItemSet, uno::Any const& rValue) { OUString uStyle; if (!(rValue >>= uStyle)) { throw lang::IllegalArgumentException(); } String sStyle; SwStyleNameMapper::FillUIName(uStyle, sStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True); SwDoc *const pDoc = rPam.GetDoc(); //default character style must not be set as default format SwDocStyleSheet *const pStyle = static_cast( pDoc->GetDocShell() ->GetStyleSheetPool()->Find(sStyle, SFX_STYLE_FAMILY_CHAR)); if (!pStyle || (static_cast(pStyle)->GetCharFmt() == pDoc->GetDfltCharFmt())) { throw lang::IllegalArgumentException(); } ::std::auto_ptr pDrop; SfxPoolItem const* pItem(0); if (SFX_ITEM_SET == rItemSet.GetItemState(RES_PARATR_DROP, sal_True, &pItem)) { pDrop.reset(new SwFmtDrop(*static_cast(pItem))); } if (!pDrop.get()) { pDrop.reset(new SwFmtDrop); } const rtl::Reference xStyle(new SwDocStyleSheet(*pStyle)); pDrop->SetCharFmt(xStyle->GetCharFmt()); rItemSet.Put(*pDrop); } static void lcl_setRubyCharstyle(SfxItemSet & rItemSet, uno::Any const& rValue) { OUString sTmp; if (!(rValue >>= sTmp)) { throw lang::IllegalArgumentException(); } ::std::auto_ptr pRuby; const SfxPoolItem* pItem; if (SFX_ITEM_SET == rItemSet.GetItemState(RES_TXTATR_CJK_RUBY, sal_True, &pItem)) { pRuby.reset(new SwFmtRuby(*static_cast(pItem))); } if (!pRuby.get()) { pRuby.reset(new SwFmtRuby(aEmptyStr)); } String sStyle; SwStyleNameMapper::FillUIName(sTmp, sStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True ); pRuby->SetCharFmtName(sStyle); pRuby->SetCharFmtId(0); if (sStyle.Len() > 0) { const sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( sStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT); pRuby->SetCharFmtId(nId); } rItemSet.Put(*pRuby); } bool SwUnoCursorHelper::SetCursorPropertyValue( SfxItemPropertySimpleEntry const& rEntry, const uno::Any& rValue, SwPaM & rPam, SfxItemSet & rItemSet) throw (lang::IllegalArgumentException) { if (!(rEntry.nFlags & beans::PropertyAttribute::MAYBEVOID) && (rValue.getValueType() == ::getCppuVoidType())) { return false; } bool bRet = true; switch (rEntry.nWID) { case RES_TXTATR_CHARFMT: lcl_setCharStyle(rPam.GetDoc(), rValue, rItemSet); break; case RES_TXTATR_AUTOFMT: lcl_setAutoStyle(rPam.GetDoc()->GetIStyleAccess(), rValue, rItemSet, false); break; case FN_UNO_CHARFMT_SEQUENCE: lcl_setCharFmtSequence(rPam, rValue); break; case FN_UNO_PARA_STYLE : SwUnoCursorHelper::SetTxtFmtColl(rValue, rPam); break; case RES_AUTO_STYLE: lcl_setAutoStyle(rPam.GetDoc()->GetIStyleAccess(), rValue, rItemSet, true); break; case FN_UNO_PAGE_STYLE: //FIXME nothing here? break; case FN_UNO_NUM_START_VALUE: lcl_SetNodeNumStart( rPam, rValue ); break; case FN_UNO_NUM_LEVEL: // --> OD 2008-07-14 #i91601# case FN_UNO_LIST_ID: // <-- case FN_UNO_IS_NUMBER: { // multi selection is not considered SwTxtNode *const pTxtNd = rPam.GetNode()->GetTxtNode(); if (FN_UNO_NUM_LEVEL == rEntry.nWID) { sal_Int16 nLevel = 0; if (rValue >>= nLevel) { pTxtNd->SetAttrListLevel(nLevel); } } // --> OD 2008-07-14 #i91601# else if (FN_UNO_LIST_ID == rEntry.nWID) { ::rtl::OUString sListId; if (rValue >>= sListId) { pTxtNd->SetListId( sListId ); } } // <-- else if (FN_UNO_IS_NUMBER == rEntry.nWID) { sal_Bool bIsNumber(sal_False); if (rValue >>= bIsNumber) { if (!bIsNumber) { pTxtNd->SetCountedInList( false ); } } } //PROPERTY_MAYBEVOID! } break; case FN_NUMBER_NEWSTART: { sal_Bool bVal = sal_False; if (!(rValue >>= bVal)) { throw lang::IllegalArgumentException(); } rPam.GetDoc()->SetNumRuleStart(*rPam.GetPoint(), bVal); } break; case FN_UNO_NUM_RULES: SwUnoCursorHelper::setNumberingProperty(rValue, rPam); break; case RES_PARATR_DROP: { if (MID_DROPCAP_CHAR_STYLE_NAME == rEntry.nMemberId) { lcl_setDropcapCharStyle(rPam, rItemSet, rValue); } else { bRet = false; } } break; case RES_TXTATR_CJK_RUBY: { if (MID_RUBY_CHARSTYLE == rEntry.nMemberId) { lcl_setRubyCharstyle(rItemSet, rValue); } else { bRet = false; } } break; case RES_PAGEDESC: { if (MID_PAGEDESC_PAGEDESCNAME == rEntry.nMemberId) { SwUnoCursorHelper::SetPageDesc( rValue, *rPam.GetDoc(), rItemSet); } else { bRet = false; } } break; default: bRet = false; } return bRet; } SwFmtColl * SwUnoCursorHelper::GetCurTxtFmtColl(SwPaM & rPaM, const bool bConditional) { static const sal_uInt16 nMaxLookup = 1000; SwFmtColl *pFmt = 0; // if ( GetCrsrCnt() > nMaxLookup ) // return 0; bool bError = false; SwPaM *pTmpCrsr = &rPaM; do { const ULONG nSttNd = pTmpCrsr->Start()->nNode.GetIndex(); const ULONG nEndNd = pTmpCrsr->End()->nNode.GetIndex(); if( nEndNd - nSttNd >= nMaxLookup ) { pFmt = 0; break; } const SwNodes& rNds = rPaM.GetDoc()->GetNodes(); for( ULONG n = nSttNd; n <= nEndNd; ++n ) { SwTxtNode const*const pNd = rNds[ n ]->GetTxtNode(); if( pNd ) { SwFmtColl *const pNdFmt = (bConditional) ? pNd->GetFmtColl() : &pNd->GetAnyFmtColl(); if( !pFmt ) { pFmt = pNdFmt; } else if( pFmt != pNdFmt ) { bError = true; break; } } } pTmpCrsr = static_cast(pTmpCrsr->GetNext()); } while ( pTmpCrsr != &rPaM ); return (bError) ? 0 : pFmt; } /* -------------------------------------------------- * Hilfsfunktion fuer PageDesc * --------------------------------------------------*/ SwPageDesc* GetPageDescByName_Impl(SwDoc& rDoc, const String& rName) { SwPageDesc* pRet = 0; sal_uInt16 nDCount = rDoc.GetPageDescCnt(); sal_uInt16 i; for( i = 0; i < nDCount; i++ ) { SwPageDesc* pDsc = &rDoc._GetPageDesc( i ); if(pDsc->GetName() == rName) { pRet = pDsc; break; } } if(!pRet) { for(i = RC_POOLPAGEDESC_BEGIN; i <= STR_POOLPAGE_LANDSCAPE; ++i) { const String aFmtName(SW_RES(i)); if(aFmtName == rName) { pRet = rDoc.GetPageDescFromPool( static_cast< sal_uInt16 >( RES_POOLPAGE_BEGIN + i - RC_POOLPAGEDESC_BEGIN) ); break; } } } return pRet; } /****************************************************************** * SwXTextCursor ******************************************************************/ class SwXTextCursor::Impl : public SwClient { public: const SfxItemPropertySet & m_rPropSet; const enum CursorType m_eType; const uno::Reference< text::XText > m_xParentText; SwEventListenerContainer m_ListenerContainer; bool m_bIsDisposed; Impl( SwXTextCursor & rThis, SwDoc & rDoc, const enum CursorType eType, uno::Reference xParent, SwPosition const& rPoint, SwPosition const*const pMark) : SwClient(rDoc.CreateUnoCrsr(rPoint, sal_False)) , m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR)) , m_eType(eType) , m_xParentText(xParent) , m_ListenerContainer(static_cast< ::cppu::OWeakObject* >(&rThis)) , m_bIsDisposed(false) { if (pMark) { GetCursor()->SetMark(); *GetCursor()->GetMark() = *pMark; } } ~Impl() { // Impl owns the cursor; delete it here: SolarMutex is locked delete GetRegisteredIn(); } SwUnoCrsr * GetCursor() { return (m_bIsDisposed) ? 0 : static_cast(const_cast(GetRegisteredIn())); } SwUnoCrsr & GetCursorOrThrow() { SwUnoCrsr *const pUnoCursor( GetCursor() ); if (!pUnoCursor) { throw uno::RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( "SwXTextCursor: disposed or invalid")), 0); } return *pUnoCursor; } void Invalidate() { m_bIsDisposed = true; m_ListenerContainer.Disposing(); } // SwClient virtual void Modify(SfxPoolItem *pOld, SfxPoolItem *pNew); }; void SwXTextCursor::Impl::Modify(SfxPoolItem *pOld, SfxPoolItem *pNew) { ClientModify(this, pOld, pNew); if (!GetRegisteredIn() || // if the cursor leaves its designated section, it becomes invalid ((pOld != NULL) && (pOld->Which() == RES_UNOCURSOR_LEAVES_SECTION))) { Invalidate(); } } SwUnoCrsr const* SwXTextCursor::GetCursor() const { return m_pImpl->GetCursor(); } SwUnoCrsr * SwXTextCursor::GetCursor() { return m_pImpl->GetCursor(); } SwPaM const* SwXTextCursor::GetPaM() const { return m_pImpl->GetCursor(); } SwPaM * SwXTextCursor::GetPaM() { return m_pImpl->GetCursor(); } SwDoc const* SwXTextCursor::GetDoc() const { return m_pImpl->GetCursor() ? m_pImpl->GetCursor()->GetDoc() : 0; } SwDoc * SwXTextCursor::GetDoc() { return m_pImpl->GetCursor() ? m_pImpl->GetCursor()->GetDoc() : 0; } SwXTextCursor::SwXTextCursor( SwDoc & rDoc, uno::Reference< text::XText > const& xParent, const enum CursorType eType, const SwPosition& rPos, SwPosition const*const pMark) : m_pImpl( new SwXTextCursor::Impl(*this, rDoc, eType, xParent, rPos, pMark ) ) { } SwXTextCursor::SwXTextCursor(uno::Reference< text::XText > const& xParent, SwPaM const& rSourceCursor, const enum CursorType eType) : m_pImpl( new SwXTextCursor::Impl(*this, *rSourceCursor.GetDoc(), eType, xParent, *rSourceCursor.GetPoint(), rSourceCursor.HasMark() ? rSourceCursor.GetMark() : 0) ) { } SwXTextCursor::~SwXTextCursor() { } void SwXTextCursor::DeleteAndInsert(const ::rtl::OUString& rText, const bool bForceExpandHints) { SwUnoCrsr *const pUnoCrsr = m_pImpl->GetCursor(); if(pUnoCrsr) { // Start/EndAction SwDoc* pDoc = pUnoCrsr->GetDoc(); UnoActionContext aAction(pDoc); const xub_StrLen nTxtLen = rText.getLength(); pDoc->StartUndo(UNDO_INSERT, NULL); SwCursor * pCurrent = pUnoCrsr; do { if (pCurrent->HasMark()) { pDoc->DeleteAndJoin(*pCurrent); } if(nTxtLen) { const bool bSuccess( SwUnoCursorHelper::DocInsertStringSplitCR( *pDoc, *pCurrent, rText, bForceExpandHints ) ); DBG_ASSERT( bSuccess, "Doc->Insert(Str) failed." ); (void) bSuccess; SwUnoCursorHelper::SelectPam(*pUnoCrsr, true); pCurrent->Left(rText.getLength(), CRSR_SKIP_CHARS, FALSE, FALSE); } pCurrent = static_cast(pCurrent->GetNext()); } while (pCurrent != pUnoCrsr); pDoc->EndUndo(UNDO_INSERT, NULL); } } enum ForceIntoMetaMode { META_CHECK_BOTH, META_INIT_START, META_INIT_END }; static sal_Bool lcl_ForceIntoMeta(SwPaM & rCursor, uno::Reference const & xParentText, const enum ForceIntoMetaMode eMode) { sal_Bool bRet( sal_True ); // means not forced in META_CHECK_BOTH SwXMeta const * const pXMeta( dynamic_cast(xParentText.get()) ); OSL_ENSURE(pXMeta, "no parent?"); if (!pXMeta) throw uno::RuntimeException(); SwTxtNode * pTxtNode; xub_StrLen nStart; xub_StrLen nEnd; const bool bSuccess( pXMeta->SetContentRange(pTxtNode, nStart, nEnd) ); OSL_ENSURE(bSuccess, "no pam?"); if (!bSuccess) throw uno::RuntimeException(); // force the cursor back into the meta if it has moved outside SwPosition start(*pTxtNode, nStart); SwPosition end(*pTxtNode, nEnd); switch (eMode) { case META_INIT_START: *rCursor.GetPoint() = start; break; case META_INIT_END: *rCursor.GetPoint() = end; break; case META_CHECK_BOTH: if (*rCursor.Start() < start) { *rCursor.Start() = start; bRet = sal_False; } if (*rCursor.End() > end) { *rCursor.End() = end; bRet = sal_False; } break; } return bRet; } bool SwXTextCursor::IsAtEndOfMeta() const { if (CURSOR_META == m_pImpl->m_eType) { SwUnoCrsr const * const pCursor( m_pImpl->GetCursor() ); SwXMeta const*const pXMeta( dynamic_cast(m_pImpl->m_xParentText.get()) ); OSL_ENSURE(pXMeta, "no meta?"); if (pCursor && pXMeta) { SwTxtNode * pTxtNode; xub_StrLen nStart; xub_StrLen nEnd; const bool bSuccess( pXMeta->SetContentRange(pTxtNode, nStart, nEnd) ); OSL_ENSURE(bSuccess, "no pam?"); if (bSuccess) { const SwPosition end(*pTxtNode, nEnd); if ( (*pCursor->GetPoint() == end) || (*pCursor->GetMark() == end)) { return true; } } } } return false; } OUString SwXTextCursor::getImplementationName() throw (uno::RuntimeException) { return C2U("SwXTextCursor"); } static char const*const g_ServicesTextCursor[] = { "com.sun.star.text.TextCursor", "com.sun.star.style.CharacterProperties", "com.sun.star.style.CharacterPropertiesAsian", "com.sun.star.style.CharacterPropertiesComplex", "com.sun.star.style.ParagraphProperties", "com.sun.star.style.ParagraphPropertiesAsian", "com.sun.star.style.ParagraphPropertiesComplex", "com.sun.star.text.TextSortable", }; static const size_t g_nServicesTextCursor( SAL_N_ELEMENTS(g_ServicesTextCursor)); sal_Bool SAL_CALL SwXTextCursor::supportsService(const OUString& rServiceName) throw (uno::RuntimeException) { return ::sw::SupportsServiceImpl( g_nServicesTextCursor, g_ServicesTextCursor, rServiceName); } uno::Sequence< OUString > SAL_CALL SwXTextCursor::getSupportedServiceNames() throw (uno::RuntimeException) { return ::sw::GetSupportedServiceNamesImpl( g_nServicesTextCursor, g_ServicesTextCursor); } const uno::Sequence< sal_Int8 > & SwXTextCursor::getUnoTunnelId() { static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId(); return aSeq; } sal_Int64 SAL_CALL SwXTextCursor::getSomething(const uno::Sequence< sal_Int8 >& rId) throw (uno::RuntimeException) { const sal_Int64 nRet( ::sw::UnoTunnelImpl(rId, this) ); return (nRet) ? nRet : OTextCursorHelper::getSomething(rId); } void SAL_CALL SwXTextCursor::collapseToStart() throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); if (rUnoCursor.HasMark()) { if (*rUnoCursor.GetPoint() > *rUnoCursor.GetMark()) { rUnoCursor.Exchange(); } rUnoCursor.DeleteMark(); } } void SAL_CALL SwXTextCursor::collapseToEnd() throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); if (rUnoCursor.HasMark()) { if (*rUnoCursor.GetPoint() < *rUnoCursor.GetMark()) { rUnoCursor.Exchange(); } rUnoCursor.DeleteMark(); } } sal_Bool SAL_CALL SwXTextCursor::isCollapsed() throw (uno::RuntimeException) { SolarMutexGuard aGuard; sal_Bool bRet = sal_True; SwUnoCrsr *const pUnoCrsr = m_pImpl->GetCursor(); if(pUnoCrsr && pUnoCrsr->GetMark()) { bRet = (*pUnoCrsr->GetPoint() == *pUnoCrsr->GetMark()); } return bRet; } sal_Bool SAL_CALL SwXTextCursor::goLeft(sal_Int16 nCount, sal_Bool Expand) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); SwUnoCursorHelper::SelectPam(rUnoCursor, Expand); sal_Bool bRet = rUnoCursor.Left( nCount, CRSR_SKIP_CHARS, FALSE, FALSE); if (CURSOR_META == m_pImpl->m_eType) { bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText, META_CHECK_BOTH) && bRet; } return bRet; } sal_Bool SAL_CALL SwXTextCursor::goRight(sal_Int16 nCount, sal_Bool Expand) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); SwUnoCursorHelper::SelectPam(rUnoCursor, Expand); sal_Bool bRet = rUnoCursor.Right(nCount, CRSR_SKIP_CHARS, FALSE, FALSE); if (CURSOR_META == m_pImpl->m_eType) { bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText, META_CHECK_BOTH) && bRet; } return bRet; } void SAL_CALL SwXTextCursor::gotoStart(sal_Bool Expand) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); SwUnoCursorHelper::SelectPam(rUnoCursor, Expand); if (CURSOR_BODY == m_pImpl->m_eType) { rUnoCursor.Move( fnMoveBackward, fnGoDoc ); //check, that the cursor is not in a table SwTableNode * pTblNode = rUnoCursor.GetNode()->FindTableNode(); SwCntntNode * pCNode = 0; while (pTblNode) { rUnoCursor.GetPoint()->nNode = *pTblNode->EndOfSectionNode(); pCNode = GetDoc()->GetNodes().GoNext(&rUnoCursor.GetPoint()->nNode); pTblNode = (pCNode) ? pCNode->FindTableNode() : 0; } if (pCNode) { rUnoCursor.GetPoint()->nContent.Assign(pCNode, 0); } SwStartNode const*const pTmp = rUnoCursor.GetNode()->StartOfSectionNode(); if (pTmp->IsSectionNode()) { SwSectionNode const*const pSectionStartNode = static_cast(pTmp); if (pSectionStartNode->GetSection().IsHiddenFlag()) { pCNode = GetDoc()->GetNodes().GoNextSection( &rUnoCursor.GetPoint()->nNode, sal_True, sal_False); if (pCNode) { rUnoCursor.GetPoint()->nContent.Assign(pCNode, 0); } } } } else if ( (CURSOR_FRAME == m_pImpl->m_eType) || (CURSOR_TBLTEXT == m_pImpl->m_eType) || (CURSOR_HEADER == m_pImpl->m_eType) || (CURSOR_FOOTER == m_pImpl->m_eType) || (CURSOR_FOOTNOTE== m_pImpl->m_eType) || (CURSOR_REDLINE == m_pImpl->m_eType)) { rUnoCursor.MoveSection(fnSectionCurr, fnSectionStart); } else if (CURSOR_META == m_pImpl->m_eType) { lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText, META_INIT_START); } } void SAL_CALL SwXTextCursor::gotoEnd(sal_Bool Expand) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); SwUnoCursorHelper::SelectPam(rUnoCursor, Expand); if (CURSOR_BODY == m_pImpl->m_eType) { rUnoCursor.Move( fnMoveForward, fnGoDoc ); } else if ( (CURSOR_FRAME == m_pImpl->m_eType) || (CURSOR_TBLTEXT == m_pImpl->m_eType) || (CURSOR_HEADER == m_pImpl->m_eType) || (CURSOR_FOOTER == m_pImpl->m_eType) || (CURSOR_FOOTNOTE== m_pImpl->m_eType) || (CURSOR_REDLINE == m_pImpl->m_eType)) { rUnoCursor.MoveSection( fnSectionCurr, fnSectionEnd); } else if (CURSOR_META == m_pImpl->m_eType) { lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText, META_INIT_END); } } void SAL_CALL SwXTextCursor::gotoRange( const uno::Reference< text::XTextRange > & xRange, sal_Bool bExpand) throw (uno::RuntimeException) { SolarMutexGuard aGuard; if (!xRange.is()) { throw uno::RuntimeException(); } SwUnoCrsr & rOwnCursor( m_pImpl->GetCursorOrThrow() ); uno::Reference xRangeTunnel( xRange, uno::UNO_QUERY); SwXTextRange* pRange = 0; OTextCursorHelper* pCursor = 0; if(xRangeTunnel.is()) { pRange = ::sw::UnoTunnelGetImplementation(xRangeTunnel); pCursor = ::sw::UnoTunnelGetImplementation(xRangeTunnel); } if (!pRange && !pCursor) { throw uno::RuntimeException(); } SwStartNodeType eSearchNodeType = SwNormalStartNode; switch (m_pImpl->m_eType) { case CURSOR_FRAME: eSearchNodeType = SwFlyStartNode; break; case CURSOR_TBLTEXT: eSearchNodeType = SwTableBoxStartNode; break; case CURSOR_FOOTNOTE: eSearchNodeType = SwFootnoteStartNode; break; case CURSOR_HEADER: eSearchNodeType = SwHeaderStartNode; break; case CURSOR_FOOTER: eSearchNodeType = SwFooterStartNode; break; //case CURSOR_INVALID: //case CURSOR_BODY: default: ; } const SwStartNode* pOwnStartNode = rOwnCursor.GetNode()->FindSttNodeByType(eSearchNodeType); SwPaM aPam(GetDoc()->GetNodes()); const SwPaM * pPam(0); if (pCursor) { pPam = pCursor->GetPaM(); } else if (pRange) { if (pRange->GetPositions(aPam)) { pPam = & aPam; } } if (!pPam) { throw uno::RuntimeException(); } const SwStartNode* pTmp = pPam->GetNode()->FindSttNodeByType(eSearchNodeType); //SectionNodes ueberspringen while(pTmp && pTmp->IsSectionNode()) { pTmp = pTmp->StartOfSectionNode(); } while(pOwnStartNode && pOwnStartNode->IsSectionNode()) { pOwnStartNode = pOwnStartNode->StartOfSectionNode(); } if(pOwnStartNode != pTmp) { throw uno::RuntimeException(); } if (CURSOR_META == m_pImpl->m_eType) { SwPaM CopyPam(*pPam->GetMark(), *pPam->GetPoint()); const bool bNotForced( lcl_ForceIntoMeta( CopyPam, m_pImpl->m_xParentText, META_CHECK_BOTH) ); if (!bNotForced) { throw uno::RuntimeException( C2U("gotoRange: parameter range not contained in nesting" " text content for which this cursor was created"), static_cast(this)); } } //jetzt muss die Selektion erweitert werden if(bExpand) { // der Cursor soll alles einschliessen, was bisher von ihm und dem uebergebenen // Range eingeschlossen wurde const SwPosition aOwnLeft(*rOwnCursor.Start()); const SwPosition aOwnRight(*rOwnCursor.End()); SwPosition const& rParamLeft = *pPam->Start(); SwPosition const& rParamRight = *pPam->End(); // jetzt sind vier SwPositions da, zwei davon werden gebraucht, also welche? *rOwnCursor.GetPoint() = (aOwnRight > rParamRight) ? aOwnRight : *rOwnCursor.GetPoint() = rParamRight; rOwnCursor.SetMark(); *rOwnCursor.GetMark() = (aOwnLeft < rParamLeft) ? aOwnLeft : *rOwnCursor.GetMark() = rParamLeft; } else { // cursor should be the given range *rOwnCursor.GetPoint() = *pPam->GetPoint(); if (pPam->HasMark()) { rOwnCursor.SetMark(); *rOwnCursor.GetMark() = *pPam->GetMark(); } else { rOwnCursor.DeleteMark(); } } } sal_Bool SAL_CALL SwXTextCursor::isStartOfWord() throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); const sal_Bool bRet = rUnoCursor.IsStartWordWT( i18n::WordType::DICTIONARY_WORD ); return bRet; } sal_Bool SAL_CALL SwXTextCursor::isEndOfWord() throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); const sal_Bool bRet = rUnoCursor.IsEndWordWT( i18n::WordType::DICTIONARY_WORD ); return bRet; } sal_Bool SAL_CALL SwXTextCursor::gotoNextWord(sal_Bool Expand) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); //Probleme gibt's noch mit einem Absatzanfang, an dem kein Wort beginnt. sal_Bool bRet = sal_False; // remember old position to check if cursor has moved // since the called functions are sometimes a bit unreliable // in specific cases... SwPosition *const pPoint = rUnoCursor.GetPoint(); SwNode *const pOldNode = &pPoint->nNode.GetNode(); xub_StrLen const nOldIndex = pPoint->nContent.GetIndex(); SwUnoCursorHelper::SelectPam(rUnoCursor, Expand); // end of paragraph if (rUnoCursor.GetCntntNode() && (pPoint->nContent == rUnoCursor.GetCntntNode()->Len())) { rUnoCursor.Right(1, CRSR_SKIP_CHARS, FALSE, FALSE); } else { const bool bTmp = rUnoCursor.GoNextWordWT( i18n::WordType::DICTIONARY_WORD ); // if there is no next word within the current paragraph // try to go to the start of the next paragraph if (!bTmp) { rUnoCursor.MovePara(fnParaNext, fnParaStart); } } // return true if cursor has moved bRet = (&pPoint->nNode.GetNode() != pOldNode) || (pPoint->nContent.GetIndex() != nOldIndex); if (bRet && (CURSOR_META == m_pImpl->m_eType)) { bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText, META_CHECK_BOTH); } return bRet; } sal_Bool SAL_CALL SwXTextCursor::gotoPreviousWord(sal_Bool Expand) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); // hier machen Leerzeichen am Absatzanfang Probleme sal_Bool bRet = sal_False; SwPosition *const pPoint = rUnoCursor.GetPoint(); SwNode *const pOldNode = &pPoint->nNode.GetNode(); xub_StrLen const nOldIndex = pPoint->nContent.GetIndex(); SwUnoCursorHelper::SelectPam(rUnoCursor, Expand); // start of paragraph? if (pPoint->nContent == 0) { rUnoCursor.Left(1, CRSR_SKIP_CHARS, FALSE, FALSE); } else { rUnoCursor.GoPrevWordWT( i18n::WordType::DICTIONARY_WORD ); if (pPoint->nContent == 0) { rUnoCursor.Left(1, CRSR_SKIP_CHARS, FALSE, FALSE); } } // return true if cursor has moved bRet = (&pPoint->nNode.GetNode() != pOldNode) || (pPoint->nContent.GetIndex() != nOldIndex); if (bRet && (CURSOR_META == m_pImpl->m_eType)) { bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText, META_CHECK_BOTH); } return bRet; } sal_Bool SAL_CALL SwXTextCursor::gotoEndOfWord(sal_Bool Expand) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); sal_Bool bRet = sal_False; SwPosition *const pPoint = rUnoCursor.GetPoint(); SwNode & rOldNode = pPoint->nNode.GetNode(); xub_StrLen const nOldIndex = pPoint->nContent.GetIndex(); const sal_Int16 nWordType = i18n::WordType::DICTIONARY_WORD; SwUnoCursorHelper::SelectPam(rUnoCursor, Expand); if (!rUnoCursor.IsEndWordWT( nWordType )) { rUnoCursor.GoEndWordWT( nWordType ); } // restore old cursor if we are not at the end of a word by now // otherwise use current one bRet = rUnoCursor.IsEndWordWT( nWordType ); if (!bRet) { pPoint->nNode = rOldNode; pPoint->nContent = nOldIndex; } else if (CURSOR_META == m_pImpl->m_eType) { bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText, META_CHECK_BOTH); } return bRet; } sal_Bool SAL_CALL SwXTextCursor::gotoStartOfWord(sal_Bool Expand) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); sal_Bool bRet = sal_False; SwPosition *const pPoint = rUnoCursor.GetPoint(); SwNode & rOldNode = pPoint->nNode.GetNode(); xub_StrLen const nOldIndex = pPoint->nContent.GetIndex(); const sal_Int16 nWordType = i18n::WordType::DICTIONARY_WORD; SwUnoCursorHelper::SelectPam(rUnoCursor, Expand); if (!rUnoCursor.IsStartWordWT( nWordType )) { rUnoCursor.GoStartWordWT( nWordType ); } // restore old cursor if we are not at the start of a word by now // otherwise use current one bRet = rUnoCursor.IsStartWordWT( nWordType ); if (!bRet) { pPoint->nNode = rOldNode; pPoint->nContent = nOldIndex; } else if (CURSOR_META == m_pImpl->m_eType) { bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText, META_CHECK_BOTH); } return bRet; } sal_Bool SAL_CALL SwXTextCursor::isStartOfSentence() throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); // start of paragraph? sal_Bool bRet = rUnoCursor.GetPoint()->nContent == 0; // with mark ->no sentence start // (check if cursor is no selection, i.e. it does not have // a mark or else point and mark are identical) if (!bRet && (!rUnoCursor.HasMark() || *rUnoCursor.GetPoint() == *rUnoCursor.GetMark())) { SwCursor aCrsr(*rUnoCursor.GetPoint(),0,false); SwPosition aOrigPos = *aCrsr.GetPoint(); aCrsr.GoSentence(SwCursor::START_SENT ); bRet = aOrigPos == *aCrsr.GetPoint(); } return bRet; } sal_Bool SAL_CALL SwXTextCursor::isEndOfSentence() throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); // end of paragraph? sal_Bool bRet = rUnoCursor.GetCntntNode() && (rUnoCursor.GetPoint()->nContent == rUnoCursor.GetCntntNode()->Len()); // with mark->no sentence end // (check if cursor is no selection, i.e. it does not have // a mark or else point and mark are identical) if (!bRet && (!rUnoCursor.HasMark() || *rUnoCursor.GetPoint() == *rUnoCursor.GetMark())) { SwCursor aCrsr(*rUnoCursor.GetPoint(), 0, false); SwPosition aOrigPos = *aCrsr.GetPoint(); aCrsr.GoSentence(SwCursor::END_SENT); bRet = aOrigPos == *aCrsr.GetPoint(); } return bRet; } sal_Bool SAL_CALL SwXTextCursor::gotoNextSentence(sal_Bool Expand) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); const bool bWasEOS = isEndOfSentence(); SwUnoCursorHelper::SelectPam(rUnoCursor, Expand); sal_Bool bRet = rUnoCursor.GoSentence(SwCursor::NEXT_SENT); if (!bRet) { bRet = rUnoCursor.MovePara(fnParaNext, fnParaStart); } // if at the end of the sentence (i.e. at the space after the '.') // advance to next word in order for GoSentence to work properly // next time and have isStartOfSentence return true after this call if (!rUnoCursor.IsStartWord()) { const bool bNextWord = rUnoCursor.GoNextWord(); if (bWasEOS && !bNextWord) { bRet = sal_False; } } if (CURSOR_META == m_pImpl->m_eType) { bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText, META_CHECK_BOTH) && bRet; } return bRet; } sal_Bool SAL_CALL SwXTextCursor::gotoPreviousSentence(sal_Bool Expand) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); SwUnoCursorHelper::SelectPam(rUnoCursor, Expand); sal_Bool bRet = rUnoCursor.GoSentence(SwCursor::PREV_SENT); if (!bRet) { bRet = rUnoCursor.MovePara(fnParaPrev, fnParaStart); if (bRet) { rUnoCursor.MovePara(fnParaCurr, fnParaEnd); // at the end of a paragraph move to the sentence end again rUnoCursor.GoSentence(SwCursor::PREV_SENT); } } if (CURSOR_META == m_pImpl->m_eType) { bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText, META_CHECK_BOTH) && bRet; } return bRet; } sal_Bool SAL_CALL SwXTextCursor::gotoStartOfSentence(sal_Bool Expand) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); sal_Bool bRet = sal_False; SwUnoCursorHelper::SelectPam(rUnoCursor, Expand); // if we're at the para start then we wont move // but bRet is also true if GoSentence failed but // the start of the sentence is reached bRet = SwUnoCursorHelper::IsStartOfPara(rUnoCursor) || rUnoCursor.GoSentence(SwCursor::START_SENT) || SwUnoCursorHelper::IsStartOfPara(rUnoCursor); if (CURSOR_META == m_pImpl->m_eType) { bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText, META_CHECK_BOTH) && bRet; } return bRet; } sal_Bool SAL_CALL SwXTextCursor::gotoEndOfSentence(sal_Bool Expand) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); sal_Bool bRet = sal_False; SwUnoCursorHelper::SelectPam(rUnoCursor, Expand); // bRet is true if GoSentence() succeeded or if the // MovePara() succeeded while the end of the para is // not reached already sal_Bool bAlreadyParaEnd = SwUnoCursorHelper::IsEndOfPara(rUnoCursor); bRet = !bAlreadyParaEnd && (rUnoCursor.GoSentence(SwCursor::END_SENT) || rUnoCursor.MovePara(fnParaCurr, fnParaEnd)); if (CURSOR_META == m_pImpl->m_eType) { bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText, META_CHECK_BOTH) && bRet; } return bRet; } sal_Bool SAL_CALL SwXTextCursor::isStartOfParagraph() throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); const sal_Bool bRet = SwUnoCursorHelper::IsStartOfPara(rUnoCursor); return bRet; } sal_Bool SAL_CALL SwXTextCursor::isEndOfParagraph() throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); const sal_Bool bRet = SwUnoCursorHelper::IsEndOfPara(rUnoCursor); return bRet; } sal_Bool SAL_CALL SwXTextCursor::gotoStartOfParagraph(sal_Bool Expand) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); if (CURSOR_META == m_pImpl->m_eType) { return sal_False; } SwUnoCursorHelper::SelectPam(rUnoCursor, Expand); sal_Bool bRet = SwUnoCursorHelper::IsStartOfPara(rUnoCursor); if (!bRet) { bRet = rUnoCursor.MovePara(fnParaCurr, fnParaStart); } // since MovePara(fnParaCurr, fnParaStart) only returns false // if we were already at the start of the paragraph this function // should always complete successfully. DBG_ASSERT( bRet, "gotoStartOfParagraph failed" ); return bRet; } sal_Bool SAL_CALL SwXTextCursor::gotoEndOfParagraph(sal_Bool Expand) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); if (CURSOR_META == m_pImpl->m_eType) { return sal_False; } SwUnoCursorHelper::SelectPam(rUnoCursor, Expand); sal_Bool bRet = SwUnoCursorHelper::IsEndOfPara(rUnoCursor); if (!bRet) { bRet = rUnoCursor.MovePara(fnParaCurr, fnParaEnd); } // since MovePara(fnParaCurr, fnParaEnd) only returns false // if we were already at the end of the paragraph this function // should always complete successfully. DBG_ASSERT( bRet, "gotoEndOfParagraph failed" ); return bRet; } sal_Bool SAL_CALL SwXTextCursor::gotoNextParagraph(sal_Bool Expand) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); if (CURSOR_META == m_pImpl->m_eType) { return sal_False; } SwUnoCursorHelper::SelectPam(rUnoCursor, Expand); const sal_Bool bRet = rUnoCursor.MovePara(fnParaNext, fnParaStart); return bRet; } sal_Bool SAL_CALL SwXTextCursor::gotoPreviousParagraph(sal_Bool Expand) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); if (CURSOR_META == m_pImpl->m_eType) { return sal_False; } SwUnoCursorHelper::SelectPam(rUnoCursor, Expand); const sal_Bool bRet = rUnoCursor.MovePara(fnParaPrev, fnParaStart); return bRet; } uno::Reference< text::XText > SAL_CALL SwXTextCursor::getText() throw (uno::RuntimeException) { SolarMutexGuard g; return m_pImpl->m_xParentText; } uno::Reference< text::XTextRange > SAL_CALL SwXTextCursor::getStart() throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); uno::Reference< text::XTextRange > xRet; SwPaM aPam(*rUnoCursor.Start()); const uno::Reference< text::XText > xParent = getText(); if (CURSOR_META == m_pImpl->m_eType) { // return cursor to prevent modifying SwXTextRange for META SwXTextCursor * const pXCursor( new SwXTextCursor(*rUnoCursor.GetDoc(), xParent, CURSOR_META, *rUnoCursor.GetPoint()) ); pXCursor->gotoStart(sal_False); xRet = static_cast(pXCursor); } else { xRet = new SwXTextRange(aPam, xParent); } return xRet; } uno::Reference< text::XTextRange > SAL_CALL SwXTextCursor::getEnd() throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); uno::Reference< text::XTextRange > xRet; SwPaM aPam(*rUnoCursor.End()); const uno::Reference< text::XText > xParent = getText(); if (CURSOR_META == m_pImpl->m_eType) { // return cursor to prevent modifying SwXTextRange for META SwXTextCursor * const pXCursor( new SwXTextCursor(*rUnoCursor.GetDoc(), xParent, CURSOR_META, *rUnoCursor.GetPoint()) ); pXCursor->gotoEnd(sal_False); xRet = static_cast(pXCursor); } else { xRet = new SwXTextRange(aPam, xParent); } return xRet; } OUString SAL_CALL SwXTextCursor::getString() throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); OUString aTxt; SwUnoCursorHelper::GetTextFromPam(rUnoCursor, aTxt); return aTxt; } void SAL_CALL SwXTextCursor::setString(const OUString& aString) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); (void) rUnoCursor; // just to check if valid const bool bForceExpandHints( (CURSOR_META != m_pImpl->m_eType) ? false : dynamic_cast(m_pImpl->m_xParentText.get()) ->CheckForOwnMemberMeta(*GetPaM(), true) ); DeleteAndInsert(aString, bForceExpandHints); } uno::Any SwUnoCursorHelper::GetPropertyValue( SwPaM& rPaM, const SfxItemPropertySet& rPropSet, const OUString& rPropertyName) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) { uno::Any aAny; SfxItemPropertySimpleEntry const*const pEntry = rPropSet.getPropertyMap()->getByName(rPropertyName); if (!pEntry) { throw beans::UnknownPropertyException( OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: ")) + rPropertyName, static_cast(0)); } beans::PropertyState eTemp; const sal_Bool bDone = SwUnoCursorHelper::getCrsrPropertyValue( *pEntry, rPaM, &aAny, eTemp ); if (!bDone) { SfxItemSet aSet(rPaM.GetDoc()->GetAttrPool(), RES_CHRATR_BEGIN, RES_FRMATR_END - 1, RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER, RES_UNKNOWNATR_CONTAINER, RES_UNKNOWNATR_CONTAINER, 0L); SwUnoCursorHelper::GetCrsrAttr(rPaM, aSet); rPropSet.getPropertyValue(*pEntry, aSet, aAny); } return aAny; } void SwUnoCursorHelper::SetPropertyValue( SwPaM& rPaM, const SfxItemPropertySet& rPropSet, const OUString& rPropertyName, const uno::Any& rValue, const SetAttrMode nAttrMode, const bool bTableMode) throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) { SwDoc *const pDoc = rPaM.GetDoc(); SfxItemPropertySimpleEntry const*const pEntry = rPropSet.getPropertyMap()->getByName(rPropertyName); if (!pEntry) { throw beans::UnknownPropertyException( OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: ")) + rPropertyName, static_cast(0)); } if (pEntry->nFlags & beans::PropertyAttribute::READONLY) { throw beans::PropertyVetoException( OUString(RTL_CONSTASCII_USTRINGPARAM("Property is read-only: ")) + rPropertyName, static_cast(0)); } SfxItemSet aItemSet( pDoc->GetAttrPool(), pEntry->nWID, pEntry->nWID ); SwUnoCursorHelper::GetCrsrAttr( rPaM, aItemSet ); if (!SwUnoCursorHelper::SetCursorPropertyValue( *pEntry, rValue, rPaM, aItemSet)) { rPropSet.setPropertyValue(*pEntry, rValue, aItemSet ); } SwUnoCursorHelper::SetCrsrAttr(rPaM, aItemSet, nAttrMode, bTableMode); } uno::Sequence< beans::PropertyState > SwUnoCursorHelper::GetPropertyStates( SwPaM& rPaM, const SfxItemPropertySet& rPropSet, const uno::Sequence< OUString >& rPropertyNames, const SwGetPropertyStatesCaller eCaller) throw (beans::UnknownPropertyException, uno::RuntimeException) { const OUString* pNames = rPropertyNames.getConstArray(); uno::Sequence< beans::PropertyState > aRet(rPropertyNames.getLength()); beans::PropertyState* pStates = aRet.getArray(); SfxItemPropertyMap const*const pMap = rPropSet.getPropertyMap(); ::std::auto_ptr pSet; ::std::auto_ptr pSetParent; for (sal_Int32 i = 0, nEnd = rPropertyNames.getLength(); i < nEnd; i++) { SfxItemPropertySimpleEntry const*const pEntry = pMap->getByName( pNames[i] ); if(!pEntry) { if (pNames[i].equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_SKIP_HIDDEN_TEXT)) || pNames[i].equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_SKIP_PROTECTED_TEXT))) { pStates[i] = beans::PropertyState_DEFAULT_VALUE; continue; } else if (SW_PROPERTY_STATE_CALLER_SWX_TEXT_PORTION_TOLERANT == eCaller) { //this values marks the element as unknown property pStates[i] = beans::PropertyState_MAKE_FIXED_SIZE; continue; } else { throw beans::UnknownPropertyException( OUString( RTL_CONSTASCII_USTRINGPARAM("Unknown property: ")) + pNames[i], static_cast(0)); } } if (((SW_PROPERTY_STATE_CALLER_SWX_TEXT_PORTION == eCaller) || (SW_PROPERTY_STATE_CALLER_SWX_TEXT_PORTION_TOLERANT == eCaller)) && pEntry->nWID < FN_UNO_RANGE_BEGIN && pEntry->nWID > FN_UNO_RANGE_END && pEntry->nWID < RES_CHRATR_BEGIN && pEntry->nWID > RES_TXTATR_END ) { pStates[i] = beans::PropertyState_DEFAULT_VALUE; } else { if ( pEntry->nWID >= FN_UNO_RANGE_BEGIN && pEntry->nWID <= FN_UNO_RANGE_END ) { SwUnoCursorHelper::getCrsrPropertyValue( *pEntry, rPaM, 0, pStates[i] ); } else { if (!pSet.get()) { switch ( eCaller ) { case SW_PROPERTY_STATE_CALLER_SWX_TEXT_PORTION_TOLERANT: case SW_PROPERTY_STATE_CALLER_SWX_TEXT_PORTION: pSet.reset( new SfxItemSet( rPaM.GetDoc()->GetAttrPool(), RES_CHRATR_BEGIN, RES_TXTATR_END )); break; case SW_PROPERTY_STATE_CALLER_SINGLE_VALUE_ONLY: pSet.reset( new SfxItemSet( rPaM.GetDoc()->GetAttrPool(), pEntry->nWID, pEntry->nWID )); break; default: pSet.reset( new SfxItemSet( rPaM.GetDoc()->GetAttrPool(), RES_CHRATR_BEGIN, RES_FRMATR_END - 1, RES_UNKNOWNATR_CONTAINER, RES_UNKNOWNATR_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER, 0L )); } // --> OD 2006-07-12 #i63870# SwUnoCursorHelper::GetCrsrAttr( rPaM, *pSet ); // <-- } pStates[i] = ( pSet->Count() ) ? rPropSet.getPropertyState( *pEntry, *pSet ) : beans::PropertyState_DEFAULT_VALUE; //try again to find out if a value has been inherited if( beans::PropertyState_DIRECT_VALUE == pStates[i] ) { if (!pSetParent.get()) { pSetParent.reset( pSet->Clone( FALSE ) ); // --> OD 2006-07-12 #i63870# SwUnoCursorHelper::GetCrsrAttr( rPaM, *pSetParent, TRUE, FALSE ); // <-- } pStates[i] = ( (pSetParent)->Count() ) ? rPropSet.getPropertyState( *pEntry, *pSetParent ) : beans::PropertyState_DEFAULT_VALUE; } } } } return aRet; } beans::PropertyState SwUnoCursorHelper::GetPropertyState( SwPaM& rPaM, const SfxItemPropertySet& rPropSet, const OUString& rPropertyName) throw (beans::UnknownPropertyException, uno::RuntimeException) { uno::Sequence< OUString > aStrings ( 1 ); aStrings[0] = rPropertyName; uno::Sequence< beans::PropertyState > aSeq = GetPropertyStates(rPaM, rPropSet, aStrings, SW_PROPERTY_STATE_CALLER_SINGLE_VALUE_ONLY ); return aSeq[0]; } static void lcl_SelectParaAndReset( SwPaM &rPaM, SwDoc & rDoc, SvUShortsSort const*const pWhichIds = 0 ) { // if we are reseting paragraph attributes, we need to select the full paragraph first SwPosition aStart = *rPaM.Start(); SwPosition aEnd = *rPaM.End(); ::std::auto_ptr< SwUnoCrsr > pTemp ( rDoc.CreateUnoCrsr(aStart, FALSE) ); if(!SwUnoCursorHelper::IsStartOfPara(*pTemp)) { pTemp->MovePara(fnParaCurr, fnParaStart); } pTemp->SetMark(); *pTemp->GetPoint() = aEnd; SwUnoCursorHelper::SelectPam(*pTemp, true); if(!SwUnoCursorHelper::IsEndOfPara(*pTemp)) { pTemp->MovePara(fnParaCurr, fnParaEnd); } rDoc.ResetAttrs(*pTemp, sal_True, pWhichIds); } void SwUnoCursorHelper::SetPropertyToDefault( SwPaM& rPaM, const SfxItemPropertySet& rPropSet, const OUString& rPropertyName) throw (beans::UnknownPropertyException, uno::RuntimeException) { SwDoc & rDoc = *rPaM.GetDoc(); SfxItemPropertySimpleEntry const*const pEntry = rPropSet.getPropertyMap()->getByName(rPropertyName); if (!pEntry) { throw beans::UnknownPropertyException( OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: ")) + rPropertyName, static_cast(0)); } if (pEntry->nFlags & beans::PropertyAttribute::READONLY) { throw uno::RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( "setPropertyToDefault: property is read-only: ")) + rPropertyName, 0); } if (pEntry->nWID < RES_FRMATR_END) { SvUShortsSort aWhichIds; aWhichIds.Insert(pEntry->nWID); if (pEntry->nWID < RES_PARATR_BEGIN) { rDoc.ResetAttrs(rPaM, sal_True, &aWhichIds); } else { lcl_SelectParaAndReset ( rPaM, rDoc, &aWhichIds ); } } else { SwUnoCursorHelper::resetCrsrPropertyValue(*pEntry, rPaM); } } uno::Any SwUnoCursorHelper::GetPropertyDefault( SwPaM& rPaM, const SfxItemPropertySet& rPropSet, const OUString& rPropertyName) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) { SfxItemPropertySimpleEntry const*const pEntry = rPropSet.getPropertyMap()->getByName(rPropertyName); if (!pEntry) { throw beans::UnknownPropertyException( OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: ")) + rPropertyName, static_cast(0)); } uno::Any aRet; if (pEntry->nWID < RES_FRMATR_END) { SwDoc & rDoc = *rPaM.GetDoc(); const SfxPoolItem& rDefItem = rDoc.GetAttrPool().GetDefaultItem(pEntry->nWID); rDefItem.QueryValue(aRet, pEntry->nMemberId); } return aRet; } uno::Reference< beans::XPropertySetInfo > SAL_CALL SwXTextCursor::getPropertySetInfo() throw (uno::RuntimeException) { SolarMutexGuard g; static uno::Reference< beans::XPropertySetInfo > xRef; if(!xRef.is()) { static SfxItemPropertyMapEntry aCrsrExtMap_Impl[] = { { SW_PROP_NAME(UNO_NAME_IS_SKIP_HIDDEN_TEXT), FN_SKIP_HIDDEN_TEXT, &::getBooleanCppuType(), PROPERTY_NONE, 0}, { SW_PROP_NAME(UNO_NAME_IS_SKIP_PROTECTED_TEXT), FN_SKIP_PROTECTED_TEXT, &::getBooleanCppuType(), PROPERTY_NONE, 0}, {0,0,0,0,0,0} }; const uno::Reference< beans::XPropertySetInfo > xInfo = m_pImpl->m_rPropSet.getPropertySetInfo(); // PropertySetInfo verlaengern! const uno::Sequence aPropSeq = xInfo->getProperties(); xRef = new SfxExtItemPropertySetInfo( aCrsrExtMap_Impl, aPropSeq ); } return xRef; } void SAL_CALL SwXTextCursor::setPropertyValue( const OUString& rPropertyName, const uno::Any& rValue) throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); if (rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_IS_SKIP_HIDDEN_TEXT))) { sal_Bool bSet(sal_False); if (!(rValue >>= bSet)) { throw lang::IllegalArgumentException(); } rUnoCursor.SetSkipOverHiddenSections(bSet); } else if (rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_SKIP_PROTECTED_TEXT))) { sal_Bool bSet(sal_False); if (!(rValue >>= bSet)) { throw lang::IllegalArgumentException(); } rUnoCursor.SetSkipOverProtectSections(bSet); } else { SwUnoCursorHelper::SetPropertyValue(rUnoCursor, m_pImpl->m_rPropSet, rPropertyName, rValue); } } uno::Any SAL_CALL SwXTextCursor::getPropertyValue(const OUString& rPropertyName) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); uno::Any aAny; if (rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_IS_SKIP_HIDDEN_TEXT))) { const sal_Bool bSet = rUnoCursor.IsSkipOverHiddenSections(); aAny <<= bSet; } else if (rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_SKIP_PROTECTED_TEXT))) { const sal_Bool bSet = rUnoCursor.IsSkipOverProtectSections(); aAny <<= bSet; } else { aAny = SwUnoCursorHelper::GetPropertyValue(rUnoCursor, m_pImpl->m_rPropSet, rPropertyName); } return aAny; } void SAL_CALL SwXTextCursor::addPropertyChangeListener( const ::rtl::OUString& /*rPropertyName*/, const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) { OSL_ENSURE(false, "SwXTextCursor::addPropertyChangeListener(): not implemented"); } void SAL_CALL SwXTextCursor::removePropertyChangeListener( const ::rtl::OUString& /*rPropertyName*/, const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) { OSL_ENSURE(false, "SwXTextCursor::removePropertyChangeListener(): not implemented"); } void SAL_CALL SwXTextCursor::addVetoableChangeListener( const ::rtl::OUString& /*rPropertyName*/, const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) { OSL_ENSURE(false, "SwXTextCursor::addVetoableChangeListener(): not implemented"); } void SAL_CALL SwXTextCursor::removeVetoableChangeListener( const ::rtl::OUString& /*rPropertyName*/, const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) { OSL_ENSURE(false, "SwXTextCursor::removeVetoableChangeListener(): not implemented"); } beans::PropertyState SAL_CALL SwXTextCursor::getPropertyState(const OUString& rPropertyName) throw (beans::UnknownPropertyException, uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); const beans::PropertyState eRet = SwUnoCursorHelper::GetPropertyState( rUnoCursor, m_pImpl->m_rPropSet, rPropertyName); return eRet; } uno::Sequence< beans::PropertyState > SAL_CALL SwXTextCursor::getPropertyStates( const uno::Sequence< OUString >& rPropertyNames) throw (beans::UnknownPropertyException, uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); return SwUnoCursorHelper::GetPropertyStates( rUnoCursor, m_pImpl->m_rPropSet, rPropertyNames); } void SAL_CALL SwXTextCursor::setPropertyToDefault(const OUString& rPropertyName) throw (beans::UnknownPropertyException, uno::RuntimeException) { // forward: need no solar mutex here uno::Sequence < OUString > aSequence ( &rPropertyName, 1 ); setPropertiesToDefault ( aSequence ); } uno::Any SAL_CALL SwXTextCursor::getPropertyDefault(const OUString& rPropertyName) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) { // forward: need no solar mutex here const uno::Sequence < OUString > aSequence ( &rPropertyName, 1 ); return getPropertyDefaults ( aSequence ).getConstArray()[0]; } // para specific attribut ranges static USHORT g_ParaResetableSetRange[] = { RES_FRMATR_BEGIN, RES_FRMATR_END-1, RES_PARATR_BEGIN, RES_PARATR_END-1, RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1, RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1, 0 }; // selection specific attribut ranges static USHORT g_ResetableSetRange[] = { RES_CHRATR_BEGIN, RES_CHRATR_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, 0 }; static void lcl_EnumerateIds(USHORT const* pIdRange, SvUShortsSort & rWhichIds) { while (*pIdRange) { const USHORT nStart = sal::static_int_cast(*pIdRange++); const USHORT nEnd = sal::static_int_cast(*pIdRange++); for (USHORT nId = nStart + 1; nId <= nEnd; ++nId) { rWhichIds.Insert( nId ); } } } void SAL_CALL SwXTextCursor::setAllPropertiesToDefault() throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); SvUShortsSort aParaWhichIds; SvUShortsSort aWhichIds; lcl_EnumerateIds(g_ParaResetableSetRange, aParaWhichIds); lcl_EnumerateIds(g_ResetableSetRange, aWhichIds); if (aParaWhichIds.Count()) { lcl_SelectParaAndReset(rUnoCursor, *rUnoCursor.GetDoc(), &aParaWhichIds); } if (aWhichIds.Count()) { rUnoCursor.GetDoc()->ResetAttrs(rUnoCursor, sal_True, &aWhichIds); } } void SAL_CALL SwXTextCursor::setPropertiesToDefault( const uno::Sequence< OUString >& rPropertyNames) throw (beans::UnknownPropertyException, uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); const sal_Int32 nCount = rPropertyNames.getLength(); if ( nCount ) { SwDoc & rDoc = *rUnoCursor.GetDoc(); const OUString * pNames = rPropertyNames.getConstArray(); SvUShortsSort aWhichIds; SvUShortsSort aParaWhichIds; for (sal_Int32 i = 0; i < nCount; i++) { SfxItemPropertySimpleEntry const*const pEntry = m_pImpl->m_rPropSet.getPropertyMap()->getByName( pNames[i] ); if (!pEntry) { if (pNames[i].equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_SKIP_HIDDEN_TEXT)) || pNames[i].equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_SKIP_PROTECTED_TEXT))) { continue; } throw beans::UnknownPropertyException( OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: ")) + pNames[i], static_cast(this)); } if (pEntry->nFlags & beans::PropertyAttribute::READONLY) { throw uno::RuntimeException( OUString(RTL_CONSTASCII_USTRINGPARAM( "setPropertiesToDefault: property is read-only: ")) + pNames[i], static_cast(this)); } if (pEntry->nWID < RES_FRMATR_END) { if (pEntry->nWID < RES_PARATR_BEGIN) { aWhichIds.Insert(pEntry->nWID); } else { aParaWhichIds.Insert(pEntry->nWID); } } else if (pEntry->nWID == FN_UNO_NUM_START_VALUE) { SwUnoCursorHelper::resetCrsrPropertyValue(*pEntry, rUnoCursor); } } if (aParaWhichIds.Count()) { lcl_SelectParaAndReset(rUnoCursor, rDoc, &aParaWhichIds); } if (aWhichIds.Count()) { rDoc.ResetAttrs(rUnoCursor, sal_True, &aWhichIds); } } } uno::Sequence< uno::Any > SAL_CALL SwXTextCursor::getPropertyDefaults( const uno::Sequence< OUString >& rPropertyNames) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); const sal_Int32 nCount = rPropertyNames.getLength(); uno::Sequence< uno::Any > aRet(nCount); if ( nCount ) { SwDoc & rDoc = *rUnoCursor.GetDoc(); const OUString *pNames = rPropertyNames.getConstArray(); uno::Any *pAny = aRet.getArray(); for (sal_Int32 i = 0; i < nCount; i++) { SfxItemPropertySimpleEntry const*const pEntry = m_pImpl->m_rPropSet.getPropertyMap()->getByName( pNames[i] ); if (!pEntry) { if (pNames[i].equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_SKIP_HIDDEN_TEXT)) || pNames[i].equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_SKIP_PROTECTED_TEXT))) { continue; } throw beans::UnknownPropertyException( OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: ")) + pNames[i], static_cast(0)); } if (pEntry->nWID < RES_FRMATR_END) { const SfxPoolItem& rDefItem = rDoc.GetAttrPool().GetDefaultItem(pEntry->nWID); rDefItem.QueryValue(pAny[i], pEntry->nMemberId); } } } return aRet; } void SAL_CALL SwXTextCursor::makeRedline( const ::rtl::OUString& rRedlineType, const uno::Sequence< beans::PropertyValue >& rRedlineProperties) throw (lang::IllegalArgumentException, uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); SwUnoCursorHelper::makeRedline(rUnoCursor, rRedlineType, rRedlineProperties); } void SAL_CALL SwXTextCursor::insertDocumentFromURL(const OUString& rURL, const uno::Sequence< beans::PropertyValue >& rOptions) throw (lang::IllegalArgumentException, io::IOException, uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); SwUnoCursorHelper::InsertFile(&rUnoCursor, rURL, rOptions); } uno::Sequence< beans::PropertyValue > SwUnoCursorHelper::CreateSortDescriptor(const bool bFromTable) { uno::Sequence< beans::PropertyValue > aRet(5); beans::PropertyValue* pArray = aRet.getArray(); uno::Any aVal; aVal.setValue( &bFromTable, ::getCppuBooleanType()); pArray[0] = beans::PropertyValue(C2U("IsSortInTable"), -1, aVal, beans::PropertyState_DIRECT_VALUE); aVal <<= sal_Unicode(' '); pArray[1] = beans::PropertyValue(C2U("Delimiter"), -1, aVal, beans::PropertyState_DIRECT_VALUE); aVal <<= (sal_Bool) sal_False; pArray[2] = beans::PropertyValue(C2U("IsSortColumns"), -1, aVal, beans::PropertyState_DIRECT_VALUE); aVal <<= (sal_Int32) 3; pArray[3] = beans::PropertyValue(C2U("MaxSortFieldsCount"), -1, aVal, beans::PropertyState_DIRECT_VALUE); uno::Sequence< table::TableSortField > aFields(3); table::TableSortField* pFields = aFields.getArray(); lang::Locale aLang( SvxCreateLocale( LANGUAGE_SYSTEM ) ); // get collator algorithm to be used for the locale uno::Sequence< OUString > aSeq( GetAppCollator().listCollatorAlgorithms( aLang ) ); const sal_Int32 nLen = aSeq.getLength(); DBG_ASSERT( nLen > 0, "list of collator algorithms is empty!"); OUString aCollAlg; if (nLen > 0) { aCollAlg = aSeq.getConstArray()[0]; } #if OSL_DEBUG_LEVEL > 1 const OUString *pTxt = aSeq.getConstArray(); (void)pTxt; #endif pFields[0].Field = 1; pFields[0].IsAscending = sal_True; pFields[0].IsCaseSensitive = sal_False; pFields[0].FieldType = table::TableSortFieldType_ALPHANUMERIC; pFields[0].CollatorLocale = aLang; pFields[0].CollatorAlgorithm = aCollAlg; pFields[1].Field = 1; pFields[1].IsAscending = sal_True; pFields[1].IsCaseSensitive = sal_False; pFields[1].FieldType = table::TableSortFieldType_ALPHANUMERIC; pFields[1].CollatorLocale = aLang; pFields[1].CollatorAlgorithm = aCollAlg; pFields[2].Field = 1; pFields[2].IsAscending = sal_True; pFields[2].IsCaseSensitive = sal_False; pFields[2].FieldType = table::TableSortFieldType_ALPHANUMERIC; pFields[2].CollatorLocale = aLang; pFields[2].CollatorAlgorithm = aCollAlg; aVal <<= aFields; pArray[4] = beans::PropertyValue(C2U("SortFields"), -1, aVal, beans::PropertyState_DIRECT_VALUE); return aRet; } uno::Sequence< beans::PropertyValue > SAL_CALL SwXTextCursor::createSortDescriptor() throw (uno::RuntimeException) { SolarMutexGuard aGuard; return SwUnoCursorHelper::CreateSortDescriptor(false); } sal_Bool SwUnoCursorHelper::ConvertSortProperties( const uno::Sequence< beans::PropertyValue >& rDescriptor, SwSortOptions& rSortOpt) { sal_Bool bRet = sal_True; const beans::PropertyValue* pProperties = rDescriptor.getConstArray(); rSortOpt.bTable = sal_False; rSortOpt.cDeli = ' '; rSortOpt.eDirection = SRT_COLUMNS; //!! UI text may be contrary though !! SwSortKey* pKey1 = new SwSortKey; pKey1->nColumnId = USHRT_MAX; pKey1->bIsNumeric = TRUE; pKey1->eSortOrder = SRT_ASCENDING; SwSortKey* pKey2 = new SwSortKey; pKey2->nColumnId = USHRT_MAX; pKey2->bIsNumeric = TRUE; pKey2->eSortOrder = SRT_ASCENDING; SwSortKey* pKey3 = new SwSortKey; pKey3->nColumnId = USHRT_MAX; pKey3->bIsNumeric = TRUE; pKey3->eSortOrder = SRT_ASCENDING; SwSortKey* aKeys[3] = {pKey1, pKey2, pKey3}; sal_Bool bOldSortdescriptor(sal_False); sal_Bool bNewSortdescriptor(sal_False); for (sal_Int32 n = 0; n < rDescriptor.getLength(); ++n) { uno::Any aValue( pProperties[n].Value ); // String sPropName = pProperties[n].Name; const OUString& rPropName = pProperties[n].Name; // old and new sortdescriptor if (rPropName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("IsSortInTable"))) { if (aValue.getValueType() == ::getBooleanCppuType()) { rSortOpt.bTable = *(sal_Bool*)aValue.getValue(); } else { bRet = sal_False; } } else if (rPropName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Delimiter"))) { sal_Unicode uChar = sal_Unicode(); if (aValue >>= uChar) { rSortOpt.cDeli = uChar; } else { bRet = sal_False; } } // old sortdescriptor else if (rPropName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("SortColumns"))) { bOldSortdescriptor = sal_True; sal_Bool bTemp(sal_False); if (aValue >>= bTemp) { rSortOpt.eDirection = bTemp ? SRT_COLUMNS : SRT_ROWS; } else { bRet = sal_False; } } else if ( rPropName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("IsCaseSensitive"))) { bOldSortdescriptor = sal_True; sal_Bool bTemp(sal_False); if (aValue >>= bTemp) { rSortOpt.bIgnoreCase = !bTemp; } else { bRet = sal_False; } } else if (rPropName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("CollatorLocale"))) { bOldSortdescriptor = sal_True; lang::Locale aLocale; if (aValue >>= aLocale) { rSortOpt.nLanguage = SvxLocaleToLanguage( aLocale ); } else { bRet = sal_False; } } else if (rPropName.matchAsciiL("CollatorAlgorithm", 17) && rPropName.getLength() == 18 && (rPropName.getStr()[17] >= '0' && rPropName.getStr()[17] <= '9')) { bOldSortdescriptor = sal_True; sal_uInt16 nIndex = rPropName.getStr()[17]; nIndex -= '0'; OUString aTxt; if ((aValue >>= aTxt) && nIndex < 3) { aKeys[nIndex]->sSortType = aTxt; } else { bRet = sal_False; } } else if (rPropName.matchAsciiL("SortRowOrColumnNo", 17) && rPropName.getLength() == 18 && (rPropName.getStr()[17] >= '0' && rPropName.getStr()[17] <= '9')) { bOldSortdescriptor = sal_True; sal_uInt16 nIndex = rPropName.getStr()[17]; nIndex -= '0'; sal_Int16 nCol = -1; if (aValue.getValueType() == ::getCppuType((const sal_Int16*)0) && nIndex < 3) { aValue >>= nCol; } if (nCol >= 0) { aKeys[nIndex]->nColumnId = nCol; } else { bRet = sal_False; } } else if (0 == rPropName.indexOf(C2U("IsSortNumeric")) && rPropName.getLength() == 14 && (rPropName.getStr()[13] >= '0' && rPropName.getStr()[13] <= '9')) { bOldSortdescriptor = sal_True; sal_uInt16 nIndex = rPropName.getStr()[13]; nIndex = nIndex - '0'; if (aValue.getValueType() == ::getBooleanCppuType() && nIndex < 3) { sal_Bool bTemp = *(sal_Bool*)aValue.getValue(); aKeys[nIndex]->bIsNumeric = bTemp; } else { bRet = sal_False; } } else if (0 == rPropName.indexOf(C2U("IsSortAscending")) && rPropName.getLength() == 16 && (rPropName.getStr()[15] >= '0' && rPropName.getStr()[15] <= '9')) { bOldSortdescriptor = sal_True; sal_uInt16 nIndex = rPropName.getStr()[15]; nIndex -= '0'; if (aValue.getValueType() == ::getBooleanCppuType() && nIndex < 3) { sal_Bool bTemp = *(sal_Bool*)aValue.getValue(); aKeys[nIndex]->eSortOrder = (bTemp) ? SRT_ASCENDING : SRT_DESCENDING; } else { bRet = sal_False; } } // new sortdescriptor else if (rPropName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("IsSortColumns"))) { bNewSortdescriptor = sal_True; if (aValue.getValueType() == ::getBooleanCppuType()) { sal_Bool bTemp = *(sal_Bool*)aValue.getValue(); rSortOpt.eDirection = bTemp ? SRT_COLUMNS : SRT_ROWS; } else { bRet = sal_False; } } else if (rPropName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("SortFields"))) { bNewSortdescriptor = sal_True; uno::Sequence < table::TableSortField > aFields; if (aValue >>= aFields) { sal_Int32 nCount(aFields.getLength()); if (nCount <= 3) { table::TableSortField* pFields = aFields.getArray(); for (sal_Int32 i = 0; i < nCount; ++i) { rSortOpt.bIgnoreCase = !pFields[i].IsCaseSensitive; rSortOpt.nLanguage = SvxLocaleToLanguage( pFields[i].CollatorLocale ); aKeys[i]->sSortType = pFields[i].CollatorAlgorithm; aKeys[i]->nColumnId = static_cast(pFields[i].Field); aKeys[i]->bIsNumeric = (pFields[i].FieldType == table::TableSortFieldType_NUMERIC); aKeys[i]->eSortOrder = (pFields[i].IsAscending) ? SRT_ASCENDING : SRT_DESCENDING; } } else { bRet = sal_False; } } else { bRet = sal_False; } } } if (bNewSortdescriptor && bOldSortdescriptor) { DBG_ERROR("someone tried to set the old deprecated and " "the new sortdescriptor"); bRet = sal_False; } if (pKey1->nColumnId != USHRT_MAX) { rSortOpt.aKeys.C40_INSERT(SwSortKey, pKey1, rSortOpt.aKeys.Count()); } if (pKey2->nColumnId != USHRT_MAX) { rSortOpt.aKeys.C40_INSERT(SwSortKey, pKey2, rSortOpt.aKeys.Count()); } if (pKey3->nColumnId != USHRT_MAX) { rSortOpt.aKeys.C40_INSERT(SwSortKey, pKey3, rSortOpt.aKeys.Count()); } return bRet && rSortOpt.aKeys.Count() > 0; } void SAL_CALL SwXTextCursor::sort(const uno::Sequence< beans::PropertyValue >& rDescriptor) throw (uno::RuntimeException) { SolarMutexGuard aGuard; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); if (rUnoCursor.HasMark()) { SwSortOptions aSortOpt; if (!SwUnoCursorHelper::ConvertSortProperties(rDescriptor, aSortOpt)) { throw uno::RuntimeException(); } UnoActionContext aContext( rUnoCursor.GetDoc() ); SwPosition & rStart = *rUnoCursor.Start(); SwPosition & rEnd = *rUnoCursor.End(); SwNodeIndex aPrevIdx( rStart.nNode, -1 ); const ULONG nOffset = rEnd.nNode.GetIndex() - rStart.nNode.GetIndex(); const xub_StrLen nCntStt = rStart.nContent.GetIndex(); rUnoCursor.GetDoc()->SortText(rUnoCursor, aSortOpt); // Selektion wieder setzen rUnoCursor.DeleteMark(); rUnoCursor.GetPoint()->nNode.Assign( aPrevIdx.GetNode(), +1 ); SwCntntNode *const pCNd = rUnoCursor.GetCntntNode(); xub_StrLen nLen = pCNd->Len(); if (nLen > nCntStt) { nLen = nCntStt; } rUnoCursor.GetPoint()->nContent.Assign(pCNd, nLen ); rUnoCursor.SetMark(); rUnoCursor.GetPoint()->nNode += nOffset; SwCntntNode *const pCNd2 = rUnoCursor.GetCntntNode(); rUnoCursor.GetPoint()->nContent.Assign( pCNd2, pCNd2->Len() ); } } uno::Reference< container::XEnumeration > SAL_CALL SwXTextCursor::createContentEnumeration(const OUString& rServiceName) throw (uno::RuntimeException) { SolarMutexGuard g; if (!rServiceName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.TextContent"))) { throw uno::RuntimeException(); } SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); uno::Reference< container::XEnumeration > xRet = new SwXParaFrameEnumeration(rUnoCursor, PARAFRAME_PORTION_TEXTRANGE); return xRet; } uno::Reference< container::XEnumeration > SAL_CALL SwXTextCursor::createEnumeration() throw (uno::RuntimeException) { SolarMutexGuard g; SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() ); const uno::Reference xTunnel( m_pImpl->m_xParentText, uno::UNO_QUERY); SwXText* pParentText = 0; if (xTunnel.is()) { pParentText = ::sw::UnoTunnelGetImplementation(xTunnel); } DBG_ASSERT(pParentText, "parent is not a SwXText"); if (!pParentText) { throw uno::RuntimeException(); } ::std::auto_ptr pNewCrsr( rUnoCursor.GetDoc()->CreateUnoCrsr(*rUnoCursor.GetPoint()) ); if (rUnoCursor.HasMark()) { pNewCrsr->SetMark(); *pNewCrsr->GetMark() = *rUnoCursor.GetMark(); } const CursorType eSetType = (CURSOR_TBLTEXT == m_pImpl->m_eType) ? CURSOR_SELECTION_IN_TABLE : CURSOR_SELECTION; SwTableNode const*const pStartNode( (CURSOR_TBLTEXT == m_pImpl->m_eType) ? rUnoCursor.GetPoint()->nNode.GetNode().FindTableNode() : 0); SwTable const*const pTable( (pStartNode) ? & pStartNode->GetTable() : 0 ); const uno::Reference< container::XEnumeration > xRet = new SwXParagraphEnumeration( pParentText, pNewCrsr, eSetType, pStartNode, pTable); return xRet; } uno::Type SAL_CALL SwXTextCursor::getElementType() throw (uno::RuntimeException) { return text::XTextRange::static_type(); } sal_Bool SAL_CALL SwXTextCursor::hasElements() throw (uno::RuntimeException) { return sal_True; } uno::Sequence< OUString > SAL_CALL SwXTextCursor::getAvailableServiceNames() throw (uno::RuntimeException) { uno::Sequence< OUString > aRet(1); OUString* pArray = aRet.getArray(); pArray[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextContent")); return aRet; } IMPLEMENT_FORWARD_REFCOUNT( SwXTextCursor,SwXTextCursor_Base ) uno::Any SAL_CALL SwXTextCursor::queryInterface(const uno::Type& rType) throw (uno::RuntimeException) { return (rType == lang::XUnoTunnel::static_type()) ? OTextCursorHelper::queryInterface(rType) : SwXTextCursor_Base::queryInterface(rType); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */