1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: unotextmarkup.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include <unotextmarkup.hxx>
35 #include <vos/mutex.hxx>
36 #include <vcl/svapp.hxx>
37 #include <SwSmartTagMgr.hxx>
38 #include <com/sun/star/text/TextMarkupType.hpp>
39 #include <com/sun/star/text/TextMarkupDescriptor.hpp>
40 #include <com/sun/star/container/XStringKeyMap.hpp>
42 #include <SwGrammarMarkUp.hxx>
44 #include <IGrammarContact.hxx>
46 using namespace ::com::sun::star
;
51 SwXTextMarkup::SwXTextMarkup( SwTxtNode
& rTxtNode
, const ModelToViewHelper::ConversionMap
* pMap
)
52 : mpTxtNode( &rTxtNode
), mpConversionMap( pMap
)
57 SwXTextMarkup::~SwXTextMarkup()
59 delete mpConversionMap
;
62 uno::Reference
< container::XStringKeyMap
> SAL_CALL
SwXTextMarkup::getMarkupInfoContainer() throw (uno::RuntimeException
)
64 vos::OGuard
aGuard(Application::GetSolarMutex());
66 uno::Reference
< container::XStringKeyMap
> xProp
= new SwXStringKeyMap
;
70 void SAL_CALL
SwXTextMarkup::commitTextMarkup(
72 const ::rtl::OUString
& rIdentifier
,
75 const uno::Reference
< container::XStringKeyMap
> & xMarkupInfoContainer
)
76 throw (uno::RuntimeException
)
78 vos::OGuard
aGuard(Application::GetSolarMutex());
80 // paragraph already dead or modified?
81 if ( !mpTxtNode
|| nLength
<= 0 )
84 if ( nType
== text::TextMarkupType::SMARTTAG
&&
85 !SwSmartTagMgr::Get().IsSmartTagTypeEnabled( rIdentifier
) )
88 // get appropriate list to use...
89 SwWrongList
* pWList
= 0;
90 bool bRepaint
= false;
91 if ( nType
== text::TextMarkupType::SPELLCHECK
)
93 pWList
= mpTxtNode
->GetWrong();
96 pWList
= new SwWrongList( WRONGLIST_SPELL
);
97 mpTxtNode
->SetWrong( pWList
);
100 else if ( nType
== text::TextMarkupType::PROOFREADING
|| nType
== text::TextMarkupType::SENTENCE
)
102 IGrammarContact
*pGrammarContact
= getGrammarContact( *mpTxtNode
);
103 if( pGrammarContact
)
105 pWList
= pGrammarContact
->getGrammarCheck( *mpTxtNode
, true );
106 ASSERT( pWList
, "GrammarContact _has_ to deliver a wrong list" )
110 pWList
= mpTxtNode
->GetGrammarCheck();
113 mpTxtNode
->SetGrammarCheck( new SwGrammarMarkUp() );
114 pWList
= mpTxtNode
->GetGrammarCheck();
117 bRepaint
= pWList
== mpTxtNode
->GetGrammarCheck();
118 if( pWList
->GetBeginInv() < STRING_LEN
)
119 ((SwGrammarMarkUp
*)pWList
)->ClearGrammarList();
121 else if ( nType
== text::TextMarkupType::SMARTTAG
)
123 pWList
= mpTxtNode
->GetSmartTags();
126 pWList
= new SwWrongList( WRONGLIST_SMARTTAG
);
127 mpTxtNode
->SetSmartTags( pWList
);
132 ASSERT( false, "Unknown mark-up type" )
137 const ModelToViewHelper::ModelPosition aStartPos
=
138 ModelToViewHelper::ConvertToModelPosition( mpConversionMap
, nStart
);
139 const ModelToViewHelper::ModelPosition aEndPos
=
140 ModelToViewHelper::ConvertToModelPosition( mpConversionMap
, nStart
+ nLength
- 1);
142 const bool bStartInField
= aStartPos
.mbIsField
;
143 const bool bEndInField
= aEndPos
.mbIsField
;
144 bool bCommit
= false;
146 if ( bStartInField
&& bEndInField
&& aStartPos
.mnPos
== aEndPos
.mnPos
)
148 nStart
= aStartPos
.mnSubPos
;
149 const xub_StrLen nFieldPosModel
= static_cast< xub_StrLen
>(aStartPos
.mnPos
);
150 const USHORT nInsertPos
= pWList
->GetWrongPos( nFieldPosModel
);
152 SwWrongList
* pSubList
= pWList
->SubList( nInsertPos
);
155 if( nType
== text::TextMarkupType::PROOFREADING
|| nType
== text::TextMarkupType::SENTENCE
)
156 pSubList
= new SwGrammarMarkUp();
158 pSubList
= new SwWrongList( pWList
->GetWrongListType() );
159 pWList
->InsertSubList( nFieldPosModel
, 1, nInsertPos
, pSubList
);
165 else if ( !bStartInField
&& !bEndInField
)
167 nStart
= aStartPos
.mnPos
;
169 nLength
= aEndPos
.mnPos
+ 1 - aStartPos
.mnPos
;
171 else if( nType
== text::TextMarkupType::PROOFREADING
|| nType
== text::TextMarkupType::SENTENCE
)
174 nStart
= aStartPos
.mnPos
;
175 sal_Int32 nEnd
= aEndPos
.mnPos
;
176 if( bStartInField
&& nType
!= text::TextMarkupType::SENTENCE
)
178 const xub_StrLen nFieldPosModel
= static_cast< xub_StrLen
>(aStartPos
.mnPos
);
179 const USHORT nInsertPos
= pWList
->GetWrongPos( nFieldPosModel
);
180 SwWrongList
* pSubList
= pWList
->SubList( nInsertPos
);
183 pSubList
= new SwGrammarMarkUp();
184 pWList
->InsertSubList( nFieldPosModel
, 1, nInsertPos
, pSubList
);
186 const sal_uInt32 nTmpStart
= ModelToViewHelper::ConvertToViewPosition( mpConversionMap
, aStartPos
.mnPos
);
187 const sal_uInt32 nTmpLen
= ModelToViewHelper::ConvertToViewPosition( mpConversionMap
, aStartPos
.mnPos
+ 1 )
188 - nTmpStart
- aStartPos
.mnSubPos
;
191 if( nType
== text::TextMarkupType::SENTENCE
)
193 ((SwGrammarMarkUp
*)pSubList
)->setSentence( static_cast< xub_StrLen
>(aStartPos
.mnSubPos
) );
197 pSubList
->Insert( rIdentifier
, xMarkupInfoContainer
,
198 static_cast< xub_StrLen
>(aStartPos
.mnSubPos
), static_cast< xub_StrLen
>(nTmpLen
) );
202 if( bEndInField
&& nType
!= text::TextMarkupType::SENTENCE
)
204 const xub_StrLen nFieldPosModel
= static_cast< xub_StrLen
>(aEndPos
.mnPos
);
205 const USHORT nInsertPos
= pWList
->GetWrongPos( nFieldPosModel
);
206 SwWrongList
* pSubList
= pWList
->SubList( nInsertPos
);
209 pSubList
= new SwGrammarMarkUp();
210 pWList
->InsertSubList( nFieldPosModel
, 1, nInsertPos
, pSubList
);
212 const sal_uInt32 nTmpLen
= aEndPos
.mnSubPos
+ 1;
213 pSubList
->Insert( rIdentifier
, xMarkupInfoContainer
, 0, static_cast< xub_StrLen
>(nTmpLen
) );
218 nLength
= nEnd
- nStart
;
225 if( nType
== text::TextMarkupType::SENTENCE
)
226 ((SwGrammarMarkUp
*)pWList
)->setSentence( static_cast< xub_StrLen
>(nStart
) );
228 pWList
->Insert( rIdentifier
, xMarkupInfoContainer
,
229 static_cast< xub_StrLen
>(nStart
), static_cast< xub_StrLen
>(nLength
) );
233 finishGrammarCheck( *mpTxtNode
);
237 void lcl_commitGrammarMarkUp(
238 const ModelToViewHelper::ConversionMap
* pConversionMap
,
239 SwGrammarMarkUp
* pWList
,
241 const ::rtl::OUString
& rIdentifier
,
244 const uno::Reference
< container::XStringKeyMap
> & xMarkupInfoContainer
)
246 ASSERT( nType
== text::TextMarkupType::PROOFREADING
|| nType
== text::TextMarkupType::SENTENCE
, "Wrong mark-up type" )
247 const ModelToViewHelper::ModelPosition aStartPos
=
248 ModelToViewHelper::ConvertToModelPosition( pConversionMap
, nStart
);
249 const ModelToViewHelper::ModelPosition aEndPos
=
250 ModelToViewHelper::ConvertToModelPosition( pConversionMap
, nStart
+ nLength
- 1);
252 const bool bStartInField
= aStartPos
.mbIsField
;
253 const bool bEndInField
= aEndPos
.mbIsField
;
254 bool bCommit
= false;
256 if ( bStartInField
&& bEndInField
&& aStartPos
.mnPos
== aEndPos
.mnPos
)
258 nStart
= aStartPos
.mnSubPos
;
259 const xub_StrLen nFieldPosModel
= static_cast< xub_StrLen
>(aStartPos
.mnPos
);
260 const USHORT nInsertPos
= pWList
->GetWrongPos( nFieldPosModel
);
262 SwGrammarMarkUp
* pSubList
= (SwGrammarMarkUp
*)pWList
->SubList( nInsertPos
);
265 pSubList
= new SwGrammarMarkUp();
266 pWList
->InsertSubList( nFieldPosModel
, 1, nInsertPos
, pSubList
);
272 else if ( !bStartInField
&& !bEndInField
)
274 nStart
= aStartPos
.mnPos
;
276 nLength
= aEndPos
.mnPos
+ 1 - aStartPos
.mnPos
;
281 nStart
= aStartPos
.mnPos
;
282 sal_Int32 nEnd
= aEndPos
.mnPos
;
283 if( bStartInField
&& nType
!= text::TextMarkupType::SENTENCE
)
285 const xub_StrLen nFieldPosModel
= static_cast< xub_StrLen
>(aStartPos
.mnPos
);
286 const USHORT nInsertPos
= pWList
->GetWrongPos( nFieldPosModel
);
287 SwGrammarMarkUp
* pSubList
= (SwGrammarMarkUp
*)pWList
->SubList( nInsertPos
);
290 pSubList
= new SwGrammarMarkUp();
291 pWList
->InsertSubList( nFieldPosModel
, 1, nInsertPos
, pSubList
);
293 const sal_uInt32 nTmpStart
= ModelToViewHelper::ConvertToViewPosition( pConversionMap
, aStartPos
.mnPos
);
294 const sal_uInt32 nTmpLen
= ModelToViewHelper::ConvertToViewPosition( pConversionMap
, aStartPos
.mnPos
+ 1 )
295 - nTmpStart
- aStartPos
.mnSubPos
;
297 pSubList
->Insert( rIdentifier
, xMarkupInfoContainer
,
298 static_cast< xub_StrLen
>(aStartPos
.mnSubPos
), static_cast< xub_StrLen
>(nTmpLen
) );
301 if( bEndInField
&& nType
!= text::TextMarkupType::SENTENCE
)
303 const xub_StrLen nFieldPosModel
= static_cast< xub_StrLen
>(aEndPos
.mnPos
);
304 const USHORT nInsertPos
= pWList
->GetWrongPos( nFieldPosModel
);
305 SwGrammarMarkUp
* pSubList
= (SwGrammarMarkUp
*)pWList
->SubList( nInsertPos
);
308 pSubList
= new SwGrammarMarkUp();
309 pWList
->InsertSubList( nFieldPosModel
, 1, nInsertPos
, pSubList
);
311 const sal_uInt32 nTmpLen
= aEndPos
.mnSubPos
+ 1;
312 pSubList
->Insert( rIdentifier
, xMarkupInfoContainer
, 0, static_cast< xub_StrLen
>(nTmpLen
) );
317 nLength
= nEnd
- nStart
;
324 if( nType
== text::TextMarkupType::SENTENCE
)
325 ((SwGrammarMarkUp
*)pWList
)->setSentence( static_cast< xub_StrLen
>(nStart
+nLength
) );
327 pWList
->Insert( rIdentifier
, xMarkupInfoContainer
,
328 static_cast< xub_StrLen
>(nStart
), static_cast< xub_StrLen
>(nLength
) );
333 void SAL_CALL
SwXTextMarkup::commitMultiTextMarkup(
334 const uno::Sequence
< text::TextMarkupDescriptor
> &rMarkups
)
335 throw (lang::IllegalArgumentException
, uno::RuntimeException
)
337 vos::OGuard
aGuard(Application::GetSolarMutex());
339 // paragraph already dead or modified?
343 // check for equal length of all sequnces
344 sal_Int32 nLen
= rMarkups
.getLength();
346 // for grammar checking there should be exactly one sentence markup
347 // and 0..n grammar markups.
348 // Different markups are not expected but may be applied anyway since
349 // that should be no problem...
350 // but it has to be implemented, at the moment only this function is for
351 // grammar markups and sentence markup only!
352 sal_Int32 nSentenceMarkUpIndex
= -1;
353 const text::TextMarkupDescriptor
*pMarkups
= rMarkups
.getConstArray();
355 for( i
= 0; i
< nLen
; ++i
)
357 if (pMarkups
[i
].nType
== text::TextMarkupType::SENTENCE
)
359 if (nSentenceMarkUpIndex
== -1)
360 nSentenceMarkUpIndex
= i
;
361 else // there is already one sentence markup
362 throw lang::IllegalArgumentException();
364 else if( pMarkups
[i
].nType
!= text::TextMarkupType::PROOFREADING
)
368 if( nSentenceMarkUpIndex
== -1 )
371 // get appropriate list to use...
372 SwGrammarMarkUp
* pWList
= 0;
373 bool bRepaint
= false;
374 IGrammarContact
*pGrammarContact
= getGrammarContact( *mpTxtNode
);
375 if( pGrammarContact
)
377 pWList
= pGrammarContact
->getGrammarCheck( *mpTxtNode
, true );
378 ASSERT( pWList
, "GrammarContact _has_ to deliver a wrong list" )
382 pWList
= mpTxtNode
->GetGrammarCheck();
385 mpTxtNode
->SetGrammarCheck( new SwGrammarMarkUp() );
386 pWList
= mpTxtNode
->GetGrammarCheck();
387 pWList
->SetInvalid( 0, STRING_LEN
);
390 bRepaint
= pWList
== mpTxtNode
->GetGrammarCheck();
392 bool bAcceptGrammarError
= false;
393 if( pWList
->GetBeginInv() < STRING_LEN
)
395 const ModelToViewHelper::ModelPosition aSentenceEnd
=
396 ModelToViewHelper::ConvertToModelPosition( mpConversionMap
,
397 pMarkups
[nSentenceMarkUpIndex
].nOffset
+ pMarkups
[nSentenceMarkUpIndex
].nLength
);
398 bAcceptGrammarError
= (xub_StrLen
)aSentenceEnd
.mnPos
> pWList
->GetBeginInv();
399 pWList
->ClearGrammarList( (xub_StrLen
)aSentenceEnd
.mnPos
);
402 if( bAcceptGrammarError
)
404 for( i
= 0; i
< nLen
; ++i
)
406 const text::TextMarkupDescriptor
&rDesc
= pMarkups
[i
];
407 lcl_commitGrammarMarkUp( mpConversionMap
, pWList
, rDesc
.nType
,
408 rDesc
.aIdentifier
, rDesc
.nOffset
, rDesc
.nLength
, rDesc
.xMarkupInfoContainer
);
414 i
= nSentenceMarkUpIndex
;
415 const text::TextMarkupDescriptor
&rDesc
= pMarkups
[i
];
416 lcl_commitGrammarMarkUp( mpConversionMap
, pWList
, rDesc
.nType
,
417 rDesc
.aIdentifier
, rDesc
.nOffset
, rDesc
.nLength
, rDesc
.xMarkupInfoContainer
);
421 finishGrammarCheck( *mpTxtNode
);
427 void SwXTextMarkup::Modify( SfxPoolItem
* /*pOld*/, SfxPoolItem
* /*pNew*/ )
429 // FME 2007-07-16 #i79641# In my opinion this is perfectly legal,
430 // therefore I remove the assertion in SwModify::_Remove()
432 pRegisteredIn
->Remove( this );
435 vos::OGuard
aGuard(Application::GetSolarMutex());
442 SwXStringKeyMap::SwXStringKeyMap()
446 uno::Any SAL_CALL
SwXStringKeyMap::getValue(const ::rtl::OUString
& aKey
) throw (uno::RuntimeException
, container::NoSuchElementException
)
448 std::map
< rtl::OUString
, uno::Any
>::const_iterator aIter
= maMap
.find( aKey
);
449 if ( aIter
== maMap
.end() )
450 throw container::NoSuchElementException();
452 return (*aIter
).second
;
455 ::sal_Bool SAL_CALL
SwXStringKeyMap::hasValue(const ::rtl::OUString
& aKey
) throw (uno::RuntimeException
)
457 return maMap
.find( aKey
) != maMap
.end();
460 void SAL_CALL
SwXStringKeyMap::insertValue(const ::rtl::OUString
& aKey
, const uno::Any
& aValue
) throw (uno::RuntimeException
, lang::IllegalArgumentException
, container::ElementExistException
)
462 std::map
< rtl::OUString
, uno::Any
>::const_iterator aIter
= maMap
.find( aKey
);
463 if ( aIter
!= maMap
.end() )
464 throw container::ElementExistException();
466 maMap
[ aKey
] = aValue
;
469 ::sal_Int32 SAL_CALL
SwXStringKeyMap::getCount() throw (uno::RuntimeException
)
474 ::rtl::OUString SAL_CALL
SwXStringKeyMap::getKeyByIndex(::sal_Int32 nIndex
) throw (uno::RuntimeException
, lang::IndexOutOfBoundsException
)
476 if ( (sal_uInt32
)nIndex
>= maMap
.size() )
477 throw lang::IndexOutOfBoundsException();
479 return ::rtl::OUString();
482 uno::Any SAL_CALL
SwXStringKeyMap::getValueByIndex(::sal_Int32 nIndex
) throw (uno::RuntimeException
, lang::IndexOutOfBoundsException
)
484 if ( (sal_uInt32
)nIndex
>= maMap
.size() )
485 throw lang::IndexOutOfBoundsException();