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 #include <editeng/unolingu.hxx>
28
29 #include <unobaseclass.hxx>
30 #include <unoflatpara.hxx>
31
32 #include <vos/mutex.hxx>
33 #include <vcl/svapp.hxx>
34 #include <com/sun/star/text/TextMarkupType.hpp>
35 #include <unotextmarkup.hxx>
36 #include <ndtxt.hxx>
37 #include <doc.hxx>
38 #include <docsh.hxx>
39 #include <viewsh.hxx>
40 #include <viewimp.hxx>
41 #include <breakit.hxx>
42 #include <pam.hxx>
43 #include <unobaseclass.hxx>
44 #include <unotextrange.hxx>
45 #include <pagefrm.hxx>
46 #include <cntfrm.hxx>
47 #include <rootfrm.hxx>
48 #include <poolfmt.hxx>
49 #include <pagedesc.hxx>
50 #include <IGrammarContact.hxx>
51 #include <viewopt.hxx>
52
53 #include <com/sun/star/lang/XUnoTunnel.hpp>
54 #include <com/sun/star/text/XTextRange.hpp>
55
56 using namespace ::com::sun::star;
57
58 /******************************************************************************
59 * SwXFlatParagraph
60 ******************************************************************************/
61
SwXFlatParagraph(SwTxtNode & rTxtNode,rtl::OUString aExpandText,const ModelToViewHelper::ConversionMap * pMap)62 SwXFlatParagraph::SwXFlatParagraph( SwTxtNode& rTxtNode, rtl::OUString aExpandText, const ModelToViewHelper::ConversionMap* pMap ) :
63 SwXTextMarkup( rTxtNode, pMap ),
64 maExpandText( aExpandText )
65 {
66 }
67
~SwXFlatParagraph()68 SwXFlatParagraph::~SwXFlatParagraph()
69 {
70 }
71
getTypes()72 uno::Sequence< uno::Type > SwXFlatParagraph::getTypes( )
73 {
74 uno::Sequence< uno::Type > aTypes = SwXTextMarkup::getTypes();
75 aTypes.realloc( aTypes.getLength() + 1 );
76 aTypes[aTypes.getLength()-1] = ::getCppuType((uno::Reference< text::XFlatParagraph >*)0);
77 return aTypes;
78 }
79
getImplementationId()80 uno::Sequence< sal_Int8 > SwXFlatParagraph::getImplementationId( )
81 {
82 vos::OGuard aGuard(Application::GetSolarMutex());
83 static uno::Sequence< sal_Int8 > aId( 16 );
84 static sal_Bool bInit = sal_False;
85 if(!bInit)
86 {
87 rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
88 bInit = sal_True;
89 }
90 return aId;
91 }
92
queryInterface(const uno::Type & rType)93 uno::Any SAL_CALL SwXFlatParagraph::queryInterface( const uno::Type& rType )
94 {
95 if ( rType == ::getCppuType((uno::Reference< text::XFlatParagraph >*)0) )
96 {
97 return uno::makeAny( uno::Reference < text::XFlatParagraph >(this) );
98 }
99 else
100 return SwXTextMarkup::queryInterface( rType );
101 }
102
acquire()103 void SAL_CALL SwXFlatParagraph::acquire() throw()
104 {
105 SwXTextMarkup::acquire();
106 }
107
release()108 void SAL_CALL SwXFlatParagraph::release() throw()
109 {
110 SwXTextMarkup::release();
111 }
112
getTxtNode() const113 const SwTxtNode* SwXFlatParagraph::getTxtNode() const
114 {
115 return mpTxtNode;
116 }
117
getMarkupInfoContainer()118 css::uno::Reference< css::container::XStringKeyMap > SAL_CALL SwXFlatParagraph::getMarkupInfoContainer()
119 {
120 return SwXTextMarkup::getMarkupInfoContainer();
121 }
122
commitTextRangeMarkup(::sal_Int32 nType,const::rtl::OUString & aIdentifier,const uno::Reference<text::XTextRange> & xRange,const css::uno::Reference<css::container::XStringKeyMap> & xMarkupInfoContainer)123 void SAL_CALL SwXFlatParagraph::commitTextRangeMarkup(::sal_Int32 nType, const ::rtl::OUString & aIdentifier, const uno::Reference< text::XTextRange> & xRange,
124 const css::uno::Reference< css::container::XStringKeyMap > & xMarkupInfoContainer)
125 {
126 vos::OGuard aGuard(Application::GetSolarMutex());
127 SwXTextMarkup::commitTextRangeMarkup( nType, aIdentifier, xRange, xMarkupInfoContainer );
128 }
129
130
commitStringMarkup(::sal_Int32 nType,const::rtl::OUString & rIdentifier,::sal_Int32 nStart,::sal_Int32 nLength,const css::uno::Reference<css::container::XStringKeyMap> & rxMarkupInfoContainer)131 void SAL_CALL SwXFlatParagraph::commitStringMarkup(::sal_Int32 nType, const ::rtl::OUString & rIdentifier, ::sal_Int32 nStart, ::sal_Int32 nLength, const css::uno::Reference< css::container::XStringKeyMap > & rxMarkupInfoContainer)
132 {
133 vos::OGuard aGuard(Application::GetSolarMutex());
134 SwXTextMarkup::commitStringMarkup( nType, rIdentifier, nStart, nLength, rxMarkupInfoContainer );
135 }
136
137 // text::XFlatParagraph:
getText()138 ::rtl::OUString SAL_CALL SwXFlatParagraph::getText()
139 {
140 return maExpandText;
141 }
142
143 // text::XFlatParagraph:
setChecked(::sal_Int32 nType,::sal_Bool bVal)144 void SAL_CALL SwXFlatParagraph::setChecked( ::sal_Int32 nType, ::sal_Bool bVal )
145 {
146 vos::OGuard aGuard(Application::GetSolarMutex());
147
148 if ( mpTxtNode )
149 {
150 if ( text::TextMarkupType::SPELLCHECK == nType )
151 mpTxtNode->SetWrongDirty( !bVal );
152 else if ( text::TextMarkupType::SMARTTAG == nType )
153 mpTxtNode->SetSmartTagDirty( !bVal );
154 else if( text::TextMarkupType::PROOFREADING == nType )
155 {
156 mpTxtNode->SetGrammarCheckDirty( !bVal );
157 if( bVal )
158 ::finishGrammarCheck( *mpTxtNode );
159 }
160 }
161 }
162
163 // text::XFlatParagraph:
isChecked(::sal_Int32 nType)164 ::sal_Bool SAL_CALL SwXFlatParagraph::isChecked( ::sal_Int32 nType )
165 {
166 vos::OGuard aGuard(Application::GetSolarMutex());
167 if ( mpTxtNode )
168 {
169 if ( text::TextMarkupType::SPELLCHECK == nType )
170 return mpTxtNode->IsWrongDirty();
171 else if ( text::TextMarkupType::PROOFREADING == nType )
172 return mpTxtNode->IsGrammarCheckDirty();
173 else if ( text::TextMarkupType::SMARTTAG == nType )
174 return mpTxtNode->IsSmartTagDirty();
175 }
176
177 return sal_False;
178 }
179
180 // text::XFlatParagraph:
isModified()181 ::sal_Bool SAL_CALL SwXFlatParagraph::isModified()
182 {
183 vos::OGuard aGuard(Application::GetSolarMutex());
184 return 0 == mpTxtNode;
185 }
186
187 // text::XFlatParagraph:
getLanguageOfText(::sal_Int32 nPos,::sal_Int32 nLen)188 lang::Locale SAL_CALL SwXFlatParagraph::getLanguageOfText(::sal_Int32 nPos, ::sal_Int32 nLen)
189 {
190 vos::OGuard aGuard(Application::GetSolarMutex());
191 if (!mpTxtNode)
192 return SvxCreateLocale( LANGUAGE_NONE );
193
194 const lang::Locale aLocale( SW_BREAKITER()->GetLocale( mpTxtNode->GetLang( static_cast<sal_uInt16>(nPos), static_cast<sal_uInt16>(nLen) ) ) );
195 return aLocale;
196 }
197
198 // text::XFlatParagraph:
getPrimaryLanguageOfText(::sal_Int32 nPos,::sal_Int32 nLen)199 lang::Locale SAL_CALL SwXFlatParagraph::getPrimaryLanguageOfText(::sal_Int32 nPos, ::sal_Int32 nLen)
200 {
201 vos::OGuard aGuard(Application::GetSolarMutex());
202
203 if (!mpTxtNode)
204 return SvxCreateLocale( LANGUAGE_NONE );
205
206 const lang::Locale aLocale( SW_BREAKITER()->GetLocale( mpTxtNode->GetLang( static_cast<sal_uInt16>(nPos), static_cast<sal_uInt16>(nLen) ) ) );
207 return aLocale;
208 }
209
210 // text::XFlatParagraph:
changeText(::sal_Int32 nPos,::sal_Int32 nLen,const::rtl::OUString & aNewText,const css::uno::Sequence<css::beans::PropertyValue> & aAttributes)211 void SAL_CALL SwXFlatParagraph::changeText(::sal_Int32 nPos, ::sal_Int32 nLen, const ::rtl::OUString & aNewText, const css::uno::Sequence< css::beans::PropertyValue > & aAttributes)
212 {
213 vos::OGuard aGuard(Application::GetSolarMutex());
214
215 if ( !mpTxtNode )
216 return;
217
218 SwTxtNode* pOldTxtNode = mpTxtNode;
219
220 SwPaM aPaM( *mpTxtNode, static_cast<sal_uInt16>(nPos), *mpTxtNode, static_cast<sal_uInt16>(nPos + nLen) );
221
222 UnoActionContext aAction( mpTxtNode->GetDoc() );
223
224 const uno::Reference< text::XTextRange > xRange =
225 SwXTextRange::CreateXTextRange(
226 *mpTxtNode->GetDoc(), *aPaM.GetPoint(), aPaM.GetMark() );
227 uno::Reference< beans::XPropertySet > xPropSet( xRange, uno::UNO_QUERY );
228 if ( xPropSet.is() )
229 {
230 for ( sal_uInt16 i = 0; i < aAttributes.getLength(); ++i )
231 xPropSet->setPropertyValue( aAttributes[i].Name, aAttributes[i].Value );
232 }
233
234 mpTxtNode = pOldTxtNode; // setPropertyValue() modifies this. We restore the old state.
235
236 IDocumentContentOperations* pIDCO = mpTxtNode->getIDocumentContentOperations();
237 pIDCO->ReplaceRange( aPaM, aNewText, false );
238
239 mpTxtNode = 0;
240 }
241
242 // text::XFlatParagraph:
changeAttributes(::sal_Int32 nPos,::sal_Int32 nLen,const css::uno::Sequence<css::beans::PropertyValue> & aAttributes)243 void SAL_CALL SwXFlatParagraph::changeAttributes(::sal_Int32 nPos, ::sal_Int32 nLen, const css::uno::Sequence< css::beans::PropertyValue > & aAttributes)
244 {
245 vos::OGuard aGuard(Application::GetSolarMutex());
246
247 if ( !mpTxtNode )
248 return;
249
250 SwPaM aPaM( *mpTxtNode, static_cast<sal_uInt16>(nPos), *mpTxtNode, static_cast<sal_uInt16>(nPos + nLen) );
251
252 UnoActionContext aAction( mpTxtNode->GetDoc() );
253
254 const uno::Reference< text::XTextRange > xRange =
255 SwXTextRange::CreateXTextRange(
256 *mpTxtNode->GetDoc(), *aPaM.GetPoint(), aPaM.GetMark() );
257 uno::Reference< beans::XPropertySet > xPropSet( xRange, uno::UNO_QUERY );
258 if ( xPropSet.is() )
259 {
260 for ( sal_uInt16 i = 0; i < aAttributes.getLength(); ++i )
261 xPropSet->setPropertyValue( aAttributes[i].Name, aAttributes[i].Value );
262 }
263
264 mpTxtNode = 0;
265 }
266
267 // text::XFlatParagraph:
getLanguagePortions()268 css::uno::Sequence< ::sal_Int32 > SAL_CALL SwXFlatParagraph::getLanguagePortions()
269 {
270 vos::OGuard aGuard(Application::GetSolarMutex());
271 return css::uno::Sequence< ::sal_Int32>();
272 }
273
274
275 const uno::Sequence< sal_Int8 >&
getUnoTunnelId()276 SwXFlatParagraph::getUnoTunnelId()
277 {
278 static uno::Sequence<sal_Int8> aSeq(CreateUnoTunnelId());
279 return aSeq;
280 }
281
282
283 sal_Int64 SAL_CALL
getSomething(const uno::Sequence<sal_Int8> & rId)284 SwXFlatParagraph::getSomething(
285 const uno::Sequence< sal_Int8 >& rId)
286 {
287 return sw::UnoTunnelImpl(rId, this);
288 }
289
290
291 /******************************************************************************
292 * SwXFlatParagraphIterator
293 ******************************************************************************/
294
SwXFlatParagraphIterator(SwDoc & rDoc,sal_Int32 nType,sal_Bool bAutomatic)295 SwXFlatParagraphIterator::SwXFlatParagraphIterator( SwDoc& rDoc, sal_Int32 nType, sal_Bool bAutomatic )
296 : mpDoc( &rDoc ),
297 mnType( nType ),
298 mbAutomatic( bAutomatic ),
299 mnCurrentNode( 0 ),
300 mnStartNode( 0 ),
301 mnEndNode( rDoc.GetNodes().Count() ),
302 mbWrapped( sal_False )
303 {
304 //mnStartNode = mnCurrentNode = get node from current cursor TODO!
305
306 // register as listener and get notified when document is closed
307 mpDoc->GetPageDescFromPool( RES_POOLPAGE_STANDARD )->Add(this);
308 }
309
~SwXFlatParagraphIterator()310 SwXFlatParagraphIterator::~SwXFlatParagraphIterator()
311 {
312 }
313
314
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)315 void SwXFlatParagraphIterator::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
316 {
317 ClientModify( this, pOld, pNew );
318 // check if document gets closed...
319 if(!GetRegisteredIn())
320 {
321 vos::OGuard aGuard(Application::GetSolarMutex());
322 mpDoc = 0;
323 }
324 }
325
326
getFirstPara()327 uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getFirstPara()
328 {
329 return getNextPara(); // TODO
330 }
331
getNextPara()332 uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getNextPara()
333 {
334 vos::OGuard aGuard(Application::GetSolarMutex());
335
336 uno::Reference< text::XFlatParagraph > xRet;
337 if (!mpDoc)
338 return xRet;
339
340 SwTxtNode* pRet = 0;
341 if ( mbAutomatic )
342 {
343 ViewShell* pViewShell = 0;
344 mpDoc->GetEditShell( &pViewShell );
345
346 SwPageFrm* pCurrentPage = pViewShell ? pViewShell->Imp()->GetFirstVisPage() : 0;
347 SwPageFrm* pStartPage = pCurrentPage;
348 SwPageFrm* pStopPage = 0;
349
350 while ( pCurrentPage != pStopPage )
351 {
352 if (mnType != text::TextMarkupType::SPELLCHECK || pCurrentPage->IsInvalidSpelling() )
353 {
354 // this method is supposed to return an empty paragraph in case Online Checking is disabled
355 if ( ( mnType == text::TextMarkupType::PROOFREADING || mnType == text::TextMarkupType::SPELLCHECK )
356 && !pViewShell->GetViewOptions()->IsOnlineSpell() )
357 return xRet;
358
359 // search for invalid content:
360 SwCntntFrm* pCnt = pCurrentPage->ContainsCntnt();
361
362 while( pCnt && pCurrentPage->IsAnLower( pCnt ) )
363 {
364 SwTxtNode* pTxtNode = dynamic_cast<SwTxtNode*>( pCnt->GetNode()->GetTxtNode() );
365
366 if ( pTxtNode &&
367 ((mnType == text::TextMarkupType::SPELLCHECK &&
368 pTxtNode->IsWrongDirty()) ||
369 (mnType == text::TextMarkupType::PROOFREADING &&
370 pTxtNode->IsGrammarCheckDirty())) )
371 {
372 pRet = pTxtNode;
373 break;
374 }
375
376 pCnt = pCnt->GetNextCntntFrm();
377 }
378 }
379
380 if ( pRet )
381 break;
382
383 // if there is no invalid text node on the current page,
384 // we validate the page
385 pCurrentPage->ValidateSpelling();
386
387 // proceed with next page, wrap at end of document if required:
388 pCurrentPage = static_cast<SwPageFrm*>(pCurrentPage->GetNext());
389
390 if ( !pCurrentPage && !pStopPage )
391 {
392 pStopPage = pStartPage;
393 pCurrentPage = static_cast<SwPageFrm*>(pViewShell->GetLayout()->Lower());
394 }
395 }
396 }
397 else // non-automatic checking
398 {
399 const SwNodes& rNodes = mpDoc->GetNodes();
400 const sal_uLong nMaxNodes = rNodes.Count();
401
402 while ( mnCurrentNode < mnEndNode && mnCurrentNode < nMaxNodes )
403 {
404 SwNode* pNd = rNodes[ mnCurrentNode ];
405
406 ++mnCurrentNode;
407
408 pRet = dynamic_cast<SwTxtNode*>(pNd);
409 if ( pRet )
410 break;
411
412 if ( mnCurrentNode == mnEndNode && !mbWrapped )
413 {
414 mnCurrentNode = 0;
415 mnEndNode = mnStartNode;
416 }
417 }
418 }
419
420 if ( pRet )
421 {
422 // Expand the string:
423 rtl::OUString aExpandText;
424 const ModelToViewHelper::ConversionMap* pConversionMap =
425 pRet->BuildConversionMap( aExpandText );
426
427 xRet = new SwXFlatParagraph( *pRet, aExpandText, pConversionMap );
428 // keep hard references...
429 m_aFlatParaList.insert( xRet );
430 }
431
432 return xRet;
433 }
434
getLastPara()435 uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getLastPara()
436 {
437 return getNextPara();
438 }
439
getParaAfter(const uno::Reference<text::XFlatParagraph> & xPara)440 uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getParaAfter(const uno::Reference< text::XFlatParagraph > & xPara)
441 {
442 vos::OGuard aGuard(Application::GetSolarMutex());
443
444 uno::Reference< text::XFlatParagraph > xRet;
445 if (!mpDoc)
446 return xRet;
447
448 const uno::Reference<lang::XUnoTunnel> xFPTunnel(xPara, uno::UNO_QUERY);
449 OSL_ASSERT(xFPTunnel.is());
450 SwXFlatParagraph* const pFlatParagraph(sw::UnoTunnelGetImplementation<SwXFlatParagraph>(xFPTunnel));
451
452 if ( !pFlatParagraph )
453 return xRet;
454
455 const SwTxtNode* pCurrentNode = pFlatParagraph->getTxtNode();
456
457 if ( !pCurrentNode )
458 return xRet;
459
460 SwTxtNode* pNextTxtNode = 0;
461 const SwNodes& rNodes = pCurrentNode->GetDoc()->GetNodes();
462
463 for( sal_uLong nCurrentNode = pCurrentNode->GetIndex() + 1; nCurrentNode < rNodes.Count(); ++nCurrentNode )
464 {
465 SwNode* pNd = rNodes[ nCurrentNode ];
466 pNextTxtNode = dynamic_cast<SwTxtNode*>(pNd);
467 if ( pNextTxtNode )
468 break;
469 }
470
471 if ( pNextTxtNode )
472 {
473 // Expand the string:
474 rtl::OUString aExpandText;
475 const ModelToViewHelper::ConversionMap* pConversionMap =
476 pNextTxtNode->BuildConversionMap( aExpandText );
477
478 xRet = new SwXFlatParagraph( *pNextTxtNode, aExpandText, pConversionMap );
479 // keep hard references...
480 m_aFlatParaList.insert( xRet );
481 }
482
483 return xRet;
484 }
485
getParaBefore(const uno::Reference<text::XFlatParagraph> & xPara)486 uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getParaBefore(const uno::Reference< text::XFlatParagraph > & xPara )
487 {
488 vos::OGuard aGuard(Application::GetSolarMutex());
489
490 uno::Reference< text::XFlatParagraph > xRet;
491 if (!mpDoc)
492 return xRet;
493
494 const uno::Reference<lang::XUnoTunnel> xFPTunnel(xPara, uno::UNO_QUERY);
495 OSL_ASSERT(xFPTunnel.is());
496 SwXFlatParagraph* const pFlatParagraph(sw::UnoTunnelGetImplementation<SwXFlatParagraph>(xFPTunnel));
497
498 if ( !pFlatParagraph )
499 return xRet;
500
501 const SwTxtNode* pCurrentNode = pFlatParagraph->getTxtNode();
502
503 if ( !pCurrentNode )
504 return xRet;
505
506 SwTxtNode* pPrevTxtNode = 0;
507 const SwNodes& rNodes = pCurrentNode->GetDoc()->GetNodes();
508
509 for( sal_uLong nCurrentNode = pCurrentNode->GetIndex() - 1; nCurrentNode > 0; --nCurrentNode )
510 {
511 SwNode* pNd = rNodes[ nCurrentNode ];
512 pPrevTxtNode = dynamic_cast<SwTxtNode*>(pNd);
513 if ( pPrevTxtNode )
514 break;
515 }
516
517 if ( pPrevTxtNode )
518 {
519 // Expand the string:
520 rtl::OUString aExpandText;
521 const ModelToViewHelper::ConversionMap* pConversionMap =
522 pPrevTxtNode->BuildConversionMap( aExpandText );
523
524 xRet = new SwXFlatParagraph( *pPrevTxtNode, aExpandText, pConversionMap );
525 // keep hard references...
526 m_aFlatParaList.insert( xRet );
527 }
528
529 return xRet;
530 }
531