merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / unocore / unotextmarkup.cxx
blob9aca9a4c85c46a1838e58cb2dded5c5f9f58b24b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: unotextmarkup.cxx,v $
10 * $Revision: 1.6 $
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>
41 #include <ndtxt.hxx>
42 #include <SwGrammarMarkUp.hxx>
44 #include <IGrammarContact.hxx>
46 using namespace ::com::sun::star;
49 * SwXTextMarkup
51 SwXTextMarkup::SwXTextMarkup( SwTxtNode& rTxtNode, const ModelToViewHelper::ConversionMap* pMap )
52 : mpTxtNode( &rTxtNode ), mpConversionMap( pMap )
54 mpTxtNode->Add(this);
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;
67 return xProp;
70 void SAL_CALL SwXTextMarkup::commitTextMarkup(
71 ::sal_Int32 nType,
72 const ::rtl::OUString & rIdentifier,
73 ::sal_Int32 nStart,
74 ::sal_Int32 nLength,
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 )
82 return;
84 if ( nType == text::TextMarkupType::SMARTTAG &&
85 !SwSmartTagMgr::Get().IsSmartTagTypeEnabled( rIdentifier ) )
86 return;
88 // get appropriate list to use...
89 SwWrongList* pWList = 0;
90 bool bRepaint = false;
91 if ( nType == text::TextMarkupType::SPELLCHECK )
93 pWList = mpTxtNode->GetWrong();
94 if ( !pWList )
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" )
108 else
110 pWList = mpTxtNode->GetGrammarCheck();
111 if ( !pWList )
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();
124 if ( !pWList )
126 pWList = new SwWrongList( WRONGLIST_SMARTTAG );
127 mpTxtNode->SetSmartTags( pWList );
130 else
132 ASSERT( false, "Unknown mark-up type" )
133 return;
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 );
153 if ( !pSubList )
155 if( nType == text::TextMarkupType::PROOFREADING || nType == text::TextMarkupType::SENTENCE )
156 pSubList = new SwGrammarMarkUp();
157 else
158 pSubList = new SwWrongList( pWList->GetWrongListType() );
159 pWList->InsertSubList( nFieldPosModel, 1, nInsertPos, pSubList );
162 pWList = pSubList;
163 bCommit = true;
165 else if ( !bStartInField && !bEndInField )
167 nStart = aStartPos.mnPos;
168 bCommit = true;
169 nLength = aEndPos.mnPos + 1 - aStartPos.mnPos;
171 else if( nType == text::TextMarkupType::PROOFREADING || nType == text::TextMarkupType::SENTENCE )
173 bCommit = true;
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 );
181 if ( !pSubList )
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;
189 if( nTmpLen > 0 )
191 if( nType == text::TextMarkupType::SENTENCE )
193 ((SwGrammarMarkUp*)pSubList)->setSentence( static_cast< xub_StrLen >(aStartPos.mnSubPos) );
194 bCommit = false;
196 else
197 pSubList->Insert( rIdentifier, xMarkupInfoContainer,
198 static_cast< xub_StrLen >(aStartPos.mnSubPos), static_cast< xub_StrLen >(nTmpLen) );
200 ++nStart;
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 );
207 if ( !pSubList )
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) );
215 else
216 ++nEnd;
217 if( nEnd > nStart )
218 nLength = nEnd - nStart;
219 else
220 bCommit = false;
223 if ( bCommit )
225 if( nType == text::TextMarkupType::SENTENCE )
226 ((SwGrammarMarkUp*)pWList)->setSentence( static_cast< xub_StrLen >(nStart) );
227 else
228 pWList->Insert( rIdentifier, xMarkupInfoContainer,
229 static_cast< xub_StrLen >(nStart), static_cast< xub_StrLen >(nLength) );
232 if( bRepaint )
233 finishGrammarCheck( *mpTxtNode );
237 void lcl_commitGrammarMarkUp(
238 const ModelToViewHelper::ConversionMap* pConversionMap,
239 SwGrammarMarkUp* pWList,
240 ::sal_Int32 nType,
241 const ::rtl::OUString & rIdentifier,
242 ::sal_Int32 nStart,
243 ::sal_Int32 nLength,
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 );
263 if ( !pSubList )
265 pSubList = new SwGrammarMarkUp();
266 pWList->InsertSubList( nFieldPosModel, 1, nInsertPos, pSubList );
269 pWList = pSubList;
270 bCommit = true;
272 else if ( !bStartInField && !bEndInField )
274 nStart = aStartPos.mnPos;
275 bCommit = true;
276 nLength = aEndPos.mnPos + 1 - aStartPos.mnPos;
278 else
280 bCommit = true;
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 );
288 if ( !pSubList )
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;
296 if( nTmpLen > 0 )
297 pSubList->Insert( rIdentifier, xMarkupInfoContainer,
298 static_cast< xub_StrLen >(aStartPos.mnSubPos), static_cast< xub_StrLen >(nTmpLen) );
299 ++nStart;
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 );
306 if ( !pSubList )
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) );
314 else
315 ++nEnd;
316 if( nEnd > nStart )
317 nLength = nEnd - nStart;
318 else
319 bCommit = false;
322 if ( bCommit )
324 if( nType == text::TextMarkupType::SENTENCE )
325 ((SwGrammarMarkUp*)pWList)->setSentence( static_cast< xub_StrLen >(nStart+nLength) );
326 else
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?
340 if ( !mpTxtNode )
341 return;
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();
354 sal_Int32 i;
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 )
365 return;
368 if( nSentenceMarkUpIndex == -1 )
369 return;
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" )
380 else
382 pWList = mpTxtNode->GetGrammarCheck();
383 if ( !pWList )
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 );
411 else
413 bRepaint = false;
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 );
420 if( bRepaint )
421 finishGrammarCheck( *mpTxtNode );
423 return;
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()
431 if ( pRegisteredIn )
432 pRegisteredIn->Remove( this );
433 // <--
435 vos::OGuard aGuard(Application::GetSolarMutex());
436 mpTxtNode = 0;
440 * SwXStringKeyMap
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)
471 return maMap.size();
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();
487 return uno::Any();