xref: /AOO41X/main/sw/source/core/doc/docdde.cxx (revision 12ad4c42153346fda96f0ac6386beaeb2adda508)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 
28 
29 #include <stdlib.h>
30 
31 #ifndef _APP_HXX
32 #include <vcl/svapp.hxx>
33 #endif
34 #include <tools/urlobj.hxx>
35 
36 #define _SVSTDARR_STRINGS
37 #include <svl/svstdarr.hxx>
38 #include <sfx2/linkmgr.hxx>         // LinkManager
39 #include <unotools/charclass.hxx>
40 #include <fmtcntnt.hxx>
41 #include <doc.hxx>
42 #include <swserv.hxx>           // fuer Server-Funktionalitaet
43 #include <IMark.hxx>
44 #include <bookmrk.hxx>
45 #include <section.hxx>          // fuer SwSectionFmt
46 #include <swtable.hxx>          // fuer SwTable
47 #include <node.hxx>
48 #include <ndtxt.hxx>
49 #include <pam.hxx>
50 #include <docary.hxx>
51 #include <MarkManager.hxx>
52 
53 using namespace ::com::sun::star;
54 
55 namespace
56 {
57 
lcl_FindDdeBookmark(const IDocumentMarkAccess & rMarkAccess,const String & rName,const bool bCaseSensitive)58     static ::sw::mark::DdeBookmark* lcl_FindDdeBookmark(
59         const IDocumentMarkAccess& rMarkAccess,
60         const String& rName,
61         const bool bCaseSensitive )
62     {
63         //Iterating over all bookmarks, checking DdeBookmarks
64         const ::rtl::OUString sNameLc = bCaseSensitive ? rName : GetAppCharClass().lower(rName);
65         for(IDocumentMarkAccess::const_iterator_t ppMark = rMarkAccess.getAllMarksBegin();
66             ppMark != rMarkAccess.getAllMarksEnd();
67             ppMark++)
68         {
69             if ( IDocumentMarkAccess::GetType( *(ppMark->get()) ) == IDocumentMarkAccess::DDE_BOOKMARK)
70             {
71                 ::sw::mark::DdeBookmark* const pBkmk = dynamic_cast< ::sw::mark::DdeBookmark*>(ppMark->get());
72                 if (
73                     (bCaseSensitive && (pBkmk->GetName() == sNameLc)) ||
74                     (!bCaseSensitive && GetAppCharClass().lower(pBkmk->GetName()) == String(sNameLc))
75                    )
76                 {
77                     return pBkmk;
78                 }
79             }
80         }
81         return NULL;
82     }
83 }
84 
85 struct _FindItem
86 {
87     const String m_Item;
88     SwTableNode* pTblNd;
89     SwSectionNode* pSectNd;
90 
_FindItem_FindItem91     _FindItem(const String& rS)
92         : m_Item(rS), pTblNd(0), pSectNd(0)
93     {}
94 };
95 
lcl_FindSection(const SwSectionFmtPtr & rpSectFmt,void * pArgs,bool bCaseSensitive)96 sal_Bool lcl_FindSection( const SwSectionFmtPtr& rpSectFmt, void* pArgs, bool bCaseSensitive )
97 {
98     _FindItem * const pItem( static_cast<_FindItem*>(pArgs) );
99     SwSection* pSect = rpSectFmt->GetSection();
100     if( pSect )
101     {
102         String sNm( (bCaseSensitive)
103                 ? pSect->GetSectionName()
104                 : GetAppCharClass().lower( pSect->GetSectionName() ));
105         String sCompare( (bCaseSensitive)
106                 ? pItem->m_Item
107                 : GetAppCharClass().lower( pItem->m_Item ) );
108         if( sNm == sCompare )
109         {
110             // gefunden, als erfrage die Daten
111             const SwNodeIndex* pIdx;
112             if( 0 != (pIdx = rpSectFmt->GetCntnt().GetCntntIdx() ) &&
113                 &rpSectFmt->GetDoc()->GetNodes() == &pIdx->GetNodes() )
114             {
115                 // eine Tabelle im normalen NodesArr
116                 pItem->pSectNd = pIdx->GetNode().GetSectionNode();
117                 return sal_False;
118             }
119 //nein!!            // sollte der Namen schon passen, der Rest aber nicht, dann haben wir
120             // sie nicht. Die Namen sind immer eindeutig.
121         }
122     }
123     return sal_True;        // dann weiter
124 }
lcl_FindSectionCaseSensitive(const SwSectionFmtPtr & rpSectFmt,void * pArgs)125 sal_Bool lcl_FindSectionCaseSensitive( const SwSectionFmtPtr& rpSectFmt, void* pArgs )
126 {
127     return lcl_FindSection( rpSectFmt, pArgs, true );
128 }
lcl_FindSectionCaseInsensitive(const SwSectionFmtPtr & rpSectFmt,void * pArgs)129 sal_Bool lcl_FindSectionCaseInsensitive( const SwSectionFmtPtr& rpSectFmt, void* pArgs )
130 {
131     return lcl_FindSection( rpSectFmt, pArgs, false );
132 }
133 
134 
135 
lcl_FindTable(const SwFrmFmtPtr & rpTableFmt,void * pArgs)136 sal_Bool lcl_FindTable( const SwFrmFmtPtr& rpTableFmt, void* pArgs )
137 {
138     _FindItem * const pItem( static_cast<_FindItem*>(pArgs) );
139     String sNm( GetAppCharClass().lower( rpTableFmt->GetName() ));
140     if (sNm.Equals( pItem->m_Item ))
141     {
142         SwTable* pTmpTbl;
143         SwTableBox* pFBox;
144         if( 0 != ( pTmpTbl = SwTable::FindTable( rpTableFmt ) ) &&
145             0 != ( pFBox = pTmpTbl->GetTabSortBoxes()[0] ) &&
146             pFBox->GetSttNd() &&
147             &rpTableFmt->GetDoc()->GetNodes() == &pFBox->GetSttNd()->GetNodes() )
148         {
149             // eine Tabelle im normalen NodesArr
150             pItem->pTblNd = (SwTableNode*)
151                                         pFBox->GetSttNd()->FindTableNode();
152             return sal_False;
153         }
154 //nein!     // sollte der Namen schon passen, der Rest aber nicht, dann haben wir
155         // sie nicht. Die Namen sind immer eindeutig.
156     }
157     return sal_True;        // dann weiter
158 }
159 
160 
161 
GetData(const String & rItem,const String & rMimeType,uno::Any & rValue) const162 bool SwDoc::GetData( const String& rItem, const String& rMimeType,
163                      uno::Any & rValue ) const
164 {
165     //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive
166     bool bCaseSensitive = true;
167     while( true )
168     {
169         ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive);
170         if(pBkmk)
171             return SwServerObject(*pBkmk).GetData(rValue, rMimeType);
172 
173         // haben wir ueberhaupt das Item vorraetig?
174         String sItem( bCaseSensitive ? rItem : GetAppCharClass().lower(rItem));
175         _FindItem aPara( sItem );
176         ((SwSectionFmts&)*pSectionFmtTbl).ForEach( 0, pSectionFmtTbl->Count(),
177                                                     bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara );
178         if( aPara.pSectNd )
179         {
180             // gefunden, als erfrage die Daten
181             return SwServerObject( *aPara.pSectNd ).GetData( rValue, rMimeType );
182         }
183         if( !bCaseSensitive )
184             break;
185         bCaseSensitive = false;
186     }
187 
188     _FindItem aPara( GetAppCharClass().lower( rItem ));
189     ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach( 0, pTblFrmFmtTbl->Count(),
190                                             lcl_FindTable, &aPara );
191     if( aPara.pTblNd )
192     {
193         return SwServerObject( *aPara.pTblNd ).GetData( rValue, rMimeType );
194     }
195 
196     return sal_False;
197 }
198 
199 
200 
SetData(const String & rItem,const String & rMimeType,const uno::Any & rValue)201 bool SwDoc::SetData( const String& rItem, const String& rMimeType,
202                      const uno::Any & rValue )
203 {
204     //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive
205     bool bCaseSensitive = true;
206     while( true )
207     {
208         ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive);
209         if(pBkmk)
210             return SwServerObject(*pBkmk).SetData(rMimeType, rValue);
211 
212         // haben wir ueberhaupt das Item vorraetig?
213         String sItem( bCaseSensitive ? rItem : GetAppCharClass().lower(rItem));
214         _FindItem aPara( sItem );
215         pSectionFmtTbl->ForEach( 0, pSectionFmtTbl->Count(), bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara );
216         if( aPara.pSectNd )
217         {
218             // gefunden, als erfrage die Daten
219             return SwServerObject( *aPara.pSectNd ).SetData( rMimeType, rValue );
220         }
221         if( !bCaseSensitive )
222             break;
223         bCaseSensitive = false;
224     }
225 
226     String sItem(GetAppCharClass().lower(rItem));
227     _FindItem aPara( sItem );
228     pTblFrmFmtTbl->ForEach( 0, pTblFrmFmtTbl->Count(), lcl_FindTable, &aPara );
229     if( aPara.pTblNd )
230     {
231         return SwServerObject( *aPara.pTblNd ).SetData( rMimeType, rValue );
232     }
233 
234     return sal_False;
235 }
236 
237 
238 
CreateLinkSource(const String & rItem)239 ::sfx2::SvLinkSource* SwDoc::CreateLinkSource(const String& rItem)
240 {
241     SwServerObject* pObj = NULL;
242 
243     //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive
244     bool bCaseSensitive = true;
245     while( true )
246     {
247         // bookmarks
248         ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive);
249         if(pBkmk && pBkmk->IsExpanded()
250             && (0 == (pObj = pBkmk->GetRefObject())))
251         {
252             // mark found, but no link yet -> create hotlink
253             pObj = new SwServerObject(*pBkmk);
254             pBkmk->SetRefObject(pObj);
255             GetLinkManager().InsertServer(pObj);
256         }
257         if(pObj)
258             return pObj;
259 
260         _FindItem aPara(bCaseSensitive ? rItem : GetAppCharClass().lower(rItem));
261         // sections
262         ((SwSectionFmts&)*pSectionFmtTbl).ForEach(0, pSectionFmtTbl->Count(), bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara);
263         if(aPara.pSectNd
264             && (0 == (pObj = aPara.pSectNd->GetSection().GetObject())))
265         {
266             // section found, but no link yet -> create hotlink
267             pObj = new SwServerObject( *aPara.pSectNd );
268             aPara.pSectNd->GetSection().SetRefObject( pObj );
269             GetLinkManager().InsertServer(pObj);
270         }
271         if(pObj)
272             return pObj;
273         if( !bCaseSensitive )
274             break;
275         bCaseSensitive = false;
276     }
277 
278     _FindItem aPara( GetAppCharClass().lower(rItem) );
279     // tables
280     ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach(0, pTblFrmFmtTbl->Count(), lcl_FindTable, &aPara);
281     if(aPara.pTblNd
282         && (0 == (pObj = aPara.pTblNd->GetTable().GetObject())))
283     {
284         // table found, but no link yet -> create hotlink
285         pObj = new SwServerObject(*aPara.pTblNd);
286         aPara.pTblNd->GetTable().SetRefObject(pObj);
287         GetLinkManager().InsertServer(pObj);
288     }
289     return pObj;
290 }
291 
SelectServerObj(const String & rStr,SwPaM * & rpPam,SwNodeRange * & rpRange) const292 sal_Bool SwDoc::SelectServerObj( const String& rStr, SwPaM*& rpPam,
293                             SwNodeRange*& rpRange ) const
294 {
295     // haben wir ueberhaupt das Item vorraetig?
296     rpPam = 0;
297     rpRange = 0;
298 
299     String sItem( INetURLObject::decode( rStr, INET_HEX_ESCAPE,
300                                         INetURLObject::DECODE_WITH_CHARSET,
301                                         RTL_TEXTENCODING_UTF8 ));
302 
303     xub_StrLen nPos = sItem.Search( cMarkSeperator );
304 
305     const CharClass& rCC = GetAppCharClass();
306 
307     // Erweiterung fuer die Bereiche, nicht nur Bookmarks/Bereiche linken,
308     // sondern auch Rahmen(Text!), Tabellen, Gliederungen:
309     if( STRING_NOTFOUND != nPos )
310     {
311         sal_Bool bWeiter = sal_False;
312         String sName( sItem.Copy( 0, nPos ) );
313         String sCmp( sItem.Copy( nPos + 1 ));
314         rCC.toLower( sItem );
315 
316         _FindItem aPara( sName );
317 
318         if( sCmp.EqualsAscii( pMarkToTable ) )
319         {
320             rCC.toLower( sName );
321             ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach( 0, pTblFrmFmtTbl->Count(),
322                                                     lcl_FindTable, &aPara );
323             if( aPara.pTblNd )
324             {
325                 rpRange = new SwNodeRange( *aPara.pTblNd, 0,
326                                 *aPara.pTblNd->EndOfSectionNode(), 1 );
327                 return sal_True;
328             }
329         }
330         else if( sCmp.EqualsAscii( pMarkToFrame ) )
331         {
332             SwNodeIndex* pIdx;
333             SwNode* pNd;
334             const SwFlyFrmFmt* pFlyFmt = FindFlyByName( sName );
335             if( pFlyFmt &&
336                 0 != ( pIdx = (SwNodeIndex*)pFlyFmt->GetCntnt().GetCntntIdx() ) &&
337                 !( pNd = &pIdx->GetNode())->IsNoTxtNode() )
338             {
339                 rpRange = new SwNodeRange( *pNd, 1, *pNd->EndOfSectionNode() );
340                 return sal_True;
341             }
342         }
343         else if( sCmp.EqualsAscii( pMarkToRegion ) )
344         {
345             sItem = sName;              // wird unten behandelt !
346             bWeiter = sal_True;
347         }
348         else if( sCmp.EqualsAscii( pMarkToOutline ) )
349         {
350             SwPosition aPos( SwNodeIndex( (SwNodes&)GetNodes() ));
351             if( GotoOutline( aPos, sName ))
352             {
353                 SwNode* pNd = &aPos.nNode.GetNode();
354                 //sal_uInt8 nLvl = pNd->GetTxtNode()->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
355                 const int nLvl = pNd->GetTxtNode()->GetAttrOutlineLevel()-1;//<-end,zhaojianwei
356 
357                 const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
358                 sal_uInt16 nTmpPos;
359                 rOutlNds.Seek_Entry( pNd, &nTmpPos );
360                 rpRange = new SwNodeRange( aPos.nNode, 0, aPos.nNode );
361 
362                 // dann suche jetzt noch das Ende vom Bereich
363                 for( ++nTmpPos;
364                         nTmpPos < rOutlNds.Count() &&
365                         nLvl < rOutlNds[ nTmpPos ]->GetTxtNode()->
366                                 //GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
367                                 GetAttrOutlineLevel()-1;//<-end,zhaojianwei
368                     ++nTmpPos )
369                     ;       // es gibt keinen Block
370 
371                 if( nTmpPos < rOutlNds.Count() )
372                     rpRange->aEnd = *rOutlNds[ nTmpPos ];
373                 else
374                     rpRange->aEnd = GetNodes().GetEndOfContent();
375                 return sal_True;
376             }
377         }
378 
379         if( !bWeiter )
380             return sal_False;
381     }
382 
383     //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive
384     bool bCaseSensitive = true;
385     while( true )
386     {
387         ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, sItem, bCaseSensitive);
388         if(pBkmk)
389         {
390             if(pBkmk->IsExpanded())
391                 rpPam = new SwPaM(
392                     pBkmk->GetMarkPos(),
393                     pBkmk->GetOtherMarkPos());
394             return static_cast<bool>(rpPam);
395         }
396 
397         //
398         _FindItem aPara( bCaseSensitive ? sItem : rCC.lower( sItem ) );
399 
400         if( pSectionFmtTbl->Count() )
401         {
402             ((SwSectionFmts&)*pSectionFmtTbl).ForEach( 0, pSectionFmtTbl->Count(),
403                                                     bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara );
404             if( aPara.pSectNd )
405             {
406                 rpRange = new SwNodeRange( *aPara.pSectNd, 1,
407                                         *aPara.pSectNd->EndOfSectionNode() );
408                 return sal_True;
409 
410             }
411         }
412         if( !bCaseSensitive )
413             break;
414         bCaseSensitive = false;
415     }
416     return sal_False;
417 }
418 
419