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 #include <unotextmarkup.hxx>
27 
28 #include <vos/mutex.hxx>
29 #include <vcl/svapp.hxx>
30 #include <SwSmartTagMgr.hxx>
31 #include <com/sun/star/text/TextMarkupType.hpp>
32 #include <com/sun/star/text/TextMarkupDescriptor.hpp>
33 #include <com/sun/star/container/XStringKeyMap.hpp>
34 #include <ndtxt.hxx>
35 #include <SwGrammarMarkUp.hxx>
36 
37 #include <IGrammarContact.hxx>
38 
39 #include <com/sun/star/lang/XUnoTunnel.hpp>
40 #include <com/sun/star/text/XTextRange.hpp>
41 
42 #include <pam.hxx>
43 
44 #include <unotextrange.hxx>
45 #include <unotextcursor.hxx>
46 
47 
48 using namespace ::com::sun::star;
49 
50 /*
51  * SwXTextMarkup
52  */
SwXTextMarkup(SwTxtNode & rTxtNode,const ModelToViewHelper::ConversionMap * pMap)53 SwXTextMarkup::SwXTextMarkup( SwTxtNode& rTxtNode, const ModelToViewHelper::ConversionMap* pMap )
54     : mpTxtNode( &rTxtNode ), mpConversionMap( pMap )
55 {
56     // FME 2007-07-16 #i79641# SwXTextMarkup is allowed to be removed ...
57     SetIsAllowedToBeRemovedInModifyCall(true);
58     mpTxtNode->Add(this);
59 }
60 
~SwXTextMarkup()61 SwXTextMarkup::~SwXTextMarkup()
62 {
63      delete mpConversionMap;
64 }
65 
getMarkupInfoContainer()66 uno::Reference< container::XStringKeyMap > SAL_CALL SwXTextMarkup::getMarkupInfoContainer() throw (uno::RuntimeException)
67 {
68     vos::OGuard aGuard(Application::GetSolarMutex());
69 
70     uno::Reference< container::XStringKeyMap > xProp = new SwXStringKeyMap;
71     return xProp;
72 }
73 
commitTextRangeMarkup(::sal_Int32 nType,const::rtl::OUString & aIdentifier,const uno::Reference<text::XTextRange> & xRange,const uno::Reference<container::XStringKeyMap> & xMarkupInfoContainer)74 void SAL_CALL SwXTextMarkup::commitTextRangeMarkup(::sal_Int32 nType, const ::rtl::OUString & aIdentifier, const uno::Reference< text::XTextRange> & xRange,
75                                                    const uno::Reference< container::XStringKeyMap > & xMarkupInfoContainer) throw (uno::RuntimeException)
76 {
77     vos::OGuard  aGuard(Application::GetSolarMutex());
78 
79     uno::Reference<lang::XUnoTunnel> xRangeTunnel( xRange, uno::UNO_QUERY);
80 
81     if(!xRangeTunnel.is()) return;
82 
83     SwXTextRange* pRange = 0;
84     OTextCursorHelper* pCursor = 0;
85 
86     if(xRangeTunnel.is())
87     {
88     	pRange  = reinterpret_cast<SwXTextRange*>( sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething(SwXTextRange::getUnoTunnelId())));
89     	pCursor = reinterpret_cast<OTextCursorHelper*>( sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething(OTextCursorHelper::getUnoTunnelId())));
90     }
91 
92     if (pRange)
93     {
94         SwDoc* pDoc = reinterpret_cast<SwDoc*>(pRange->GetDoc());
95 
96         if (!pDoc) return;
97 
98         SwUnoInternalPaM aPam(*pDoc);
99 
100         ::sw::XTextRangeToSwPaM(aPam, xRange);
101 
102         SwPosition* startPos = aPam.Start();
103         SwPosition* endPos   = aPam.End();
104 
105         commitStringMarkup (nType, aIdentifier, startPos->nContent.GetIndex(), endPos->nContent.GetIndex() - startPos->nContent.GetIndex(), xMarkupInfoContainer);
106     }
107     else if (pCursor)
108     {
109         SwPaM aPam(*pCursor->GetPaM());
110 
111         SwPosition* startPos = aPam.Start();
112         SwPosition* endPos   = aPam.End();
113 
114         commitStringMarkup (nType, aIdentifier, startPos->nContent.GetIndex(), endPos->nContent.GetIndex() - startPos->nContent.GetIndex(), xMarkupInfoContainer);
115     }
116 }
117 
118 
commitStringMarkup(::sal_Int32 nType,const::rtl::OUString & rIdentifier,::sal_Int32 nStart,::sal_Int32 nLength,const uno::Reference<container::XStringKeyMap> & xMarkupInfoContainer)119 void SAL_CALL SwXTextMarkup::commitStringMarkup(
120     ::sal_Int32 nType,
121     const ::rtl::OUString & rIdentifier,
122     ::sal_Int32 nStart,
123     ::sal_Int32 nLength,
124     const uno::Reference< container::XStringKeyMap > & xMarkupInfoContainer)
125     throw (uno::RuntimeException)
126 {
127     vos::OGuard aGuard(Application::GetSolarMutex());
128 
129     // paragraph already dead or modified?
130     if ( !mpTxtNode || nLength <= 0 )
131         return;
132 
133     if ( nType == text::TextMarkupType::SMARTTAG &&
134         !SwSmartTagMgr::Get().IsSmartTagTypeEnabled( rIdentifier ) )
135         return;
136 
137 	// get appropriate list to use...
138     SwWrongList* pWList = 0;
139     bool bRepaint = false;
140     if ( nType == text::TextMarkupType::SPELLCHECK )
141     {
142         pWList = mpTxtNode->GetWrong();
143         if ( !pWList )
144         {
145             pWList = new SwWrongList( WRONGLIST_SPELL );
146             mpTxtNode->SetWrong( pWList );
147         }
148     }
149     else if ( nType == text::TextMarkupType::PROOFREADING || nType == text::TextMarkupType::SENTENCE )
150     {
151         IGrammarContact *pGrammarContact = getGrammarContact( *mpTxtNode );
152         if( pGrammarContact )
153         {
154             pWList = pGrammarContact->getGrammarCheck( *mpTxtNode, true );
155             ASSERT( pWList, "GrammarContact _has_ to deliver a wrong list" )
156         }
157         else
158         {
159             pWList = mpTxtNode->GetGrammarCheck();
160             if ( !pWList )
161             {
162                 mpTxtNode->SetGrammarCheck( new SwGrammarMarkUp() );
163                 pWList = mpTxtNode->GetGrammarCheck();
164             }
165         }
166         bRepaint = pWList == mpTxtNode->GetGrammarCheck();
167         if( pWList->GetBeginInv() < STRING_LEN )
168             ((SwGrammarMarkUp*)pWList)->ClearGrammarList();
169     }
170     else if ( nType == text::TextMarkupType::SMARTTAG )
171     {
172         pWList = mpTxtNode->GetSmartTags();
173         if ( !pWList )
174         {
175             pWList = new SwWrongList( WRONGLIST_SMARTTAG );
176             mpTxtNode->SetSmartTags( pWList );
177         }
178     }
179 	else
180     {
181         ASSERT( false, "Unknown mark-up type" )
182 		return;
183     }
184 
185 
186     const ModelToViewHelper::ModelPosition aStartPos =
187             ModelToViewHelper::ConvertToModelPosition( mpConversionMap, nStart );
188     const ModelToViewHelper::ModelPosition aEndPos   =
189             ModelToViewHelper::ConvertToModelPosition( mpConversionMap, nStart + nLength - 1);
190 
191     const bool bStartInField = aStartPos.mbIsField;
192     const bool bEndInField   = aEndPos.mbIsField;
193     bool bCommit = false;
194 
195     if ( bStartInField && bEndInField && aStartPos.mnPos == aEndPos.mnPos )
196     {
197         nStart = aStartPos.mnSubPos;
198         const xub_StrLen nFieldPosModel = static_cast< xub_StrLen >(aStartPos.mnPos);
199         const sal_uInt16 nInsertPos = pWList->GetWrongPos( nFieldPosModel );
200 
201         SwWrongList* pSubList = pWList->SubList( nInsertPos );
202         if ( !pSubList )
203         {
204             if( nType == text::TextMarkupType::PROOFREADING || nType == text::TextMarkupType::SENTENCE )
205                 pSubList = new SwGrammarMarkUp();
206             else
207                 pSubList = new SwWrongList( pWList->GetWrongListType() );
208             pWList->InsertSubList( nFieldPosModel, 1, nInsertPos, pSubList );
209         }
210 
211         pWList = pSubList;
212         bCommit = true;
213     }
214     else if ( !bStartInField && !bEndInField )
215     {
216         nStart = aStartPos.mnPos;
217         bCommit = true;
218         nLength = aEndPos.mnPos + 1 - aStartPos.mnPos;
219     }
220     else if( nType == text::TextMarkupType::PROOFREADING || nType == text::TextMarkupType::SENTENCE )
221     {
222         bCommit = true;
223         nStart = aStartPos.mnPos;
224         sal_Int32 nEnd = aEndPos.mnPos;
225         if( bStartInField && nType != text::TextMarkupType::SENTENCE )
226         {
227             const xub_StrLen nFieldPosModel = static_cast< xub_StrLen >(aStartPos.mnPos);
228             const sal_uInt16 nInsertPos = pWList->GetWrongPos( nFieldPosModel );
229             SwWrongList* pSubList = pWList->SubList( nInsertPos );
230             if ( !pSubList )
231             {
232                 pSubList = new SwGrammarMarkUp();
233                 pWList->InsertSubList( nFieldPosModel, 1, nInsertPos, pSubList );
234             }
235             const sal_uInt32 nTmpStart = ModelToViewHelper::ConvertToViewPosition( mpConversionMap, aStartPos.mnPos );
236             const sal_uInt32 nTmpLen = ModelToViewHelper::ConvertToViewPosition( mpConversionMap, aStartPos.mnPos + 1 )
237                                        - nTmpStart - aStartPos.mnSubPos;
238             if( nTmpLen > 0 )
239             {
240                 if( nType == text::TextMarkupType::SENTENCE )
241                 {
242                     ((SwGrammarMarkUp*)pSubList)->setSentence( static_cast< xub_StrLen >(aStartPos.mnSubPos) );
243                     bCommit = false;
244                 }
245                 else
246                     pSubList->Insert( rIdentifier, xMarkupInfoContainer,
247                         static_cast< xub_StrLen >(aStartPos.mnSubPos), static_cast< xub_StrLen >(nTmpLen) );
248             }
249             ++nStart;
250         }
251         if( bEndInField && nType != text::TextMarkupType::SENTENCE )
252         {
253             const xub_StrLen nFieldPosModel = static_cast< xub_StrLen >(aEndPos.mnPos);
254             const sal_uInt16 nInsertPos = pWList->GetWrongPos( nFieldPosModel );
255             SwWrongList* pSubList = pWList->SubList( nInsertPos );
256             if ( !pSubList )
257             {
258                 pSubList = new SwGrammarMarkUp();
259                 pWList->InsertSubList( nFieldPosModel, 1, nInsertPos, pSubList );
260             }
261             const sal_uInt32 nTmpLen = aEndPos.mnSubPos + 1;
262             pSubList->Insert( rIdentifier, xMarkupInfoContainer, 0, static_cast< xub_StrLen >(nTmpLen) );
263         }
264         else
265             ++nEnd;
266         if( nEnd > nStart )
267             nLength = nEnd - nStart;
268         else
269             bCommit = false;
270     }
271 
272     if ( bCommit )
273 	{
274         if( nType == text::TextMarkupType::SENTENCE )
275             ((SwGrammarMarkUp*)pWList)->setSentence( static_cast< xub_StrLen >(nStart) );
276         else
277             pWList->Insert( rIdentifier, xMarkupInfoContainer,
278 				static_cast< xub_StrLen >(nStart), static_cast< xub_StrLen >(nLength) );
279 	}
280 
281     if( bRepaint )
282         finishGrammarCheck( *mpTxtNode );
283 }
284 
285 
lcl_commitGrammarMarkUp(const ModelToViewHelper::ConversionMap * pConversionMap,SwGrammarMarkUp * pWList,::sal_Int32 nType,const::rtl::OUString & rIdentifier,::sal_Int32 nStart,::sal_Int32 nLength,const uno::Reference<container::XStringKeyMap> & xMarkupInfoContainer)286 void lcl_commitGrammarMarkUp(
287     const ModelToViewHelper::ConversionMap* pConversionMap,
288     SwGrammarMarkUp* pWList,
289     ::sal_Int32 nType,
290     const ::rtl::OUString & rIdentifier,
291     ::sal_Int32 nStart,
292     ::sal_Int32 nLength,
293     const uno::Reference< container::XStringKeyMap > & xMarkupInfoContainer)
294 {
295     ASSERT( nType == text::TextMarkupType::PROOFREADING || nType == text::TextMarkupType::SENTENCE, "Wrong mark-up type" )
296     const ModelToViewHelper::ModelPosition aStartPos =
297             ModelToViewHelper::ConvertToModelPosition( pConversionMap, nStart );
298     const ModelToViewHelper::ModelPosition aEndPos   =
299             ModelToViewHelper::ConvertToModelPosition( pConversionMap, nStart + nLength - 1);
300 
301     const bool bStartInField = aStartPos.mbIsField;
302     const bool bEndInField   = aEndPos.mbIsField;
303     bool bCommit = false;
304 
305     if ( bStartInField && bEndInField && aStartPos.mnPos == aEndPos.mnPos )
306     {
307         nStart = aStartPos.mnSubPos;
308         const xub_StrLen nFieldPosModel = static_cast< xub_StrLen >(aStartPos.mnPos);
309         const sal_uInt16 nInsertPos = pWList->GetWrongPos( nFieldPosModel );
310 
311         SwGrammarMarkUp* pSubList = (SwGrammarMarkUp*)pWList->SubList( nInsertPos );
312         if ( !pSubList )
313         {
314             pSubList = new SwGrammarMarkUp();
315             pWList->InsertSubList( nFieldPosModel, 1, nInsertPos, pSubList );
316         }
317 
318         pWList = pSubList;
319         bCommit = true;
320     }
321     else if ( !bStartInField && !bEndInField )
322     {
323         nStart = aStartPos.mnPos;
324         bCommit = true;
325         nLength = aEndPos.mnPos + 1 - aStartPos.mnPos;
326     }
327     else
328     {
329         bCommit = true;
330         nStart = aStartPos.mnPos;
331         sal_Int32 nEnd = aEndPos.mnPos;
332         if( bStartInField && nType != text::TextMarkupType::SENTENCE )
333         {
334             const xub_StrLen nFieldPosModel = static_cast< xub_StrLen >(aStartPos.mnPos);
335             const sal_uInt16 nInsertPos = pWList->GetWrongPos( nFieldPosModel );
336             SwGrammarMarkUp* pSubList = (SwGrammarMarkUp*)pWList->SubList( nInsertPos );
337             if ( !pSubList )
338             {
339                 pSubList = new SwGrammarMarkUp();
340                 pWList->InsertSubList( nFieldPosModel, 1, nInsertPos, pSubList );
341             }
342             const sal_uInt32 nTmpStart = ModelToViewHelper::ConvertToViewPosition( pConversionMap, aStartPos.mnPos );
343             const sal_uInt32 nTmpLen = ModelToViewHelper::ConvertToViewPosition( pConversionMap, aStartPos.mnPos + 1 )
344                                        - nTmpStart - aStartPos.mnSubPos;
345             if( nTmpLen > 0 )
346                 pSubList->Insert( rIdentifier, xMarkupInfoContainer,
347                     static_cast< xub_StrLen >(aStartPos.mnSubPos), static_cast< xub_StrLen >(nTmpLen) );
348             ++nStart;
349         }
350         if( bEndInField && nType != text::TextMarkupType::SENTENCE )
351         {
352             const xub_StrLen nFieldPosModel = static_cast< xub_StrLen >(aEndPos.mnPos);
353             const sal_uInt16 nInsertPos = pWList->GetWrongPos( nFieldPosModel );
354             SwGrammarMarkUp* pSubList = (SwGrammarMarkUp*)pWList->SubList( nInsertPos );
355             if ( !pSubList )
356             {
357                 pSubList = new SwGrammarMarkUp();
358                 pWList->InsertSubList( nFieldPosModel, 1, nInsertPos, pSubList );
359             }
360             const sal_uInt32 nTmpLen = aEndPos.mnSubPos + 1;
361             pSubList->Insert( rIdentifier, xMarkupInfoContainer, 0, static_cast< xub_StrLen >(nTmpLen) );
362         }
363         else
364             ++nEnd;
365         if( nEnd > nStart )
366             nLength = nEnd - nStart;
367         else
368             bCommit = false;
369     }
370 
371     if ( bCommit )
372 	{
373         if( nType == text::TextMarkupType::SENTENCE )
374             ((SwGrammarMarkUp*)pWList)->setSentence( static_cast< xub_StrLen >(nStart+nLength) );
375         else
376             pWList->Insert( rIdentifier, xMarkupInfoContainer,
377 				static_cast< xub_StrLen >(nStart), static_cast< xub_StrLen >(nLength) );
378 	}
379 }
380 
381 
commitMultiTextMarkup(const uno::Sequence<text::TextMarkupDescriptor> & rMarkups)382 void SAL_CALL SwXTextMarkup::commitMultiTextMarkup(
383 	const uno::Sequence< text::TextMarkupDescriptor > &rMarkups )
384 throw (lang::IllegalArgumentException, uno::RuntimeException)
385 {
386     vos::OGuard aGuard(Application::GetSolarMutex());
387 
388     // paragraph already dead or modified?
389     if ( !mpTxtNode )
390         return;
391 
392     // check for equal length of all sequnces
393     sal_Int32 nLen = rMarkups.getLength();
394 
395     // for grammar checking there should be exactly one sentence markup
396     // and 0..n grammar markups.
397     // Different markups are not expected but may be applied anyway since
398     // that should be no problem...
399     // but it has to be implemented, at the moment only this function is for
400     // grammar markups and sentence markup only!
401     sal_Int32 nSentenceMarkUpIndex = -1;
402     const text::TextMarkupDescriptor *pMarkups = rMarkups.getConstArray();
403     sal_Int32 i;
404     for( i = 0;  i < nLen;  ++i )
405     {
406         if (pMarkups[i].nType == text::TextMarkupType::SENTENCE)
407         {
408             if (nSentenceMarkUpIndex == -1)
409                 nSentenceMarkUpIndex = i;
410             else    // there is already one sentence markup
411                 throw lang::IllegalArgumentException();
412         }
413 		else if( pMarkups[i].nType != text::TextMarkupType::PROOFREADING )
414             return;
415     }
416 
417     if( nSentenceMarkUpIndex == -1 )
418         return;
419 
420     // get appropriate list to use...
421     SwGrammarMarkUp* pWList = 0;
422     bool bRepaint = false;
423     IGrammarContact *pGrammarContact = getGrammarContact( *mpTxtNode );
424     if( pGrammarContact )
425     {
426         pWList = pGrammarContact->getGrammarCheck( *mpTxtNode, true );
427         ASSERT( pWList, "GrammarContact _has_ to deliver a wrong list" )
428     }
429     else
430     {
431         pWList = mpTxtNode->GetGrammarCheck();
432         if ( !pWList )
433         {
434             mpTxtNode->SetGrammarCheck( new SwGrammarMarkUp() );
435             pWList = mpTxtNode->GetGrammarCheck();
436             pWList->SetInvalid( 0, STRING_LEN );
437         }
438     }
439     bRepaint = pWList == mpTxtNode->GetGrammarCheck();
440 
441     bool bAcceptGrammarError = false;
442     if( pWList->GetBeginInv() < STRING_LEN )
443     {
444         const ModelToViewHelper::ModelPosition aSentenceEnd =
445             ModelToViewHelper::ConvertToModelPosition( mpConversionMap,
446                 pMarkups[nSentenceMarkUpIndex].nOffset + pMarkups[nSentenceMarkUpIndex].nLength );
447         bAcceptGrammarError = (xub_StrLen)aSentenceEnd.mnPos > pWList->GetBeginInv();
448         pWList->ClearGrammarList( (xub_StrLen)aSentenceEnd.mnPos );
449     }
450 
451     if( bAcceptGrammarError )
452     {
453         for( i = 0;  i < nLen;  ++i )
454 		{
455 			const text::TextMarkupDescriptor &rDesc = pMarkups[i];
456             lcl_commitGrammarMarkUp( mpConversionMap, pWList, rDesc.nType,
457                 rDesc.aIdentifier, rDesc.nOffset, rDesc.nLength, rDesc.xMarkupInfoContainer );
458 		}
459     }
460     else
461     {
462         bRepaint = false;
463         i = nSentenceMarkUpIndex;
464 		const text::TextMarkupDescriptor &rDesc = pMarkups[i];
465         lcl_commitGrammarMarkUp( mpConversionMap, pWList, rDesc.nType,
466             rDesc.aIdentifier, rDesc.nOffset, rDesc.nLength, rDesc.xMarkupInfoContainer );
467     }
468 
469     if( bRepaint )
470         finishGrammarCheck( *mpTxtNode );
471 
472     return;
473 }
474 
475 
Modify(const SfxPoolItem *,const SfxPoolItem *)476 void SwXTextMarkup::Modify( const SfxPoolItem* /*pOld*/, const SfxPoolItem* /*pNew*/ )
477 {
478     // FME 2007-07-16 #i79641# In my opinion this is perfectly legal,
479     // therefore I remove the assertion in SwModify::_Remove()
480     if ( GetRegisteredIn() )
481         GetRegisteredInNonConst()->Remove( this );
482     // <--
483 
484     vos::OGuard aGuard(Application::GetSolarMutex());
485     mpTxtNode = 0;
486 }
487 
488 /*
489  * SwXStringKeyMap
490  */
SwXStringKeyMap()491 SwXStringKeyMap::SwXStringKeyMap()
492 {
493 }
494 
getValue(const::rtl::OUString & aKey)495 uno::Any SAL_CALL SwXStringKeyMap::getValue(const ::rtl::OUString & aKey) throw (uno::RuntimeException, container::NoSuchElementException)
496 {
497     std::map< rtl::OUString, uno::Any >::const_iterator aIter = maMap.find( aKey );
498     if ( aIter == maMap.end() )
499         throw container::NoSuchElementException();
500 
501     return (*aIter).second;
502 }
503 
hasValue(const::rtl::OUString & aKey)504 ::sal_Bool SAL_CALL SwXStringKeyMap::hasValue(const ::rtl::OUString & aKey) throw (uno::RuntimeException)
505 {
506     return maMap.find( aKey ) != maMap.end();
507 }
508 
insertValue(const::rtl::OUString & aKey,const uno::Any & aValue)509 void SAL_CALL SwXStringKeyMap::insertValue(const ::rtl::OUString & aKey, const uno::Any & aValue) throw (uno::RuntimeException, lang::IllegalArgumentException, container::ElementExistException)
510 {
511     std::map< rtl::OUString, uno::Any >::const_iterator aIter = maMap.find( aKey );
512     if ( aIter != maMap.end() )
513         throw container::ElementExistException();
514 
515     maMap[ aKey ] = aValue;
516 }
517 
getCount()518 ::sal_Int32 SAL_CALL SwXStringKeyMap::getCount() throw (uno::RuntimeException)
519 {
520     return maMap.size();
521 }
522 
getKeyByIndex(::sal_Int32 nIndex)523 ::rtl::OUString SAL_CALL SwXStringKeyMap::getKeyByIndex(::sal_Int32 nIndex) throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
524 {
525     if ( (sal_uInt32)nIndex >= maMap.size() )
526         throw lang::IndexOutOfBoundsException();
527 
528     return ::rtl::OUString();
529 }
530 
getValueByIndex(::sal_Int32 nIndex)531 uno::Any SAL_CALL SwXStringKeyMap::getValueByIndex(::sal_Int32 nIndex) throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
532 {
533     if ( (sal_uInt32)nIndex >= maMap.size() )
534         throw lang::IndexOutOfBoundsException();
535 
536     return uno::Any();
537 }
538 
539