| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sw.hxx" |
| |
| |
| |
| #include <stdlib.h> |
| |
| #ifndef _APP_HXX |
| #include <vcl/svapp.hxx> |
| #endif |
| #include <tools/urlobj.hxx> |
| |
| #define _SVSTDARR_STRINGS |
| #include <svl/svstdarr.hxx> |
| #include <sfx2/linkmgr.hxx> // LinkManager |
| #include <unotools/charclass.hxx> |
| #include <fmtcntnt.hxx> |
| #include <doc.hxx> |
| #include <swserv.hxx> // fuer Server-Funktionalitaet |
| #include <IMark.hxx> |
| #include <bookmrk.hxx> |
| #include <section.hxx> // fuer SwSectionFmt |
| #include <swtable.hxx> // fuer SwTable |
| #include <node.hxx> |
| #include <ndtxt.hxx> |
| #include <pam.hxx> |
| #include <docary.hxx> |
| #include <MarkManager.hxx> |
| |
| using namespace ::com::sun::star; |
| |
| namespace |
| { |
| |
| static ::sw::mark::DdeBookmark* lcl_FindDdeBookmark( |
| const IDocumentMarkAccess& rMarkAccess, |
| const String& rName, |
| const bool bCaseSensitive ) |
| { |
| //Iterating over all bookmarks, checking DdeBookmarks |
| const ::rtl::OUString sNameLc = bCaseSensitive ? rName : GetAppCharClass().lower(rName); |
| for(IDocumentMarkAccess::const_iterator_t ppMark = rMarkAccess.getAllMarksBegin(); |
| ppMark != rMarkAccess.getAllMarksEnd(); |
| ppMark++) |
| { |
| if ( IDocumentMarkAccess::GetType( *(ppMark->get()) ) == IDocumentMarkAccess::DDE_BOOKMARK) |
| { |
| ::sw::mark::DdeBookmark* const pBkmk = dynamic_cast< ::sw::mark::DdeBookmark*>(ppMark->get()); |
| if ( |
| (bCaseSensitive && (pBkmk->GetName() == sNameLc)) || |
| (!bCaseSensitive && GetAppCharClass().lower(pBkmk->GetName()) == String(sNameLc)) |
| ) |
| { |
| return pBkmk; |
| } |
| } |
| } |
| return NULL; |
| } |
| } |
| |
| struct _FindItem |
| { |
| const String m_Item; |
| SwTableNode* pTblNd; |
| SwSectionNode* pSectNd; |
| |
| _FindItem(const String& rS) |
| : m_Item(rS), pTblNd(0), pSectNd(0) |
| {} |
| }; |
| |
| sal_Bool lcl_FindSection( const SwSectionFmtPtr& rpSectFmt, void* pArgs, bool bCaseSensitive ) |
| { |
| _FindItem * const pItem( static_cast<_FindItem*>(pArgs) ); |
| SwSection* pSect = rpSectFmt->GetSection(); |
| if( pSect ) |
| { |
| String sNm( (bCaseSensitive) |
| ? pSect->GetSectionName() |
| : GetAppCharClass().lower( pSect->GetSectionName() )); |
| String sCompare( (bCaseSensitive) |
| ? pItem->m_Item |
| : GetAppCharClass().lower( pItem->m_Item ) ); |
| if( sNm == sCompare ) |
| { |
| // gefunden, als erfrage die Daten |
| const SwNodeIndex* pIdx; |
| if( 0 != (pIdx = rpSectFmt->GetCntnt().GetCntntIdx() ) && |
| &rpSectFmt->GetDoc()->GetNodes() == &pIdx->GetNodes() ) |
| { |
| // eine Tabelle im normalen NodesArr |
| pItem->pSectNd = pIdx->GetNode().GetSectionNode(); |
| return sal_False; |
| } |
| //nein!! // sollte der Namen schon passen, der Rest aber nicht, dann haben wir |
| // sie nicht. Die Namen sind immer eindeutig. |
| } |
| } |
| return sal_True; // dann weiter |
| } |
| sal_Bool lcl_FindSectionCaseSensitive( const SwSectionFmtPtr& rpSectFmt, void* pArgs ) |
| { |
| return lcl_FindSection( rpSectFmt, pArgs, true ); |
| } |
| sal_Bool lcl_FindSectionCaseInsensitive( const SwSectionFmtPtr& rpSectFmt, void* pArgs ) |
| { |
| return lcl_FindSection( rpSectFmt, pArgs, false ); |
| } |
| |
| |
| |
| sal_Bool lcl_FindTable( const SwFrmFmtPtr& rpTableFmt, void* pArgs ) |
| { |
| _FindItem * const pItem( static_cast<_FindItem*>(pArgs) ); |
| String sNm( GetAppCharClass().lower( rpTableFmt->GetName() )); |
| if (sNm.Equals( pItem->m_Item )) |
| { |
| SwTable* pTmpTbl; |
| SwTableBox* pFBox; |
| if( 0 != ( pTmpTbl = SwTable::FindTable( rpTableFmt ) ) && |
| 0 != ( pFBox = pTmpTbl->GetTabSortBoxes()[0] ) && |
| pFBox->GetSttNd() && |
| &rpTableFmt->GetDoc()->GetNodes() == &pFBox->GetSttNd()->GetNodes() ) |
| { |
| // eine Tabelle im normalen NodesArr |
| pItem->pTblNd = (SwTableNode*) |
| pFBox->GetSttNd()->FindTableNode(); |
| return sal_False; |
| } |
| //nein! // sollte der Namen schon passen, der Rest aber nicht, dann haben wir |
| // sie nicht. Die Namen sind immer eindeutig. |
| } |
| return sal_True; // dann weiter |
| } |
| |
| |
| |
| bool SwDoc::GetData( const String& rItem, const String& rMimeType, |
| uno::Any & rValue ) const |
| { |
| //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive |
| bool bCaseSensitive = true; |
| while( true ) |
| { |
| ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive); |
| if(pBkmk) |
| return SwServerObject(*pBkmk).GetData(rValue, rMimeType); |
| |
| // haben wir ueberhaupt das Item vorraetig? |
| String sItem( bCaseSensitive ? rItem : GetAppCharClass().lower(rItem)); |
| _FindItem aPara( sItem ); |
| ((SwSectionFmts&)*pSectionFmtTbl).ForEach( 0, pSectionFmtTbl->Count(), |
| bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara ); |
| if( aPara.pSectNd ) |
| { |
| // gefunden, als erfrage die Daten |
| return SwServerObject( *aPara.pSectNd ).GetData( rValue, rMimeType ); |
| } |
| if( !bCaseSensitive ) |
| break; |
| bCaseSensitive = false; |
| } |
| |
| _FindItem aPara( GetAppCharClass().lower( rItem )); |
| ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach( 0, pTblFrmFmtTbl->Count(), |
| lcl_FindTable, &aPara ); |
| if( aPara.pTblNd ) |
| { |
| return SwServerObject( *aPara.pTblNd ).GetData( rValue, rMimeType ); |
| } |
| |
| return sal_False; |
| } |
| |
| |
| |
| bool SwDoc::SetData( const String& rItem, const String& rMimeType, |
| const uno::Any & rValue ) |
| { |
| //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive |
| bool bCaseSensitive = true; |
| while( true ) |
| { |
| ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive); |
| if(pBkmk) |
| return SwServerObject(*pBkmk).SetData(rMimeType, rValue); |
| |
| // haben wir ueberhaupt das Item vorraetig? |
| String sItem( bCaseSensitive ? rItem : GetAppCharClass().lower(rItem)); |
| _FindItem aPara( sItem ); |
| pSectionFmtTbl->ForEach( 0, pSectionFmtTbl->Count(), bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara ); |
| if( aPara.pSectNd ) |
| { |
| // gefunden, als erfrage die Daten |
| return SwServerObject( *aPara.pSectNd ).SetData( rMimeType, rValue ); |
| } |
| if( !bCaseSensitive ) |
| break; |
| bCaseSensitive = false; |
| } |
| |
| String sItem(GetAppCharClass().lower(rItem)); |
| _FindItem aPara( sItem ); |
| pTblFrmFmtTbl->ForEach( 0, pTblFrmFmtTbl->Count(), lcl_FindTable, &aPara ); |
| if( aPara.pTblNd ) |
| { |
| return SwServerObject( *aPara.pTblNd ).SetData( rMimeType, rValue ); |
| } |
| |
| return sal_False; |
| } |
| |
| |
| |
| ::sfx2::SvLinkSource* SwDoc::CreateLinkSource(const String& rItem) |
| { |
| SwServerObject* pObj = NULL; |
| |
| //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive |
| bool bCaseSensitive = true; |
| while( true ) |
| { |
| // bookmarks |
| ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive); |
| if(pBkmk && pBkmk->IsExpanded() |
| && (0 == (pObj = pBkmk->GetRefObject()))) |
| { |
| // mark found, but no link yet -> create hotlink |
| pObj = new SwServerObject(*pBkmk); |
| pBkmk->SetRefObject(pObj); |
| GetLinkManager().InsertServer(pObj); |
| } |
| if(pObj) |
| return pObj; |
| |
| _FindItem aPara(bCaseSensitive ? rItem : GetAppCharClass().lower(rItem)); |
| // sections |
| ((SwSectionFmts&)*pSectionFmtTbl).ForEach(0, pSectionFmtTbl->Count(), bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara); |
| if(aPara.pSectNd |
| && (0 == (pObj = aPara.pSectNd->GetSection().GetObject()))) |
| { |
| // section found, but no link yet -> create hotlink |
| pObj = new SwServerObject( *aPara.pSectNd ); |
| aPara.pSectNd->GetSection().SetRefObject( pObj ); |
| GetLinkManager().InsertServer(pObj); |
| } |
| if(pObj) |
| return pObj; |
| if( !bCaseSensitive ) |
| break; |
| bCaseSensitive = false; |
| } |
| |
| _FindItem aPara( GetAppCharClass().lower(rItem) ); |
| // tables |
| ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach(0, pTblFrmFmtTbl->Count(), lcl_FindTable, &aPara); |
| if(aPara.pTblNd |
| && (0 == (pObj = aPara.pTblNd->GetTable().GetObject()))) |
| { |
| // table found, but no link yet -> create hotlink |
| pObj = new SwServerObject(*aPara.pTblNd); |
| aPara.pTblNd->GetTable().SetRefObject(pObj); |
| GetLinkManager().InsertServer(pObj); |
| } |
| return pObj; |
| } |
| |
| sal_Bool SwDoc::SelectServerObj( const String& rStr, SwPaM*& rpPam, |
| SwNodeRange*& rpRange ) const |
| { |
| // haben wir ueberhaupt das Item vorraetig? |
| rpPam = 0; |
| rpRange = 0; |
| |
| String sItem( INetURLObject::decode( rStr, INET_HEX_ESCAPE, |
| INetURLObject::DECODE_WITH_CHARSET, |
| RTL_TEXTENCODING_UTF8 )); |
| |
| xub_StrLen nPos = sItem.Search( cMarkSeperator ); |
| |
| const CharClass& rCC = GetAppCharClass(); |
| |
| // Erweiterung fuer die Bereiche, nicht nur Bookmarks/Bereiche linken, |
| // sondern auch Rahmen(Text!), Tabellen, Gliederungen: |
| if( STRING_NOTFOUND != nPos ) |
| { |
| sal_Bool bWeiter = sal_False; |
| String sName( sItem.Copy( 0, nPos ) ); |
| String sCmp( sItem.Copy( nPos + 1 )); |
| rCC.toLower( sItem ); |
| |
| _FindItem aPara( sName ); |
| |
| if( sCmp.EqualsAscii( pMarkToTable ) ) |
| { |
| rCC.toLower( sName ); |
| ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach( 0, pTblFrmFmtTbl->Count(), |
| lcl_FindTable, &aPara ); |
| if( aPara.pTblNd ) |
| { |
| rpRange = new SwNodeRange( *aPara.pTblNd, 0, |
| *aPara.pTblNd->EndOfSectionNode(), 1 ); |
| return sal_True; |
| } |
| } |
| else if( sCmp.EqualsAscii( pMarkToFrame ) ) |
| { |
| SwNodeIndex* pIdx; |
| SwNode* pNd; |
| const SwFlyFrmFmt* pFlyFmt = FindFlyByName( sName ); |
| if( pFlyFmt && |
| 0 != ( pIdx = (SwNodeIndex*)pFlyFmt->GetCntnt().GetCntntIdx() ) && |
| !( pNd = &pIdx->GetNode())->IsNoTxtNode() ) |
| { |
| rpRange = new SwNodeRange( *pNd, 1, *pNd->EndOfSectionNode() ); |
| return sal_True; |
| } |
| } |
| else if( sCmp.EqualsAscii( pMarkToRegion ) ) |
| { |
| sItem = sName; // wird unten behandelt ! |
| bWeiter = sal_True; |
| } |
| else if( sCmp.EqualsAscii( pMarkToOutline ) ) |
| { |
| SwPosition aPos( SwNodeIndex( (SwNodes&)GetNodes() )); |
| if( GotoOutline( aPos, sName )) |
| { |
| SwNode* pNd = &aPos.nNode.GetNode(); |
| //sal_uInt8 nLvl = pNd->GetTxtNode()->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei |
| const int nLvl = pNd->GetTxtNode()->GetAttrOutlineLevel()-1;//<-end,zhaojianwei |
| |
| const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds(); |
| sal_uInt16 nTmpPos; |
| rOutlNds.Seek_Entry( pNd, &nTmpPos ); |
| rpRange = new SwNodeRange( aPos.nNode, 0, aPos.nNode ); |
| |
| // dann suche jetzt noch das Ende vom Bereich |
| for( ++nTmpPos; |
| nTmpPos < rOutlNds.Count() && |
| nLvl < rOutlNds[ nTmpPos ]->GetTxtNode()-> |
| //GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei |
| GetAttrOutlineLevel()-1;//<-end,zhaojianwei |
| ++nTmpPos ) |
| ; // es gibt keinen Block |
| |
| if( nTmpPos < rOutlNds.Count() ) |
| rpRange->aEnd = *rOutlNds[ nTmpPos ]; |
| else |
| rpRange->aEnd = GetNodes().GetEndOfContent(); |
| return sal_True; |
| } |
| } |
| |
| if( !bWeiter ) |
| return sal_False; |
| } |
| |
| //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive |
| bool bCaseSensitive = true; |
| while( true ) |
| { |
| ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, sItem, bCaseSensitive); |
| if(pBkmk) |
| { |
| if(pBkmk->IsExpanded()) |
| rpPam = new SwPaM( |
| pBkmk->GetMarkPos(), |
| pBkmk->GetOtherMarkPos()); |
| return static_cast<bool>(rpPam); |
| } |
| |
| // |
| _FindItem aPara( bCaseSensitive ? sItem : rCC.lower( sItem ) ); |
| |
| if( pSectionFmtTbl->Count() ) |
| { |
| ((SwSectionFmts&)*pSectionFmtTbl).ForEach( 0, pSectionFmtTbl->Count(), |
| bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara ); |
| if( aPara.pSectNd ) |
| { |
| rpRange = new SwNodeRange( *aPara.pSectNd, 1, |
| *aPara.pSectNd->EndOfSectionNode() ); |
| return sal_True; |
| |
| } |
| } |
| if( !bCaseSensitive ) |
| break; |
| bCaseSensitive = false; |
| } |
| return sal_False; |
| } |
| |